Advent of Code
- __blackjack__
- User
- Beiträge: 13998
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Kebap: Muss ich gleich mal prüfen ob "\d+" tatsächlich funktioniert mit meinen Eingabedaten. Die Aufgabe war da ein bisschen spezifischer → "\d{1,3}". Das heisst "mul(42,4711)" wäre illegal, würde von "\d+" aber erfasst.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
@__blackjack__: Stimmt, das hatte ich wohl überlesen oder wieder vergessen. Jedenfalls hat es mein Ergebnis nicht beeinflusst.
Ich war hingegen an zwei anderen Stellen gestolpert:
- Der Status muss am Ende nicht "aktiviert" sein, also müssen ggf. mul-Befehle am Ende ignoriert werden. OK, leicht zu beheben. Randfälle sind ja Klassiker.
- Der Regex sucht nicht über Zeilenenden (also im gewissen Sinne auch "über einen Rand") hinweg. Also sowas wie hier hatte ich zuerst falsch behandelt:
Ich war hingegen an zwei anderen Stellen gestolpert:
- Der Status muss am Ende nicht "aktiviert" sein, also müssen ggf. mul-Befehle am Ende ignoriert werden. OK, leicht zu beheben. Randfälle sind ja Klassiker.
- Der Regex sucht nicht über Zeilenenden (also im gewissen Sinne auch "über einen Rand") hinweg. Also sowas wie hier hatte ich zuerst falsch behandelt:
Bei mir wurde zunächst nur foobar ignoriert. Wobei tatsächlich die kompletten zwei Zeilen ignoriert gehören! Der Workaround war zuerst \n zu löschen.don't()_blablabla
jippie_don't()_foobar_do()
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.
Danke für euren Input für Tag 2.
Bis jetzt habe ich noch kein Code geschrieben, der mir gefällt
Heute wurde es auch nicht besser, dafür war ich sehr schnell fertig. (Was gut war, weil ich leider nicht viel Zeit dazu hatte)
Ach und Tag 2 noch (fand das vorgeschlagene `skip_index`) schöner wie mein slicing:
Grüße
Dennis
Bis jetzt habe ich noch kein Code geschrieben, der mir gefällt
Heute wurde es auch nicht besser, dafür war ich sehr schnell fertig. (Was gut war, weil ich leider nicht viel Zeit dazu hatte)
Code: Alles auswählen
#!/usr/bin/env python
import re
from pathlib import Path
INPUT_FILE = Path(__file__).parent / "input03.txt"
PUZZLE_INPUT = """\
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
""".splitlines()
EXPRESSION = re.compile(r"mul\(\d*,\d*\)|don't\(\)|do\(\)")
def parse_input(lines):
expressions = []
for line in lines:
expressions.extend(re.findall(EXPRESSION, line))
return expressions
def decode_expression(expression):
if expression.startswith("mul"):
return map(int, re.findall(r"\d*,\d*", expression)[0].split(","))
return 0, 0
def get_mul(mul):
x, y = decode_expression(mul)
return x * y
def run_mul_expressions(expressions):
return sum(get_mul(expression) for expression in expressions)
def run_and_enable_mul_expressions(expressions):
run = True
multiples = []
for expression in expressions:
if expression == "don't()":
run = False
elif expression == "do()":
run = True
elif run:
multiples.append(get_mul(expression))
return sum(multiples)
def main():
puzzle_input = PUZZLE_INPUT
puzzle_input = INPUT_FILE.read_text(encoding="UTF-8").splitlines()
expressions = parse_input(puzzle_input)
print(run_mul_expressions(expressions))
print(run_and_enable_mul_expressions(expressions))
if __name__ == "__main__":
main()
Code: Alles auswählen
#!/usr/bin/env python
from itertools import pairwise
from pathlib import Path
INPUT_FILE = Path(__file__).parent / "input02.txt"
PUZZLE_INPUT = """\
7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9
""".splitlines()
def is_safe(report):
return (
all(1 <= x - y <= 3 for x, y in pairwise(report))
or all(1 <= y - x <= 3 for x, y in pairwise(report))
)
def get_safe_reports(reports):
return sum(is_safe(report) for report in reports)
def skip_index(iterable, index):
for i, value in enumerate(iterable):
if i != index:
yield value
def get_tolerated_safe_reports(reports):
safe_reports = 0
for report in reports:
if is_safe(report):
safe_reports += 1
else:
for index in range(len(report)):
if is_safe(list(skip_index(report, index))):
safe_reports += 1
break
return safe_reports
def main():
# puzzle_input = PUZZLE_INPUT
puzzle_input = INPUT_FILE.read_text(encoding="UTF-8").splitlines()
reports = list(map(lambda x: list(map(int, x.split())), puzzle_input))
print(get_safe_reports(reports))
print(get_tolerated_safe_reports(reports))
if __name__ == "__main__":
main()
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
- __blackjack__
- User
- Beiträge: 13998
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Hm, ich denke die lassen langsam nach. Früher hätten sie sichergestellt das weder "\d+" und schon gar nicht "\d*" funktioniert hätte. 
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Wenn man was parsen muss, ist Prolog immer eine gute Wahl:
Interessanterweise brauche ich für meinen Input den Test auf höchstens drei Ziffern auch nicht. Scheint also gewollt zu sein, dass das keine „richtige“ Anforderung ist.
Code: Alles auswählen
#!/usr/bin/env -S swipl -g main -t halt
:- use_module(library(dcg/basics)).
:- use_module(library(pure_input)).
one_to_three_digit_integer(Int) --> integer(Int), { 0 =< Int, Int < 1000 }.
mul(Product) -->
"mul(", one_to_three_digit_integer(Lhs), ",", one_to_three_digit_integer(Rhs), ")",
{ Product is Lhs * Rhs }.
conditional_mul(Value) --> mul(Value).
conditional_mul(0) --> "don't()", string(_), "do()".
multiplications(Mul, Result) -->
string(_), call(Mul, Product), multiplications(Mul, Rest),
{ Result is Rest + Product }.
multiplications(_, 0) --> string(_), eos.
main :-
phrase_from_file(multiplications(mul, Part1), input),
write(Part1), nl,
phrase_from_file(multiplications(conditional_mul, Part2), input),
write(Part2), nl.
- __blackjack__
- User
- Beiträge: 13998
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Vielleicht weil es erst der dritte Tag ist. 
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Oh:

Eigentlich wollte ich `+`weil ich wohl die Aufgabenstellung nicht ordentlich gelesen habeit specifies that the previous character can be matched zero or more times, instead of exactly once.
"When I got the music, I got a place to go" [Rancid, 1993]
- __blackjack__
- User
- Beiträge: 13998
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Kebap: Zeilenenden löschen ist aber auch gefährlich, denn das würde beispielsweise aus einem "d\no()" ein "do()" machen was es gar nicht geben sollte.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
- __blackjack__
- User
- Beiträge: 13998
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Also ich habe eine Funktion die beide Teile benutzen, die die Koordinaten des jeweiligen Startbuchstabens liefert. 
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
- __blackjack__
- User
- Beiträge: 13998
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@nezzcarth: Wenn ich so drüber nachdenke kann man da aber *eine* Funktion schreiben, die das Suchmuster als Datenstruktur bekommt.
@all: Heute war soweit ich das sehe, die erste schwierigere Aufgabe, also Aufgabenteil 2. Also zumindest sofern man nicht auf den Namen des Algorithmus kommt, den man da benutzen kann. Und es ist natürlich dann auch praktisch, dass es den Algorithmus schon fertig in der Standardbibliothek gibt.
@all: Heute war soweit ich das sehe, die erste schwierigere Aufgabe, also Aufgabenteil 2. Also zumindest sofern man nicht auf den Namen des Algorithmus kommt, den man da benutzen kann. Und es ist natürlich dann auch praktisch, dass es den Algorithmus schon fertig in der Standardbibliothek gibt.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
@__blackjack__: Da hast du tatsächlich auch wieder Recht..!

__blackjack__ hat geschrieben: Mittwoch 4. Dezember 2024, 09:58 @Kebap: Zeilenenden löschen ist aber auch gefährlich, denn das würde beispielsweise aus einem "d\no()" ein "do()" machen was es gar nicht geben sollte.
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.
Ich war gestern den ganzen Tag unterwegs und wie ich heute feststellen musste, habe ich nur ein dummes Rätsel verpasst. Ich will die Rätsel immer nutzen um an mir zu arbeiten, aber hier fällt mir nur ein, das ich mir merke wo in welcher Reihe und welcher Position ein "X" steht und dann muss ich gefühlt über 100 verschachtelte Schleifen den gefunden Index, wie auch die Reihe in alle Richtungen erhöhen und schauen ob irgendwie das Wort zusammen kommt.
Ich erinnere mich an letztes Jahr, da musste man Symbole suchen, aber wenigstens nur im Umkreis von einem Index-Wert und das war bei mir schon doof unleserlich. Ich wette, falls __blackjack__ das in Python gelöst hat, gibt es wieder "schlaue" Map-Objekte und dann geht das wie von alleine. Aber ich komm auf sowas einfach nicht.
Ich erinnere mich an letztes Jahr, da musste man Symbole suchen, aber wenigstens nur im Umkreis von einem Index-Wert und das war bei mir schon doof unleserlich. Ich wette, falls __blackjack__ das in Python gelöst hat, gibt es wieder "schlaue" Map-Objekte und dann geht das wie von alleine. Aber ich komm auf sowas einfach nicht.
"When I got the music, I got a place to go" [Rancid, 1993]
Falls wir an dasselbe denken, war zumindest mein Input so aufgebaut, dass er mit dem Ding aus der Standardbibliothek problemlos durchlief, beim eigentlichen Input aber Probleme machte.__blackjack__ hat geschrieben: Donnerstag 5. Dezember 2024, 13:41 Und es ist natürlich dann auch praktisch, dass es den Algorithmus schon fertig in der Standardbibliothek gibt.![]()

Ich finde, die heutige Aufgabe war geradezu prädestiniert dazu, sie in einem Basheinzeiler zu lösen:
Das ist nur 100x langsamer als meine Python-Lösung.
Code: Alles auswählen
for eq in "==" "!="; do grep , input | tr ',' '|' | xargs -I '{}' bash -c 'l=$(grep -E '"'"'({})\|({})'"'"' input | tr '"'"'|'"'"' '"'"' '"'"' | tsort | grep -E '"'"'{}'"'"'); n=$(echo "$l" | wc -l); if [[ $(echo '"'"'{}'"'"' | tr '"'"'|'"'"' '"'"','"'"'), '$eq' $(echo "$l" | tr '"'"'\n'"'"' '"'"','"'"') ]]; then echo "$l" | head -n $(($n / 2 + 1)) | tail -n1; fi' | sed -E 's/\s+/+/g' | paste -sd+ | bc; done
Meinst du (Achtung, Spoiler!) das hier? Das habe ich nicht benutzt, meine Lösung ist einfacher und benutzt nur Builtins und eine wenig benutzte, aber bei AoC immer wieder erstaunlich hilfreiche Funktion aus `functools`. Das funktioniert, weil die Inputdaten eine totale Ordnung bilden und jedes Paar aus den einzelnen Updates immer in genau einer der beiden möglichen Reihenfolge vorkommt.__blackjack__ hat geschrieben: Donnerstag 5. Dezember 2024, 13:41 Und es ist natürlich dann auch praktisch, dass es den Algorithmus schon fertig in der Standardbibliothek gibt.![]()
Es gibt auch einen anderen Lösungsansatz, der nicht unbedingt einfacher, aber vielleicht interessanter ist: In einem String kann man `XMAS` einfach mit `str.count` zählen. Wenn man den String drehen könnte, würde man `XMAS` auch diagonal/senkrecht/rückwärts einfach mit `str.count` suchen können...Dennis89 hat geschrieben: Donnerstag 5. Dezember 2024, 18:09 Ich war gestern den ganzen Tag unterwegs und wie ich heute feststellen musste, habe ich nur ein dummes Rätsel verpasst. Ich will die Rätsel immer nutzen um an mir zu arbeiten, aber hier fällt mir nur ein, das ich mir merke wo in welcher Reihe und welcher Position ein "X" steht und dann muss ich gefühlt über 100 verschachtelte Schleifen den gefunden Index, wie auch die Reihe in alle Richtungen erhöhen und schauen ob irgendwie das Wort zusammen kommt.

Das „nicht ohne Weiteres“ ist dann aber ein relativ einfacher Schritt? Alle Paare ignorieren, bei denen nicht beide Zahlen in der betrachteten Update-Zeile vorkommen? So hab ich es zumindest in der gezeigten Bash-Lösung gemacht.nezzcarth hat geschrieben: Donnerstag 5. Dezember 2024, 18:46 Der Input ist mutwillig so gestaltet, dass das im Spoiler Angesprochene explizit nicht so ohne Weiteres funktioniert.
- __blackjack__
- User
- Beiträge: 13998
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@nezzcarth: Wir denken an das selbe. Der Hinweis Regeln die sich auf Seitenzahlen beziehen, die nicht im jeweiligen Update vorkommen, zu ignorieren, steht soweit ich mich erinnere ja sogar in der Aufgabe. Ich bin da aber auch erst einmal in die Ausnahme wegen einem Kreis gerannt.
@Dennis89: Eine Schleife um die ganzen Koordinaten des Startbuchstabens "X" zu finden, und eine Schleife über die 8 möglichen Richtungen, und dann eine Schleife die diese Richtung absucht. Das sind doch bloss 3 Schleifen. Eine davon ist in einer Funktion ausgelagert und die kann man im zweiten Aufgabenteil benutzen um die ganzen Koordinaten des Startbuchstabens dort zu finden.
@Dennis89: Eine Schleife um die ganzen Koordinaten des Startbuchstabens "X" zu finden, und eine Schleife über die 8 möglichen Richtungen, und dann eine Schleife die diese Richtung absucht. Das sind doch bloss 3 Schleifen. Eine davon ist in einer Funktion ausgelagert und die kann man im zweiten Aufgabenteil benutzen um die ganzen Koordinaten des Startbuchstabens dort zu finden.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis