faecher:informatik:oberstufe:java:aoc:aco2023:day6: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:day6:start [06.12.2023 09:09] – angelegt Marco Kuemmelfaecher:informatik:oberstufe:java:aoc:aco2023:day6:start [06.12.2023 19:13] (aktuell) – [Aufgabe] Frank Schiebel
Zeile 1: Zeile 1:
 +~~NOTOC~~
 +====== Tag 6: Wait For It ======
 +
 +===== Aufgabe =====
 +
 +  * {{ :faecher:informatik:oberstufe:java:aoc:aco2023:day6:aoc2023day6.png?linkonly|Aufgabe}}
 +  *  {{ :faecher:informatik:oberstufe:java:aoc:aco2023:day6:d6.zip |Inputdateien}}: 
 +    * Beispiel d6e.txt
 +    * Input d6i.txt. 
 +
 +
 +++++ Kontrollergebnisse |
 +  * Eingabedatei d6e.txt: 
 +    * Teil 1 - ''288''
 +    * Teil 2 - ''71503''  
 +  * Eingabedatei d6i.txt: 
 +    * Teil 1 - ''160816''
 +    * Teil 2 - ''46561107''
 +++++
 +
 +===== Hinweise =====
 +
 +
 <tabs> <tabs>
   * [[#variante1|Variante 1]]   * [[#variante1|Variante 1]]
 +  * [[#variante2|Variante 2: Etwas Mathematik?]]
  
 <pane id="variante1">  <pane id="variante1"> 
Zeile 45: Zeile 69:
 </code> </code>
 ++++ ++++
 +
 +==== Hilfestellung Teil 2 ====
 +  * Teil 2 ist tatsächlich noch einiges einfacher als Teil 1. Dadurch, dass die erste und zweite Zahl jeweils als eine Zahl interpretiert wird, kann das Array wegfallen und damit kann auch eine Schleife wegfallen.
 +  * Wichtig ist nun allerdings, dass man beide Zahlen als ''long'' speichert, da die Zahlen den Wertebereich von int andernfalls überschreiten können.
 +  * Um aus den ersten Zahlen einer Zeile eine gemeinsame Zahl zu machen bevor man sie parsed, kann man alle Leerzeichen zwischen den Ziffern entfernen mit ''replaceAll(" ","")''. Damit wird jedes Leerzeichen durch 'nix' ersetzt. 
 +
 +++++ Lösungsvorschlag |
 +<code java>
 +public long partTwo() {
 +    long time = Long.parseLong(inputLines.get(0).split(":")[1].replaceAll(" ", ""));
 +    long distance = Long.parseLong(inputLines.get(1).split(":")[1].replaceAll(" ", ""));
 +
 +    long numberOfWaysToBeat = 0;
 +    for (long buttonTime = 0; buttonTime < time; buttonTime++) {
 +        if ((buttonTime * (time-buttonTime)) > distance) {
 +            numberOfWaysToBeat++;
 +        }
 +    }
 +
 +    return numberOfWaysToBeat;
 +}
 +</code>
 +++++
 +</pane>
 +
 +<pane id="variante2"> 
 +==== Variante 2: Mitternachtsformel ====
 +
 +Wenn man unter der Dusche etwas nachdenkt, stellt man fest, dass das eigentlich eine Matheaufgabe ist: Man kann berechnen, wie  weit man kommt, je nach dem wie lang man den Knopf drückt und wenn man weiß, welche Zeit insgesamt zur Verfügung steht.
 +
 +**Fragen:**  
 +
 +  * Wie weit kommt man in der Zeit 17ms, wenn man den Knopf 3ms drückt?
 +  * Wie sieht es bei 37ms und 13ms gedrücktem Knopf aus?
 +  * Wie bei  ''t'' ms und ''p'' ms gedrückten Knopf?
 +
 +++++ Tipp 1: |
 +Wenn man ''p'' ms lang den Knopf drückt, kann sich das Boot ''t-p'' ms lang mit der Geschwindigkeit ''p'' bewegen, kommt also
 +
 +  d_t(p) = (t-p)*p
 +
 +Millimeter weit. Für jedes gegebene ''t'' und ''p'' ergibt sich eine andere Entfernung. 
 +
 +++++
 +
 +
 +Multipliziere deine Formel aus, was erhältst du dann?
 +++++ Tipp 2: |
 +  d_t(p) = (t-p)*p = -p² + tp
 +  
 +Eine nach unten geöffnete Parabel.
 +++++
 +
 +Für das zweite Wertepaar ''t=15'' und ''d=40'' kann man mit diesen Überlegungen folgendes Bildchen zeichnen, in dem man ablesen, kann dass man mindestens 4 und höchstens 11 ms drücken muss, um den bisherigen Rekord von 40mm zu überbieten
 +
 +{{ :faecher:informatik:oberstufe:java:aoc:aco2023:day6:bsp2.png?600 |}}
 +
 +Nun kann man die Aufgabe mit der Mitternachtsformel und den beiden Methoden ''Math.floor'' und ''Math.ceil'' direkt lösen, ganz ohne Schleifen und das klappt dann auch für beide Teile, wenn man aus der Aufgabe des Vortags noch mit long Variablen hantiert, sonst muss man den Typ für Teil 2 noch umstellen.
 +
 +Aufpassen muss man noch bei Fällen wie dem dritten Beispiel, wenn die Mitternachtsformel direkt die Ränder des Bereichs liefert - die gehören nämlich nicht dazu, weil das Boot echt weiter als das bisherige Maximum fahren soll. Hier muss man den Fall, dass die MNF "aufgeht" noch extra abfangen.
 +
 +[[https://codeberg.org/qg-info-unterricht/aoc-bluej-2023/src/branch/main/day6.java|BlueJ-Lösungsvorschlag zum "spicken" findet sich hier]]
 +
 </pane> </pane>
 </tabs> </tabs>
  • faecher/informatik/oberstufe/java/aoc/aco2023/day6/start.1701853781.txt.gz
  • Zuletzt geändert: 06.12.2023 09:09
  • von Marco Kuemmel