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.
Interessant. Mijn code verschilt eigenlijk niet echt van de jouwe, maar 16GB geheugen is gewoon te weinig voor mijn implementatie. Wel raar, want het enige dat ik nodig heb zijn 100-200 miljoen coordinaten in een Set. Als een coordinaat in een Set 20 Byte neemt, dan zou je met 20*200 = 4G geheugen klaar moeten zijn. Klaarblijkelijk neemt de JVM wat meer. Ik bedoel maar: als het niet 20 Byte is, maar 80 dan zit je al aan 16GB...MatHack schreef op vrijdag 9 december 2022 @ 18:49:
Heb je het hier over dag 9? Want zo geheugen intensief is dag 9 toch niet? Ik heb maar 8GB in de VM waar ik in zit te werken en had geen enkele geheugenprobleem met jouw grote set (10M lines) in C#.
Siditamentis astuentis pactum.
Het hangt er erg vanaf welke datastructuren je gebruikt en of de voor de hand liggende standaarddatastructuren een beetje efficiënt geïmplementeerd zijn.MatHack schreef op vrijdag 9 december 2022 @ 18:49:
Heb je het hier over dag 9? Want zo geheugen intensief is dag 9 toch niet? Ik heb maar 8GB in de VM waar ik in zit te werken en had geen enkele geheugenprobleem met jouw grote set (10M lines) in C#.
Bijvoorbeeld, als je in Python integers in een set gooit, dan heeft dat behoorlijk wat overhead:
$ /usr/bin/time -v python3 -c 'set(range(10_000_000))' |& grep 'Maximum resident set size' Maximum resident set size (kbytes): 584304
Dus een set met 10 miljoen integers (waarden < 1 miljard dus passen makkelijk in 32 bits) kost al 571 MB, of 58 bytes per integer!
En paren van integers, wat een natuurlijke representatie is voor dit probleem:
$ /usr/bin/time -v python3 -c 'set(zip(range(10_000_000), range(10_000_000)))' |& grep 'Maximum resident set size' Maximum resident set size (kbytes): 1525612
1489 MB, of 156 bytes per paar! Op die manier kun je in 8 GB dus slechts ~55 miljoen elementen kwijt, en als je de antwoorden van large-2 gezien hebt, dan snap je dat je met deze aanpak met Python in de problemen komt.
Ik vermoed dat b.v. een HashMap<> in Java ook niet enorm efficient is. In C++ met std::unordered_set<> was het ook niet fantastisch (alloceert een apart object per paar).
En als je beide delen tegelijk probeert op te lossen verdubbel je benodigde hoeveelheid geheugen ook nog eens (bijna).
Okee, hier komen veel spoilersJern_97 schreef op vrijdag 9 december 2022 @ 19:29:
Toevallig zin om uit te leggen hoe je te werk gaat om dit probleem enigzins te parallelliseren?
Ik heb echt totaal geen idee...
Vandaar dat ik begon met een single-threaded implementatie waarbij ik de punten die ik tijden de simulatie tegenkom niet in een hash table stop, maar in een vector. Op het eind sorteer ik de vectors en tel ik de unieke waarden. In theorie zou dat trager moeten zijn: O(N log N) voor het sorteren i.p.v. O(N) voor de hash set, maar in de praktijk blijkt het meer dan twee keer zo snel (mogelijk omdat sorteren veel meer locality of reference heeft dan hash table access).
In mijn laatste versie probeer ik het sorteren en dedupliceren parallel te doen met het simuleren. De code is nog erg lelijk: ik buffer een paar megabyte aan data en start dan een aparte thread om de data alvast te sorteren. Vervolgens bouw ik een stack van gesorteerde arrays en probeer ik lijsten van gelijke grootte online te mergen á la merge sort.
Er valt nog wel het een ander aan te verbeteren maar dit is al zeer veelbelovend.
Ook een goed idee. Dat had ik nog niet verzonnen..oisyn schreef op vrijdag 9 december 2022 @ 19:53:
spoiler:In principe kun je op een willekeurige plek in de input stream beginnen, er zijn bij bepaalde moves wel garanties te maken waar de tail zich dan moet bevinden. Het enige wat je niet weet is waar je bent tov het begin, dus als het eerste deel is aangekomen waar het tweede deel is begonnen kun je de resultaten aan elkaar knopen. Zo kunnen meerdere threads dus hun eigen deel voor hun rekening nemen.
Ik had wel een andere manier bedacht om de simulatie te versnellen tot een paar memory lookups zonder loops:
Vervolgens kun je dan per state de positie van de staart opslaan relatief aan de kop. Voor elke beweging moet je dan de positie van de kop updaten (dat is triviaal) en de state transitie uitvoeren (state = table[state][direction]).
Aangezien er negen knopen zijn (de kop niet meegeteld) die elk op negen verschillende posities kunnen liggen ten opzichte van hun voorgang is het totaal aantal states 99 = 387,420,489. Als je voor elke state 20 bytes opslaat (4 × 4 bytes voor transities, plus ~1 byte voor de positie van de staart, rond af naar boven) kost die tabel een kleine 8 GB. Die kun je van te voren berekenen en dan in het geheugen mappen.
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Wij kunnen elkaar de hand schudden, deel 1 vlot in elkaar, de aanpassing naar deel 2 gaat niet helemaal tof, morgen verderCreepy schreef op vrijdag 9 december 2022 @ 22:06:
Dag 9 deel 1 af, deel 2 bijna. Maar laat begonnen vandaag en ff geen zin om het af te ronden. Komt van het weekend wel.
spoiler:Head kan je direct berekenen. Tail dan stap voor stap laten volgen. Daarvan nog een loopje maken zodat de hele tail stap voor stap blijft volgen voor deel 2. Bijna klaar.... Had eerst een loop om elk onderdeel van de tail naar het einde te laten gaan en dan pas het volgende deel maar dat gaat logischerwijs niet werken.
Cranzai schreef op vrijdag 9 december 2022 @ 22:19:
[...]
Wij kunnen elkaar de hand schudden, deel 1 vlot in elkaar, de aanpassing naar deel 2 gaat niet helemaal tof, morgen verder
Anyone who gets in between me and my morning coffee should be insecure.
Ik durf de weddenschap wel aan dat dat helemaal niet sneller is. Een kleine tabel past in de L1 cache, bij zo'n enorme tabel ben je continu tegen cache misses aan het vechten. Dan beter 9 iteraties over iets wat in een handjevol cachelines pastSoultaker schreef op vrijdag 9 december 2022 @ 20:54:
spoiler:Aangezien er negen knopen zijn (de kop niet meegeteld) die elk op negen verschillende posities kunnen liggen ten opzichte van hun voorgang is het totaal aantal states 99 = 387,420,489. Als je voor elke state 20 bytes opslaat (4 × 4 bytes voor transities, plus ~1 byte voor de positie van de staart, rond af naar boven) kost die tabel een kleine 8 GB. Die kun je van te voren berekenen en dan in het geheugen mappen.
Mijn eerste poging:
===[ input.txt ]========== Time: 424us (load:33us, sim:194us, sort:196us) 2545 ===[ aoc_2022_day09_large-1.txt ]========== Time: 914.038us (load:37us, sim:257.906us, sort:656.093us) 14108518 ===[ aoc_2022_day09_large-2.txt ]========== Time: 9.803.152us (load:64us, sim:2.295.402us, sort:7.507.685us) 139740182
(dit zijn part2 tijden, part1 is maar marginaal sneller)
.edit: Dit is al een stuk rapper
===[ input.txt ]========== Time: 2.254us (load:42us, sim:2.211us, sort:0us) 2545 ===[ aoc_2022_day09_large-1.txt ]========== Time: 328.476us (load:38us, sim:328.437us, sort:0us) 14108518 ===[ aoc_2022_day09_large-2.txt ]========== Time: 3.189.763us (load:49us, sim:3.189.713us, sort:0us) 139740182
[ Voor 24% gewijzigd door .oisyn op 10-12-2022 04:43 ]
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.
Verder voor deel 2 de 240 cycle values precalculaten en dan pas er doorheen lopen om te renderen maakte het eitje.
[ Voor 35% gewijzigd door MrHaas op 10-12-2022 06:35 ]
Dag 10 in Java
Siditamentis astuentis pactum.
Leuke puzzel weer! Ik heb er best lang over gedaan, omdat ik eerst een langdradige imperatieve oplossing probeerde te schrijven, waarmee het lastig was om...
Toen ben ik maar opnieuw begonnen met een functional-style oplossing, en toen "klikte" het, en werd alles ineens veel makkelijker! De uiteindelijke oplossing is 20 regels code. Ik ben best tevreden
Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...
Was ff zoeken, maar toen had ik eindelijk een oplossingsrichting waar ik mee kon leven (voornamelijk om dezelfde redenen die @Dricus ook aangeeft in zijn spoiler). Toen alleen nog in deel 2:
En copy-paste van het antwoord van deel 2 ging niet echt, dus moest nog opletten wat ik invoerde ook (n.a.v. reacties gisteren)

There's no place like 127.0.0.1
MatHack schreef op zaterdag 10 december 2022 @ 08:34:
Dag 10 in C#
Was ff zoeken, maar toen had ik eindelijk een oplossingsrichting waar ik mee kon leven (voornamelijk om dezelfde redenen die @Dricus ook aangeeft in zijn spoiler). Toen alleen nog in deel 2:
spoiler:Stoeien met one-off errors, heerlijk dat cycle en position niet gelijk lopen...
En copy-paste van het antwoord van deel 2 ging niet echt, dus moest nog opletten wat ik invoerde ook (n.a.v. reacties gisteren)
Of als het bogus data is, zoals voorkomt bij de voorbeelden, kan die ook de output printen en kan ik die visueel verifieren in mijn test.
Dag 10 - Rust
Code ziet er uit of t makkelijker kan (wat ook vast het geval is), maar dat is een zorg voor later.
Ik heb geen verkoudheid en snap het deel van wanneer ik nu wel en niet een pixel moet blitten ook totaal nietTrailBlazer schreef op zaterdag 10 december 2022 @ 08:30:
het zal wel aan mijn zwaar verkouden hoofd liggen maar ik kan geen chocola maken van task2 vandaag
RangedNeedles schreef op zaterdag 10 december 2022 @ 11:29:
[...]
Ik heb geen verkoudheid en snap het deel van wanneer ik nu wel en niet een pixel moet blitten ook totaal niet
pseudo:
pixel = absolute(x - (cycle%40)) < 2 ? '#' : '.'
Dan dien je nog wel rekening te houden met de rij waar je de pixel print.
Daar was ik al bang voor, vandaar dat ik er maar geen werk van gemaakt heb. Maar het hangt wel een beetje van je invoer af: het kan zijn dat je access niet volledig random is (b.v. als je meer dan 9 stappen in dezelfde richting doet, blijf je altijd in dezelfde toestand; dit kun je trouwens ook gebruiken om je reguliere algoritme te versnellen)..oisyn schreef op zaterdag 10 december 2022 @ 03:26:
Ik durf de weddenschap wel aan dat dat helemaal niet sneller is. Een kleine tabel past in de L1 cache, bij zo'n enorme tabel ben je continu tegen cache misses aan het vechten. Dan beter 9 iteraties over iets wat in een handjevol cachelines past
Nice.edit: Dit is al een stuk rapper. Nog steeds singlethreaded, maar een andere datastructuur om bij te houden welke cells je al gehad hebt. Kost wel 2GB mem in die grootste file.
[ Voor 8% gewijzigd door Soultaker op 10-12-2022 11:39 ]
Het is voor mij wel goed leesbaar zo. Ik heb gelijk even mijn eigen code gerefactored met wat trucjes in jouw code. thnxFrankMennink schreef op zaterdag 10 december 2022 @ 10:54:
Dag 10 in Python
Code ziet er uit of t makkelijker kan (wat ook vast het geval is), maar dat is een zorg voor later.
Oh voor de output van deel twee:
Me think, why waste time say lot word, when few word do trick.
Sparse bitsetSoultaker schreef op zaterdag 10 december 2022 @ 11:38:
[...]
NiceWat voor data structuur is dat/staat je code ergens? Doe je een soort van counting sort misschien? (Alle bezochte posities markeren met bits en dan aantal 1-bits tellen; vereist wel dat je de 2D array representeert om een manier dat je niet alle lege ruimte expliciet representeert).
Er is nog wel wat ruimte voor optimalisaties, hoor. Veel low hanging fruit nog, zoals idd langere moves die geen state changes meer introduceren, een early out als een parent knot niet beweegt, een 4-entry cache voor level 0 pages zodat ik die niet elke keer hoef op te zoeken, en dan heb ik het nog niet eens gehad over parallellisatie.
Het is jammer dat de opdrachten zo snel op elkaar volgen, iedereen is alweer vertrokken naar een ander probleem
[ Voor 24% gewijzigd door .oisyn op 10-12-2022 12:03 ]
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.
Dit trucje wilde ik ook nog toepassen, ik denk dat het mijn implementatie wat makkelijker maakt!_mike_ schreef op zaterdag 10 december 2022 @ 12:06:
Rust
spoiler:een 2-cycle add kan je ook zien als een 1-cycle noop + een 1-cycle add
Als ik morgen wat meer tijd heb maar even afmaken 😅
tarlitz schreef op zaterdag 10 december 2022 @ 12:15:
Oef, ik heb part 2 wel 10x gelezen voordat ik hem snapte, maar daarna was het een vrij simpele aanpassing aan part 1 om hem goed te krijgen. Er zit alleen nog een bugje in m'n display waarbij de 1ste kolom aan het eind staat![]()
[...]
Dit trucje wilde ik ook nog toepassen, ik denk dat het mijn implementatie wat makkelijker maakt!
Als ik morgen wat meer tijd heb maar even afmaken 😅
https://github.com/CodeEn...er/aoc/aoc2022/Day09.java
Zo maar eens aan vandaag beginnen.
[ Voor 19% gewijzigd door Creepy op 10-12-2022 12:50 ]
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Was weer prima te doen. Na een 5 of wat AOC's te doen heb je wel je handigheidjes. En de Kotlin Stdlib is zo lekker uitgebreid met collections.
Engineering is like Tetris. Succes disappears and errors accumulate.
Misschien interessant om na de AoC (door het jaar heen of zo) een of enkele opdrachten eruit te halen endaarmee aan de slag te gaan zoals jullie dat nu doen en die eens goed uitdiepen....oisyn schreef op zaterdag 10 december 2022 @ 11:57:
[...]
Het is jammer dat de opdrachten zo snel op elkaar volgen, iedereen is alweer vertrokken naar een ander probleem
Wie du mir, so ich dir.
Dag 10 ook gefixt

https://github.com/CodeEn...er/aoc/aoc2022/Day10.java
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Heel nice die bitset implementatie! Compileert zelfs nog op mijn CPU en is idd. erg snel: ongeveer 3,7s voor de large-2 (slechts ~15% trager dan op jouw CPU, interessant genoeg)..oisyn schreef op zaterdag 10 december 2022 @ 11:57:
Sparse bitset. Code staat op mijn github. De bitset is 4 levels aan pages van 64k entries.[/url]
Ik zie dat je wel een transitie-tabel hebt geïmplementeerd maar dan voor maar 1 stap. In theorie zou je het ook kunnen doen voor 2 of meer stappen tegelijk, afhankelijk van hoeveel er in je cache past (b.v. 3 stappen is 26 KB, denk ik).
Ook interessant te zien dat je de lookup tables volledige at compiletime genereert; ik wist niet dat constexpr functies gewoon loops en variable assignments kunnen bevatten, blijkbaar loop ik nog een paar C++-versies achter.
edit:
Ik had voor de grap de early out geïmplementeerd. Dat leek voor de grote data set ~5% snelheidswinst op te leveren, maar voor de officiële wordt het juist trager. Dat is vreemd want mijn grote set bevat relatief veel minder stappen die de early-out gebruiken (~15% voor mijn data set, ~85% voor de officiële dataset) dus ik had verwacht dat het precies omgekeerd zou zijn.
Geen idee wat daar precies gebeurt; misschien hebben de extra conditionals een negatief effect op de gegenereerde code binnen de loop.
Voor dag 10 hoef je daar niet bang voor te zijn, daar lijkt me vrij weinig interessants aan te optimaliseren (ik heb er dan ook geen grote set voor gepost).Het is jammer dat de opdrachten zo snel op elkaar volgen, iedereen is alweer vertrokken naar een ander probleem
[ Voor 20% gewijzigd door Soultaker op 10-12-2022 14:50 ]
Toch grappig hoe ik bijna op dezelfde code ben gekomen en toch de code er anders uit ziet. Net weer andere functies gekozen om het mee te doen: https://github.com/marcde...jonge/advent2022/Day10.ktarmageddon_2k1 schreef op zaterdag 10 december 2022 @ 12:49:
En.... Dag 10 in Kotlin.
Was weer prima te doen. Na een 5 of wat AOC's te doen heb je wel je handigheidjes. En de Kotlin Stdlib is zo lekker uitgebreid met collections.
Anyone who gets in between me and my morning coffee should be insecure.
kan vast wel wat netter en efficienter alleen niet zo veel eer aan te behalen imho
Het idee is dat je over meerdere dagen een processor-simulator bouwt. Over een paar dagen komen er wat instructies bij en een paar dagen daarna nog eens totdat je uiteindelijk een geavanceerde processor hebt met een stuk of 10 instructies compleet met branches/jumps. De eerste keer dat we zoiets moesten bouwen zat alles in 1 dag gepropt en dat was best veel werk. De laatste jaren is het over meerdere dagen uitgesmeerd.TrailBlazer schreef op zaterdag 10 december 2022 @ 16:43:
kan vast wel wat netter en efficienter alleen niet zo veel eer aan te behalen imho
Zo dan, even de pecl package voor Data Structures installeren en dag 9 gaat van 1.8s rekentijd naar 25ms. Daar kan ik mee leven.MueR schreef op zaterdag 10 december 2022 @ 16:34:
Dag 9 kan ik nog wel wat aan verbeteren.. Dag 10 was makkelijk.
Anyone who gets in between me and my morning coffee should be insecure.
Dat was alleen het geval in 2019, toen moesten we de beruchte intcode computer bouwen.Daos schreef op zaterdag 10 december 2022 @ 17:09:
[...]
Het idee is dat je over meerdere dagen een processor-simulator bouwt. Over een paar dagen komen er wat instructies bij en een paar dagen daarna nog eens totdat je uiteindelijk een geavanceerde processor hebt met een stuk of 10 instructies compleet met branches/jumps. De eerste keer dat we zoiets moesten bouwen zat alles in 1 dag gepropt en dat was best veel werk. De laatste jaren is het over meerdere dagen uitgesmeerd.
Alle andere jaren kregen we over het algemeen maar 1 a 2 opdrachten met een instructieset om te implementeren.
Waarbij in de begin jaren de opdracht vooral was om het algoritme te analyseren en zelf efficiënter te schrijven wilde je klaar zijn voor de heat death van het universum.
Klopt ja, dat wil ik ook nog proberen. Maar zolang ik niet alle 9 tegelijk doe heb ik wel 9 (eigenlijkSoultaker schreef op zaterdag 10 december 2022 @ 14:43:
Ik zie dat je wel een transitie-tabel hebt geïmplementeerd maar dan voor maar 1 stap. In theorie zou je het ook kunnen doen voor 2 of meer stappen tegelijk, afhankelijk van hoeveel er in je cache past (b.v. 3 stappen is 26 KB, denk ik).
Ja heerlijk heOok interessant te zien dat je de lookup tables volledige at compiletime genereert; ik wist niet dat constexpr functies gewoon loops en variable assignments kunnen bevatten, blijkbaar loop ik nog een paar C++-versies achter.
Bij mij is die early out echt een enorme kostenpost. Hij gaat van 2,8s op de grootste dataset naar 4,2sIk had voor de grap de early out geïmplementeerd. Dat leek voor de grote data set ~5% snelheidswinst op te leveren, maar voor de officiële wordt het juist trager. Dat is vreemd want mijn grote set bevat relatief veel minder stappen die de early-out gebruiken (~15% voor mijn data set, ~85% voor de officiële dataset) dus ik had verwacht dat het precies omgekeerd zou zijn.

heb net eens naar het verschil in assembly zitten kijken, en zonder de early out wordt de loop volledig geunrolled en zit er geen enkele branch in. Met early out wordt het gewoon een daadwerkelijke loop. MSVC++ heeft geen force-unroll directive helaas, ben wel benieuwd hoe een unrolled loop met early out zou performen.
Ik zat weer eens door Intel intrinsics guide te bladeren en ik vond daar _pdep_u64 (PDEP). Prachtige instructie, daarmee kun je de bits van een getal uit elkaar trekken aan de hand van een control bit pattern (_pext_u64 (PEXT) doet precies het tegenovergestelde). Een pattern als 0b010101010101... insert allemaal 0 bits (bit 0 blijft op z'n plek, bit 1 gaat naar bit 2, bit 2 naar bit 4, bit 3 naar bit 6, etc). Daarmee kan ik het x- en y-coordinaat dus per bit interleaven ipv per byte, elke cacheline wordt daarmee effectief een blokje van 8x8 in mijn grid (ipv dat elke verandering in y een andere cacheline opleverde). Daarmee ging mijn running time van 3.0s naar 2.8s
.edit: 2.6s met 4-entry bitset page cache.
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.
Ik had bedacht dat je de dx/dy in 1 byte kunt packen (b.v. met een bit field, 4 bits elk), dan kun je nog steeds vrij snel rap uitpakken en heb je twee bytes voor nextState. Merk op dat je nextState en moveDir élke iteratie nodig hebt en dx/dy alleen aan het eind van de lus, maximaal 1 keer dus, dus lijkt me dat je die als eerste inpakt..oisyn schreef op zaterdag 10 december 2022 @ 22:16:
3 Stappen tegelijk past al niet meer in een char, al zou ik ervoor kunnen kiezen om ofwel dx/dy ofwel moveDir er niet in te stoppen, want die zeggen eigenlijk hetzelfde.
Dat is toch niet zo moeilijk te testen?Bij mij is die early out echt een enorme kostenpost. Hij gaat van 2,8s op de grootste dataset naar 4,2s. Ik
heb net eens naar het verschil in assembly zitten kijken, en zonder de early out wordt de loop volledig geunrolled en zit er geen enkele branch in. Met early out wordt het gewoon een daadwerkelijke loop. MSVC++ heeft geen force-unroll directive helaas, ben wel benieuwd hoe een unrolled loop met early out zou performen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| #define LOOP_BODY(k) \ { \ auto& state = knotStates[k]; \ lastMove = States[state][d]; \ state = lastMove.nextState; \ d = lastMove.moveDir; \ if (d == None) goto done; \ } LOOP_BODY(0) LOOP_BODY(1) LOOP_BODY(2) LOOP_BODY(3) LOOP_BODY(4) LOOP_BODY(5) LOOP_BODY(6) LOOP_BODY(7) LOOP_BODY(8) #undef LOOP_BODY x += lastMove.dx; y += lastMove.dy; numCells += grid.Set(x, y); done: |
Waarschijnlijk kun jij wel een mooiere permanente oplossing verzinnen met template-metaprogramming als het de moeite waard blijkt te zijn.
Of kun je deze patch eens proberen? Met clang levert dat iets van 15% winst op!
[ Voor 4% gewijzigd door Soultaker op 10-12-2022 23:21 ]
Diderikdm schreef op zaterdag 10 december 2022 @ 12:29:
[...]
spoiler:Is je eerste row 40 of 41 lang?

Ik had verwacht hier sneller doorheen te zijn, maar het heeft me een volle dag gekost.
Maar gelukkig ben ik weer bij.
let the past be the past.
Bitfields to the rescue. Dit heeft geen noemenswaardige impact op de performance.Soultaker schreef op zaterdag 10 december 2022 @ 22:55:
[...]
Ik had bedacht dat je de dx/dy in 1 byte kunt packen (b.v. met een bit field, 4 bits elk), dan kun je nog steeds vrij snel rap uitpakken en heb je twee bytes voor nextState. Merk op dat je nextState en moveDir élke iteratie nodig hebt en dx/dy alleen aan het eind van de lus, maximaal 1 keer dus, dus lijkt me dat je die als eerste inpakt.
1
2
3
4
5
6
7
| struct Move { uint nextState : 24; uint moveDir : 4; int dx : 2; int dy : 2; }; |
Ruimte voor 16,7 miljoen states
En constexpr is awesome
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| template<int A, int B> constexpr auto CombineStates(StateArray<A> a, StateArray<B> b) { StateArray<A * B> result; for (int i = 0; i < A; i++) { for (int j = 0; j < B; j++) { for (int d = 0; d < 9; d++) { auto move = a[i][d]; auto newa = move.nextState; auto newd = move.moveDir; move = b[j][newd]; auto newb = move.nextState; move.nextState = newa * B + newb; result[i * B + j][d] = move; } } } return result; } constexpr auto DoubleStates = CombineStates(States, States); constexpr auto TripleStates = CombineStates(DoubleStates, States); |
MSVC++ genereert daar dezelfde code als de "structurele" oplossing met de check in de for conditie. En dus geen loop unroll.Of kun je deze patch eens proberen? Met clang levert dat iets van 15% winst op!
.edit: met 4xDoubleState+1xSingleState naar 1.8s.
met 3xTripleState naar 1.5s.
2xQuad+Single ook 1.5s. Niet zo gek, want dat zijn nog steeds 3 state transities. Compiletijden beginnen nu wel toe te nemen
Ok voor PentaStates moest ik het aantal constexpr eval steps verhogen anders slikte de compiler het niet
1.4s wel
.edit: Met een iets handigere bitpacking (movestate 16 bits, movedir 8 bits) performt de 3x TripleState en handmatige unroll met early out trouwens ook met 1.4s. Dus ik denk dat ik het daar op hou.
[ Voor 20% gewijzigd door .oisyn op 11-12-2022 01: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.
Ik dacht dat het
Ik vond hem wel weer grappig. Ik ben eigenlijk vooral benieuwd of we morgen de CPU van gisteren terug gaan zien.
OMG @ invoer
OMG @ expressies parsen
OMG @ BigInteger te traag
Dag 11 in Java https://github.com/varien...tofcode2022/Puzzle11.java.
Siditamentis astuentis pactum.
Engineering is like Tetris. Succes disappears and errors accumulate.
tbh vond ik het parsen vandaag best simpel. Ja, het lijkt veel tekst, maar als je in alle input kijkt dan valt de variatie heel erg mee.armageddon_2k1 schreef op zondag 11 december 2022 @ 08:35:
Tja, de moeilijkheid van AOC wordt toch vaak in het parsen gestopt.... moet even zin maken voor vandaag.
Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'
Oh, ja dat is zeker waar :-)Janoz schreef op zondag 11 december 2022 @ 08:39:
[...]
tbh vond ik het parsen vandaag best simpel. Ja, het lijkt veel tekst, maar als je in alle input kijkt dan valt de variatie heel erg mee.
Engineering is like Tetris. Succes disappears and errors accumulate.
There's no place like 127.0.0.1
Ik zou willen dat ik er niet zo ingestonken was....
[ Voor 22% gewijzigd door armageddon_2k1 op 11-12-2022 10:39 ]
Engineering is like Tetris. Succes disappears and errors accumulate.
Klopt mijn redenering?
Dag 11 - Python
Zou best kunnen. Probeer het eens uit te werken met een heel klein aantal testvalues en lage waardes ervan. Bv, 3,5,7. Dat is nog doableMrHaas schreef op zondag 11 december 2022 @ 10:50:
Leuke puzzel, maar
spoiler:zat nu te denken of je het kan oplossen voor een arbitrair aantal ronden: volgens mij kan je een item representeren als (monkey index, value % M) waar bij M de lcm is van de test values. Aangezien het aantal states eindig is (aantal monkeys * M), heeft elk item een bepaalde frequentie. Je moet dan alleen nog voor 1 cycle van een item bijhouden hoe vaak ie elke monkey bezoekt.
Klopt mijn redenering?
Engineering is like Tetris. Succes disappears and errors accumulate.
Zonder die hint was het me niet gelukt, thanksDiderikdm schreef op zondag 11 december 2022 @ 11:28:
Niet al te duidelijke code, 1.5s runtime, dus kan nog wel wat verbeteren. Wel een geinige puzzel. Deel twee deed me een beetje denken aan 2020 dag 13 waarna ik wel een hint had.
spoiler:Chinese Remainder Theorem
Dag 11 - Python
Ik had eerst een poging in BigIntegers, maar na een paar seconden runtime realiseerde ik me dat ik met een andere oplossing moest komen. Deze doet beide delen nu in 20ms, dus ben daar wel weer blij mee
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Yes, het is gelukt. Smerige code, maar het werkt. Kan nu binnen 100ms uitkomst bepalen voor elk willekeurig aantal rondes.armageddon_2k1 schreef op zondag 11 december 2022 @ 11:29:
[...]
Zou best kunnen. Probeer het eens uit te werken met een heel klein aantal testvalues en lage waardes ervan. Bv, 3,5,7. Dat is nog doable
Dit zei ik al hè.oisyn schreef op zondag 11 december 2022 @ 01:20:
Met een iets handigere bitpacking (movestate 16 bits, movedir 8 bits)
Waarschijnlijk is de optimale layout zoiets:
1
2
3
4
5
6
| struct { unsigned nextState : 16; int dr : 4; int dc : 4; unsigned nextDir : 8; } |
Zodat je nextState kunt berekenen met 1 AND instructie, nextDir met 1 SHIFT instructie, en de minst-gebruikte dr/dc met 1 SHIFT + 1 AND elk. Maar laten we wel zijn, het verschil is minimaal.
Nice! Ik vind 3×3 ook het meest natuurlijke voor dit probleem.performt de 3x TripleState en handmatige unroll met early out trouwens ook met 1.4s. Dus ik denk dat ik het daar op hou.
Kun je de laatste versie eens naar Github pushen btw?
Varienaja schreef op zondag 11 december 2022 @ 08:12:
spoiler:OMG @ long te klein
OMG @ BigInteger te traag
[ Voor 19% gewijzigd door Soultaker op 11-12-2022 14:24 . Reden: Mogelijke spoiler voor deel 2 getagd. ]
Pff, echt véél te lang vastgezeten op een totaal verkeerd spoor.
Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...
Volgens mij zeg jij dit elk jaar wanneer je
bedoelt.
Soultaker schreef op zondag 11 december 2022 @ 14:09:
[...]
Volgens mij zeg jij dit elk jaar wanneer je
spoiler:kleinste gemene veelvoud (least common multiple)
bedoelt.De twee zijn wel aan elkaar gerelateerd maar wat jij noemt is veel ingewikkelder en hier helemaal niet nodig.
Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...
Je hebt gelijk en nu je het zegt valt het me pas op dat (in mijn invoer tenminste)Dricus schreef op zondag 11 december 2022 @ 14:16:
spoiler:En least common multiple is ook niet eens nodig, je kunt gewoon alle "divisible by" getallen met elkaar vermenigvuldigen. Alleen schaalt dat natuurlijk niet met het aantal apen en de hoogte van de "divisible by" getallen.
Grappig genoeg wordt deel 1 daarmee moeilijker dan deel 2.MrHaas schreef op zondag 11 december 2022 @ 13:18:
Yes, het is gelukt. Smerige code, maar het werkt. Kan nu binnen 100ms uitkomst bepalen voor elk willekeurig aantal rondes.
Old habits die hardSoultaker schreef op zondag 11 december 2022 @ 14:09:
[...]
Volgens mij zeg jij dit elk jaar wanneer je
spoiler:kleinste gemene veelvoud (least common multiple)
bedoelt.De twee zijn wel aan elkaar gerelateerd maar wat jij noemt is veel ingewikkelder en hier helemaal niet nodig.
Soultaker schreef op zondag 11 december 2022 @ 14:35:
[...]
Je hebt gelijk en nu je het zegt valt het me pas op dat (in mijn invoer tenminste)
spoiler:.alle delers priemgetallen zijn, dus het product is gelijk aan het kleinste gemene veelvoud.

Stel niet uit tot morgen wat je vandaag nog tot morgen kunt uitstellen...
Deel 2 is wat traag met ~130ms.
Anyone who gets in between me and my morning coffee should be insecure.
Moet zeggen dat dag 10 een makkelijke was, maar voor dag 11 was ik in dezelfde valkuil getrapt als een aantal andere in het forum.
Ik zat verkeerd te denken
let the past be the past.
Als ze word of byte aligned zijn dan kunnen ze gewoon worden geladen met een word of byte-sized read met zero extension, dus het maakt niet zo heel veel uit waar in de struct ze staan.Soultaker schreef op zondag 11 december 2022 @ 13:38:
Zodat je nextState kunt berekenen met 1 AND instructie, nextDir met 1 SHIFT instructie
Dacht dat ik al dat had gedaan. Nu alsnogKun je de laatste versie eens naar Github pushen btw?
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.
Als scheikundige kende ik het in ieder geval niet
Dat vraag ik me ook af inderdaad. Heb wel HTS werktuigbouw gedaan (soort van) maar dit nooit bij wiskunde gehad.Cranzai schreef op zondag 11 december 2022 @ 17:50:
Nou vroeg ik mij af, het wiskundige trucje vandaag, is dat iets dat bij informatica opleidingen vaker voorbij komt of is het iets dat je toevallig moest weten?
Als scheikundige kende ik het in ieder geval niet
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.
[ Voor 7% gewijzigd door Soultaker op 11-12-2022 18:48 ]
[ Voor 100% gewijzigd door Soultaker op 11-12-2022 19:35 ]
Dag 11 - Rust
Priemgetallen ja, maar getaltheorie wat minder.Soultaker schreef op zondag 11 december 2022 @ 18:48:
...en hash functies, hash tables, caching, load balancing, sharding...
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.
Dat is dan iets recents, 10-15 jaar geleden kwam dit nog niet voor op het HBO..oisyn schreef op zondag 11 december 2022 @ 18:35:
Het is wel iets dat bij informaticaopleidingen naar voren komt omdat het belangrijk is in cryptografie.
Op de universiteit was cryptografie een keuzevak, dus kon je ook de opleiding doorlopen zonder getal theorie.
Of misschien is niet elke HBO gelijk?Remcoder schreef op zondag 11 december 2022 @ 19:35:
[...]
Dat is dan iets recents, 10-15 jaar geleden kwam dit nog niet voor op het HBO.
* .oisyn is afgestudeerd in 2004. Hogeschool van Utrecht.
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.
Blijkt maar weer dat ik "scientist first, programmer second" ben (niet dat informatici geen wetenschappers zijn)
Dit kwam op mijn universiteit in het eerste programmeervak aan bod. Dat vak word gevolgd door alle informatica en kunstmatige intelligentie studenten, plus een deel van wiskunde, econometrie, natuurkunde, scheikunde en sterrenkunde.Cranzai schreef op zondag 11 december 2022 @ 17:50:
Nou vroeg ik mij af, het wiskundige trucje vandaag, is dat iets dat bij informatica opleidingen vaker voorbij komt of is het iets dat je toevallig moest weten?
Als scheikundige kende ik het in ieder geval niet
Oh kijk aan, mag ik vragen welke uni dat was?Gropah schreef op zondag 11 december 2022 @ 20:01:
[...]
Dit kwam op mijn universiteit in het eerste programmeervak aan bod. Dat vak word gevolgd door alle informatica en kunstmatige intelligentie studenten, plus een deel van wiskunde, econometrie, natuurkunde, scheikunde en sterrenkunde.
(Zelf een alumnus van de RUG)
[ Voor 19% gewijzigd door MatHack op 11-12-2022 20:05 ]
There's no place like 127.0.0.1
Andersom geldt dat dan ook voor jouw statement.oisyn schreef op zondag 11 december 2022 @ 19:36:
[...]
Of misschien is niet elke HBO gelijk?.
* .oisyn is afgestudeerd in 2004. Hogeschool van Utrecht.
Maar ik zei toch niet dat het bij élke opleiding naar voren kwam?Remcoder schreef op zondag 11 december 2022 @ 20:10:
[...]
Andersom geldt dat dan ook voor jouw statement
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.
Ik heb bedrijfskundige informatica gestudeerd maar ik kende het ook alleen van voorgaande AoC jaren. En bij AoC is het ook het enige waar ik het toepas 😁Cranzai schreef op zondag 11 december 2022 @ 17:50:
Nou vroeg ik mij af, het wiskundige trucje vandaag, is dat iets dat bij informatica opleidingen vaker voorbij komt of is het iets dat je toevallig moest weten?
Als scheikundige kende ik het in ieder geval niet
(afgestudeerd in 1994...)
[ Voor 3% gewijzigd door P_Tingen op 11-12-2022 20:22 ]
... en gaat over tot de orde van de dag
DiezelfdeCranzai schreef op zondag 11 december 2022 @ 20:02:
[...]
Oh kijk aan, mag ik vragen welke uni dat was?
(Zelf een alumnus van de RUG)
For context; degene die dat vak geeft is nogal fan van wiskunde bij opdrachten. Krijg je getallen die je makkelijk kan controleren. Maar hij weet niet helemaal wat het niveau van de middelbare school is. En vind niet dat een klein beetje extra wiskunde een probleem moet zijn.
Ik zit te genieten van jullie discussies in jullie alternate reality trouwens. Ga zo door
C++ is hier een dying craft valt me op trouwens....
[ Voor 8% gewijzigd door farlane op 11-12-2022 20:49 ]
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
aoc_2022_day11_large-1.txt (12 KB), som van de cijfers van de antwoorden: 21, 72.
aoc_2022_day11_large-2.txt (135 KB), som van de cijfers van de antwoorden: 48, 60.
Hint: ik heb de inputs zo ontworpen dat je in principe géén big integer library nodig voor deze problemen (wel 64-bits integers), behalve misschien voor large-2 deel 1, afhankelijk van hoe je het aanpakt.
Ja, maar ik ken dijkstra ook helemaal niet. Net als @Cranzai heb ik een scheikunde achtergrond en is advent of code echt de eerste keer dat ik zulk soort algoritmes tegen kom. Laat staan dat ik dat voor een aoc puzzel ga implementeren. Dan gebruik ik een library. Anders worden dat soort opdrachten erg lastig.Thorwing schreef op zondag 11 december 2022 @ 20:39:
zelfs al kende je 'het trucje' niet, is het best logisch te redeneren. Het is alsof je gaat klagen dat je het Dijkstra algoritme niet kent bij een toekomstige opgave (wat zeker gaat komen). Dit bedoel ik niet lullig natuurlijk. Ik had er ook moeite mee vandaag aangezien ik het ook niet wist. Programmeer puzzles vragen nou eenmaal wat logisch inzicht waar we allemaal wat moeite mee hebben om 6 uur s'ochtends natuurlijk.
Ik vind deze discussie daarom wel extra interessant, want ik sta echt versteld van wat ik allemaal zie qua oplossingen. En blijkbaar komt dit dus wél voorbij in de informatica opleidingen. Dit is goed om te weten voor mijn eigen zelfwaarde 😅
Dat trucje van vandaag zou ik zelf nooit opgekomen zijn als ik het niet vorig jaar ook al tegengekomen was. Dat vind ik ook het leuke van aoc. Zeker met opdrachten als deze leer ik veel van de oplossingen die voorbij komen.
Ik vind het altijd wel gaaf om andere opleidingen dit te zien doen, het was ook zeker geen sneer. Maar de leidraad van AoC is dat zonder programmeer of wiskundige achtergrond, je nog logisch kan redeneren hoe je er komt. Natuurlijk gaat dit vééél langer duren zonder voorkennis, dus ik blaam je helemaal niet als je googled. Kunnen googlen is het hele idee van een programmeur zijn dus je bent al een top programmeur als je dat kan haha.tarlitz schreef op zondag 11 december 2022 @ 20:53:
[...]
Ja, maar ik ken dijkstra ook helemaal niet. Net als @Cranzai heb ik een scheikunde achtergrond en is advent of code echt de eerste keer dat ik zulk soort algoritmes tegen kom.
Dat trucje van vandaag zou ik zelf nooit opgekomen zijn als ik het niet vorig jaar ook al tegengekomen was. Dat vind ik ook het leuke van aoc.
In de latere dagen ga je redeneren en dingen doen en kom je erna achter dat dit eigenlijk "memoization" of "dijkstra" of wat dan ook is. Met voorkennis kun je dit altijd sneller aangezien er dan meteen een lampje gaat branden.
Hmmm, dan ben ik dat vak niet tegengekomen, tenzij het een vak in C was? Kan ook zijn dat het de scheikundige technologen waren die dat vak volgden? Die hebben net een ander curriculumGropah schreef op zondag 11 december 2022 @ 20:32:
[...]
Diezelfde
For context; degene die dat vak geeft is nogal fan van wiskunde bij opdrachten. Krijg je getallen die je makkelijk kan controleren. Maar hij weet niet helemaal wat het niveau van de middelbare school is. En vind niet dat een klein beetje extra wiskunde een probleem moet zijn.
Zelf in de richting theoretische chemie gegaan
Mwoah ja nee weet ik niet, Dijkstra kwam ik vorig jaar ook voor het eerst tegen idd. Toen liep ik ook helemaal vast qua redenaties totdat ik die hint kreeg.Thorwing schreef op zondag 11 december 2022 @ 20:39:
zelfs al kende je 'het trucje' niet, is het best logisch te redeneren. Het is alsof je gaat klagen dat je het Dijkstra algoritme niet kent bij een toekomstige opgave (wat zeker gaat komen). Dit bedoel ik niet lullig natuurlijk. Ik had er ook moeite mee vandaag aangezien ik het ook niet wist. Programmeer puzzles vragen nou eenmaal wat logisch inzicht waar we allemaal wat moeite mee hebben om 6 uur s'ochtends natuurlijk.
Met deze heb ik nog geprobeerd met de test van de aap aan de slag te gaan maar dat werkte niet. Deze oplossing had ik zo 123 niet direct bedacht