Advent of Code
- __blackjack__
- User
- Beiträge: 14240
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Aaah, hatte ich noch gar nicht nachgeschaut. Weiss gar nicht mit welchem Rechner/System ich das dieses Jahr angehen will. Bin halbwegs sattelfest in CP/M auf Intel 8080, aber PDP-11 ist auch irgendwie interessant. Da aber noch kein Betriebssystem angeschaut. Vielleicht am Wochenende mal Unix installieren und dann vielleicht einen nativen C-Compiler in den Fingern haben‽
“All tribal myths are true, for a given value of 'true'.” — Terry Pratchett, The Last Continent
- __blackjack__
- User
- Beiträge: 14240
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
CP/M mit z80pack, weil man den Altair/IMSAI da so schön grafisch hat. PDP würde ich mit simh machen.
“All tribal myths are true, for a given value of 'true'.” — Terry Pratchett, The Last Continent
Traditionellerweise löse ich die ersten 2-3 Tage per Excel, einfach weils am schnellsten geht, die Daten manuell herum zu schubsen, statt eine sattelfeste automatische Lösung zu programmieren.
Diesmal hab ich Tag 1 pflichtgemäßg per Python versucht, und immerhin den ersten Teil auch geschafft, nur beim zweiten bekomme ich die Info, dass meine Antwort zu hoch gegriffen sei. Ich fand noch nicht alle Gründe. Einen Schnitzer hatte ich schon ausgebaut, dass die Position 100 fälschlich doppelt berechnet wurde. Bin jetzt schon ein paar Dutzend Zeilen manuell durchgegangen, aber die Logik scheint soweit erstmal stichfest. Was habe ich noch übersehen?
Das i hab ich extra so unerwartet abgekürzt benannt, um die Stammuser hier zu grüßen. 
Diesmal hab ich Tag 1 pflichtgemäßg per Python versucht, und immerhin den ersten Teil auch geschafft, nur beim zweiten bekomme ich die Info, dass meine Antwort zu hoch gegriffen sei. Ich fand noch nicht alle Gründe. Einen Schnitzer hatte ich schon ausgebaut, dass die Position 100 fälschlich doppelt berechnet wurde. Bin jetzt schon ein paar Dutzend Zeilen manuell durchgegangen, aber die Logik scheint soweit erstmal stichfest. Was habe ich noch übersehen?
Code: Alles auswählen
import os
from dataclasses import dataclass
@dataclass
class Instruction:
direction: str
length: int
text: str
def parse_data_01(data):
instructions = []
for line in data.split("\n"):
first_char = line[0]
if first_char == "R":
direction = +1
elif first_char == "L":
direction = -1
else:
raise ValueError("Direction must be coded as L or R, but found: {first_char}.")
other_chars = line[1:]
length = int(other_chars)
instructions.append(Instruction(direction, length, line))
return instructions
def solve_01(data):
zeroes_hit = 0
zeroes_passed = 0
position = 50
print(f"- The dial starts by pointing at {position}.")
instructions = parse_data_01(data)
for i in instructions:
position = (position + (i.direction * i.length))
while position < 0:
zeroes_passed += 1
position += + 100
while position > 100:
zeroes_passed += 1
position -= 100
if position in (0, 100):
position = 0
zeroes_hit += 1
zeroes_passed += 1
print(f"- The dial is rotated {i.text} to point at {position}.")
print(f"- Hit position 0 a total of {zeroes_hit} times.")
print(f"- Passed position 0 a total of {zeroes_passed} times.")
if __name__ == "__main__":
folder = "C:/data/py/26-aoc2025"
number = "01"
file_path = os.path.join(folder, f"{number}.txt")
with open(file_path) as f:
data = f.read().strip()
solve_01(data)
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Es gibt noch eine weitere Position, die in Deinem Code manchmal (etwa in der Hälfte der Fälle) doppelt gezählt wird.Kebap hat geschrieben: Montag 1. Dezember 2025, 14:48 Einen Schnitzer hatte ich schon ausgebaut, dass die Position 100 fälschlich doppelt berechnet wurde. Bin jetzt schon ein paar Dutzend Zeilen manuell durchgegangen, aber die Logik scheint soweit erstmal stichfest. Was habe ich noch übersehen?
Ich hatte erst den gleichen Fehler beim 2. Teil gemacht, daher hab ich das schnell gefunden.
- __blackjack__
- User
- Beiträge: 14240
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Kebap: Das ``position > 100`` ist komisch. Sollte das nicht >99 sein und den Fall ``if position == 100`` kann man sich dann sparen‽
“All tribal myths are true, for a given value of 'true'.” — Terry Pratchett, The Last Continent
Teil 1 in ging in Bash noch relativ einfach als Einzeiler:
Oder gegolft sogar unter 80 Zeichen:
Aber für Teil 2 hab’ ich mehrere Zeilen gebraucht:
Dass in der `for`-Schleife alles in einer arithmetic expansion gemacht wird, ist eine Performanceoptimierung. Bash ist sehr geeignet für sowas, nur 100x langsamer als der selbe Algorithmus in Python umgesetzt.
Code: Alles auswählen
n=50; < input tr LR -+ | while read line; do ((n = (n $line + 100) % 100)); echo $n; done | grep -c '^0$'
Code: Alles auswählen
n=50;tr LR -+<i|while read l;do((n=(n$l+100)%100));echo $n;done|grep -c '^0$'
Code: Alles auswählen
n=50
part_2=0
while read line; do
((step = line < 0 ? -1 : 1))
((step_count = line < 0 ? -line : line))
for ((i = 0; i < step_count; ++i)); do
((n = (n + step + 100) % 100, n == 0 && ++part_2))
done
done < <(tr LR -+ < input)
echo $part_2
Hmm, ich habe nun ein Beispiel isolieren können, das fälschlich doppelt gezählt wird.Manul hat geschrieben: Montag 1. Dezember 2025, 17:29Es gibt noch eine weitere Position, die in Deinem Code manchmal (etwa in der Hälfte der Fälle) doppelt gezählt wird.Kebap hat geschrieben: Montag 1. Dezember 2025, 14:48 Einen Schnitzer hatte ich schon ausgebaut, dass die Position 100 fälschlich doppelt berechnet wurde. Bin jetzt schon ein paar Dutzend Zeilen manuell durchgegangen, aber die Logik scheint soweit erstmal stichfest. Was habe ich noch übersehen?
Ich hatte erst den gleichen Fehler beim 2. Teil gemacht, daher hab ich das schnell gefunden.
Tatsächlich an derselben Position, die ich bereits repariert wähnte:
Code: Alles auswählen
- The dial starts by pointing at 50.
- The dial is rotated R50 to point at 0.
- Passed zero: 2 times.
- Hit zero: 1 time.
Habe den Vorschlag von __blackjack__ umgesetzt, aber das brachte keine Besserung.
edit: Habe jetzt meinen letzten Entwurf mit den While-Schleifen weggeworfen, die jede Drehung einzeln summieren.
Statt dessen benutze ich nun die Kraft der Division, um direkt die richtige Anzahl der Hunderterübergänge zu errechnen:
Code: Alles auswählen
zeroes_passed += abs(position // 100)
position = position % 100
zeroes_hit += (position == 0)
edit: Sie ist zu HOCH, obwohl mir jetzt wieder Fälle aufgefallen sind, die ich gar nicht richtig mitzähle:
Code: Alles auswählen
- The dial starts by pointing at 1.
- The dial is rotated L1 to point at 0. Passed 0: 0 times. Hit 0: 1 times.
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Die war auch schon repariert. Zumindest tritt das mit Deinem oben geposteten Code nicht auf.Kebap hat geschrieben: Mittwoch 3. Dezember 2025, 12:03 Hmm, ich habe nun ein Beispiel isolieren können, das fälschlich doppelt gezählt wird.
Tatsächlich an derselben Position, die ich bereits repariert wähnte:
Code: Alles auswählen
- The dial starts by pointing at 50. - The dial is rotated R50 to point at 0. - Passed zero: 2 times. - Hit zero: 1 time.
Das hat im Gegenteil wahrscheinlich den Fehler eingeführt. Ich mag was übersehen, aber ich halte den Vorschlag mit ">99" ausnahmsweise für nicht hilfreich.Kebap hat geschrieben: Mittwoch 3. Dezember 2025, 12:03 Irgendwie hab ich gerade einen Knoten im Kopf, wie ich das am besten löse, ohne zu viel zu verlieren.
Habe den Vorschlag von __blackjack__ umgesetzt, aber das brachte keine Besserung.
Warum sollte es das? Wenn Du die drei Zeilen oben im Kopf mit der Endposition durchgehst, sollte klar werden, dass "zeroes_passed" hier nicht hochgezählt wird.Kebap hat geschrieben: Mittwoch 3. Dezember 2025, 12:03[...]Code: Alles auswählen
zeroes_passed += abs(position // 100) position = position % 100 zeroes_hit += (position == 0)[...]Code: Alles auswählen
- The dial starts by pointing at 1. - The dial is rotated L1 to point at 0. Passed 0: 0 times. Hit 0: 1 times.
Sollte doch auch 1x passed sein. Hmrgl.
Tag 1 in Rust, aber erstmal nur für die Beispiele aus Part 1:
Das Lesen aus dem Dateianhang baue ich noch ein. Bin gespannt, ob mir da mein Parser zum Verhängnis wird. 
Jedenfalls ist das ein schönes Anwendungsbeispiel für die scan()-Methode, finde ich.
Code: Alles auswählen
fn parse_steps(instruction: &str) -> i32 {
instruction.trim_start_matches("R")
.replace("L", "-")
.parse()
.unwrap()
}
fn find_path(start: i32, instructions: Vec<&str>) -> impl Iterator<Item = i32> {
instructions.into_iter().map(parse_steps)
.scan(start, |position, steps| {
*position = (*position + steps).rem_euclid(100);
dbg!(&position);
Some(*position)
})
}
fn main() {
let instructions = vec!["L68", "L30", "R48", "L5", "R60", "L55", "L1", "L99", "R14", "L82"];
let zeros = find_path(50, instructions).filter(|n| *n == 0);
dbg!(zeros.count());
}Jedenfalls ist das ein schönes Anwendungsbeispiel für die scan()-Methode, finde ich.
