faecher:informatik:oberstufe:java:aoc:aco2023:day7:start

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

Nächste Überarbeitung
Vorherige Überarbeitung
faecher:informatik:oberstufe:java:aoc:aco2023:day7:start [07.12.2023 14:00] – angelegt Marco Kuemmelfaecher:informatik:oberstufe:java:aoc:aco2023:day7:start [07.12.2023 19:43] (aktuell) – [Variante 2: Objekte] Frank Schiebel
Zeile 1: Zeile 1:
 +
 +~~NOTOC~~
 <tabs> <tabs>
   * [[#variante1|Variante 1]]   * [[#variante1|Variante 1]]
 +  * [[#variante2|Variante 2: Objekte und Comparable]]
  
 <pane id="variante1">  <pane id="variante1"> 
Zeile 11: Zeile 14:
   * Pro String-Array muss nun der Typ der Karte ermittelt werden und das String-Array der passenden ArrayList zugefügt werden.   * Pro String-Array muss nun der Typ der Karte ermittelt werden und das String-Array der passenden ArrayList zugefügt werden.
   * Am Ende muss man alle eingetragenen ArrayLists in der richtigen Reihenfolge durchlaufen, die String-Arrays pro ArrayList korrekt sortieren und alle Werte zusammenrechnen.   * Am Ende muss man alle eingetragenen ArrayLists in der richtigen Reihenfolge durchlaufen, die String-Arrays pro ArrayList korrekt sortieren und alle Werte zusammenrechnen.
 +  * Für die korrekte Sortierung wird man wiederum vermutlich nicht herumkommen einen eigenen ''Comparator'' zu erstellen, mit dem man eine eigene/neue Sortierreihenfolge erzwingen kann. 
 +
 +Dieser nachfolgende Lösungsvorschlag ist an einzelnen Stellen **nicht** besonders schön programmiert. Funktionieren tut er dennoch.
 +++++ Lösungsvorschlag |
 +<code java>
 +Comparator<String[]> cardComparator = new Comparator<String[]>() {
 +        // Die eigene Reihenfolge definieren
 +        String customOrder = "AKQJT98765432"; // Hier deine gewünschte Reihenfolge einfügen
 +
 +        @Override
 +        public int compare(String[] arr1, String[] arr2) {
 +            String s1 = arr1[0];
 +            String s2 = arr2[0];
 +
 +            int minLength = Math.min(s1.length(), s2.length());
 +            for (int i = 0; i < minLength; i++) {
 +                int index1 = customOrder.indexOf(s1.charAt(i));
 +                int index2 = customOrder.indexOf(s2.charAt(i));
 +                if (index1 != index2) {
 +                    return Integer.compare(index1, index2);
 +                }
 +            }
 +            return Integer.compare(s1.length(), s2.length());
 +        }
 +    };
 +    
 +private int getType(String hand) {
 +    boolean fiveOfAKind = false;
 +    boolean fourOfAKind = false;
 +    boolean threeOfAKind = false;
 +    int pairs = 0;
 +
 +    char[] chars = hand.toCharArray();
 +    Arrays.sort(chars);
 +
 +    char lastChar = chars[0];
 +    int counter = 1;
 +    for (int i = 1; i < chars.length; i++) {
 +        if (chars[i] != lastChar) {
 +            
 +            if (counter == 4) {
 +                fourOfAKind = true;
 +            } else if (counter == 3) {
 +                threeOfAKind = true;
 +            } else if (counter == 2) {
 +                pairs++;
 +            }
 +            lastChar = chars[i];
 +            counter = 1;
 +            continue;
 +        }
 +
 +        counter++;
 +    }
 +    if (counter == 5) {
 +        fiveOfAKind = true;
 +    } else if (counter == 4) {
 +        fourOfAKind = true;
 +    } else if (counter == 3) {
 +        threeOfAKind = true;
 +    } else if (counter == 2) {
 +        pairs++;
 +    }
 +
 +    if (fiveOfAKind) {
 +        return 0;
 +    } else if (fourOfAKind) {
 +        return 1;
 +    } else if (threeOfAKind && pairs == 1) {
 +        return 2;
 +    } else if (threeOfAKind && pairs == 0) {
 +        return 3;
 +    } else if (pairs == 2) {
 +        return 4;
 +    } else if (pairs == 1) {
 +        return 5;
 +    } else {
 +        return 6;
 +    }
 +}
 +
 +
 +public long partOne() {
 +    ArrayList<String[]> lines = new ArrayList<String[]>();
 +
 +    for (String line: inputLines) {
 +        lines.add(line.split(" "));
 +    }
 +
 +    // Die folgende Datenstruktur enthält 7 ArrayLists für String[] (die einzelnen Zeilen).  
 +    // In der ersten ArrayList werden die stärksten Kartentypen gespeichert und in den darauffolgenden die schwächeren.
 +    ArrayList<ArrayList<String[]>> ranks = new ArrayList<ArrayList<String[]>>();
 +    for (int i = 0; i < 7; i++) {
 +        ranks.add(new ArrayList<String[]>());
 +    }
 +
 +    // sortiere die einzelnen Zeilen nach Karten-Typ-Rang. Es ist noch NICHT nach Kartenwert innerhalb eines Kartentyps sortiert.
 +    for (String[] line: lines) {
 +        ranks.get(getType(line[0])).add(line);
 +    }
 +     
 +    long result = 0;
 +    int rankCounter = 1;
 +    for (int r = ranks.size() - 1 ; r >= 0; r--) {
 +        ArrayList<String[]> rank = ranks.get(r);
 +        
 +        rank.sort(cardComparator);
 +        for (int l = rank.size() - 1; l >= 0; l--) {
 +            String line = rank.get(l)[1];
 +            result += rankCounter * Integer.parseInt(line);
 +            rankCounter++;
 +        }
 +    }
 +
 +    return result;
 +}
 +</code>
 +++++
 +
 +====== Hilfestellung Teil 2 ======
 +Für Teil 2 benötigt man an zwei Stellen kleinere Anpassungen.
 +  - Bei der Erfassung der Types muss anders vorgegangen werden. Man kann die Methode ''getType()'' so umprogrammieren, dass sie nun die Joker ''J'' zunächst bewusst ignoriert. Anschließend nimmt man den errechneten Karten-Typ und korrigiert ihn pro vorhandenen Joker 'nach oben'. Beispiel: ''4JJKQ'' wird zunächst exklusive der zwei J als 'High Card' klassifiziert. Nimmt man im ersten Durchlauf einen Joker hinzu, so **muss** aus einer 'High Card' immer Päärchen werden. Nimmt man im zweiten Durchlauf den zweiten Joker hinzu, so **muss** aus einem Päärchen ein Drilling werden. Das ist damit die finale Kategorie dieser Karte.
 +  - Der Comparator muss minimal umgeschrieben werden, indem man die Reihenfolge der Zeichen ändert.
 +
 +
 +++++ Lösungsvorschlag |
 +<code java>
 +private int getType2(String hand) {
 +    boolean fiveOfAKind = false;
 +    boolean fourOfAKind = false;
 +    boolean threeOfAKind = false;
 +    int pairs = 0;
 +
 +    char[] chars = hand.toCharArray();
 +    Arrays.sort(chars);
 +
 +    char lastChar = chars[0];
 +    int counter = 1;
 +    for (int i = 1; i < chars.length; i++) {
 +        if (chars[i] == 'J') {
 +            continue;
 +        }
 +        
 +        if (chars[i] != lastChar) {
 +
 +            if (counter == 4) {
 +                fourOfAKind = true;
 +            } else if (counter == 3) {
 +                threeOfAKind = true;
 +            } else if (counter == 2) {
 +                pairs++;
 +            }
 +            lastChar = chars[i];
 +            counter = 1;
 +            continue;
 +        }
 +
 +        counter++;
 +    }
 +    if (counter == 5) {
 +        fiveOfAKind = true;
 +    } else if (counter == 4) {
 +        fourOfAKind = true;
 +    } else if (counter == 3) {
 +        threeOfAKind = true;
 +    } else if (counter == 2) {
 +        pairs++;
 +    }
 +
 +    if (fiveOfAKind) {
 +        return 0;
 +    } else if (fourOfAKind) {
 +        return 1;
 +    } else if (threeOfAKind && pairs == 1) {
 +        return 2;
 +    } else if (threeOfAKind && pairs == 0) {
 +        return 3;
 +    } else if (pairs == 2) {
 +        return 4;
 +    } else if (pairs == 1) {
 +        return 5;
 +    } else {
 +        return 6;
 +    }
 +}
 +
 +private int pimpType(int type, String card) {
 +    int amountOfJ = 0;
 +    for (int i = 0; i < card.length(); i++) {
 +        if (card.charAt(i) == 'J') {
 +            amountOfJ++;
 +        }
 +    }
 +
 +    int result = type;
 +    for (int i = 0; i < amountOfJ; i++) {
 +        if (type == 0 || type == 1) {
 +            type = 0;
 +        } else if (type == 2 || type == 3) {
 +            type = 1;
 +        } else if (type == 4) {
 +            type = 2;
 +        } else if (type == 5) {
 +            type = 3;
 +        } else {
 +            type = 5;
 +        }
 +    }
 +
 +    return type;
 +}
 +
 +public long partTwo() {
 +    ArrayList<String[]> lines = new ArrayList<String[]>();
 +
 +    for (String line: inputLines) {
 +        lines.add(line.split(" "));
 +    }
 +
 +    // Die folgende Datenstruktur enthält 7 ArrayLists für String[] (die einzelnen Zeilen).  
 +    // In der ersten ArrayList werden die stärksten Kartentypen gespeichert und in den darauffolgenden die schwächeren.
 +    ArrayList<ArrayList<String[]>> ranks = new ArrayList<ArrayList<String[]>>();
 +    for (int i = 0; i < 7; i++) {
 +        ranks.add(new ArrayList<String[]>());
 +    }
 +
 +    // sortiere die einzelnen Zeilen nach Karten-Typ-Rang. Es ist noch NICHT nach Kartenwert innerhalb eines Kartentyps sortiert.
 +    for (String[] line: lines) {
 +        int type = getType2(line[0]);
 +        type = pimpType(type, line[0]);
 +        ranks.get(type).add(line);
 +    }
 +
 +    long result = 0;
 +    int rankCounter = 1;
 +    for (int r = ranks.size() - 1 ; r >= 0; r--) {
 +        ArrayList<String[]> rank = ranks.get(r);
 +
 +        rank.sort(cardComparator2);
 +        for (int l = rank.size() - 1; l >= 0; l--) {
 +            String line = rank.get(l)[1];
 +            result += rankCounter * Integer.parseInt(line);
 +            rankCounter++;
 +        }
 +    }
 +
 +    return result;
 +}
 +</code>
 +++++
 +</pane>
 +<pane id="variante2"> 
 +====== Variante 2: Objekte ======
 +
 +Variante zwei wieder mit Objekten:
 +
 +{{ :faecher:informatik:oberstufe:java:aoc:aco2023:day7:2023-12-07_20-31.png?nolink&600 |}}
 +
 +Wie bei den Sortieralgorithmen  [[faecher:informatik:oberstufe:algorithmen:sorting:problemstellung:start|hier]] erläutert, kann man bei Java-Klassen das "Comparable"-Interface implementieren, damit ist es möglich, in der Methode ''compareTo'' eigene Regeln festzulegen, nach denen die Objekte dieser Klasse sortiert werden sollen. Genau das benötigen wir hier:
 +
 +  * Wir erzeugen für jede Zeile in der Eingabe ein ''Hand''-Objekt, für den wir den Typ bestimmen und in einem Attribut ablegen.
 +  * Dann wollen wir die Objekte sortieren - allerdings reicht der Vergleich der Typen nicht aus, weil man bei zwei "Hands" desselben Typs die einzelnen Karten vergleichen soll.
 +  * Also implementieren wir in der Klasse Hand die Methode ''compareTo'', die genau das macht.
 +
 +Die Lösung für Teil 1 und Teil 2 findet sich im selben Code, ich habe versucht das verständlich zu kommentieren. Wenn du nicht viel Programmiererfahrung hast, musst du wahrscheinlich auch an anderer Stelle noch nachlesen:
 +
 +  * Teil 1: [[https://codeberg.org/qg-info-unterricht/aoc-bluej-2023/src/commit/a897fdacc8c6ad31785a9eb3c7bb682192a925c9/Hand.java|Hand.java]], [[https://codeberg.org/qg-info-unterricht/aoc-bluej-2023/src/commit/a897fdacc8c6ad31785a9eb3c7bb682192a925c9/day7.java|day7.java]]
 +  * Teil 1&2: [[https://codeberg.org/qg-info-unterricht/aoc-bluej-2023/src/branch/main/Hand.java|Hand.java]]  [[https://codeberg.org/qg-info-unterricht/aoc-bluej-2023/src/branch/main/day7.java|day7.java]]
 +
  
 </pane> </pane>
 </tabs> </tabs>
  • faecher/informatik/oberstufe/java/aoc/aco2023/day7/start.1701957659.txt.gz
  • Zuletzt geändert: 07.12.2023 14:00
  • von Marco Kuemmel