मेरे पास एक Map<Integer, Character> alphabetMap है, जिसमें संख्या से लेकर वर्णमाला तक के लिंक हैं।

उदाहरण के लिए: [1: 'A', 2: 'B', ... , 26: 'Z']

मेरे पास एक रोटेट () विधि है, जो प्रविष्टियों को बदलते लिंक के साथ रखना चाहिए

पहली बार विधि का उपयोग करने के बाद मेरा नक्शा [1: 'Z', 2: 'A', 3: 'B', ... , 26: 'Y'] होना चाहिए

यहाँ मेरी वर्तमान प्राप्ति है:

public void rotate() {
    final Map<Integer, Character> tempMap = new HashMap<>();
    alphabetMap.forEach((key, value) -> tempMap.put(key == 26 ? 1 : key + 1, value));
    alphabetMap = tempMap;
}

क्या मेरी प्रविष्टियों को तेज़ी से "घुमाने" के लिए कोई और तरीका/एल्गोरिदम है?

1
Максим Рыбалкин 12 जिंदा 2022, 15:44
2
चूँकि कुंजियाँ संख्यात्मक क्रम में हैं, मेरा सुझाव है कि मानचित्र के भीतर एक सरणी या सूची का उपयोग करें।
 – 
Code-Apprentice
12 जिंदा 2022, 19:08

4 जवाब

"तेज़" रोटेशन के लिए मानचित्र को एक सूची और फिर विधि से बदला जा सकता है Collections.rotate का उपयोग किया जा सकता है। फिर सूची तत्वों को सूचकांक द्वारा [0..25] श्रेणी में पहुँचा जा सकता है।

या एक छोटा आवरण वर्ग लागू किया जा सकता है:

static class MyCharMap {
    private List<Character> chars = IntStream
        .rangeClosed('A', 'Z')
        .mapToObj(c -> (char)c)
        .collect(Collectors.toList());
        
    public void rotate() {
        Collections.rotate(chars, 1);
    }
    
    public Character get(Integer i) {
        assert(1 <= i && i <= 26);
        return chars.get(i - 1);
    }
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(4 * chars.size() + 2);
        sb.append('{');
        for (int i = 0, n = chars.size(); i < n; i++) {
            if (i > 0) sb.append(", ");
            sb.append(i + 1).append(':').append(chars.get(i));
        }
        sb.append('}');
        return sb.toString();
    }
}

परीक्षण:

MyCharMap chars = new MyCharMap();
        
chars.rotate();
chars.rotate();
System.out.println(chars);
System.out.println(chars.get(1));

आउटपुट:

{1:Y, 2:Z, 3:A, 4:B, 5:C, 6:D, 7:E, 8:F, 9:G, 10:H, 11:I, 12:J, 13:K, 14:L, 15:M, 16:N, 17:O, 18:P, 19:Q, 20:R, 21:S, 22:T, 23:U, 24:V, 25:W, 26:X}
Y

3
Alex Rudenko 12 जिंदा 2022, 16:47

मानचित्र का उपयोग करते समय आपके दृष्टिकोण में कुछ भी गलत नहीं है। लेकिन चूंकि रोटेशन कुछ क्रम के सापेक्ष होना चाहिए और नक्शे अनियंत्रित हैं, आप एलेक्स रुडेंको द्वारा सुझाई गई सूची का उपयोग करना चाह सकते हैं। .

मानचित्रों का उपयोग करने का एक और विकल्प यहां दिया गया है। यह आपूर्ति किए गए मानचित्र के लिए किसी भी राशि (चिह्न के आधार पर) से बाएं या दाएं घुमाव की अनुमति देता है जिसमें अनुक्रमिक पूर्णांक कुंजियां 1 से शुरू होती हैं। यह remainder operator का उपयोग करके आकार से अधिक की गणना के लिए भी समायोजित करता है। बाएँ या दाएँ घुमाव के लिए ऑफ़सेट की बस गणना की जाती है और नक्शा बदल दिया जाता है और बाद के प्रसंस्करण के लिए वापस कर दिया जाता है।

BiFunction<Map<Integer, Character>, Integer, Map<Integer, Character>> rotate =
        (mp, cnt) -> {
            int size = mp.values().size();
            int count = cnt < 0 ? size + (cnt % size) - 1 :
                    cnt - 1;
            return mp.entrySet().stream()
                    .map(e -> new AbstractMap.SimpleEntry<>(
                            (e.getKey() + count) % size + 1,
                            e.getValue()))
                    .collect(Collectors.toMap(e -> e.getKey(),
                            e -> e.getValue()));
        };

System.out.println(map);     // original map - 10 elements
map = rotate.apply(map,1);   // right one - starting at J
System.out.println(map);        
map = rotate.apply(map,-2);  // left two, skipping A, going to B
System.out.println(map);
map = rotate.apply(map, -21);// Essentially left one going to C
System.out.println(map);
map = rotate.apply(map, 22); // Essentially right two going to A
System.out.println(map);

प्रिंट

{1=A, 2=B, 3=C, 4=D, 5=E, 6=F, 7=G, 8=H, 9=I, 10=J}
{1=J, 2=A, 3=B, 4=C, 5=D, 6=E, 7=F, 8=G, 9=H, 10=I}
{1=B, 2=C, 3=D, 4=E, 5=F, 6=G, 7=H, 8=I, 9=J, 10=A}
{1=C, 2=D, 3=E, 4=F, 5=G, 6=H, 7=I, 8=J, 9=A, 10=B}
{1=A, 2=B, 3=C, 4=D, 5=E, 6=F, 7=G, 8=H, 9=I, 10=J}

लैम्ब्डा संस्करण को आसानी से एक नियमित विधि से बदला जा सकता है जो एक एकल घुमाव मान लेता है और एक निश्चित मानचित्र पर काम करता है।

3
WJS 12 जिंदा 2022, 19:06

जैसा कि @code-apprentice ने टिप्पणी में कहा है

चूँकि कुंजियाँ संख्यात्मक क्रम में हैं, मैं मानचित्र के बजाय एक सरणी या सूची का उपयोग करने का सुझाव देता हूँ।

यदि आप अभी भी एक नक्शा वापस करना चाहते हैं, तो आप Collections.rotate(...) विधि अपेक्षित मानचित्र के पुनर्निर्माण के साथ संयोजन में।

BiFunction<List<?>, Integer, Map<Integer, ?>> rotate =
        (list, distance) -> {

            Function<List<?>, Map<Integer, ?>> setMap = (arrayList) -> IntStream.range(0, arrayList.size())
                    .boxed()
                    .collect(Collectors.toMap(arrayList::get, Function.identity()))
                    .entrySet()
                    .stream()
                    .peek(e -> e.setValue(e.getValue() + 1))
                    .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));

            Collections.rotate(list, distance);
            return setMap.apply(list);

        };

System.out.println(rotate.apply(Arrays.asList('A', 'B', 'C', 'D'), 1)); // {1=D, 2=A, 3=B, 4=C}
System.out.println(rotate.apply(Arrays.asList("Peter", "James", "Sam", "Tiffany", "Mathew"), -3)); // {1=Tiffany, 2=Mathew, 3=Peter, 4=James, 5=Sam}
0
steven7mwesigwa 13 जिंदा 2022, 01:22

एलेक्स रुडेंको के उत्तर के आधार पर, आप एक कस्टम मानचित्र बना सकते हैं जो Collections.rotate(...) पीछे सीन।

कस्टम नक्शा:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

class MyMap {
    private static int counter = 0;
    private final Map<Integer, ?> initMap;
    private final List<?> list;
    private Map<Integer, ?> rotatedMap;

    public MyMap(List<?> list) {
        this.list = list;
        this.initMap = setMap(this.list);
        this.rotatedMap = cloneMap(this.initMap);
    }

    private Map<Integer, ?> setMap(List<?> list) {
        return IntStream.range(0, list.size())
                .boxed()
                .collect(Collectors.toMap(list::get, Function.identity()))
                .entrySet()
                .stream()
                .peek(e -> e.setValue(e.getValue() + 1))
                .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
    }

    private Map<Integer, ?> cloneMap(Map<Integer, ?> map) {
        return map.entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    public Map<Integer, ?> get() {
        counter = 0;
        return rotatedMap;
    }

    public MyMap reset() {
        counter = 0;
        this.rotatedMap = cloneMap(this.initMap);
        return this;

    }

    public MyMap rotate() {
        return rotateMap(++counter);
    }

    public MyMap rotate(int distance) {
        return rotateMap(distance);
    }

    private List<?> cloneList(List<?> list) {
        return list.stream().map(e -> e).collect(Collectors.toList());
    }

    private MyMap rotateMap(int distance) {
        List<?> list = cloneList(this.list);
        Collections.rotate(list, distance);
        this.rotatedMap = setMap(list);
        return this;
    }

    public String toString() {
        return rotatedMap.toString();
    }
}

उदाहरण 1 (दो बार घुमाएँ, घुमाएँ रीसेट करें, दो बार घुमाएँ।):

// Rotate twice, Reset rotation, Rotate twice.
MyMap myCharMap1 = new MyMap(Arrays.asList('A', 'B', 'C', 'D'));
System.out.println(myCharMap1
        .rotate(2)
        .reset()
        .rotate().rotate()
        .get()); // {1=C, 2=D, 3=A, 4=B}

उदाहरण 2 (तीन बार घुमाएँ। एक स्ट्रिंग सूची को घुमा सकते हैं):

//Rotate thrice.
MyMap myMap = new MyMap(Arrays.asList("Peter", "James", "Sam", "Tiffany", "Mathew"));
System.out.println(myMap.rotate(3).get()); // {1=Sam, 2=Tiffany, 3=Mathew, 4=Peter, 5=James}

उदाहरण 3 (एक बार घुमाएँ। एक संख्यात्मक सूची को भी घुमा सकते हैं):

// Rotate once. Can rotate a numeric list as well.
MyMap myDigitMap3 = new MyMap(Arrays.asList(38, 56, 98, 160));
System.out.println(myDigitMap3.rotate(1).get()); // {1=160, 2=38, 3=56, 4=98}

उदाहरण 4 (नकारात्मक घुमाव स्वीकार कर सकते हैं):

//Can accept negative rotations.
MyMap myMap = new MyMap(Arrays.asList("Peter", "James", "Sam", "Tiffany", "Mathew"));
System.out.println(myMap.rotate(-3).get()); // {1=Tiffany, 2=Mathew, 3=Peter, 4=James, 5=Sam}
0
steven7mwesigwa 13 जिंदा 2022, 01:25