Advent of Code 2024 Vorige deel Overzicht

Pagina: 1 ... 9 10 Laatste
Acties:

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Janoz schreef op vrijdag 20 december 2024 @ 12:25:
Als we het toch over interpretaties hebben, Eigenlijk vond ik mijn eigen aanname vanochtend niet eens heel raar.
spoiler:
Nergens staat dat een cheat perse het kortste pad zou moeten hebben. Stel, een cheat pad van 18 levert een besparing van 35 stappen op. In mijn opinie van vanochtend is er dan ook een pad van 20 stappen welke een besparing van 33 oplevert. Op het eindpunt even heen en weer stappen.
Ik moest ook even goed lezen wat de bedoeling was (ik ging er in eerste instantie vanuit dat een shortcut in een rechte lijn moest liggen b.v.) maar er staat expliciet in de opgave:
spoiler:
Each cheat has a distinct start position (the position where the cheat is activated, just before the first move that is allowed to go through walls) and end position; cheats are uniquely identified by their start position and end position.

[..]

Because this cheat has the same start and end positions as the one above, it's the same cheat, even though the path taken during the cheat is different:
Volgens mij is dat niet te verenigen met jouw interpretatie :)

Acties:
  • +1 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 03-06 22:28

FCA

FCA schreef op vrijdag 20 december 2024 @ 11:39:
[...]


Voor deel 1-5 gaat mijn oplossing goed, deel 6 en 7
spoiler:
bevatten doodlopende wegen, ik weet niet of ik dat helemaal strict volgens de invoerbeschrijving vind ("Because there is only a single path from the start to the end").

Deel 5 vond ik dan wel weer een leuke edge case
spoiler:
obstakelvrije stukken die geen onderdeel zijn van de route, niet verbonden zijn met zowel begin als einde



Challenge 1
Day 20 - Part 1 : ..293
        generator: 300ns,
        runner: 31.9039ms

Parsing: 7.0449ms
Day 20 - Part 2 : ..808
        generator: 700ns,
        runner: 596.0102ms

Challenge 2
Parsing: 66.5358ms
Done with initial distance calc
Day 20 - Part 1 : ..956
        generator: 300ns,
        runner: 503.899ms

Parsing: 67.8503ms
Day 20 - Part 2 : ..982
        generator: 800ns,
        runner: 15.3887608s

Challenge 3:
Parsing: 1.1708931s
Done with initial distance calc
Day 20 - Part 1 : ..743
        generator: 2µs,
        runner: 8.3208074s

Parsing: 999.6695ms
Day 20 - Part 2 : ..943
        generator: 1µs,
        runner: 245.5121416s

Wat sneller dus, maar dat kan denk ik vooral verklaart worden door het verschil in gebruikte taal.
Verandering van het hashing algoritme, en
spoiler:
elke keer als ik een element neem van de start locatie, dit verwijderen, en ook de cheat in omgekeerde richting checken (dus van cheat_end naar cheat_start).

Levert volgende op:
Challenge 3
Parsing: 772.58ms
Day 20 - Part 1 :..743
        generator: 4.3µs,
        runner: 3.787326s

Parsing: 807.1034ms
Day 20 - Part 2 :  ..943
        generator: 700ns,
        runner: 129.0934452s

Dat is dus bijna een 2x speed up (waarvan het grootste gedeelte door de update van het hashing algoritme komt .. 8)7 , dat was een stap van 245s naar ~150s)
Waarschijnlijk is het effectiver om geen hashmap bij te houden en gewoon alles uit een array te halen, maar ik heb esthetische bezwaren daartegen O-)

edit: nog een factor 2 eruit weten te slepen door
spoiler:
Van boven naar beneden door de lijst met open ruimtes heen te lopen, dan hoef je nooit meer boven te checken, en hoef je dus maar de helft van de ruit te checken. Voor deel 1 is dit langzamer (je verliest blijkbaar wordt door door de geordende lijst te lopen, maar voor deel 2 veel sneller.


Challenge 3:
Parsing: 895.6684ms
Day 20 - Part 1 : ...743
        generator: 4.1µs,
        runner: 3.8967507s

Parsing: 935.5786ms
Day 20 - Part 2 : ...943
        generator: 1.1µs,
        runner: 54.7016369s

[ Voor 12% gewijzigd door FCA op 20-12-2024 14:12 ]

Verandert z'n sig te weinig.


Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Met numpy kan ik challenge 3 in ongeveer 80 seconden oplossen:
$ time python3 solve-numpy.py < aoc-2024-day-20-challenge-3.txt 
ReadInput() took 0.1883 seconds
FindDistances((3060, 1695),) took 12.4759 seconds
FindDistances((3039, 1695),) took 12.8817 seconds
Solve(2,) took 0.7871 seconds
...743
Solve(20,) took 52.0556 seconds
...943

real	1m18.480s
user	1m10.334s
sys	0m7.964s

Het grootste deel van de tijd zit in Numpy, maar FindDistances() is in Python code geïmplementeerd. Eigenlijk zou ik dat deel het liefst met PyPy runnen, maar helaas heb ik geen werkende Numpy+PyPy installatie momenteel. Ik denk dat ik het hier maar even bij laat.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Soultaker schreef op vrijdag 20 december 2024 @ 13:13:
[...]

Ik moest ook even goed lezen wat de bedoeling was (ik ging er in eerste instantie vanuit dat een shortcut in een rechte lijn moest liggen b.v.) maar er staat expliciet in de opgave:

[...]

Volgens mij is dat niet te verenigen met jouw interpretatie :)
Ja, dat ook nog, naast dat de 'race' uberhaupt het kortste pad moet hebben.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • +3 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:14
Ik geloof dat ik mijn code ook aardig verbeterd heb:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ day20 < big_inputs/aoc-2024-day-20-challenge-1.txt
Executing
 ├── Input parsed in 3,131µs
 ├── Part 1 calculated in 1,363µs: ...293
 ├── Part 2 calculated in 27,057µs: ...808
 └── Total time: 31,596µs

$ day20 < big_inputs/aoc-2024-day-20-challenge-2.txt
Executing
 ├── Input parsed in 13,072µs
 ├── Part 1 calculated in 5,920µs: ...956
 ├── Part 2 calculated in 162,386µs: ...982
 └── Total time: 181,433µs

$ day20 < big_inputs/aoc-2024-day-20-challenge-3.txt
Executing
 ├── Input parsed in 159,460µs
 ├── Part 1 calculated in 64,242µs: ...743
 ├── Part 2 calculated in 1,777,040µs: ...943
 └── Total time: 2,000,801µs


spoiler:
Ik gebruik nu mijn Grid type waar ik alle afstanden op bewaar en dat blijkt ongeveer 10x sneller dan een HashMap.

Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Zo, vandaag was wel een pittige uitdaging! Gelukkig is het weekend. Gefeliciteerd @Friits dat je de gouden ster als snelste hebt weten te pakken!

Ik had deel 1 nog vrij snel gebruteforcet (rank 87 op het global leaderboard; m'n op een-na-beste resultaat dit jaar!) maar ik denk niet dat het een spoiler is om op te merken dat je daar met deel 2 niet veel aan hebt.

Het is niet zo moeilijk om een oplossing te vinden:
spoiler:
Je kunt vrij eenvoudig bedenken wat de korste paden zijn op het laagste niveau. Bijvoorbeeld om "123A" te typen moet de robot erboven "<<^A>A>AvA" typen. Dan moet de robot daarboven "v<<AA..." typen enzovoorts, recursief.


Maar de korste oplossing vinden is lastiger, want:
spoiler:
je hebt keuzevrijheid bij het pad wat je kiest. In plaats van "<<^" kun je ook "<^<" of "^<<" doen om op dezelfde positie terecht te komen.

Een aantal van deze opties kun je elimineren: "<^<" is strict slechter dan de andere twee omdat de robot onder je daarbij nodeloos moet verplaatsen. Kortom, je hebt hooguit twee opties: of de horizontale beweging eerst, of de verticale. Maar dat geldt op elk niveau natuurlijk.


Het deel waarmee ik moeite had het me in te beelden was dit:
spoiler:
Het lijkt in eerste instantie alsof een kortste pad op een laag niveau ook een kortste pad op hogere niveaus zou moeten opleveren.

Waarom zou "v>" efficiënter moeten zijn dan ">v"? Op het tweede niveau is de transitie van 'v' naar '>' even kostbaar als omgekeerd (">" resp. "<"). Maar op het derde niveau is het verschillend, omdat '<' verder van de A-knop ligt dan '>'. Dus met twee robots is "v>" te prefereren boven "<v".

Ik heb een tijdje geprobeerd dit soort regels statisch te coden, maar dat leidde niet tot een correcte oplossing zelfs niet bij deel 1. Ik snap niet helemaal waarom niet. Uiteindelijk heb ik het opgelost met dynamic programming, maar het zou me niet verbazen als er ook een “statische” oplossing is.


De uiteindelijke code is nog best eenvoudig: 21.py Je moet alleen even het juiste perspectief hebben. :)

[ Voor 4% gewijzigd door Soultaker op 21-12-2024 10:54 ]


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:14
Soultaker schreef op zaterdag 21 december 2024 @ 10:53:
...

De uiteindelijke code is nog best eenvoudig: 21.py Je moet alleen even het juiste perspectief hebben. :)
Ik zie dat ik vrijwel dezelfde implementatie in Rust heb gemaakt voor vandaag. Volgens mij kun je er ook niet veel meer mee :)

Ik heb nog wel wat tijd lopen verdoen met microbenchmarks. Ik kwam de smallvec library tegen die hier best wel van pas komt. In plaats van dat de strings op de heap terecht komen, zijn het nu kleine strings die tot 8 characters gewoon op de stack blijven. Dan maakt qua performance nog best wel wat uit. De berekening door deel 2 gaat nu in 66 microseconden 8)7 Het doet er verder niet toe, maar het is wel leuk om te kijken hoe ver je kunt gaan soms. :D

Ik ben wel jaloers op de @Cache optie van Python. Dat maakt deze implementatie wel een stuk makkelijker! Misschien eens zie of ik iets dergelijks kan bereiken met macros...

[ Voor 7% gewijzigd door Marcj op 21-12-2024 18:03 ]


Acties:
  • +1 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
Marcj schreef op zaterdag 21 december 2024 @ 18:02:
Volgens mij kun je er ook niet veel meer mee :)
Ik heb er een tijd op vastgezeten vandaag. Maar uiteindelijk is mijn solver als volgt:

https://github.com/Robbin.../blob/main/day21/day21.cc

spoiler:
[code=c++]
long long DP[5][5][25];
const int MAX_LEVEL = 25;

long long solve(const int from, const int to, const int level) {
if (level == MAX_LEVEL) {
return 1;
}

if (DP[from][to][level] != -1) {
return DP[from][to][level];
}

long long bestDist = INF;
for (auto& path : minPaths[from][to]) {
long long currDist = solve(moveId['A'], moveId[path[0]], level + 1);
for (int i = 0; i < int(path.size()) - 1; i++) {
currDist += solve(moveId[path[i]], moveId[path[i + 1]], level + 1);
}
bestDist = min(bestDist, currDist);
}

return DP[from][to][level] = bestDist;
}
[/code]

Dus ik verwerk de paden al binnen de solve voor een state zodat cache values opvragen en opslaan O(1) is.


Zou fijn zijn als de code tag (formatting) ook werkt binnen spoilers trouwens :) .

[ Voor 9% gewijzigd door Robbinb1993 op 21-12-2024 19:16 ]


Acties:
  • +1 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:14
Robbinb1993 schreef op zaterdag 21 december 2024 @ 18:09:
[...]

Ik heb er een tijd op vastgezeten vandaag. Maar uiteindelijk is mijn solver als volgt:
...
Nice! Uiteindelijk doe je hetzelfde werk als wat onze andere oplossingen ook doen, maar dan in een andere volgorde. Qua snelheid maakt het waarschijnlijk eigenlijk niks uit.
Zou fijn zijn als de code tag (formatting) ook werkt binnen spoilers trouwens :) .
Ja, daar ben ik ook al een paar keer tegenaan gelopen :D

Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Marcj schreef op zaterdag 21 december 2024 @ 18:02:
Ik zie dat ik vrijwel dezelfde implementatie in Rust heb gemaakt voor vandaag. Volgens mij kun je er ook niet veel meer mee :)
Ik heb de “statische” versie uiteindelijk nog wel werkend gekregen (21-alt.py) maar het is gebaseerd op een hoop geëxperimenteer. In zekere zin is de “dynamische” oplossing simpeler. Soms loont het om het probleem abstract te houden.
Ik ben wel jaloers op de @Cache optie van Python. Dat maakt deze implementatie wel een stuk makkelijker!
@cache is inderdaad heel erg handig, vooral omdat het betekent dat je je kunt focussen op de logica achter je oplossing. Maar vandaag was het niet echt een killer feature. Ik heb ruim 2 uur over de oplossing gedaan, terwijl ik de memoization handmatig in 1 à 2 minuten had kunnen implementeren. De meerwaarde daarvan was dus beperkt. :P

Neemt niet weg dat @cache wel heel behulpzaam kan zijn. Mijn beste score dit jaar was op dag 11 (rank 52 op het global leaderboard) en daar heb ik inderdaad gewoon @cache op de functie van deel 1 geplakt om deel 2 op te lossen: 11.py.
Misschien eens zie of ik iets dergelijks kan bereiken met macros...
Het is vast mogelijk om ook in Rust de resultaten te cachen. Waarschijnlijk zijn macro's zelfs overkill. Je moet alleen een functie kunnen genereren die dezelfde signature heeft als een bestaande functie, en je moet argumenten kunnen forwarden naar de onderliggende functie (in C++ heet dat perfect forwarding).
Robbinb1993 schreef op zaterdag 21 december 2024 @ 18:09:
Zou fijn zijn als de code tag (formatting) ook werkt binnen spoilers trouwens :) .
Ja, dit of de mogelijkheid om een code-blok ingeklapt te tonen. Maar dit soort feature requests zijn al jaren (decennia?) geleden geopperd (voorbeeld) en nooit geïmplementeerd, dus ik denk dat het er ook nooit van zal komen.

Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Vandaag viel erg mee.

spoiler:
Op basis van de probleemstelling was ik bang dat we allerlei moeilijke wiskundige formules zouden moeten gaan verzinnen, maar gelukkig kon je alles gewoon bruteforce simuleren.

Mijn grootste struikelblok was dat ik met m'n slaapdronken kop 2024 in plaats van 2048 getypt had bij het implementeren van de PRNG... dan komen er natuurlijk heel andere getallen uit. Ik moest wel even staren voordat ik dat zag.

Voor deel 2 heb ik gewoon het hele verhaal gesimuleerd, en dan geteld hoeveel banenen elke key oplevert. Je kunt al beredeneren dat het aantal unieke keys niet meer kan zijn dan 194 = 130321, maar in de praktijk is het nog minder (38606 voor mijn invoer).


Ook een mooie gelegenheid om Python's Counter te gebruiken: 22.py

M'n oplossing is alleen relatief traag: ongeveer 4,4 seconde met PyPy (7,6 seconde zonder) maar ik zie ook niet zo 1-2-3 hoe ik het significant sneller kan maken.

Acties:
  • +1 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
Soultaker schreef op zondag 22 december 2024 @ 07:14:
Vandaag viel erg mee.

spoiler:
Op basis van de probleemstelling was ik bang dat we allerlei moeilijke wiskundige formules zouden moeten gaan verzinnen, maar gelukkig kon je alles gewoon bruteforce simuleren.

Mijn grootste struikelblok was dat ik met m'n slaapdronken kop 2024 in plaats van 2048 getypt had bij het implementeren van de PRNG... dan komen er natuurlijk heel andere getallen uit. Ik moest wel even staren voordat ik dat zag.

Voor deel 2 heb ik gewoon het hele verhaal gesimuleerd, en dan geteld hoeveel banenen elke key oplevert. Je kunt al beredeneren dat het aantal unieke keys niet meer kan zijn dan 194 = 130321, maar in de praktijk is het nog minder (38606 voor mijn invoer).


Ook een mooie gelegenheid om Python's Counter te gebruiken: 22.py

M'n oplossing is alleen relatief traag: ongeveer 4,4 seconde met PyPy (7,6 seconde zonder) maar ik zie ook niet zo 1-2-3 hoe ik het significant sneller kan maken.
Hij viel inderdaad mee vandaag. Wel fijn om even bij te komen van gisteren. Mijn oplossing draait in 17 ms:

https://github.com/Robbin.../blob/main/day22/day22.cc

spoiler:
Ik hou 'on the fly' bij tijdens het itereren over de lijst van 2000 secret numbers, of een reeks van 4 prijswijzingen al eerder gezien is voor deze lijst. En daarnaast een 1D array om de sommen van verkoopprijzen bij te houden voor de reeksen van 4 prijswijzigingen. Dan kunnen we eenvoudig het beste antwoord updaten als we deze 1D array van sommen updaten. Daarnaast kunnen we de transformatie nog optimaliseren met bitwise operations (zoals jij ook hebt gedaan). De MOD is ook een 2-macht: 2^24. Ik denk dat het grootste verschil met Python is dat de Map hashing gebruikt in plaats van directe indexing?

[ Voor 10% gewijzigd door Robbinb1993 op 22-12-2024 07:52 ]


Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
@Robbinb1993 Ah ja, ik vermoedde wel dat het in native code aanzienlijk sneller zou zijn. De truc met de 4-tuple herschrijven naar een lineaire index had ik ook bedacht, maar in Python leverde het niet direct heel veel snelheidswinst op (iets van 10%).

De truc met seenItr om dubbelen te herkennen zonder dat je elke keer je array moet clearen is ook erg mooi gevonden! Ik kan nog een paar andere optimalisaties verzinnen:
  1. Als je in transform() unsigned long gebruikt in plaats van signed long dan is 'ie aanzienlijk sneller (dat komt omdat de compiler dan de modulo-operatie kan herschrijven naar een bitmask; voor een signed integer is dat minder efficient omdat 'ie negatieve remainders moet ondersteunen terwijl de getallen in dit probleem nooit negatief zijn—een hoop extra werk voor niets dus).
  2. Je kunt de index online updaten. Dat is efficiënter en dan hoef je de invoer maar 1x in te lezen.
  3. Je kunt ook vrij makkelijk het antwoord van deel 1 tegelijkertijd berekenen.
Als ik die ideeën combineer kom ik op: robin-opt.cc, wat aanzienlijk sneller is op mijn machine (iets van 25 ms vs 55 ms voor het origineel).

En iets compleet anders: wat ben jij voor maniak dat je je code met 3 spaties indenteert 8)7 Iedereen weet toch dat alleen machten van 2 toegestaan zijn!

Acties:
  • +1 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Soultaker schreef op zondag 22 december 2024 @ 07:14:
spoiler:
Voor deel 2 heb ik gewoon het hele verhaal gesimuleerd, en dan geteld hoeveel banenen elke key oplevert. Je kunt al beredeneren dat het aantal unieke keys niet meer kan zijn dan 194 = 130321, maar in de praktijk is het nog minder (38606 voor mijn invoer).
spoiler:
Veel minder dan dat, meer dan 2/3 van die 194 set levert geen geldige sequence op die tussen 0 en 9 blijft. -9,-1,... kan bijvoorbeeld helemaal niet. Maar goed, alle getallen waren klein genoeg om in het geheugen bij te houden dus was ook deel 2 met een simpele pass te doen



https://github.com/Janoz-...oc/y2024/day22/Day22.java

[ Voor 7% gewijzigd door Janoz op 22-12-2024 08:37 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • +1 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
Soultaker schreef op zondag 22 december 2024 @ 08:18:
@Robbinb1993 Ah ja, ik vermoedde wel dat het in native code aanzienlijk sneller zou zijn. De truc met de 4-tuple herschrijven naar een lineaire index had ik ook bedacht, maar in Python leverde het niet direct heel veel snelheidswinst op (iets van 10%).

De truc met seenItr om dubbelen te herkennen zonder dat je elke keer je array moet clearen is ook erg mooi gevonden! Ik kan nog een paar andere optimalisaties verzinnen:
  1. Als je in transform() unsigned long gebruikt in plaats van signed long dan is 'ie aanzienlijk sneller (dat komt omdat de compiler dan de modulo-operatie kan herschrijven naar een bitmask; voor een signed integer is dat minder efficient omdat 'ie negatieve remainders moet ondersteunen terwijl de getallen in dit probleem nooit negatief zijn—een hoop extra werk voor niets dus).
  2. Je kunt de index online updaten. Dat is efficiënter en dan hoef je de invoer maar 1x in te lezen.
  3. Je kunt ook vrij makkelijk het antwoord van deel 1 tegelijkertijd berekenen.
Als ik die ideeën combineer kom ik op: robin-opt.cc, wat aanzienlijk sneller is op mijn machine (iets van 25 ms vs 55 ms voor het origineel).
Netjes en leerzaam. Draait bij mij nu ook een stuk sneller: 9ms.
En iets compleet anders: wat ben jij voor maniak dat je je code met 3 spaties indententeert 8)7 Iedereen weet toch dat alleen machten van 2 toegestaan zijn!
Haha, niet echt een goede reden voor. Alleen dat het wat compacter oogt. Tijdens productiewerk gebruik ik wel 4 spaces. VSCode heeft geen moeite met 3.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
De bovenstaande ideëen zijn ook in Python een stuk sneller: 22-fast.py draait in ~120 ms (wel trager dan C++ natuurlijk).
Robbinb1993 schreef op zondag 22 december 2024 @ 07:37:
spoiler:
Dan kunnen we eenvoudig het beste antwoord updaten als we deze 1D array van sommen updaten.
In m'n Python code levert het een kleine performance-winst op om
spoiler:
het antwoord van deel 2 buiten de lus te berekenen, als max(sums).

Het is een trade-off natuurlijk: als je binnen de lus update dan sla je automatisch de nullen over, maar update je answer vaker dan nodig. Als je buiten de lus update dan moet je over de hele array lopen, maar die is niet zo groot. Bij grote invoer is buiten de lus berekenen waarschijnlijk sneller.
Janoz schreef op zondag 22 december 2024 @ 08:33:
spoiler:
Veel minder dan dat, meer dan 2/3 van die 194 set levert geen geldige sequence op die tussen 0 en 9 blijft. -9,-1,... kan bijvoorbeeld helemaal niet. Maar goed, alle getallen waren klein genoeg om in het geheugen bij te houden dus was ook deel 2 met een simpele pass te doen
Goed punt!

Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Hier wat extra testdata voor dag 22: aoc-2024-day-22-challenge-1.zip

Niet heel spannend qua inhoud, maar wellicht handig als mensen willen benchmarken. (De efficiënte oplossingen zijn waarschijnlijk I/O bound.) Ter referentie:

$ time pypy3 22-fast.py < aoc-2024-day-22-challenge-1.txt 
...330
...333

real	0m2.422s
user	0m2.393s
sys	0m0.020s

Acties:
  • 0 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 15-05 16:24
Soultaker schreef op zaterdag 21 december 2024 @ 10:53:
Gefeliciteerd @Friits dat je de gouden ster als snelste hebt weten te pakken!
Thanks, toch voor één dagje bovenaan gestaan op het GoT leaderboard 8)

Met ~45 minuten voor deel 1 en ~90 minuten voor deel 2 stond ik ook rond plaats 125e en 250e op het globale leaderboard. Normaal eindig ik ergens tussen de 800–1600 en 400–800, dus dat was wel gaaf!

Vandaag was weer een normale, eenvoudige dag, en dan leg ik het toch af tegen degenen die sneller typen ;)

[ Voor 18% gewijzigd door Friits op 22-12-2024 12:23 ]


Acties:
  • +1 Henk 'm!

  • MatHack
  • Registratie: Oktober 2001
  • Niet online

MatHack

Dev by day, Gamer by night

Ik was wat aan het inhalen, en echt veels te lang over dag 19 gedaan, ik kwam elke keer te laag uit, maar ik kon me haast niet voorstellen dat mijn code fout was... achteraf gezien kan ik mezelf wel voor m'n kop stoten, want uiteindelijk kwam het door:
spoiler:
int32 ipv int64 |:(

There's no place like 127.0.0.1


Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Friits schreef op zondag 22 december 2024 @ 12:23:
Thanks, toch voor één dagje bovenaan gestaan op het GoT leaderboard 8)
Daar mag je best trots op zijn! Het was de moeilijkste opgave (tot nu toe) en ik vind snelle tijden bij moeilijke opgaven indrukwekkender dan bij makkelijkere opgaven.

(Overigens is het niet helemaal waar dat eenvoudigere opgaven slechts typwedstrijden zijn; er zijn daar vaak ook meer of minder effectieve strategiën om het probleem snel op te lossen. Typsnelheid is meestal niet de doorslaggevende factor.)
Oef, ik voel je pijn.
spoiler:
Wel een goede reden om Python te gebruiken. Of op z'n minst een taal als Rust of Zig met overflow detection in debug mode?

Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Omdat het een regenachtige dag was heb ik deel 1 van vandaag opgelost in Brainfuck:

Brainfuck:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>>++++[->++++++<]>[-[->>>>+<<<<]+>>>>]>>>>+<<<<<<<<[<<<<]>,[---------->+<[-->++
+++[<------>-]>>[>[->++<]>[<+++++>-]>>]<<<<[<<<<]>[->>>>+<<<<]>>>[>[->+<[->-<[->
>+<<]>>>>+<<<<]>>[<<+>>-]<<]>[<+>-]>>]>[-]<<<<<[<<<<]>]>[-<+++++[->++++++++++<]>
[-<+++++[->>++++++++<<]>>[->[>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<[>[->+<]>[<+>->>>>
>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<]<<<<<<]>>>>[>>>[-<+<[->-<]>[<+>-
]>]>]<<<<[<<<<]>>>>>>>>>>>>>>>>>>>>>>>>[>[->+<]>[<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>
>>>>>>>+>-]>>]<<<<[<<<<]>>>>[>>>[-<+<[->-<]>[<+>-]>]>]<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<[>[->+<]>[<+>->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]<<<<<<]>>>>[>>>[-<+<[->-<]>[<+>-
]>]>]<<<<[<<<<]>>>]<]>>[>>+>>]<<[[->+<]>[<<[->>>>+<<<<]>>>>>>]>[>[->+<]>[<++>-]>
>]<<<<[<<<<]>[->>>>+<<<<]>>>[>[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->[-
]>>[-]>+<+<<<[->+<]]]]]]]]]]]>[<+>-]>>]<<<<[<<<<]<[<<<<]<]>>>>>[->>>>]>[>[->>+<<
]>>>]<<<<[<<<<]>>>>[>>>[<+>-[<+>-[<+>-[<+>-[<+>-[<+>-[<+>-[<+>-[<+>-[-<[-]>>[-]>
>>+<<<+<[<+>-]]]]]]]]]]]<[->+<]>>]<<<<[<<<<]<<<<[<<<<]>>]<,]>>>[>>>>]>>>>[>>>>]<
<<<[->>++++++[->++++++++<]>.[-]<<<<<<<]++++++++++.[-]<<<<[-<<<<]


De performance is nog best wel acceptabel:

$ time bfi -O 22.bf < ../testdata/22.in 
...725

real	0m2.191s
user	0m2.190s
sys	0m0.000s

$ time bfi -O 22.bf < aoc-2024-day-22-challenge-1.txt
...330

real	2m13.662s
user	2m13.584s
sys	0m0.000s

Acties:
  • 0 Henk 'm!

  • CrossProd
  • Registratie: November 2014
  • Laatst online: 06-06 10:48
Soultaker schreef op zondag 22 december 2024 @ 16:34:
Omdat het een regenachtige dag was heb ik deel 1 van vandaag opgelost in Brainfuck:
Haha, nice. En hier ben ik als gemiddelde sterveling nog bezig met deel 2 van dag 21.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
CrossProd schreef op zondag 22 december 2024 @ 17:17:
Haha, nice. En hier ben ik als gemiddelde sterveling nog bezig met deel 2 van dag 21.
Dat is ook best een moeilijke uitdaging, alleen op een andere manier :P

Acties:
  • +1 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 15-05 16:24
Soultaker schreef op zondag 22 december 2024 @ 14:30:
(Overigens is het niet helemaal waar dat eenvoudigere opgaven slechts typwedstrijden zijn; er zijn daar vaak ook meer of minder effectieve strategiën om het probleem snel op te lossen. Typsnelheid is meestal niet de doorslaggevende factor.)
Ja, dat bedoelde ik ook meer als geintje, vandaar de " ;) "

Ik heb het idee dat de snelle oplossers heel goed zijn in het abstraheren van de omschrijving naar een algemeen probleem, met bijbehorende strategieën (en wellicht ook al een archief van standaard-algoritmen hebben opgebouwd). Dat gaat natuurlijk het beste als het probleem relatief eenvoudig is en goed in één van die "doosjes" past: transformeer de input naar een graaf, Dijkstra loslaten, en klaar!

Zelf ben ik meer een langeafstandsloper: niet de snelheid om te winnen op de 400 meter, maar wel geoefend in een langere tijd stevig doorwerken. En als we dan een halve marathon voorgeschoteld krijgen, kan ik wat van de sprinters achter me laten :)

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Weirde shit. Ik heb vandaag een bug in mijn algo die alleen getriggered wordt door de voorbeeld input, en niet de echte. Eerst maar weer even slapen en dan kijken hoe ik het oplos.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Zo, wat was iedereen snel klaar vandaag!

spoiler: dag 23 deel 1
Deel 1 was natuurlijk simpel te bruteforcen: loop alle tripels (u, v, w) af en check of ze aan de eisen voldoen (allemaal verbonden, minstens 1 begint met 't'). Je moet dan alleen oppassen dat je niets dubbel telt.

Je kunt het nog iets efficiënter maken door alleen de buren van de eerder gekozen vertices te proberen maar dat was niet eens nodig.


spoiler: dag 23 deel 2
Voor deel 2 had ik in eerste instantie een simpele DFS geschreven, die recursief elementen toevoegt aan een set tot 'ie maximaal is, maar dat bleek niet snel genoeg voor de officiële input.

Toen ben ik een beetje gaan Googlen op maximum clique in a graph wat natuurlijk een standaardprobleem is, en op het Bron-Kerbosch algoritme uitgekomen. Ik had er nog nooit van gehoord maar het is simpel genoeg om het snel te implementeren.

Python code: 23.py

Hoe hebben jullie het opgelost?

Acties:
  • +1 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
[b]Soultaker in "Advent of Code 2024"Soultaker schreef op maandag 23 december 2024 @i.Stijn
Hoe hebben jullie het opgelost?
Ik was wat later begonnen vandaag, maar zojuist klaar.

spoiler:
Ik heb de graaf bestudeerd en er is een bijzondere eigenschap: elke vertex heeft exact 13 buren. Oftewel er is een simpelere manier om het op te lossen: met bitmasks van size 14. We itereren over elke vertex en checken voor elke mogelijke subset van de buren inclusief zichzelf of het een clique is. En we houden dan het beste resultaat bij. Dit is dus O(N * 2^14). Voor een willekeurige graaf is dit probleem NP-hard en zou het veel moeilijker op te lossen zijn. In dit geval is de graaf sparse, waardoor Bron-Kerbosch ook goed werkt.

[ Voor 16% gewijzigd door Robbinb1993 op 23-12-2024 07:29 ]


Acties:
  • +1 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

spoiler:
Sowieso had ik al een node en edge class dus heb alles in een dubbel gerichte graaf gegooid. Deel 1 is triviaal door voor elke t_ te kijken of hij ook in de set van de buren van de buren zit en daar de unieke sets van t nemen.

Voor deel twee begon ik gewoon met een set van sets. Alle computers bij langs en voor elke computer kijken of hij verbonden was met alle andere computers in een set en hem dan aan die set toevoegen. Tot slot die computer nog zelf toevoegen als nieuwe set. Dit werkt alleen wanneer de eerste keer dat je een computer tegenkomt deze ook daadwerkelijk bij de grootste set hoort. Voor de uiteindelijke input werkte dat, maar niet de test input. De boel nog herschreven dat, zodra een computer bij een set past, 2 sets toegevoegd worden waarbij de ene de computer wel heeft en de ander niet werkte vervolgens wel voor de testinput en was voor de echte input ook in 2 seconden klaar


https://github.com/Janoz-...oc/y2024/day23/Day23.java

[ Voor 5% gewijzigd door Janoz op 23-12-2024 07:41 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Extra testdata voor dag 23: aoc-2024-day-23-challenge-1-to-5.zip

Antwoorden (voor deel twee geef ik de sha1 hash van de string met komma's maar zonder newline; b.v. "aa,bb,cc" → c38e7f3a962add7f644bb45e23816187018e746d; je kunt een online tool gebruiken om die te berekenen.)

aoc-2024-day-23-challenge-1.txt
Deel 1: 960
Deel 2: c097c9c81c66d0574d118062a028f78a11594fbe

aoc-2024-day-23-challenge-2.txt
Deel 1: 2540
Deel 2: b469c9d964c3f37e597ee0ee57513a51a52407f6

aoc-2024-day-23-challenge-3.txt
Deel 1: 4722
Deel 2: 41e4b22864b072b52b4ee2e9e835bb2bcc2c3f2a

aoc-2024-day-23-challenge-4.txt
Deel 1: 21567
Deel 2: 86077b441d9921a28c1749acf6a222038ae3b231

aoc-2024-day-23-challenge-5.txt
Deel 1: 513096
Deel 2: 55f56e43ea6c919762d64d5722d1424cd0617ea2

M'n Python oplossing doet 1,5 seconde respectievelijk 40 seconde over de eerste twee challenges; de andere duren te lang. Ben benieuwd of er een efficiënte techniek is om die op te lossen.

edit:
hier nog twee testcases op een andere manier gegenereerd

[ Voor 18% gewijzigd door Soultaker op 23-12-2024 11:48 ]


Acties:
  • 0 Henk 'm!

  • Hagdos
  • Registratie: April 2022
  • Laatst online: 13:31
spoiler:
Na deel 1 heb ik een lijst met mogelijke driehoekjes. Ik heb een functie die per groep kijkt welke buren toegevoegd zouden kunnen worden, en dan die mogelijke groepen teruggeeft. Zo maak ik van de driehoekjes een lijst met vierkantjes.

Dat blijf ik herhalen tot er nog maar één groep over is, dat is dan het antwoord.


Niet supersnel, maar het werkt. Deel 1 van @Soultaker krijg ik er nog mee gedraaid, met wat geduld. Deel 2 ga ik niet eens proberen 8)

Acties:
  • 0 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
Soultaker schreef op maandag 23 december 2024 @ 09:20:
Extra testdata voor dag 23: aoc-2024-day-23-challenge-1-to-3.zip

Antwoorden (voor deel twee geef ik de sha1 hash van de string met komma's maar zonder newline; b.v. "aa,bb,cc" → c38e7f3a962add7f644bb45e23816187018e746d; je kunt een online tool gebruiken om die te berekenen.)

aoc-2024-day-23-challenge-1.txt
Deel 1: 960
Deel 2: c097c9c81c66d0574d118062a028f78a11594fbe

aoc-2024-day-23-challenge-2.txt
Deel 1: 2540
Deel 2: b469c9d964c3f37e597ee0ee57513a51a52407f6

aoc-2024-day-23-challenge-3.txt
Deel 1: 4722
Deel 2: 41e4b22864b072b52b4ee2e9e835bb2bcc2c3f2a


M'n Python oplossing doet 1,5 seconde respectievelijk 40 seconde over de eerste twee challenges; de derde duurt te lang. Ben benieuwd of er een efficiënte techniek is om die op te lossen.
aoc-2024-day-23-challenge-1.txt: 7ms.
aoc-2024-day-23-challenge-2.txt: 120ms.
aoc-2024-day-23-challenge-3.txt: 1369ms.

spoiler:
Ik heb mijn bitmasking oplossing iets verder geoptimaliseerd door eerder te prunen d.m.v. backtracking. Ik denk wel dat als het aantal buren hoger kan zijn, Bron–Kerbosch efficiënter wordt. Ben nog bezig om dat algoritme te bestuderen.

Het is ook erg belangrijk in mijn backtracking algoritme om niet verder te zoeken als de huidige clique niet groter kan worden dan de grootste maximum clique die tot dan toe gevonden is. Als ik dan niet backtrack, is case 3 ook heel traag. Zonder die conditie doet case 3 er 112 seconden over.

Gebruik je pivoting voor het Bron-Kerbosch algoritme?


https://github.com/Robbin.../blob/main/day23/day23.cc

Edit:
Case 3 draait nu in 78 ms met
spoiler:
Bron-Kerbosch algoritme met een largest degree heuristic pivot. Als ik als pivot altijd het eerste element van P ∪ X neem, draait het in 170 ms. Als de pivot een random element in P ∪ X is dan is de tijd 91ms.


https://github.com/Robbin...23/day23_bron_kerbosch.cc

[ Voor 16% gewijzigd door Robbinb1993 op 23-12-2024 10:46 ]


Acties:
  • 0 Henk 'm!

  • Devilfish
  • Registratie: Augustus 2001
  • Laatst online: 06-06 11:04
Gek genoeg had ik de oplossing voor deel 1 en deel 2 goed, maar voor de Soultaker challenges ging deel 2 de mist in... Na nog eens goed kijken kwam ik daar ook uit...

code:
1
2
3
4
5
6
input/aoc-2024-day-23-challenge-1.txt: Answer 1: 2,6224ms
input/aoc-2024-day-23-challenge-1.txt: Answer 2: 2,9859ms
input/aoc-2024-day-23-challenge-2.txt: Answer 1: 12,2392ms
input/aoc-2024-day-23-challenge-2.txt: Answer 2: 1,3836ms
input/aoc-2024-day-23-challenge-3.txt: Answer 1: 6,2536ms
input/aoc-2024-day-23-challenge-3.txt: Answer 2: 2,2911ms


Deel 1 kan denk ik nog wel wat sneller :)

spoiler: Idee voor part2
Neem een set van alle connections voor een computer en zich zelf
Loopt door de connections en neem steeds een intersection als de connection nog in de candidate set zit
Voeg de computer opnieuw toe aan de candidate set.

Zou wellicht nog sneller zijn om computer zelf ook meteen toe te voegen aan connection set, maar dan moet ik weer andere dingen checken.


https://github.com/antonr...24/23/Solution/Program.cs

Acties:
  • 0 Henk 'm!

  • KabouterSuper
  • Registratie: September 2005
  • Niet online
Soultaker schreef op maandag 23 december 2024 @ 07:21:
Zo, wat was iedereen snel klaar vandaag!

spoiler: dag 23 deel 1
Deel 1 was natuurlijk simpel te bruteforcen: loop alle tripels (u, v, w) af en check of ze aan de eisen voldoen (allemaal verbonden, minstens 1 begint met 't'). Je moet dan alleen oppassen dat je niets dubbel telt.

Je kunt het nog iets efficiënter maken door alleen de buren van de eerder gekozen vertices te proberen maar dat was niet eens nodig.


spoiler: dag 23 deel 2
Voor deel 2 had ik in eerste instantie een simpele DFS geschreven, die recursief elementen toevoegt aan een set tot 'ie maximaal is, maar dat bleek niet snel genoeg voor de officiële input.

Toen ben ik een beetje gaan Googlen op maximum clique in a graph wat natuurlijk een standaardprobleem is, en op het Bron-Kerbosch algoritme uitgekomen. Ik had er nog nooit van gehoord maar het is simpel genoeg om het snel te implementeren.

Python code: 23.py

Hoe hebben jullie het opgelost?
Ik heb een lelijk stukje code geschreven wat verrassend genoeg snel genoeg was.
Deel 2:
spoiler:
Ik stop alles in een queue waar ik over loop tot die leeg is.
In de loop stop ik het eerste element in een nieuwe set en blijf daar elementen aan toevoegen zolang een nieuw element een edge heeft met alle elementen in de set.
Ondertussen verwijder uk het net toegevoegde element uit mijn main queue.

Het is een soort floodfill eigenlijk.

When life gives you lemons, start a battery factory


Acties:
  • +1 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:14
Mijn implementatie was met het algoritme dat de rest ook al riepen. Hij loopt best snel toch:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ day23 < big_inputs/aoc-2024-day-23-challenge-1.txt
Executing
 ├── Input parsed in 660µs
 ├── Part 1 calculated in 121µs: 960
 ├── Part 2 calculated in 11,298µs: 19
 └── Total time: 12,113µs

$ day23 < big_inputs/aoc-2024-day-23-challenge-2.txt
Executing
 ├── Input parsed in 1,262µs
 ├── Part 1 calculated in 453µs: 2540
 ├── Part 2 calculated in 22,888µs: 24
 └── Total time: 24,631µs

$ day23 < big_inputs/aoc-2024-day-23-challenge-3.txt
Executing
 ├── Input parsed in 2,699µs
 ├── Part 1 calculated in 653µs: 4722
 ├── Part 2 calculated in 42,539µs: 29
 └── Total time: 45,919µs


Ik laat hier alleen even het aantal nodes zien. Maar de sha1 van de string klopt ook :)

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Damn, jullie oplossingen schalen beter dan verwacht! Ik heb nog twee grotere testcases toegevoegd om op te benchmarken.
Robbinb1993 schreef op maandag 23 december 2024 @ 09:41:
spoiler:
Gebruik je pivoting voor het Bron-Kerbosch algoritme?
Ik heb alleen de meest basale versie geïmplementeerd waarbij je een random element als pivot pakt. Ik was er nog niet aan toegekomen het verder te optimaliseren :)
Devilfish schreef op maandag 23 december 2024 @ 10:33:
spoiler: Idee voor part2
Neem een set van alle connections voor een computer en zich zelf
Loopt door de connections en neem steeds een intersection als de connection nog in de candidate set zit
Voeg de computer opnieuw toe aan de candidate set.
KabouterSuper schreef op maandag 23 december 2024 @ 10:34:
spoiler:
Ik stop alles in een queue waar ik over loop tot die leeg is. In de loop stop ik het eerste element in een nieuwe set en blijf daar elementen aan toevoegen zolang een nieuw element een edge heeft met alle elementen in de set. Ondertussen verwijder uk het net toegevoegde element uit mijn main queue.
Misschien mis ik iets, maar geldt in beide gevallen niet dat
spoiler:
je in een suboptimale set kunt blijven zitten?

Stel de graaf bevat cliques van (a, b, c), (d, e, f), en (b, c, d, e) (voorbeeld)

Hoe garandeer je dan dat je de maximale clique van 4 vindt? Het lijkt me dat je altijd ergens moet backtracken zoals @Robbinb1993 ook doet.

Het klopt wel dat mijn random test cases hier niet specifiek op testen.

Acties:
  • 0 Henk 'm!

  • mbe81
  • Registratie: Juni 2008
  • Laatst online: 21:41
Ik vond het toch wel weer lastig vandaag. Ik heb genereer alle mogelijke opties door steeds door de lijst met computers heen te lopen en te kijken of ik er een kan toevoegen. Ik heb voor deel 2 een oplossing in 1,3 seconde. Geen toptijden dus vergeleken met sommige anderen hier maar wel tevreden.

De tweede helft van vorige week was ik erg druk en helaas zat het met dag 17 en 21 tegen. Die heb ik nog steeds niet opgelost en ook met dag 16, 18 en 20 ben ik nog niet gestart. Nog 4,5 dag in te halen dus.

Link naar vandaag: https://github.com/mbe81/.../main/days/day23/day23.go

[ Voor 8% gewijzigd door mbe81 op 23-12-2024 11:10 ]


Acties:
  • +1 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
Soultaker schreef op maandag 23 december 2024 @ 10:54:
Damn, jullie oplossingen schalen beter dan verwacht! Ik heb nog twee grotere testcases toegevoegd om op te benchmarken.


[...]

Ik heb alleen de meest basale versie geïmplementeerd waarbij je een random element als pivot pakt. Ik was er nog niet aan toegekomen het verder te optimaliseren :)


[...]


[...]

Misschien mis ik iets, maar geldt in beide gevallen niet dat
spoiler:
je in een suboptimale set kunt blijven zitten?

Stel de graaf bevat cliques van (a, b, c), (d, e, f), en (b, c, d, e) (voorbeeld)

Hoe garandeer je dan dat je de maximale clique van 4 vindt? Het lijkt me dat je altijd ergens moet backtracken zoals @Robbinb1993 ook doet.

Het klopt wel dat mijn random test cases hier niet specifiek op testen.
aoc-2024-day-23-challenge-3.txt: 7ms.
aoc-2024-day-23-challenge-4.txt: 20ms.
aoc-2024-day-23-challenge-5.txt: 69749ms. (De max. clique heeft een grootte van 49).

spoiler:
We kunnen het nog verder optimaliseren door in plaats van normale sets, bitsets te gebruiken. Hiermee kunnen we heel eenvoudig met AND operations P en X updaten voor de volgende iteratie. Ook andere operaties worden lichter. Voor pivotting gebruiken we weer de eenvoudige manier: het eerst mogelijke element als pivot. Dit omdat het goedkoper is dan zoeken naar alle mogelijke kandidaten voor de pivot.


https://github.com/Robbin...23/day23_bron_kerbosch.cc

[ Voor 6% gewijzigd door Robbinb1993 op 23-12-2024 11:23 ]


Acties:
  • +1 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 03-06 22:28

FCA

Soultaker schreef op maandag 23 december 2024 @ 09:20:
Extra testdata voor dag 23: aoc-2024-day-23-challenge-1-to-5.zip

Antwoorden (voor deel twee geef ik de sha1 hash van de string met komma's maar zonder newline; b.v. "aa,bb,cc" → c38e7f3a962add7f644bb45e23816187018e746d; je kunt een online tool gebruiken om die te berekenen.)

aoc-2024-day-23-challenge-1.txt
Deel 1: 960
Deel 2: c097c9c81c66d0574d118062a028f78a11594fbe

aoc-2024-day-23-challenge-2.txt
Deel 1: 2540
Deel 2: b469c9d964c3f37e597ee0ee57513a51a52407f6

aoc-2024-day-23-challenge-3.txt
Deel 1: 4722
Deel 2: 41e4b22864b072b52b4ee2e9e835bb2bcc2c3f2a

aoc-2024-day-23-challenge-4.txt
Deel 1: 21567
Deel 2: 86077b441d9921a28c1749acf6a222038ae3b231

aoc-2024-day-23-challenge-5.txt
Deel 1: 513096
Deel 2: 55f56e43ea6c919762d64d5722d1424cd0617ea2

M'n Python oplossing doet 1,5 seconde respectievelijk 40 seconde over de eerste twee challenges; de andere duren te lang. Ben benieuwd of er een efficiënte techniek is om die op te lossen.
Mijn oplossing is supersnel: challenge 4 deel 2 in 27ms met het goede antwoord, challenge 5 gaat verkeerd.

spoiler:
Omdat graafalgoritmes mijn zwakke punt zijn, en sowieso in Rust niet echt fijn met algemene grafen te werken is, heb ik vanochtend met mijn duffe hoofd een probabilistisch correct algoritme (geeft niet altijd het goede antwoord) geimplementeerd: greedy linear search per node. Gewoon voor elke start node extra connected nodes toevoegen als het een clique blijft. De grootste pakken, en als je "geluk" hebt is het de maximale. Werkt best vaak correct (zeker als je doordat je connecting nodes voor elke node in je maximale clique in een andere volgorde staan).

Geeft op voorbeeld, op de echte invoer en op challenge 1-4 het goede antwoord, pas voor challenge 5 gaat het mis, hij vindt een clique van 48 die blijkbaar nog niet de maximale is.

Verandert z'n sig te weinig.


Acties:
  • 0 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
FCA schreef op maandag 23 december 2024 @ 11:27:
[...]


Mijn oplossing is supersnel: challenge 4 deel 2 in 27ms met het goede antwoord, challenge 5 gaat verkeerd.

spoiler:
Omdat graafalgoritmes mijn zwakke punt zijn, en sowieso in Rust niet echt fijn met algemene grafen te werken is, heb ik vanochtend met mijn duffe hoofd een probabilistisch correct algoritme (geeft niet altijd het goede antwoord) geimplementeerd: greedy linear search per node. Gewoon voor elke start node extra connected nodes toevoegen als het een clique blijft. De grootste pakken, en als je "geluk" hebt is het de maximale. Werkt best vaak correct (zeker als je doordat je connecting nodes voor elke node in je maximale clique in een andere volgorde staan).

Geeft op voorbeeld, op de echte invoer en op challenge 1-4 het goede antwoord, pas voor challenge 5 gaat het mis, hij vindt een clique van 48 die blijkbaar nog niet de maximale is.
Hij is wel bijna maximaal (1 eronder qua grootte), dus voor een approximation algorithm werkt het wel goed. Het is ook gebruikelijk bij NP-hard problemen om het optimale antwoord te benaderen in plaats van exact te berekenen, als het niet per se optimaal hoeft te zijn maar 'goed genoeg' voldoende is.

Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
FCA schreef op maandag 23 december 2024 @ 11:27:
Mijn oplossing is supersnel: challenge 4 deel 2 in 27ms met het goede antwoord, challenge 5 gaat verkeerd.
Ah ja, dat dacht ik wel. De snelle greedy oplossingen zijn niet correct. Hier zijn nog twee testcases waar de greedy oplossingen vermoedelijk het verkeerde antwoord geven: aoc-2024-day-23-challenge-6-and-7.zip

sha1sums van deel 2:
aoc-2024-day-23-challenge-6.txt: cbef69c90c6d5ced7e1cf30378aff41d138a2d89
aoc-2024-day-23-challenge-7.txt: 9038faaec6c8d51affe90ee1b54625379f84ed7e


@Robbinb1993's oplossing lost case 6 in ieder geval wel correct op.

Acties:
  • +1 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 03-06 22:28

FCA

Soultaker schreef op maandag 23 december 2024 @ 11:47:
[...]

Ah ja, dat dacht ik wel. De snelle greedy oplossingen zijn niet correct. Hier zijn nog twee testcases waar de greedy oplossingen vermoedelijk het verkeerde antwoord geven: aoc-2024-day-23-challenge-6-and-7.zip

sha1sums van deel 2:
aoc-2024-day-23-challenge-6.txt: cbef69c90c6d5ced7e1cf30378aff41d138a2d89
aoc-2024-day-23-challenge-7.txt: 9038faaec6c8d51affe90ee1b54625379f84ed7e


@Robbinb1993's oplossing lost case 6 in ieder geval wel correct op.
Inderdaad, gaat goed mis op allebei. Met extra heuristiek vindt ik er een van grootte 23 voor challenge 6 en een van grootte 89 voor challenge 7, maar allebei niet goed genoeg.

Verandert z'n sig te weinig.


Acties:
  • +2 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
Soultaker schreef op maandag 23 december 2024 @ 11:47:
[...]

Ah ja, dat dacht ik wel. De snelle greedy oplossingen zijn niet correct. Hier zijn nog twee testcases waar de greedy oplossingen vermoedelijk het verkeerde antwoord geven: aoc-2024-day-23-challenge-6-and-7.zip

sha1sums van deel 2:
aoc-2024-day-23-challenge-6.txt: cbef69c90c6d5ced7e1cf30378aff41d138a2d89
aoc-2024-day-23-challenge-7.txt: 9038faaec6c8d51affe90ee1b54625379f84ed7e


@Robbinb1993's oplossing lost case 6 in ieder geval wel correct op.
Case 7 krijg ik niet opgelost binnen redelijke tijd. Case 5 verder geoptimaliseerd en draait nu in slechts 300 ms in plaats van ~70s:

https://github.com/Robbin...23/day23_bron_kerbosch.cc

Edit: met een color bound waarmee we nog eerder kunnen prunen, draait case 5 in 85ms.

spoiler:
Het standaard Bron-Kerbosch algoritme genereert alle max. cliques van de graaf, niet alleen de grootste. We hebben om deze reden set 'X' niet nodig in het algoritme, aangezien we alleen de grootste max. clique zoeken. X is er om vast te stellen of een clique maximaal is op het moment dat set P leeg is. Omdat we alleen de grootste max. clique zoeken, kunnen we ook de zoekboom prunen als de grootste max. clique die tot dan toe gevonden is, niet meer te overtreffen is.

[ Voor 31% gewijzigd door Robbinb1993 op 23-12-2024 17:11 ]


Acties:
  • 0 Henk 'm!

  • Devilfish
  • Registratie: Augustus 2001
  • Laatst online: 06-06 11:04
Vanaf 5 gaat het bij mij mis (met de foute sequences er nog even bij). Ik laat het even zitten voor nu, andere dingen te doen.

spoiler:
Heb wel door waar ik mis ga denk ik, ben iets te greedy :).


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
input/aoc-2024-day-23-challenge-1.txt: Answer 1: 960 (1,7499ms)
input/aoc-2024-day-23-challenge-1.txt: Answer 2: c097c9c81c66d0574d118062a028f78a11594fbe (2,6353ms)

input/aoc-2024-day-23-challenge-2.txt: Answer 1: 2540 (4,6934ms)
input/aoc-2024-day-23-challenge-2.txt: Answer 2: b469c9d964c3f37e597ee0ee57513a51a52407f6 (2,867ms)

input/aoc-2024-day-23-challenge-3.txt: Answer 1: 4722 (7,2894ms)
input/aoc-2024-day-23-challenge-3.txt: Answer 2: 41e4b22864b072b52b4ee2e9e835bb2bcc2c3f2a (2,6584ms)

input/aoc-2024-day-23-challenge-4.txt: Answer 1: 21567 (45,5121ms)
input/aoc-2024-day-23-challenge-4.txt: Answer 2: 86077b441d9921a28c1749acf6a222038ae3b231 (4,5525ms)

input/aoc-2024-day-23-challenge-5.txt: Answer 1: 513096 (895,8234ms)

input/aoc-2024-day-23-challenge-5.txt: Answer 2: d7858bd5d7b21f32e6b12892ebe7cf03c3748ded (aa,aj,al,au,av,bf,dp,du,eb,gc,gu,id,ii,kp,la,lo,me,mn,no,oy,pd,pz,qr,rp,so,sx,tc,to,ud,ul,us,vc,vf,vo,vx,ww,xa,xe,yu,zg,zi,zj) (37,0704ms)

input/aoc-2024-day-23-challenge-6.txt: Answer 1: 0 (0,0004ms)
input/aoc-2024-day-23-challenge-6.txt: Answer 2: 33e12673905f41ea2f2c5ff2f694fe59bd44961b ( bf,bm,cb,cf,do,gv,gw,ib,ja,kz,nf,nm,nr,nu,ok,ow,pl,rp,uj,ux,wj,xd,yo,yt ) (0,6058ms)

input/aoc-2024-day-23-challenge-7.txt: Answer 1: 110810 (135,0649ms)
input/aoc-2024-day-23-challenge-7.txt: Answer 2: 9f86767250de3d0be139ca114e374a72394cc4d5 (ab,ac,ag,al,an,au,bl,bs,bt,cv,cx,dc,ei,ej,ew,fd,fe,fq,ft,fu,fv,fw,gh,gs,hb,hi,hr,ij,io,ix,jb,je,jp,jq,kk,ks,lh,ln,lo,lt,md,mg,mn,mo,mx,no,np,oh,op,oy,pt,pw,py,qf,ql,qp,qr,qs,qy,rh,rk,ro,ru,rz,sd,sp,ss,tg,tm,tr,ty,ua,up,ur,ut,ux,uy,va,vg,vo,wk,xd,xi,xk,xl,xr,yh,yv,yw,ze,zn,zo) (37,4625ms)

Acties:
  • +1 Henk 'm!

  • Cee5
  • Registratie: Juni 2018
  • Laatst online: 12-04 19:50
Gister bedacht ik me opeens dat er vast een tweakers AoC is. En ja hoor, mooi om te zien! Wat toevallig ook om 4HqB te zien @Friits ik zie hem altijd op reddit voorbij komen. Vandaag een gekke situatie waarbij ik een patroon zag in de oefendata voor vraag 2 waarbij mijn antwoord heel snel is en ook werkt voor mijn input maar geen Bron Kerbosch of andere clique methodiek gebruikt. Antwoord 1 suboptimale golf.

https://github.com/Apparaat9/AoC/blob/main/2024/day_23.py

Acties:
  • +1 Henk 'm!

  • bakkerjangert
  • Registratie: Februari 2012
  • Laatst online: 22:20
Leuke opgave vandaag. Deel 2 kan denk ik op veel verschillende manieren.

spoiler:
Voor deel 2 neem ik als uitgangspunt de set van alle computers + bijbehorende connecties. Van deel 1 weet ik al dat deze even langs zijn (anders had er nog een sort(key=len) bij gemoeten. Dan check ik voor elk item in de set of ze allemaal verbonden zijn. Zoniet dan geef ik een set terug waarbij telkens één niet verbonden computer is weggehaald en voeg deze toe aan de de te loopen set. Ik blijf loopen totdat ik een set vindt met alle computers verbonden. Code in python

Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Robbinb1993 schreef op maandag 23 december 2024 @ 13:46:
Edit: met een color bound waarmee we nog eerder kunnen prunen, draait case 5 in 85ms.
De details van die optimalisatie gaan me even de pet te boven.

Wel zag ik op die pagina een referentie naar de tool cliquer, dus die heb ik even geïnstalleerd. Wat blijkt: die lost al mijn testcases bijna instantaan op. Dat is natuurlijk minder leuk dan zelf een algoritme implementeren, maar het is wel interessant om te zien wat de state of the art is.
spoiler:
Het standaard Bron-Kerbosch algoritme genereert alle max. cliques van de graaf, niet alleen de grootste. We hebben om deze reden set 'X' niet nodig in het algoritme, aangezien we alleen de grootste max. clique zoeken. X is er om vast te stellen of een clique maximaal is op het moment dat set P leeg is. Omdat we alleen de grootste max. clique zoeken, kunnen we ook de zoekboom prunen als de grootste max. clique die tot dan toe gevonden is, niet meer te overtreffen is.
Ah ja, dat klopt natuurlijk. Als je de X weghaalt wordt het algoritme extreem simpel (Python code) en dat is min of meer de DFS die ik had geïmplementeerd, behalve de laatste regel, die blijkbaar cruciaal is voor de performance!

Ook blijkt dat m'n DFS simpel werkend te krijgen is door de vertices in de clique
spoiler:
oplopend te ordenen. De volgorde maakt niet uit natuurlijk, en door een specieke volgorde te forceren voorkom je dat je alle permutaties van een vertex set herhaalt.

Achteraf vind ik het jammer dat ik naar algoritmes gezocht heb, in plaats van een paar minuten langer na te denken, want ik had dit allemaal ook zelf wel kunnen bedenken.

Acties:
  • 0 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
[b]Soultaker schreef op maandag 23 december 2024 @ 19:54:
Wel zag ik op die pagina een referentie naar de tool cliquer, dus die heb ik even geïnstalleerd. Wat blijkt: die lost al mijn testcases bijna instantaan op. Dat is natuurlijk minder leuk dan zelf een algoritme implementeren, maar het is wel interessant om te zien wat de state of the art is.
Cliques hebben ook veel praktische toepassingen, zoals in de scheikunde en biologie. Zie bijvoorbeeld Solving Maximum Clique Problem for Protein Structure Similarity en CFinder: locating cliques and overlapping modules in biological networks. Er blijft dus veel onderzoek naar plaatsvinden. Lost Cliquer test case 7 ook instantly op? Dat is voor mijn oplossing nog te veel gevraagd, de rest gaat wel snel nu.

[ Voor 3% gewijzigd door Robbinb1993 op 23-12-2024 20:36 ]


Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Ja, en ook een nog moeilijkere testcase (dit is zo'n beetje de moeilijkste die ik kan genereren met deze constraints aangezien dit de grens van 676 vertices en 228150 edges benadert).
Dat is voor mijn oplossing nog te veel gevraagd, de rest gaat wel snel nu.
Je hebt bijhoorlijk veel vooruitgang geboekt in 1 dag :) Ik denk dat de auteurs van Cliquer iets langer aan hun solver gewerkt hebben.

Acties:
  • +2 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 03-06 22:28

FCA

Ik heb inmiddels ook de "nette" oplossing, met wat optimalisaties loopt ie voor de kortere testcases (challenge 1-4) sneller dan mijn probabilistische (hoewel ik die natuurlijk ook verder zou kunnen optimaliseren), en voor challenge 5 doet ie er weliswaar langer over, maar geeft hij wel het correcte antwoord :)

spoiler:
Geinspireerd door @Robbinb1993's oplossing in C++, heb ik ook bitsets in Rust gebruikt + een snelle exit op de bound. Ik ben niet zo ver gegaan om de colorbound te implementeren, daar moet ik eerst wat beter op studeren om het te begrijpen, maar challenge 5 geeft nu bij mij in <2 sec het juiste antwoord, snel genoeg voor nu.

Verandert z'n sig te weinig.


Acties:
  • +2 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:39

.oisyn

Moderator Devschuur®

Demotivational Speaker

Running `target\release\day20.exe -i .\extra\aoc-2024-day-20-challenge-1.txt`
Time spent: 144615.6µs
29293 - 15771808
    Finished `release` profile [optimized] target(s) in 0.05s

     Running `target\release\day20.exe -i .\extra\aoc-2024-day-20-challenge-2.txt`
Time spent: 1331292.6µs
267956 - 146098982
    Finished `release` profile [optimized] target(s) in 0.05s

     Running `target\release\day20.exe -i .\extra\aoc-2024-day-20-challenge-3.txt`
Time spent: 14820151.0µs
2992743 - 1638307943

     Running `target\release\day20.exe -i .\extra\aoc-2024-day-20-challenge-4.txt`
Time spent: 33585.2µs
6450 - 3570001

     Running `target\release\day20.exe -i .\extra\aoc-2024-day-20-challenge-5.txt`
Time spent: 33548.6µs
6822 - 3607658


Ik heb nog wel een idee hoe ik dit kan optimizen maar algoritmisch blijft het lineair.

6 en 7 run ik niet want die voldoen niet aan mijn interpretatie van de opdracht:
Because there is only a single path from the start to the end and the programs all go the same speed, the races used to be pretty boring
Ze hebben geen "single path from start to end".

[ Voor 3% gewijzigd door .oisyn op 24-12-2024 02:23 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
.oisyn schreef op dinsdag 24 december 2024 @ 02:21:
Ze hebben geen "single path from start to end".
Klopt, heb ze expres apart gehouden daarom. Maar ik ben wel benieuwd hoe je algoritme werkt dat je daar niet mee overweg kunt?

Wat betreft dag 24: 8)7 Wat een opgave zeg!

spoiler:
Ik probeerde het heel lang programmatisch op te lossen. Uiteindelijk bleek het makkelijker om het semi-handmatig te doen.


Mijn idee voor de automatische oplossing was:

spoiler:
Ik had om te beginnen de invoer gevisualiseerd als een graaf. Dan zie je heel mooi de structuur als serie van 45 adders, maar waar de fouten zitten is niet meteen duidelijk.

Om het programmatisch op te lossen begon ik met het identificeren van verdachte wires. Bijvoorbeeld:
elke uitvoer z2 t/m z45 heeft twee XOR poorten als invoer (z0, z1 en z46 zijn speciale gevallen); als dat niet zo is klopt er iets niet en moet die poort dus geswapt worden.

De OR ports propageren de carries. Elke OR port moet twee ANDs als invoer hebben, anders klopt er iets niet. Etc.

Op die manier had ik 8 “foute” wires gevonden en toen dacht ik dat ik alleen nog maar de verschillende permutaties hoefde te proberen om uit te vinden wat met wat geswapt moet worden.

Om te checken of een permutatie correct was simuleerde ik simpelweg het circuit 1000 keer met random inputs tussen de 0 en 1045. Dat klinkt inefficiënt maar dat valt erg mee want je kunt meteen stoppen zodra je 1 fout antwoord krijgt (immers het juiste circuit geeft altijd het correcte antwoord) en als de wiring verkeerd is krijg je heel vaak een verkeerd antwoord. Omgekeerd is de kans dat je 1000 keer een false positive krijgt praktisch nihil.

Helaas vond ik met deze methode geen enkele geldige permutatie. Dus terug naar de graaf; gelukkig kon ik op basis van de “foute” wires wel de adders vinden waar bugs in zaten, en handmatig zijn de fouten redelijk eenvoudig te herstellen.

Ik ben er dus wel even zoet mee geweest, maar ik vond het wel een erg leuk probleem om op te lossen!

Acties:
  • +2 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:39

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op dinsdag 24 december 2024 @ 10:16:
[...]

Klopt, heb ze expres apart gehouden daarom. Maar ik ben wel benieuwd hoe je algoritme werkt dat je daar niet mee overweg kunt?
Ik doe geen dijkstra, ik reken erop dat er maar 1 mogelijke weg is. Dus ik kijk steeds vanaf de huidige positie of ik vooruit, naar links, naar rechts of achteruit kan. Die laatste is er alleen maar zodat ik niets speciaals hoef te doen voor de start, voor elke andere positie komt ie daar nooit. Maar in jouw geval natuurlijk wel want dan zijn er doodlopende paden :).

Dat pad vult dan een grid met afstanden en een lijst met coordinaten. Die coordinaten loop ik dan vervolgens lineair af om in het grid in een manhattan-straal van 20 te zoeken naar posities die minstens 100ps tijdswinst opleveren.

Ik kan mijn pad-vind-algoritme aanpassen zodat hij werkt met generieke doolhoven, maar daarmee ben ik er nog niet omdat je bij een cheat eventueel een vertakking kan nemen die niet bij het normale pad hoort, zonder dat je voor die vertakking al hoeft te cheaten.

Ik moet dan feitelijk een floodfill doen vanuit de start voor alle afstanden vanaf de start, en nog een floodfill vanuit de finish voor alle afstanden tot de finish, en dan voor elke bereikbare positie zoeken maar andere bereikbare posities in een straal van 20.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • +1 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Ik heb dag 24 ook maar semi met het handje opgelost

spoiler:
Wel even de bitwise adder met carry opgezocht zodat ik voor elke bit telkens kon kijken welke combinatie van logic operators ik zou moeten hebben, deze vervolgens semi handmatig vergeleken met wat er in mijn input zat en zo vanaf de minst significante bit naar de meest significante wandelen tot ik de 4 fouten gevonden had.

in principe was dat een relatief herhalend patroon met identificeren welke 3 letterige code ik kon vervangen door mijn constanten dus ik denk wel dat ik relatief simpel een validator kon schrijven die de fout kon vinden. Of ik die fout dan ook kan fiksen weet ik niet.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 03-06 22:28

FCA

Ja dag 24 was wel weer een AOC klassieker

spoiler:
Ook met de hand opgelost. Eerst met een test-invoer voor iedere index de (x,y) op (0,1), (1,0) en (1,1) (en de andere 43 (x,y) op (0,0) gezet) gecheckt waar de fouten ongeveer zaten, daarna met hand lopen zoeken. Zo 's ochtends vroeg zonder koffie op was het wel een gedoe om geen fouten te maken met al die memorabele namen als rht, ngn, etc )
en met een schema van een adder erbij :+

Nu nog eens rustig nadenken over een echt programmatische oplossing.

Verandert z'n sig te weinig.


Acties:
  • 0 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 03-06 22:28

FCA

Soultaker schreef op dinsdag 24 december 2024 @ 10:16:
[...]
[...]

Mijn idee voor de automatische oplossing was:

spoiler:
Ik had om te beginnen de invoer gevisualiseerd als een graaf. Dan zie je heel mooi de structuur als serie van 45 adders, maar waar de fouten zitten is niet meteen duidelijk.

Om het programmatisch op te lossen begon ik met het identificeren van verdachte wires. Bijvoorbeeld:
elke uitvoer z2 t/m z45 heeft twee XOR poorten als invoer (z0, z1 en z46 zijn speciale gevallen); als dat niet zo is klopt er iets niet en moet die poort dus geswapt worden.

De OR ports propageren de carries. Elke OR port moet twee ANDs als invoer hebben, anders klopt er iets niet. Etc.

Op die manier had ik 8 “foute” wires gevonden en toen dacht ik dat ik alleen nog maar de verschillende permutaties hoefde te proberen om uit te vinden wat met wat geswapt moet worden.

Om te checken of een permutatie correct was simuleerde ik simpelweg het circuit 1000 keer met random inputs tussen de 0 en 1045. Dat klinkt inefficiënt maar dat valt erg mee want je kunt meteen stoppen zodra je 1 fout antwoord krijgt (immers het juiste circuit geeft altijd het correcte antwoord) en als de wiring verkeerd is krijg je heel vaak een verkeerd antwoord. Omgekeerd is de kans dat je 1000 keer een false positive krijgt praktisch nihil.

Helaas vond ik met deze methode geen enkele geldige permutatie. Dus terug naar de graaf; gelukkig kon ik op basis van de “foute” wires wel de adders vinden waar bugs in zaten, en handmatig zijn de fouten redelijk eenvoudig te herstellen.

Ik ben er dus wel even zoet mee geweest, maar ik vond het wel een erg leuk probleem om op te lossen!
spoiler:
Beetje dom gedacht misschien, maar je hoeft helemaal niet te achterhalen wat de goede permutatie is. Als je 8 foute wires hebt ben je klaar, toch?

Verandert z'n sig te weinig.


Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
.oisyn schreef op dinsdag 24 december 2024 @ 12:01:
spoiler:
Ik moet dan feitelijk een floodfill doen vanuit de start voor alle afstanden vanaf de start, en nog een floodfill vanuit de finish voor alle afstanden tot de finish, en dan voor elke bereikbare positie zoeken maar andere bereikbare posities in een straal van 20.
Dat is precies wat ik had gedaan. In theorie doe ik dan wel twee keer zoveel werk vergeleken met jouw aanpak (misschien ietsje meer zelfs, omdat je behalve naar voren ook naar links en rechts moet zoeken om geen paden te missen), hoewel het ook niet heel veel uitmaakt voor de totaaltijd, die bij vrijwel alle oplossingen die ik gezien heb wordt gedomineerd door de berekening in deel 2.
FCA schreef op dinsdag 24 december 2024 @ 13:12:
spoiler:
Beetje dom gedacht misschien, maar je hoeft helemaal niet te achterhalen wat de goede permutatie is. Als je 8 foute wires hebt ben je klaar, toch?
Daar heb je helemaal gelijk in, maar ik wilde verifiëren dat het antwoord daadwerkelijk klopte voordat ik m'n antwoord inzond. (Ik hebt dit jaar nog geen enkele foute inzending gedaan, en dat wil ik graag zo houden.)
Achteraf bleek de gevonden set überhaupt niet te kloppen :+ dus ik ben blij dat ik niet geprobeerd heb 'm in te zenden.

Uiteindelijk heb ik wel een programmatische oplossing weten te schrijven, al is het relatief brute force: 24.py

Wat voor tools gebruiken jullie trouwens om dit soort problemen te visualiseren? (Ik neem aan dat de meeste mensen die dit probleem opgelost hebben de invoer op de een of andere manier gevisualiseerd hebben.) Ik gebruik GraphViz en QVGE; het werkt wel, maar het zijn geen pareltjes van gebruiksvriendelijkheid.

Acties:
  • +1 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:39

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op dinsdag 24 december 2024 @ 14:31:
[...]

Dat is precies wat ik had gedaan. In theorie doe ik dan wel twee keer zoveel werk vergeleken met jouw aanpak (misschien ietsje meer zelfs, omdat je behalve naar voren ook naar links en rechts moet zoeken om geen paden te missen), hoewel het ook niet heel veel uitmaakt voor de totaaltijd, die bij vrijwel alle oplossingen die ik gezien heb wordt gedomineerd door de berekening in deel 2.
Mijn bedachte optimalisatie is om niet de hele tijd alle cellen in een straal van 20 te testen, maar bij te houden welke delen van het pad de huidige ruit snijdt door alleen de edges van de ruit te testen (en wat letterlijke cornercases waarbij bijvoorbeeld een hoekpunt va het pad de ruit raakt, maar waarbij het pad niet de ruit binnengaat). Als je dan ranges hebt van het pad binnen de ruit kun je redelijk triviaal de mogelijkheden testen.

Dit wordt dan ook weer lastiger met doodlopende paden, omdat die mogelijk stoppen binnen de ruit.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Ik heb iig een oplossing die alle fouten in mijn input er uit haalt. Andere swaps heb ik nog geen fix voor gemaakt.

https://github.com/Janoz-...com/janoz/aoc/y2024/day24

Ben trouwens wel heel benieuwd naar andere input om nog wat automatische fixes toe te kunnen voegen :)

[ Voor 40% gewijzigd door Janoz op 24-12-2024 15:00 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Janoz schreef op dinsdag 24 december 2024 @ 14:51:
Ben trouwens wel heel benieuwd naar andere input om nog wat automatische fixes toe te kunnen voegen :)
Ik betwijfel of de inputs veel van elkaar verschillen; het lijkt er op dat de swaps vrij specifiek zijn dus mogelijk zijn ze met de hand gemaakt en dus voor iedereen hetzelfde. Maar als je wil proberen, mijn invoer staat hier: 24.in (antwoorden: 24.ref).

Acties:
  • +1 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:14
In mijn implementatie probeer ik te reverse engineeren. Het doet heel veel aannames, maar komt wel met de juiste antwoorden bij de voorbeeld invoer. Ik ga ervan uit dat het een gewone CPU adder moet zijn en probeer terug te vinden waar de bron vandaan moet komen. Het was even experimenteren, maar het werkt.

Vandaag was meer puzzel dan programmeren, maar wel een leuke!

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:14
Soultaker schreef op dinsdag 24 december 2024 @ 15:12:
[...]

Ik betwijfel of de inputs veel van elkaar verschillen; het lijkt er op dat de swaps vrij specifiek zijn dus mogelijk zijn ze met de hand gemaakt en dus voor iedereen hetzelfde. Maar als je wil proberen, mijn invoer staat hier: 24.in (antwoorden: 24.ref).
Het zal me niks verbazen als de structuur vrijwel hetzelfde is voor iedereen, maar dat de "intermediate" name gerandomized zijn. Die van mij ziet er op het eerste gezicht wel heel anders uit, maar ben te lui om nu een stuk code te schrijven die de structuur vergelijkt :)

Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Marcj schreef op dinsdag 24 december 2024 @ 15:37:
Het zal me niks verbazen als de structuur vrijwel hetzelfde is voor iedereen, maar dat de "intermediate" name gerandomized zijn. Die van mij ziet er op het eerste gezicht wel heel anders uit, maar ben te lui om nu een stuk code te schrijven die de structuur vergelijkt :)
Hoe moeilijk kan het zijn?

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Soultaker schreef op dinsdag 24 december 2024 @ 15:12:
[...]

Ik betwijfel of de inputs veel van elkaar verschillen; het lijkt er op dat de swaps vrij specifiek zijn dus mogelijk zijn ze met de hand gemaakt en dus voor iedereen hetzelfde. Maar als je wil proberen, mijn invoer staat hier: 24.in (antwoorden: 24.ref).
Ach, andere input is helemaal niet nodig bedacht ik me. Ik kan voor het testen gewoon random een verbinding switchen en kijken of mijn algo hem kan fixen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • +1 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Soultaker schreef op dinsdag 24 december 2024 @ 15:12:
[...]

Ik betwijfel of de inputs veel van elkaar verschillen; het lijkt er op dat de swaps vrij specifiek zijn dus mogelijk zijn ze met de hand gemaakt en dus voor iedereen hetzelfde. Maar als je wil proberen, mijn invoer staat hier:
Zonder aanpassing werkt mijn oplossing ook voor jouw code

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Nog wat extra testdata voor dag 24: aoc-2024-day-24-challenge-1-to-5.zip

Niet heel spannend, maar mogelijk nuttig om te benchmarken of te debuggen. Mijn Python code doet ongeveer 10 seconde over elke case.

Antwoorden (Ik geef voor deel 1 de laatste vijf cijfers van het antwoord, en voor deel 2 net als gisteren de SHA-1 hash van het antwoord zonder newline):
aoc-2024-day-24-challenge-1.txt:
Deel 1: ...96237
Deel 2: 5d18c690eca6e4cd9d25edd58ea59ceda0133345

aoc-2024-day-24-challenge-2.txt: 
Deel 1: ...67894
Deel 2: cb2b27fd8b51d014a1fe9b553b60fcb365ae4df8

aoc-2024-day-24-challenge-3.txt:
Deel 1: ...95145
Deel 2: 047310d15e08aa4d3a8963b7f4e031fac0059f74

aoc-2024-day-24-challenge-4.txt:
Deel 1: ...01414
Deel 2: 2bc99d0025e0953edb1dc09f1c1619da31cae4d1

aoc-2024-day-24-challenge-5.txt:
Deel 1: ...21972
Deel 2: f30e753af958376c453a1e463e85dc95aaacd375

Ik kan nog wel wat extra cases verzinnen maar ik weet niet of ik er tijd voor/zin in heb.

Acties:
  • +1 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Bestanden heten trouwens wel dag23 ;)

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • +1 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Ik draai ze allemaal in 18ms. Alleen bij 5 had ik de fout wel goed gevonden, maar de afhandeling was nog niet juist. Kleine fix en ze gaan allemaal goed lijkt het (had geen zin om de hash te checken, maar het antwoord dat ik geef moet een geldige situatie opleveren)

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • +1 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 03-06 22:28

FCA

Challenge 1 t/m 4 draaien correct bij mij, in ieder ~35ms, challenge 5 vind ik geen oplossing

spoiler:
Wat ik nu doe is combinatie heuristiek + brute force: ik test achtereenvolgens
1 + 0, 1+1, 11+01, 11+11, etc. (binaire getallen natuurlijk)
als er een fout antwoord is, pakt hij alle gates die deze stap geactiveerd werden, maar de vorige stap nog niet. Daarvan worden alle outputs gepermuteerd, met wat restricties (een "z"-output moet altijd de output van een XOR zijn), en gecheckt dat deze stap en de stap ervoor en stap erna nu wel goed gaan. Zo ja, dan is dat het antwoord.

Blijkbaar voor challenge 5 pak ik niet genoeg outputs. Ik zou in principe ook alle nieuw gebruikte gates kunnen pakken... hmm...

Verandert z'n sig te weinig.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Janoz schreef op dinsdag 24 december 2024 @ 16:50:
Bestanden heten trouwens wel dag23 ;)
Oeps. Ik heb het gefixt.

Acties:
  • +1 Henk 'm!

  • Asgardian28
  • Registratie: December 2012
  • Laatst online: 04-06 22:18
Nou dat was hem weer, bedankt iedereen! Vooral @Friits voor je oplossingen.
De top 3 zat er niet in, jullie zijn meestal te snel! Maar wel 1 dag eerste geëindigd ;-). Global leaderboard zat er ook niet in, een keertje 197e. En evenveel top 1000 scores als 2023 terwijl ik weinig heb geprogrammeerd, ook tevreden mee.

Voor mij meest memorabel waren de Kerstboom puzzel en natuurlijk de Robot Keypad puzzel (7 uur mee bezig geweest). Op naar de 550 sterren volgend jaar?

Acties:
  • +5 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 15-05 16:24
Graag gedaan @Asgardian28, het was weer leuk! Op de valreep nog ingehaald door @Soultaker, maar volgens mij heb ik op de twee moeilijke dagen bovenaan gestaan 8)

Als nagerechtje nog mijn oplossing voor vandaag:
spoiler:
items = [{i for i, c in enumerate(item) if c == '#'} for item in open('in.txt').read().split('\n\n')]
print(sum(not l&k for k in items for l in items)//2)

Tot volgend jaar :)

Acties:
  • 0 Henk 'm!

  • Asgardian28
  • Registratie: December 2012
  • Laatst online: 04-06 22:18
@Friits Zo kan je ook naar overlap zoeken natuurlijk, gaaf gedaan!

Acties:
  • 0 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 15-05 16:24
Dankjewel! Ik vond het wel mooi, want
spoiler:
not key & lock betekent natuurlijk letterlijk "er is geen overlap tussen key en lock".


Mijn oorspronkelijke implementatie was overigens gewoon door per kolom het aantal # te tellen. Maar na het oplossen van de puzzel ga ik altijd even stevig refactoren om m'n oplossing hier en op Reddit te plaatsen. Soms is het niet meer dan het hernoemen van variabelen (alles heet a, b, of x), maar soms kies ik ook voor een totaal andere aanpak.

Acties:
  • +2 Henk 'm!

  • torx
  • Registratie: Oktober 2006
  • Laatst online: 18:09
Pfffff dag 24 was een pittige, net pas afgerond. Gelukkig was die van vandaag goed te doen. Ik doe pas sinds 2021 mee en nu voor het eerst alles kunnen oplossen zonder hints of antwoorden :) Leuk om hier elke dag de discussie mee te lezen en achteraf te zien hoe ik veel eerder / beter tot een oplossing had kunnen komen. Bedankt allemaal!

Honda CB750 Hornet :: Yamaha Fazer FZ6 SA (2011 - 2023) | F1Pool.net


Acties:
  • +3 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 03-06 22:28

FCA

Dat was hem weer! Leuk dit jaar, nieuwe taal voor mij (Rust) af en toe wel wat zitten klunzen daardoor, en natuurlijk lang zitten puzzelen op de echte hersenkrakers (mijn vrouw overwoog een interventie op dag 21... :X )
Net buiten de top 3 op mijn werk (concurrentie was wat steviger dan vorig jaar).


En, extra doel:
time cargo run --release

[..]

Parsing: 271.696µs
Day 25 - Part 1: 3365
        generator: 121ns,
        runner: 814.007µs

Day 25 - Part 2: Done!
        generator: 50ns,
        runner: 141ns

real    0m0.366s
user    0m0.463s
sys     0m0.010s


Volledige oplossing van alle 25 dagen in minder dan een halve seconde, op een 3,5 jaar oude laptop :D

Langzaamste oplossing was dag 16, slechts 1 keer rayon gebruikt.

En @Soultaker bedankt voor alle extra challenges! Heeft me super geholpen om weer wat extra concepten te leren, en de uiteindelijke oplossingen sneller en mooier te maken.

[ Voor 14% gewijzigd door FCA op 25-12-2024 09:25 ]

Verandert z'n sig te weinig.


Acties:
  • +6 Henk 'm!

  • Hagdos
  • Registratie: April 2022
  • Laatst online: 13:31
500 sterren binnen! Beetje trots op mezelf.

Leuk om hier mee te lezen, ik zie dat er nog veel knappere koppen rondlopen. De meeste dagen ben ik al blij dat ik het antwoord vind, dan is het wel goed genoeg.

Acties:
  • +2 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:14
Ja, het was weer een leuke puzzel dit jaar met als traditioneel een eenvoudige afsluiting. Bedankt @Soultaker voor de extra uitdagen ook. Fijne kerst allemaal!

Acties:
  • +1 Henk 'm!

  • KabouterSuper
  • Registratie: September 2005
  • Niet online
Was weer een leuk jaar. En niet te vergeten, een jubileumjaar! Dank voor alle discussies, extra uitdagingen en mooie oplossingen. Ik heb persoonlijk erg veel plezier gehad omdat mijn dochter soms tot mooiere en snellere oplossingen kwam dan ik (en ook sneller de twee sterren binnen had). Ik moet nog even dag 21 deel 2 oplossen (iets met max recursion depth exceeded), dan ben ik op de 500 sterren beland. Tot volgende jaar.

When life gives you lemons, start a battery factory


Acties:
  • +1 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:39

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op dinsdag 24 december 2024 @ 16:45:
Nog wat extra testdata voor dag 24: aoc-2024-day-24-challenge-1-to-5.zip

Niet heel spannend, maar mogelijk nuttig om te benchmarken of te debuggen. Mijn Python code doet ongeveer 10 seconde over elke case.

Antwoorden (Ik geef voor deel 1 de laatste vijf cijfers van het antwoord, en voor deel 2 net als gisteren de SHA-1 hash van het antwoord zonder newline):
aoc-2024-day-24-challenge-1.txt:
Deel 1: ...96237
Deel 2: 5d18c690eca6e4cd9d25edd58ea59ceda0133345

aoc-2024-day-24-challenge-2.txt: 
Deel 1: ...67894
Deel 2: cb2b27fd8b51d014a1fe9b553b60fcb365ae4df8

aoc-2024-day-24-challenge-3.txt:
Deel 1: ...95145
Deel 2: 047310d15e08aa4d3a8963b7f4e031fac0059f74

aoc-2024-day-24-challenge-4.txt:
Deel 1: ...01414
Deel 2: 2bc99d0025e0953edb1dc09f1c1619da31cae4d1

aoc-2024-day-24-challenge-5.txt:
Deel 1: ...21972
Deel 2: f30e753af958376c453a1e463e85dc95aaacd375

Ik kan nog wel wat extra cases verzinnen maar ik weet niet of ik er tijd voor/zin in heb.
Zo, dag 24 was een leuke opdracht :D. Gezien m'n ervaring met nandbox.oisyn.nl had ik al vrij snel door wat de bedoeling was voor deel 2. Het intypen van een goede oplossing heeft me wel wat uurtjes gekost daarentegen :X. Ik ben 2x helemaal opnieuw begonnen. Algoritmisch kunnen wat lineaire searches hier en daar wellicht iets efficienter maar met <200µs is dat zinloos.

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-1.txt`
Time spent: 192.5µs
42765237996237 - igf,ihh,kwt,sta,twb,wjc,z19,z25

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-2.txt`
Time spent: 187.0µs
30069256867894 - aqi,asd,goh,nts,uib,vwl,z15,z43

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-3.txt`
Time spent: 187.2µs
23888547395145 - ioo,kbg,nwg,prc,qps,roh,z10,z20

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-4.txt`
Time spent: 184.2µs
46937781801414 - afi,gmg,hra,riv,tjt,vkv,z05,z28

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-5.txt`
Time spent: 190.9µs
57012758521972 - owg,rla,tpj,umm,z00,z01,z08,z11


Ik heb niet zo'n zin om de hashes te vergelijken dus ik ga er maar van uit dat het klopt :Y). Jammer dat je geen inputs hebt met veel meer verwisselingen. Ik denk dat mijn algoritme ze met gemak allemaal vindt, zolang van een specifieke gate er altijd maar 1 input is die verwisseld wordt.

spoiler:
Het principe is vrij simpel. Je hebt een half-adder die 2 bits input en 2 bits output heeft. De inputs worden opgeteld en de outputs zijn een resultaat en een carry.

Met inputs (a, b) en outputs (r, c):

r = a XOR b
c = a AND b


Dan bestaat er ook nog een full-adder die 3 bits optelt. Je kunt die bouwen van 2 half-adders, maar efficienter uitgeschreven wordt het:

r = (a XOR b) XOR c
c = ((a XOR b) AND c) OR (a AND b)


Waarbij de c dus altijd de carry is van de half-adder of full-adder van de vorige bit.

Ik identificeer in totaal 5 operaties:

HalfAdd(i): x(i) XOR y(i)
HalfCarry(i): x(i) AND y(i)
FullAdd(1): HalfAdd(1) XOR HalfCarry(0)
FullAdd(i>1): HalfAdd(i) XOR FullCarry(i - 1)
PartialFullCarry(1): HalfAdd(1) AND HalfCarry(0)
PartialFullCarry(i>1): HalfAdd(i) AND FullCarry(i - 1)
FullCarry(i): HalfCarry(i) OR PartialFullCarry(i)


Met de uiteindelijke outputs:

z00 = HalfAdd(0)
z{i@1..n} = FullAdd(i)
z{n} = FullCarry(n - 1)


Ik loop in bit-volgorde (van z00 t/m z45) door de outputs, waarbij ik elke operatie steeds recursief ontleedt in de deelstappen, en er dan een gate bij zoek die die deelstap doet. Als ik zo'n gate niet vindt, dan moet er een gate zijn met dezelfde operator (AND, OR, XOR) en 1 van de juiste inputs, waarbij de andere niet klopt. En bovendien moet ik al eens een gate zijn tegengekomen die de juiste input kan aanleveren.

Het blijkt altijd zo te zijn dat er precies 1 gate is met de juiste operator en 1 juiste input. De gate van de foute input swap ik dan met de gate van de juiste input, en dan ga ik verder.

Verder kan het nog zo zijn dat een z-output niet klopt. Bijvoorbeeld dat ik wel een FullAdd(10) vindt, maar dat dat niet de gate voor z10 is. In dat geval moeten z10 en die van die FullAdd(10) geswapped worden.

Als je alle z-outputs hebt doorlopen heb je ook alle swaps gedetecteerd

[ Voor 32% gewijzigd door .oisyn op 26-12-2024 04:56 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:39

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het is ook wel meteen compleet uitgestorven hier :D

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • +1 Henk 'm!

  • MadEgg
  • Registratie: Februari 2002
  • Laatst online: 23:05

MadEgg

Tux is lievvv

.oisyn schreef op donderdag 26 december 2024 @ 04:02:
[...]


Zo, dag 24 was een leuke opdracht :D. Gezien m'n ervaring met nandbox.oisyn.nl had ik al vrij snel door wat de bedoeling was voor deel 2. Het intypen van een goede oplossing heeft me wel wat uurtjes gekost daarentegen :X. Ik ben 2x helemaal opnieuw begonnen. Algoritmisch kunnen wat lineaire searches hier en daar wellicht iets efficienter maar met <200µs is dat zinloos.

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-1.txt`
Time spent: 192.5µs
42765237996237 - igf,ihh,kwt,sta,twb,wjc,z19,z25

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-2.txt`
Time spent: 187.0µs
30069256867894 - aqi,asd,goh,nts,uib,vwl,z15,z43

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-3.txt`
Time spent: 187.2µs
23888547395145 - ioo,kbg,nwg,prc,qps,roh,z10,z20

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-4.txt`
Time spent: 184.2µs
46937781801414 - afi,gmg,hra,riv,tjt,vkv,z05,z28

     Running `target\release\day24.exe -i .\extra\aoc-2024-day-24-challenge-5.txt`
Time spent: 190.9µs
57012758521972 - owg,rla,tpj,umm,z00,z01,z08,z11


Ik heb niet zo'n zin om de hashes te vergelijken dus ik ga er maar van uit dat het klopt :Y). Jammer dat je geen inputs hebt met veel meer verwisselingen. Ik denk dat mijn algoritme ze met gemak allemaal vindt, zolang van een specifieke gate er altijd maar 1 input is die verwisseld wordt.

spoiler:
Het principe is vrij simpel. Je hebt een half-adder die 2 bits input en 2 bits output heeft. De inputs worden opgeteld en de outputs zijn een resultaat en een carry.

Met inputs (a, b) en outputs (r, c):

r = a XOR b
c = a AND b


Dan bestaat er ook nog een full-adder die 3 bits optelt. Je kunt die bouwen van 2 half-adders, maar efficienter uitgeschreven wordt het:

r = (a XOR b) XOR c
c = ((a XOR b) AND c) OR (a AND b)


Waarbij de c dus altijd de carry is van de half-adder of full-adder van de vorige bit.

Ik identificeer in totaal 5 operaties:

HalfAdd(i): x(i) XOR y(i)
HalfCarry(i): x(i) AND y(i)
FullAdd(1): HalfAdd(1) XOR HalfCarry(0)
FullAdd(i>1): HalfAdd(i) XOR FullCarry(i - 1)
PartialFullCarry(1): HalfAdd(1) AND HalfCarry(0)
PartialFullCarry(i>1): HalfAdd(i) AND FullCarry(i - 1)
FullCarry(i): HalfCarry(i) OR PartialFullCarry(i)


Met de uiteindelijke outputs:

z00 = HalfAdd(0)
z{i@1..n} = FullAdd(i)
z{n} = FullCarry(n - 1)


Ik loop in bit-volgorde (van z00 t/m z45) door de outputs, waarbij ik elke operatie steeds recursief ontleedt in de deelstappen, en er dan een gate bij zoek die die deelstap doet. Als ik zo'n gate niet vindt, dan moet er een gate zijn met dezelfde operator (AND, OR, XOR) en 1 van de juiste inputs, waarbij de andere niet klopt. En bovendien moet ik al eens een gate zijn tegengekomen die de juiste input kan aanleveren.

Het blijkt altijd zo te zijn dat er precies 1 gate is met de juiste operator en 1 juiste input. De gate van de foute input swap ik dan met de gate van de juiste input, en dan ga ik verder.

Verder kan het nog zo zijn dat een z-output niet klopt. Bijvoorbeeld dat ik wel een FullAdd(10) vindt, maar dat dat niet de gate voor z10 is. In dat geval moeten z10 en die van die FullAdd(10) geswapped worden.

Als je alle z-outputs hebt doorlopen heb je ook alle swaps gedetecteerd
Deze aanpak heb ik uiteindelijk ook toegepast! Brute force ging voor geen meter :) Na het verdiepen in de schakeling heb ik het over de gates gelegd om de fouten te detecteren. Daarna de gates verwisseld in de betreffende full adders, zo waren het slechts 4 -6 mogelijke swaps en dat was prima te brute forcen. Volledig logisch oplossen kan vast ook maar ik was er wel klaar mee. Finish gehaald, zij het 2 dagen te laat.

Tja


Acties:
  • +1 Henk 'm!

  • KabouterSuper
  • Registratie: September 2005
  • Niet online
.oisyn schreef op vrijdag 27 december 2024 @ 14:13:
Het is ook wel meteen compleet uitgestorven hier :D
Zeker, ik ben alweer druk bezig met de aivd-kerstpuzzel.

When life gives you lemons, start a battery factory


Acties:
  • +2 Henk 'm!

  • Satom
  • Registratie: Mei 2011
  • Laatst online: 23:38

Satom

Verzamel ervaringen

.oisyn schreef op vrijdag 27 december 2024 @ 14:13:
Het is ook wel meteen compleet uitgestorven hier :D
Ik kom de komende dagen ergens nog hier terug, nu de kerstdagen (en verplichtingen) weer even voorbij zijn, kan ik mij gaan focussen op 23, 24 deel 2 en 25! Dan heb ik 2024 ook helemaal klaar. Als ik de flow een beetje kan vasthouden wil ik ook 2023 nog af gaan maken! :+

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:39

.oisyn

Moderator Devschuur®

Demotivational Speaker

.oisyn schreef op zaterdag 14 december 2024 @ 15:26:
Deel 2 vond ik stom en heb ik niet opgelost in code.

spoiler:
had een uitdraai gemaakt van de eerste 100 stappen en het viel me op dat op stap 38 heel veel robots een gelijke x- coördinaat hadden, en op stap 88 een gelijke y-coördinaat. Die herhalen zich natuurlijk resp. 101 en 103 stappen, dus gewoon even opgelost voor:

s = 38 (mod 101)
s = 88 (mod 103)

(Chinese reststelling)

Nog even het plaatje gegenereerd voor stap s en dat was het goede antwoord.

Misschien dat ik dit nog eens in code zal gieten, maar nu geen zin in.
Zo, dit eindelijk maar eens in code gegoten. Gebruik gemaakt van de quadrant-score, maar in plaats maximaal 101*103 iteraties te doen, heb ik maar 103 iteraties gedaan en gekeken naar de minimum helft-score in zowel x- en y-richting. Dat leverde dezelfde twee stappen op voor x en y als hierboven.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:39

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik zit nog eens terug te bladeren en ik moet zeggen dat dit jaar wel een stuk makkelijker was dan vorig jaar. Echt redelijk pittige, zoals 2023 dag 21 deel 2 of 2023 dag 24 deel 2 zaten er niet tussen.

Welke vonden jullie dit jaar het lastigst?

Ik denk dat ik veruit het meeste tijd heb gespendeerd aan de binary adder (dag 24 deel 2). Het vinden van de juiste strategie bij die keypads (dag 21) kostte ook wel even tijd om uit te werken.

.Edit: heh, ik realiseer me nu dat ik voor beide jaren dezelfde dagen noem :D

[ Voor 7% gewijzigd door .oisyn op 28-12-2024 14:57 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • KabouterSuper
  • Registratie: September 2005
  • Niet online
.oisyn schreef op zaterdag 28 december 2024 @ 14:56:
Ik zit nog eens terug te bladeren en ik moet zeggen dat dit jaar wel een stuk makkelijker was dan vorig jaar. Echt redelijk pittige, zoals 2023 dag 21 deel 2 of 2023 dag 24 deel 2 zaten er niet tussen.

Welke vonden jullie dit jaar het lastigst?

Ik denk dat ik veruit het meeste tijd heb gespendeerd aan de binary adder (dag 24 deel 2). Het vinden van de juiste strategie bij die keypads (dag 21) kostte ook wel even tijd om uit te werken.

.Edit: heh, ik realiseer me nu dat ik voor beide jaren dezelfde dagen noem :D
Dit jaar vond ik dag 21 en 24 ook het lastigst. Van 2023 vond ik dag 24 grappig genoeg niet lastig, vanwege een lineaire algebra trucje. Dag 21 en 23 van 2023 heb ik veel te lang op gezeten.

When life gives you lemons, start a battery factory


Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Dag 21 en 24 waren inderdaad uitdagend, maar wel op een leuke manier. Andere problemen waar ik relatief lang over gedaan heb waren:De rest was binnen 30 minuten te doen, wat ik als relatief makkelijk zou inschatten.
Klopt, het viel erg mee dit jaar. Als ik mijn tijden van dit jaar naast die van vorig jaar leg dan blijkt dat ik in z'n algemeenheid aanzienlijk minder tijd nodig had:

Dag Tijd 2024   Dag Tijd 2023   Verschil  Relatief
--- ---------   --- ---------   --------  --------
24  03:54:50    24  13:13:25    09:18:35   337.86%
21  02:14:52    21  03:07:08    00:52:16   138.75%
17  00:59:09    23  02:03:59    01:04:50   209.61%
12  00:53:47    25  00:56:36    00:02:49   105.24%
15  00:42:15    10  00:48:17    00:06:02   114.28%
23  00:34:10    18  00:40:23    00:06:13   118.20%
13  00:29:52    19  00:39:54    00:10:02   133.59%
14  00:23:21    20  00:39:38    00:16:17   169.74%
 9  00:18:41     5  00:33:21    00:14:40   178.50%
20  00:17:41    17  00:28:46    00:11:05   162.68%
16  00:17:27    22  00:27:34    00:10:07   157.98%
22  00:16:33    13  00:23:34    00:07:01   142.40%
18  00:16:33     7  00:16:57    00:00:24   102.42%
 8  00:16:04     8  00:15:51   -00:00:13    98.65%
 6  00:11:20    11  00:15:05    00:03:45   133.09%
 5  00:10:23    16  00:14:28    00:04:05   139.33%
10  00:09:02    14  00:13:45    00:04:43   152.21%
25  00:08:53     2  00:12:57    00:04:04   145.78%
 3  00:08:02    15  00:12:15    00:04:13   152.49%
 2  00:07:55     6  00:11:48    00:03:53   149.05%
 7  00:05:57    12  00:11:08    00:05:11   187.11%
 4  00:05:43     3  00:10:08    00:04:25   177.26%
11  00:04:53     1  00:08:15    00:03:22   168.94%
19  00:04:37     4  00:07:28    00:02:51   161.73%
 1  00:02:56     9  00:04:58    00:02:02   169.32%

Moet ik er wel bij zeggen dat oplostijd niet 100% overeenkomt met moeilijkheid. Er waren in het verleden ook wel problemen waarbij je vooral heel veel tekst moest lezen en dan precies implementeren wat er beschreven werd. Dat is wel relatief tijdrovend maar niet echt “moeilijk” te noemen.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:39

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik heb voor de grap voor dag 25 nog een andere implementatie gemaakt die in O(1) per key kan opzoeken op hoeveel locks hij past :P

spoiler:
Voor de locks hou ik de notatie aan van AoC, dus [x,y,z,w,v], maar voor de keys doe ik het "omgekeerde" en doe ik hetzelfde als bij de locks. Dus een key van [0,0,0,0,0] past alleen op een lock van [0,0,0,0,0], en een key van [5,5,5,5,5] past overal op. En een key past op een lock als alle elementen van de lock kleiner-gelijk zijn dan die van de key.

Elke lock noteer ik in een 6x6x6x6x6 array op basis van de indices van de notatie. Daarna "smeer" ik de array uit door in alle 5 de richtingen de waarden bij elkaar op te tellen. Hierdoor staat in de array hoeveel locks matchen met de key die overeenkomt met dat element in de array. Daarna is het simpelweg een kwestie van alle keys opzoeken in de array.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Als er toch nog wat mensen bezig zijn, dan hierbij wat extra testdata voor dag 25: aoc-2024-day-24-challenge-1-and-2.zip (eerste bevat geen dubbelen, tweede wel).

$ ./solve < aoc-2024-day-25-challenge-1.txt 
Parsing took: 384 us
Solving took: 1446 us
...464

$ ./solve < aoc-2024-day-25-challenge-2.txt 
Parsing took: 51936 us
Solving took: 2041 us
...696
.oisyn schreef op zondag 29 december 2024 @ 03:32:
Ik heb voor de grap voor dag 25 nog een andere implementatie gemaakt die in O(1) per key kan opzoeken op hoeveel locks hij past :P
Slim verzonnen. Ik had gewoon wat geneste for-loops gehackt. Dat is in theorie (7*6/2)5 = 4,084,101 iteraties maar dat is snel zat in de praktijk. Jouw optimalisatie reduceert dat tot 7×65 = 54,432 iteraties, niet per se met dezelfde constante factor natuurlijk.

Technisch gezien is dat allemaal O(1). Qua algoritme wordt het eigenlijk pas interessant als de sleutels groter zouden kunnen zijn dan het 5x5 formaat. Momenteel is het zo dat parsen de grootste overhead heeft.

Acties:
  • +3 Henk 'm!

  • DutchFakeTuber
  • Registratie: Februari 2016
  • Laatst online: 02-06 17:06
Vandaag dag 25 op kunnen lossen! Dit jaar had een aantal moeilijke puzzels, maar niet zoveel als de voorgaande jaren. Ik was tot dag 16 in staat om de opdrachten op diezelfde dag op te lossen, maar werk kwam er tussendoor waardoor ik de streak verloor.
Dag 21 en 24 waren erg lastig, hier had ik wel want hints voor nodig op Reddit.

Ik ga nog proberen de vorige jaren op te lossen, maar gezien hoeveel tijd dit vreet gaat het nog wel even duren. Het was weer leuk dit jaar en ik ben er volgend jaar weer bij!

Acties:
  • +2 Henk 'm!

  • Bolukan
  • Registratie: Oktober 2002
  • Laatst online: 01-04 21:59
Niet alles gedaan, maar net dag 21 deel 2 in excel opgelost. Er zijn ca 5x5 x25 cellen voor nodig en nog max 121 voor het nummerbord: dus O(746).
En de hamvraag: welke van de codes vraagt de kortste, respectievelijk langst input?

[ Voor 7% gewijzigd door Bolukan op 30-12-2024 16:32 ]


Acties:
  • +3 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:26
Bolukan schreef op maandag 30 december 2024 @ 16:24:
Niet alles gedaan, maar net dag 21 deel 2 in excel opgelost. Er zijn ca 5x5 x25 cellen voor nodig en nog max 121 voor het nummerbord: dus O(746).
In Excel? Held.
En de hamvraag: welke van de codes vraagt de kortste, respectievelijk langst input?
Ik kom op de volgende lengtes (met 25 robots en 3-cijferige codes): https://pastebin.com/raw/REzEHUTP
Gesorteerd op lengte: https://pastebin.com/raw/W5mjkstz

Eigenlijk redelijk logisch: de codes met repetities vergen de minste input omdat je niet tussendoor hoeft te verplaatsen, en de codes met cijfers die ver uit elkaar liggen (zoals 7 en 0) vergen de meeste input.




Overigens: ik zag dat Infi, een van de Nederlandse sponsors van AoC, ook een AoC-achtige opgave op hun website heeft staan: https://aoc.infi.nl/2024. Voor wie last heeft van ontwenningsverschijnselen (ik heb 'm natuurlijk ook even opgelost).

Acties:
  • +2 Henk 'm!

  • Satom
  • Registratie: Mei 2011
  • Laatst online: 23:38

Satom

Verzamel ervaringen

Zo, weer een paar sterren erbij!

Dag 23: deel 1 geen problemen mee gehad. Deel 2 toch wel even mee zitten "puzzelen". Had al vrij snel door wat de bedoeling was en hoe ik er zou kunnen komen, alleen kwam ik er niet. Daarna een compleet nieuwe oplossing geschreven, welke erg langzaam was, dus terug na de eerste oplossing. Uiteindelijk daar de bug gevonden: [spoiler]ik vergat te controleren of de gevonden computers ook echt buren zijn van elkaar.[spoiler]

Dag 25: deel 1 opgelost, vrij simpel en soepel. Verwachte nog ergens een adder on het gras, maar nee..

Nu rest mij alleen nog dag 24 (en 25) deel 2!

Acties:
  • +3 Henk 'm!

  • Satom
  • Registratie: Mei 2011
  • Laatst online: 23:38

Satom

Verzamel ervaringen

Deel 2 van dag 24 ook weten op te lossen (op nieuwjaarsdag notabene)! Deze was voor mij het lastigst.

spoiler:
In eerste instantie dacht ik dat het voldoende zou zijn om een 1 een voor een op de x en y te zetten en dan de output controleren. Als het niet klopt, kunnen we de outputs gaan wisselen. Alleen was dat iets te makkelijk gedacht. Uitendelijk van de input iets gemaakt dat kan worden ingelezen door https://digitaljs.tilk.eu/ en toen begon het kwartje deels te vallen. Ik begon de juiste outputs (die ik hiervoor had gevonden) te vergelijken met de foute. Als ik het goed herinner, zag ik ergens een OR, wat niet zou moeten kunnen. Uiteindelijk nog even moeten puzzelen met de edgecases (eerste bit, laatste bit etc.)


Dus 2024 is helemaal klaar! O-)

Acties:
  • +1 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:39

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op zondag 29 december 2024 @ 12:54:
Als er toch nog wat mensen bezig zijn, dan hierbij wat extra testdata voor dag 25: aoc-2024-day-24-challenge-1-and-2.zip (eerste bevat geen dubbelen, tweede wel).

$ ./solve < aoc-2024-day-25-challenge-1.txt 
Parsing took: 384 us
Solving took: 1446 us
...464

$ ./solve < aoc-2024-day-25-challenge-2.txt 
Parsing took: 51936 us
Solving took: 2041 us
...696
Ik had deze nog niet gedaan. Kleine aanpassing aan de parsing code (waar idd de meeste tijd in zit), en de keys in de tabel gezet zodat ik het totaal meteen kan uitrekenen bij het uitsmeren.

     Running `target\release\day25.exe -i .\extra\aoc-2024-day-25-challenge-1.txt`
Time spent: 501.1µs
1650464 - 0

     Running `target\release\day25.exe -i .\extra\aoc-2024-day-25-challenge-2.txt`
Time spent: 39365.9µs
16853493696 - 0

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Ik ben maar eens begonnen om alles te doen en heb 2015 bijna af, maar dag 19 deel 2 is wel even een dingetje hoor :D

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • bakkerjangert
  • Registratie: Februari 2012
  • Laatst online: 22:20
Ik heb even gekeken en die herinner ik me nog wel. Mocht je die code matig op willen lossen is het lastig uiteraard.

spoiler:
Dat is mij niet gelukt. Echter als je de input goed uitpluist kun je een andere manier vinden om het antwoord te beredeneren. Dat vind ik het mooie van AoC puzzels, soms is het handig om de input uit pluizen om zo tot een oplossing te komen.

Acties:
  • 0 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 28-05 19:14
Janoz schreef op maandag 6 januari 2025 @ 11:29:
Ik ben maar eens begonnen om alles te doen en heb 2015 bijna af, maar dag 19 deel 2 is wel even een dingetje hoor :D
Ik heb toevallig ook laatst alles van 2015 opgelost, en ik had ook even moeite met 19 deel 2. Maar hij is goed op te lossen met:

spoiler:
A*. Oftewel Dijkstra, maar dan nog met een heuristic van hoeveel stappen je minimaal nodig hebt vanaf dat punt om het einde te bereiken (lowerbound). En ik had het ook omgekeerd opgelost: van eindsituatie terug naar het begin.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 05-06 22:44

Janoz

Moderator Devschuur®

!litemod

Robbinb1993 schreef op maandag 6 januari 2025 @ 14:46:
[...]


Ik heb toevallig ook laatst alles van 2015 opgelost, en ik had ook even moeite met 19 deel 2. Maar hij is goed op te lossen met:

spoiler:
A*. Oftewel Dijkstra, maar dan nog met een heuristic van hoeveel stappen je minimaal nodig hebt vanaf dat punt om het einde te bereiken (lowerbound). En ik had het ook omgekeerd opgelost: van eindsituatie terug naar het begin.
Zo was ik begonnen, maar ik denk dat mijn neighbour functie niet helemaal correct was

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • +3 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:14
Als afronding van dit jaar, heb ik voor het eerst maar een een stel open-source libraries beschikbaar gesteld. Ik had al zoveel gedaan om het parser makkelijker te maken, waarom het niet beschikbaar stellen. Dus bij deze: [nom-parse-macros](https://crates.io/crates/nom-parse-macros) en [nom-parse-trait](https://crates.io/crates/nom-parse-trait). Mijn code ook opgeschoond en gebruik nu gewoon deze variant.
Pagina: 1 ... 9 10 Laatste