Advent of Code

Gute Links und Tutorials könnt ihr hier posten.
nezzcarth
User
Beiträge: 1638
Registriert: Samstag 16. April 2011, 12:47

Manul hat geschrieben: Sonntag 11. Dezember 2022, 10:59 Spielt noch jemand?
Ich bin an Tag 7 in die Rekursionsfalle getappt, obwohl ich es hätte besser wissen müssen. Danach war dann allerdings auch meine Motivation weitgehend weg und ich habe nur noch vereinzelte Aufgaben gelöst.
Benutzeravatar
grubenfox
User
Beiträge: 433
Registriert: Freitag 2. Dezember 2022, 15:49

Theoretisch ja... bin aber noch nicht dazu gekommen das Modul für Tag 7 fertigzustellen.
Benutzeravatar
__blackjack__
User
Beiträge: 13121
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Manul: Mathe-Aufgaben. Bäh. Ich vermute für Teil zwei müsste man eine Repräsentation für die Zahlen finden die nicht so ”gross” wird und bei der man die Operationen und Tests effizient durchführen kann. Dann müsste man an einer Lösung für Teil 1 nicht viel ändern. Ich hätte eine Idee, wenn da nicht die Addition als Operation wäre. (Es ist wahrscheinlich jedem aufgefallen, dass die Teilbarkeit immer eine Primzahl betrifft.)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Manul
User
Beiträge: 53
Registriert: Samstag 13. Februar 2021, 16:00

__blackjack__ hat geschrieben: Sonntag 11. Dezember 2022, 13:59 @Manul: Mathe-Aufgaben. Bäh. Ich vermute für Teil zwei müsste man eine Repräsentation für die Zahlen finden die nicht so ”gross” wird und bei der man die Operationen und Tests effizient durchführen kann.
Soweit d'accord.
__blackjack__ hat geschrieben: Sonntag 11. Dezember 2022, 13:59 Dann müsste man an einer Lösung für Teil 1 nicht viel ändern.
Sicher? Ich habe so eine Repräsentation gefunden (auch wenn ich nicht sicher bin, ob sie die effizienteste ist), aber die kommt mit dem "Abkühlen" nicht zurecht.
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

Es gibt auch eine einfache Lösung, die nicht darauf basiert, dass der Test immer auf Teilbarkeit durch eine Primzahl testet. Und man kann auch ganz normale `int` zur Repräsentation nehmen. Im Prinzip ist das Diff von Teil 1 zu Teil 2 bei mir drei Zeilen lang.
Manul
User
Beiträge: 53
Registriert: Samstag 13. Februar 2021, 16:00

narpfel hat geschrieben: Sonntag 11. Dezember 2022, 14:45 Es gibt auch eine einfache Lösung, die nicht darauf basiert, dass der Test immer auf Teilbarkeit durch eine Primzahl testet. Und man kann auch ganz normale `int` zur Repräsentation nehmen. Im Prinzip ist das Diff von Teil 1 zu Teil 2 bei mir drei Zeilen lang.
Jetzt bin ich neugierig: Wie sieht die denn aus? Ich habe in Teil 2 für alle items zu allen vorkommenden Divisoren jeweils den "worry"-Wert modulo des Divisors gespeichert. Das funktioniert prima für Addition und Multiplikation, aber nicht mehr für Integerdivision mit Abrunden.
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

@Manul: Wofür brauchst du denn die Division mit Abrunden?
Manul
User
Beiträge: 53
Registriert: Samstag 13. Februar 2021, 16:00

@narpfel: Fürs "Abkühlen" des worry level:
https://adventofcode.com/2022/day/11 hat geschrieben: After each monkey inspects an item but before it tests your worry level, your relief that the monkey's inspection didn't damage the item causes your worry level to be divided by three and rounded down to the nearest integer.
(Hervorhebung von mir)
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

@Manul: Für Teil 2?
Manul
User
Beiträge: 53
Registriert: Samstag 13. Februar 2021, 16:00

@narpfel: Nein, für Teil 1. Deswegen funktioniert ja meine Lösung für Teil 2 nur dort und nicht für Teil 1.
Benutzeravatar
sparrow
User
Beiträge: 4197
Registriert: Freitag 17. April 2009, 10:28

@Manul: Das betrifft aber nur die Aufgabe Nummer 1 von heute.
Manul
User
Beiträge: 53
Registriert: Samstag 13. Februar 2021, 16:00

@sparrow Sag ich doch: Ich habe beide Teile gelöst, aber keine Lösung gefunden, die für beide Teile passt. In Teil 1 habe ich die items ganz naiv als Integer modelliert. Da funktioniert das "Abkühlen", aber für Teil 2 explodiert mir die Rechenzeit. Für Teil 2 habe ich die oben beschriebene Modellierung benutzt. Das geht schnell, aber das Abkühlen funktioniert nicht mehr.
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

@Manul: Wenn du das so meinst, dann habe ich auch keine Lösung, die für beide Teile funktioniert:

Code: Alles auswählen

def part_1(monkeys):
    return solve(
        monkeys,
        round_count=20,
        worry_level_update=lambda worry_level: worry_level // 3,
    )


def part_2(monkeys):
    return solve(
        monkeys,
        round_count=10_000,
        worry_level_update=lambda worry_level: <<magic>>,
    )
Manul
User
Beiträge: 53
Registriert: Samstag 13. Februar 2021, 16:00

@narpfel: Aber Du hast für beide Teile die gleiche Repräsentation des worry level - das habe ich nicht hinbekommen. Magst Du teilen, wie Du's gelöst hast?
Benutzeravatar
__blackjack__
User
Beiträge: 13121
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Manul: Woher weisst Du das? Da steht ja nur ``<<magic>>``. Das kann ja auch bedeuten das man da sowohl `int`-Objekte als auch `WorryLevel`-Objekte rein füttern kann.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

__blackjack__ hat geschrieben: Sonntag 11. Dezember 2022, 13:59 @Manul: Mathe-Aufgaben. Bäh. Ich vermute für Teil zwei müsste man eine Repräsentation für die Zahlen finden die nicht so ”gross” wird und bei der man die Operationen und Tests effizient durchführen kann. Dann müsste man an einer Lösung für Teil 1 nicht viel ändern. Ich hätte eine Idee, wenn da nicht die Addition als Operation wäre. (Es ist wahrscheinlich jedem aufgefallen, dass die Teilbarkeit immer eine Primzahl betrifft.)
Da bin ich gespannt. Ich habe keine Ahnung, wie eine Repräsentation aussieht, die wegen der Addition nicht klappt.
Die "offensichtliche" Repräsentation ist ja, dass man sich nur den Rest bei Division durch eine Zahl merkt. Diese Zahl kann z.B. ein Vielfaches der Divisoren der Tests sein, dann kann man die Würfe der Affen noch nachvollziehen (weil sich die Reste der Test-Divisonen offensichtlich nicht ändern).

Wie macht man es so, dass die Addition ein Problem ist?
Benutzeravatar
__blackjack__
User
Beiträge: 13121
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bords0: Ich hatte an eine Primfaktorzerlegung gedacht. Das lässt sich leicht multiplizieren, aber Addition geht halt nicht. AFAIK. Kein Mathegenie hier. 🙂
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Manul
User
Beiträge: 53
Registriert: Samstag 13. Februar 2021, 16:00

__blackjack__ hat geschrieben: Sonntag 11. Dezember 2022, 16:59 @Manul: Woher weisst Du das?
Das hatte ich indirekt aus
narpfel hat geschrieben: Sonntag 11. Dezember 2022, 14:45 Im Prinzip ist das Diff von Teil 1 zu Teil 2 bei mir drei Zeilen lang.
geschlossen. Je nach Interpretation sehen wir hier schon 1 bis 3 geänderte Zeilen, da bleibt an anderer Stelle nicht mehr viel Luft.
Benutzeravatar
ThomasL
User
Beiträge: 1367
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Teil 1 war ja relativ zügig machbar. Bei Teil 2 musste man entweder ein Mathegenie sein oder irgendwo nachschauen. Ich habe letzteres.

Code: Alles auswählen

from math import prod

class Monkey:
    def __init__(self, data):
        self.items = list(map(int, data[1][16:].split(', ')))
        self.op = data[2][21:].split()
        self.divisor = int(data[3].split()[-1])
        self.next = [int(data[4].split()[-1]), int(data[5].split()[-1])]
        self.inspected = 0

    def inspect(self, part1):
        while self.items:
            worry = self.items.pop(0)
            self.inspected += 1
            factor = worry if self.op[1] == 'old' else int(self.op[1])
            new = worry * factor if self.op[0] == '*' else worry + factor                
            new = int(new / 3) if part1 else new % common
            monkeys[self.next[bool(new % self.divisor)]].items.append(new)

data = [line.strip() for line in open('input.txt').readlines()]
monkeys = [Monkey(data[i*7:(i+1)*7]) for i in range((len(data) // 7)+1)]

common = prod([monkey.divisor for monkey in monkeys]) # Produkt aller Modulo Werte der Affen

def run(amount, part1):
    for round in range(amount):
        for monkey in monkeys:
            monkey.inspect(part1)

run(20, True)
print('Part 1:', prod(sorted([monkey.inspected for monkey in monkeys])[-2:]))

monkeys = [Monkey(data[i*7:(i+1)*7]) for i in range((len(data) // 7)+1)]
run(10000, False)
print('Part 2:', prod(sorted([monkey.inspected for monkey in monkeys])[-2:]))
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

__blackjack__ hat geschrieben: Sonntag 11. Dezember 2022, 18:15 @bords0: Ich hatte an eine Primfaktorzerlegung gedacht. Das lässt sich leicht multiplizieren, aber Addition geht halt nicht. AFAIK. Kein Mathegenie hier. 🙂
Ah, ja, das wäre eine gute Möglichkeit, auch große Zahlen darzustellen, wenn es nur Multiplikation gäbe.

"Divisionsrest" schreit aber eigentlich nach Modulo. Man muss natürlich wissen, dass den man den in Additionen und Multiplikationen "reinziehen" kann.
Antworten