Zadanie z AdventOfCode - Regexy, działania na BigInteger, pętle i instrukcje warunkowe - zły wynik.

0

Cześć

Robię zadanie ze strony AdventOfCode - link (Jak link nie wchodzi to: https://adventofcode.com/2016/day/12). Łatwiej będzie wrzucić link, bo tam jest cała treść zadania + kod źródłowy.

Problem jest taki, że wszystko mi pięknie i ładnie hula, ale wynik wyjściowy jest zły. Nie wiem ile powinno wyjść w rejestrze "a", mi wyrzuca po odpaleniu 45. Czy mógłby ktoś życzliwy sprawdzić, gdzie u mnie jest błąd? Próbowałem wielu rzeczy i wynik wychodzi ciągle ten sam, a jakiekolwiek zmiany w cofaniu/przerzuceniu do przodu iteracji zgodnie z ostatnią instrukcją wysypuje program, bo się nie kończy. Poniżej kod:


public static void main(String[] args) throws IOException {
        List<String> code = Files.readAllLines(Paths.get("zadanie122016.txt"));

        LinkedHashMap<String, BigInteger> map = new LinkedHashMap<>();
        map.put("a", BigInteger.ZERO);
        map.put("b", BigInteger.ZERO);
        map.put("c", BigInteger.ZERO);
        map.put("d", BigInteger.ZERO);

        Pattern patternCPY = Pattern.compile("cpy");
        Pattern patternINC = Pattern.compile("inc");
        Pattern patternDEC = Pattern.compile("dec");
        Pattern patternJNZ = Pattern.compile("jnz");
        Pattern patternLetter = Pattern.compile("[a-z]");

        for (int i = 0; i < code.size(); i++) {
            Matcher matcherCPY = patternCPY.matcher(code.get(i));
            Matcher matcherINC = patternINC.matcher(code.get(i));
            Matcher matcherDEC = patternDEC.matcher(code.get(i));
            Matcher matcherJNZ = patternJNZ.matcher(code.get(i));

            String[] line = code.get(i).trim().split(" ");
            Matcher matcherIsLetter = patternLetter.matcher(line[1]);

            if (matcherCPY.find()) {
                if (matcherIsLetter.matches()) {
                    BigInteger sum = map.get(line[2]).add(map.get(line[1]));
                    map.replace(line[2], sum);
//                    map.replace(line[2], map.get(line[1]));                   komentarz poniżej kodu
                    System.out.println(code.get(i));
                } else {
                    BigInteger sum = map.get(line[2]).add(new BigInteger(line[1]));
                    map.replace(line[2], sum);
//                    map.replace(line[2], new BigInteger(line[1]));            komentarz poniżej kodu
                    System.out.println(code.get(i));
                }

            } else if (matcherINC.find()) {
                BigInteger sum = map.get(line[1]).add(BigInteger.ONE);
                map.replace(line[1], sum);
                System.out.println(code.get(i));

            } else if (matcherDEC.find()) {
                BigInteger sum = map.get(line[1]).subtract(BigInteger.ONE);
                map.replace(line[1], sum);
                System.out.println(code.get(i));

            } else if (matcherJNZ.find()) {
                if (matcherIsLetter.matches()) {
                    if (map.get(line[1]).signum() > 0) {
                        System.out.println(code.get(i));
                        i = i + (Integer.parseInt(line[2]));
                    }
                } else {
                    if (!line[1].equals("0")) {
                        System.out.println(code.get(i));
                        i = i + (Integer.parseInt(line[2]));
                    }
                }
            }
        }
        System.out.println();
        System.out.println(map.get("a"));
    }

Tam, gdzie są komentarze to kwestia zamiany z poprzednim, bo nie jestem pewien czy autorowi tego zadania pisząc "copy" miał na myśli, aby dodać tą wartość do aktualnego rejestru czy ustawić rejest na taką wartość. Tak czy siak, czy zmienię czy nie, to ciągle w rejestrze "a" jest na koniec 45.

Będę bardzo wdzięczny za pomoc, bo to ważne zadanie, które muszę jak najszybciej oddać i na prawdę widzę, że to nie kwestia, że nie umiem tylko gdzieś zrobiłem "czeski" błąd.

1

The jnz instruction moves relative to itself: an offset of -1 would continue at the previous instruction, while an offset of 2 would skip over the next instruction.

No to załóżmy, że jesteś w i = 10
2 przypadki.

  1. i = 2 - wg tego co jest w poleceniu powinieneś przejść do linii 11.
    To to co ty zrobisz to dodasz doi wartość 2 czyli skończysz pętlę z wartością 12, ale żeby było jeszcze śmiejszniej, to po pętli masz inkrementację i i wartość którą dostajesz finalnie to 13.
  2. i = -2. - wg polecenia powinieneś być w linii 8. To co ty zrobisz to i = 10 - 2 czyli dostajesz wartość dobrą, ale przy wejściu do pętli robisz sobie jeszcze i++ więc czytasz linię 10 - 2 + 1
0

@szweszwe: Zrobiłem na szybko "usprawnienie" tak jak mówisz, aby po prostu zobaczyć czy to działa i niestety program zapętla się na "jnz b -2" i nie przechodzi dalej. Ogólnie to manualnie stwierdziłem, że poeksperymentuję sobie i pozmieniam na różne wartości. Opisałem w komentarzach w kodzie co i jak. Generalnie w sytuacji 1, 2 i 3 cały czas to samo czyli zapętlanie się na tym samym. Jeśli natomiast zmieniłem jak w sytuacji 4, to niezależnie czy było przy if'ie > 0 ustawione na sytuacja 1 czy 2 to i tak wyrzucało 46 co jest błędnym wynikiem. Jak wszędzie "i = i + indexReturn;" to wychodzi 45. Generalnie ciągle to samo.

else if (matcherJNZ.find()) {
                int indexReturn = Integer.parseInt(line[2]);
                if (matcherIsLetter.matches()) {
                    if (map.get(line[1]) > 0) {
                        System.out.println(code.get(i));
                        if (indexReturn > 0){b - 
                            i = i + indexReturn - 1;    <-- zapętla - sytuacja 1;
                    //      i = i + indexReturn - 2;    <-- zapętla - sytuacja 2;
                    //      i = i + indexReturn;        <-- zapętla - sytuacja 3;
                        } else if (indexReturn < 0){
                            i = i + indexReturn - 1;    <-- tak wpisane podczas sytuacji 1,2,3;
                    //      i = i + indexReturn;        <-- sytuacja 4 i działa, ale wyrzuca 46, to zła odpowiedź, niezależnie czy sytuacja 1 lub 2
                        }
                    }
                } else {
                    if (!line[1].equals("0")) {
                        System.out.println(code.get(i));
                        if (indexReturn > 0){
                            i = i + indexReturn - 1;    <-- zapętla - sytuacja 1;
                    //      i = i + indexReturn - 2;    <-- zapętla - sytuacja 2;
                    //      i = i + indexReturn;        <-- zapętla - sytuacja 3;
                        } else if (indexReturn < 0){
                            i = i + indexReturn - 1;    <-- tak wpisane podczas sytuacji 1,2,3;
                   //      i = i + indexReturn;         <-- sytuacja 4 i działa, ale wyrzuca 46, to zła odpowiedź, niezależnie czy sytuacja 1 lub 2
                        }
                    }
                }
            }

A i z tego co mi się wydaje to w przypadku 1 z Twojej odpowiedzi to właśnie powinno wskoczyć na i = 12, z tego powodu, że jeśli jesteśmy na 10 to chcemy ominąć instrukcję 11 i od razu przejść na 12. No, ale jest ta inkrementacja, więc powinno wskoczyć na 13. Tylko skoro tak jest to czemu ta instrukcja się nie kończy i się zapętla na tym samym bez końca?

1

A, zapomniałem, że twoje kopiowanie jest złe. Jakąś sumę tam liczysz i inne cuda. Masz wartość skopiować po prostu. To co było oryginalnie zakomentowane jest dobrze więc sobie to zmień a potem sprawdź zmiany dla jnz. No i nie próbuj 3 sposobów bo tylko jeden jest dobry. Chyba jesteś w stanie powiedzieć, licząc w głowie, czy trzeba i jeśli tak to o ile zmienić obliczony indeks i :P

1

@szweszwe: Mega, mega wielkie dzięki! Teraz rzeczywiście śmiga :D jedynie z tym 1 przypadkiem z Twojego komentarza było tak jak rzeczywiście myślałem i ma przeskoczyć kolejną instrukcję.
A i zmieniałem, bo oczywiście całkowicie logiczne było to co napisałeś, ale skoro nie działało to zwątpiłem w swoją wiedzę i czy na pewno dobrze Cię zrozumiałem i stwierdziłem, że sprawdzę, a najwyżej potem wyjaśnię :D ale wszystko okej, więc temat do zamknięcia i jeszcze raz wielkie dzięki!

1 użytkowników online, w tym zalogowanych: 0, gości: 1