Advent of Code 2024 Vorige deel Overzicht

Pagina: 1 ... 6 ... 10 Laatste
Acties:

Acties:
  • +2 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-09 09:39

Janoz

Moderator Devschuur®

!litemod

KabouterSuper schreef op dinsdag 10 december 2024 @ 10:03:
Alleen om de tekstfile in te lezen, dijkstra, timings en om pypy aan te slingeren vanuit python. Voor grids heb ik nog nooit iets gebouwd.
Zo ben ik ook begonnen inderdaad, maar toch groeit het steeds verder. Meestal als ik iets 3x moet gebruiken verplaats ik het naar een generiek package. Ik heb dit jaar al behoorlijk vaak mijn Point class gebruikt. Deze heeft bijvoorbeeld een methode om zijn buren te streamen. Dit jaar is daar een Direction bij gekomen omdat niet alle functionaliteit in Point logisch was.

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!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 07:24
Zit voor de aardigheid te kijken of ik nog gebruik kan maken van de tailrec modfiier die Kotlin ondersteunt om de executie van tail recursion te optimaliseren, maar volgens mij wordt dat lastig omdat je feitelijk een 'fan out' in 4 richtingen doet in je tail die ik volgens mij niet makkelijk kan vervangen door 1 tail recursive call.

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • mbe81
  • Registratie: Juni 2008
  • Laatst online: 13-09 15:00
Oh, wat heb ik lopen kloten!

spoiler:
Ik dacht slim te zijn wilde met een loop door de mogelijke offsets heen lopen. Dus ik twee geneste for loops gemaakt van -1 tot +1 waarbij ik natuurlijk de 0,0 offset oversloeg. Na ruim anderhalf uur ploeteren bedenk ik me dat ik nu ook de diagonale offsets meeneem dus -1, -1 terwijl je alleen horizontaal of verticaal mag bewegen... Inmiddels deel 1 en 2 klaar. Nadat ik mijn fout had ontdekt was dat niet heel moeilijk meer.

Acties:
  • 0 Henk 'm!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 07:24
mbe81 schreef op dinsdag 10 december 2024 @ 11:04:
Oh, wat heb ik lopen kloten!

spoiler:
Ik dacht slim te zijn wilde met een loop door de mogelijke offsets heen lopen. Dus ik twee geneste for loops gemaakt van -1 tot +1 waarbij ik natuurlijk de 0,0 offset oversloeg. Na ruim anderhalf uur ploeteren bedenk ik me dat ik nu ook de diagonale offsets meeneem dus -1, -1 terwijl je alleen horizontaal of verticaal mag bewegen... Inmiddels deel 1 en 2 klaar. Nadat ik mijn fout had ontdekt was dat niet heel moeilijk meer.
Ja om deze reden heb ik een 'directions' enum geïntroduceerd die ook een cardinalDirections() functie heeft die een lijstje met enkel de horizontale en verticale directions teruggeeft omdat je in sommige puzzels wel en in andere puzzels weer niet diagonaal mag lopen.

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • HannoOttens
  • Registratie: September 2014
  • Laatst online: 22:51
Ik had vandaag dat mijn eerste idee voor part A de oplossing van part B was :D

Heb volgensmij wel een O(n) oplossing te pakken. Maar de oplossing kan niet meer dan 256 negens in de input aan. Draait in ongeveer 0.5ms zonder recursie.

Rust

[ Voor 17% gewijzigd door HannoOttens op 10-12-2024 12:01 . Reden: Duidelijkere uitleg ]


Acties:
  • 0 Henk 'm!

  • Satom
  • Registratie: Mei 2011
  • Laatst online: 13-09 18:19

Satom

Verzamel ervaringen

Gropah schreef op dinsdag 10 december 2024 @ 10:26:
[...]


Even snel een paste voor je gemaakt: *klik voor Kotlin code*. Let wel; het is verre van mooi of geoptimaliseerd.

spoiler:
InputReader bevat allerlei methods om data in te lezen. In dit geval een grid van chars en daar een map van een zelf gemaakt Point class naar een char. Die Point kent ook een fourNeighbors functie voor horizontale en verticale buren. Deque is een Double Edge que, gezien kotlin geen normale queue heeft. Denk dat de rest wel redelijk vanzelf sprekend is :) Mocht dat toch niet zo zijn, laat het weten (y)
Mooi of lelijk, het is voor mij perfect (en duidelijk) om eens in te verdiepen. Zou fijn zijn om voor eens en altijd af te zijn van de recursive fouten >:) (al is dat hoogstwaarschijnlijk wishful thinking)

Acties:
  • 0 Henk 'm!

  • Corniel
  • Registratie: April 2002
  • Laatst online: 31-03 14:56

Corniel

De wereld is gek!

Ik had antwoord van deel 2 ook al nadat ik deel 1 had (ik dacht, he, als ik dit nu eens skip, is dat eingelijk wel nodig). Enfin, een heerlijk kort stukje code (door alle plumbing van eerdere grid puzzles):

Dag 10.

while (me.Alive) {
me.KickAss();
}


Acties:
  • +1 Henk 'm!

  • Gropah
  • Registratie: December 2007
  • Niet online

Gropah

Admin Softe Goederen

Oompa-Loompa 💩

Satom schreef op dinsdag 10 december 2024 @ 11:20:
[...]
Mooi of lelijk, het is voor mij perfect (en duidelijk) om eens in te verdiepen. Zou fijn zijn om voor eens en altijd af te zijn van de recursive fouten >:) (al is dat hoogstwaarschijnlijk wishful thinking)
Alles wat recursief is kan in een while-lus. En als je je while-lus goed opzet lijkt het heel erg op je recursieve code ;)

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 12-09 19:26
Ok, ik had dus hetzelfde als de rest. Zo blijkt deel 1 eigenlijk ingewikkelder dan deel 2 wat mij betreft. Maar vandaag vond ik vrij saai, weinig mogelijkheden om wat slims te doen.

Het helpt ook dat mijn shared library in dit project het parsen e.d. van grids wel erg makkelijk maakt. Dat scheelt een hoop code.

[ Voor 37% gewijzigd door Marcj op 10-12-2024 12:02 ]


Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
Friits schreef op dinsdag 10 december 2024 @ 09:01:
Ik schrijf iedere keer "alles" opnieuw. Vind het leuk als iedere oplossing gewoon een zelfstandig werkend stukje code is, vooral ook zodat anderen (zowel hier als op Reddit) het zonder gedoe kunnen lezen en uitvoeren. Python is ook redelijk compact, dus heel tijd of ruimte win ik er niet mee.
Dat waardeer ik enorm. Ik probeer wel eens andermans oplossing te runnen om de performance te vergelijken of een bug te vinden, en het kost belachelijk veel tijd om uit te vinden:
  1. Hoe ik de boel kan builden (Maven? Cargo? go? sbt‽)
  2. Hoe ik de oplossing kan runnen (waar staan de binaries? java -classpath ...? etc.)
  3. Hoe ik een ander invoerbestand kan specificeren.
Een Python script dat gewoon van stdin leest en naar stdout print is daarbij een verademing.
Daarop voortbordurend, wat vind je hiervan? Geeft wat mij betreft de symmetrie tussen deel 1 en deel 2 mooier aan. (En is ook nog aanzienlijk sneller, al weet ik dat het je daar niet om te doen is.)

Acties:
  • 0 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 24-06 08:21
Mooi idd. Ik had eenzelfde idee gebruik voor een potje golf.

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 12-09 19:26
Soultaker schreef op dinsdag 10 december 2024 @ 08:18:
Qua extra data is er niet veel interessants te bedenken vandaag, maar voor wie toch wil testen, hier een iets groter invoerbestand: aoc-2024-day-10-challenge-1.zip

$ time pypy3 solve.py < aoc-2024-day-10-challenge-1.txt 
...036
...780

real    0m5.309s
user    0m5.177s
sys     0m0.084s
Deze kun je prima parallel draaien met rayon. Op mijn M1 Pro gaat dit best vlot :D

code:
1
2
3
4
5
Executing
 ├── Input parsed in 2,051µs
 ├── Part 1 calculated in 12,563µs: 152036
 ├── Part 2 calculated in 9,792µs: 8621780
 └── Total time: 24,431µs

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
Marcj schreef op dinsdag 10 december 2024 @ 12:00:
Ok, ik had dus hetzelfde als de rest. Zo blijkt deel 1 eigenlijk ingewikkelder dan deel 2 wat mij betreft.
Mee eens.

Sowieso lijkt het vaak zo omdat je voor deel 1 de basis moet leggen, waarbij je allerlei foutgevoelige problemen zoals invoer inlezen, de juiste data structuren kiezen, etc. moet oplossen. Als deel 2 dan een simpele variatie is op deel 1 (zoals op dag 7, bijvoorbeeld, waarbij je naast optellen en vermenigvuldigen ook nog concatenatie moest toevoegen als operator), dan is het verhoudingsgewijs weinig werk omdat je 90% van je code kunt hergebruiken.

Als ik naar mijn persoonlijke tijden kijk dan zie ik dat ik tot nu toe nooit significant meer tijd nodig heb gehad voor deel 2 dan voor deel 1, en regelmatig aanzienlijk minder:

	Totaaltijd	Duur deel 1	Duur deel 2	Relatief
1	00:02:56	00:01:57	00:00:59	50.43%
2	00:07:55	00:06:20	00:01:35	25.00%
3	00:08:02	00:05:21	00:02:41	50.16%
4	00:05:43	00:03:04	00:02:39	86.41%
5	00:10:23	00:05:05	00:05:18	104.26%
6	00:11:20	00:05:51	00:05:29	93.73%
7	00:05:57	00:04:45	00:01:12	25.26%
8	00:16:04	00:08:31	00:07:33	88.65%
9	00:18:41	00:09:11	00:09:30	103.45%
10	00:09:02	00:06:54	00:02:08	30.92%

Misschien verandert dat nog als de problemen later wat moeilijker worden (we zijn nog niet eens halverwege tenslotte).

Acties:
  • 0 Henk 'm!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 07:24
Ik had wel het idee dat vorig jaar deel 1 je wat vaker op het verkeerde been zette waardoor je uiteindelijk voor deel 2 de boel nog aardig op de kop moest zetten.

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-09 09:39

Janoz

Moderator Devschuur®

!litemod

Mugwump schreef op dinsdag 10 december 2024 @ 13:17:
Ik had wel het idee dat vorig jaar deel 1 je wat vaker op het verkeerde been zette waardoor je uiteindelijk voor deel 2 de boel nog aardig op de kop moest zetten.
Mwah, dat ben ik niet helemaal met je eens. Het is wel zo dat deel 1 vaak nog simpel/brute-force op te lossen is, terwijl eenzelfde benadering bij deel 2 tot extreem geheugengebruik of doorlooptijd leidt.

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!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 07:24
Janoz schreef op dinsdag 10 december 2024 @ 13:19:
[...]

Mwah, dat ben ik niet helemaal met je eens. Het is wel zo dat deel 1 vaak nog simpel/brute-force op te lossen is, terwijl eenzelfde benadering bij deel 2 tot extreem geheugengebruik of doorlooptijd leidt.
Ja dat is misschien een iets betere formulering en dat was dus vorig jaar in mijn beleving meer dan nu, maar ik begon vaak ook gewoon met de naïeve brute-force implementatie voor deel 1 en dan had je met deel 2 toch wel het meeste werk. :P

Ik doe AoC dan ook vooral om wat ervaring met een nieuwe taal op te doen, maar ook om m'n algoritmische kennis wat op te vijzelen, want in de praktijk doe ik daar gewoon te weinig mee.

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 12-09 19:26
Janoz schreef op dinsdag 10 december 2024 @ 13:19:
[...]

Mwah, dat ben ik niet helemaal met je eens. Het is wel zo dat deel 1 vaak nog simpel/brute-force op te lossen is, terwijl eenzelfde benadering bij deel 2 tot extreem geheugengebruik of doorlooptijd leidt.
Ik verwacht dat dat nog wel komt. Ook vorige jaren waren de eerste ~10 - 15 dagen vrij eenvoudig, maar wordt het daarna toch wel erg ingewikkeld.

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 12-09 19:26
Soultaker schreef op dinsdag 10 december 2024 @ 13:06:
[...]

...

Als ik naar mijn persoonlijke tijden kijk dan zie ik dat ik tot nu toe nooit significant meer tijd nodig heb gehad voor deel 2 dan voor deel 1, en regelmatig aanzienlijk minder:

...
Dat klopt bij mij ook wel. Al is vandaag met maar 11 seconden verschil wel extreem ;)

Maar de tijden zijn bij mij geen goed indicatie, omdat ik vaak niet direct om 6 uur 's ochtends hier tijd voor heb. Dan probeer ik het op het werk tussendoor te doen :X

Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
Janoz schreef op dinsdag 10 december 2024 @ 13:19:
Mwah, dat ben ik niet helemaal met je eens. Het is wel zo dat deel 1 vaak nog simpel/brute-force op te lossen is, terwijl eenzelfde benadering bij deel 2 tot extreem geheugengebruik of doorlooptijd leidt.
Dat had bij het probleem van vandaag ook best gekund. Bijvoorbeeld door wat nu deel 2 was als deel 1 te nemen (de meeste mensen leken het probleem zo toch al te interpreteren :P) en dan bij deel 2 zeggen dat je twee cijfers moet nemen om de hoogte te bepalen (dus "123456" is 1,2,3,4,5,6 in deel 1, en 12, 34, 56 in deel 2). Om alle paden van 00 tot 99 te vinden moet je dan iets slims doen zoals @Robbinb1993 in z'n oplossing doet.
Mugwump schreef op dinsdag 10 december 2024 @ 13:27:
Ik doe AoC dan ook vooral om wat ervaring met een nieuwe taal op te doen, maar ook om m'n algoritmische kennis wat op te vijzelen, want in de praktijk doe ik daar gewoon te weinig mee.
Als je een algoritmische uitdaging zoekt kun je m'n variant voor dag 2 proberen op te lossen. De code is best simpel (~10 regels in Python) als je eenmaal het juiste inzicht hebt.

Acties:
  • +1 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 02-08 07:54
Soultaker schreef op dinsdag 10 december 2024 @ 13:56:
[...]

Dat had bij het probleem van vandaag ook best gekund. Bijvoorbeeld door wat nu deel 2 was als deel 1 te nemen (de meeste mensen leken het probleem zo toch al te interpreteren :P) en dan bij deel 2 zeggen dat je twee cijfers moet nemen om de hoogte te bepalen (dus "123456" is 1,2,3,4,5,6 in deel 1, en 12, 34, 56 in deel 2). Om alle paden van 00 tot 99 te vinden moet je dan iets slims doen zoals @Robbinb1993 in z'n oplossing doet.


[...]

Als je een algoritmische uitdaging zoekt kun je m'n variant voor dag 2 proberen op te lossen. De code is best simpel (~10 regels in Python) als je eenmaal het juiste inzicht hebt.
Mooie uitdaging. Heb hem zojuist opgelost: https://github.com/Robbin...ain/day02/day2-variant.cc. Draait de test case in 49ms op mijn PC.

Acties:
  • 0 Henk 'm!

  • TrailBlazer
  • Registratie: Oktober 2000
  • Laatst online: 10-09 18:35

TrailBlazer

Karnemelk FTW

het zal wel heel stom zijn maar ik heb deel 1 opgelost met dijkstra. Alleen een recursive oplossing voor twee kom ik weer niet uit. Ik snap nooit hoe die werken :( Iemand een leesbaar recursive voorbeeld in Python?

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44

Acties:
  • 0 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 02-08 07:54
TrailBlazer schreef op dinsdag 10 december 2024 @ 17:49:
het zal wel heel stom zijn maar ik heb deel 1 opgelost met dijkstra. Alleen een recursive oplossing voor twee kom ik weer niet uit. Ik snap nooit hoe die werken :( Iemand een leesbaar recursive voorbeeld in Python?
spoiler:
Hoe ik het heb opgelost: Bereken per cell het aantal mogelijke paden vanaf die cell dat oplopend is met stappen van één en eindigt bij een 9. Bereken eerst alle paden vanaf 9, dan 8, dan 7, etcetera. Voor alle 9's is dit natuurlijk 1 (begint en eindigt daar). Voor elke 8 is dit het aantal directe orthogonale buren dat een 9 is. Voor 7 is het de som van het aantal mogelijke paden van de orthogonale buren die 8 zijn. Ga zo door tot en met 0. Dit wordt ook wel dynamisch programmeren genoemd, want we maken gebruik van resultaten van een subprobleem (het aantal paden beginnend met een hoger nummer in dit geval), om het grotere probleem op te lossen. Op deze manier kan je het ook iteratief oplossen, maar zelf heb ik het recursief gedaan (ook wel top-down DP genoemd), omdat ik dat juist makkelijker vind tegenwoordig. Iteratief is vaak wel iets sneller vanwege minder function calls. En recursief kan ook stack overflow problemen geven als je te diep gaat. Dit is O(N * M), omdat je alle cellen één keer moet doorlopen en per cel de 4 buren bekijkt.


In python ziet het er dan zo uit:

Python:
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
30
31
32
33
34
35
from functools import lru_cache

grid = [
    "89010123",
    "78121874",
    "87430965",
    "96549874",
    "45678903",
    "32019012",
    "01329801",
    "10456732"
]

N, M = len(grid), len(grid[0])

DX = [-1, 1, 0, 0]
DY = [0, 0, -1, 1]

@lru_cache(None)
def solve(x, y):
    if grid[x][y] == '9':  # Base case
        return 1

    total_paths = 0
    for dx, dy in zip(DX, DY):  # Check all 4 directions
        nx, ny = x + dx, y + dy
        if 0 <= nx < N and 0 <= ny < M and int(grid[nx][ny]) == int(grid[x][y]) + 1:
            total_paths += solve(nx, ny)

    return total_paths

# Compute total paths for cells starting with '0'
ans_part2 = sum(solve(i, j) for i in range(N) for j in range(M) if grid[i][j] == '0')

print("Total paths starting with '0':", ans_part2)


Het kan waarschijnlijk wel compacter in Python maar ik schrijf zelf weinig Python.

[ Voor 41% gewijzigd door Robbinb1993 op 10-12-2024 19:04 ]


Acties:
  • +2 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 24-06 08:21
Robbinb1993 schreef op dinsdag 10 december 2024 @ 18:01:
Het kan waarschijnlijk wel compacter in Python maar ik schrijf zelf weinig Python.
U riep? :+

e=enumerate;H={i+j*1j:c for i,r in e(open(0))for j,c in e(r)};V=[(v,v)for v in H if H[v]=='0'];[V:=[(s,v+n)for s,v in V for n in(-1j,1j,-1,1)if H.get(v+n)==h]for h in '123456789'];print(len({*V}),len(V))

Verder verveelde ik me dus heb ik deel 2 van vandaag ook even geïmplementeerd m.b.v. SciPy's convolve2d(). Even een kleine vingeroefening voordat we weer Game of Life-achtige puzzels krijgen. Voor wie benieuwd is, de code is prima leesbaar en staat hier.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op dinsdag 10 december 2024 @ 08:18:
Qua extra data is er niet veel interessants te bedenken vandaag, maar voor wie toch wil testen, hier een iets groter invoerbestand: aoc-2024-day-10-challenge-1.zip

$ time pypy3 solve.py < aoc-2024-day-10-challenge-1.txt 
...036
...780

real    0m5.309s
user    0m5.177s
sys     0m0.084s
Zoals gewoonlijk komt er bij mij weer een heel ander antwoord uit (bij deel 2) 8)7.

Wat krijgen jullie bij:
0123456789
1234567898
2345678987
3456789876
4567898765
5678987654
6789876543
7898765432
8987654321
9876543210


ik 20 en 1024.

.edit: oh jezus, ik deed offset = y * height + x, en de challenge input is niet vierkant 8)7

[ Voor 6% gewijzigd door .oisyn op 11-12-2024 01:15 ]

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!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 12-09 19:26
.oisyn schreef op woensdag 11 december 2024 @ 00:08:
[...]
.edit: oh jezus, ik deed offset = y * height + x, en de challenge input is niet vierkant 8)7
En daarom hergebruik in een Grid type. Dat soort fouten heb ik al veel te vaak gemaakt.

Acties:
  • +1 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 12-09 19:26
Ik was bang dat vandaag een moeilijke zou worden en dat deel 2 echt ondoenelijk groot zou worden en we in de wiskunde moesten duiken. Maar uiteindelijk valt het mee met een standaard puzzel techniek:

spoiler:
memoization


Vandaag voor het eerst op tijd op, dus ben gewoon nr 1589 voor deel 2 in de wereld :D

Acties:
  • +1 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 02-08 07:54
Marcj schreef op woensdag 11 december 2024 @ 06:33:
Ik was bang dat vandaag een moeilijke zou worden en dat deel 2 echt ondoenelijk groot zou worden en we in de wiskunde moesten duiken. Maar uiteindelijk valt het mee met een standaard puzzel techniek:

spoiler:
memoization


Vandaag voor het eerst op tijd op, dus ben gewoon nr 1589 voor deel 2 in de wereld :D
spoiler:
Ik memorize/cache alleen de lage values en daarmee los ik part 2 in 2 ms op.

Acties:
  • +3 Henk 'm!

  • Hagdos
  • Registratie: April 2022
  • Laatst online: 07:59
Marcj schreef op woensdag 11 december 2024 @ 06:33:
Ik was bang dat vandaag een moeilijke zou worden en dat deel 2 echt ondoenelijk groot zou worden en we in de wiskunde moesten duiken. Maar uiteindelijk valt het mee met een standaard puzzel techniek:

spoiler:
memoization


Vandaag voor het eerst op tijd op, dus ben gewoon nr 1589 voor deel 2 in de wereld :D
Same here, rank 2321 want ik was wat aan het klooien met Python

spoiler:
Ik heb geen memoization gebruikt, maar wel een dict ipv een list. De volgorde van de stenen boeit me niet, dus als ik 1000 0-en heb opgeslagen reken ik die maar 1 keer uit, maar wel voor elke stap opnieuw.

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 12-09 19:26
Robbinb1993 schreef op woensdag 11 december 2024 @ 06:44:
[...]


spoiler:
Ik memorize/cache alleen de lage values en daarmee los ik part 2 in 2 ms op.
spoiler:
Dat is wel een slimme oplossing, niet aan gedacht. Wat voor limiet werkt bij jou goed dan? Bij mij lijkt 1000 ofzo het snelste te gaan.


Trouwens, die techniek is wel erg afhankelijk van de input. Ik heb voor de grap een grote input gemaakt: day11-big.txt

Zonder aanpassingen (wel 128 bits nodig) krijg ik dit:

code:
1
2
3
4
5
Executing
 ├── Input parsed in 31,199µs
 ├── Part 1 calculated in 356,364µs: ...10116
 ├── Part 2 calculated in 322,397µs: ...09224
 └── Total time: 710,035µs

[ Voor 38% gewijzigd door Marcj op 11-12-2024 07:29 ]


Acties:
  • +2 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 24-06 08:21
* Friits begon wat laat omdat de koffie op was. Nieuw pak te snel geopend, overal koffiepoeder...
Op deze manier haal @Soultaker en @Thorwing zeker niet in op het GoT leaderboard ;)

Maar goed, gelukkig kon ik vandaag weer redelijk nette code schrijven en mijn "fans" op Reddit tevreden houden. :)

Acties:
  • 0 Henk 'm!

  • bakkerjangert
  • Registratie: Februari 2012
  • Laatst online: 13-09 19:44
Hagdos schreef op woensdag 11 december 2024 @ 06:46:
[...]


Same here, rank 2321 want ik was wat aan het klooien met Python

spoiler:
Ik heb geen memoization gebruikt, maar wel een dict ipv een list. De volgorde van de stenen boeit me niet, dus als ik 1000 0-en heb opgeslagen reken ik die maar 1 keer uit, maar wel voor elke stap opnieuw.
Exact de methode die ik ook had toegepast voor deel 2 in python. Ik had deel 1 wel gewoon brute force met lists gedaan omdat ik vermoedde bij deel 2 iets met volgordes of iets dergelijks te moeten gaan doen.

Acties:
  • 0 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 13-09 11:27

FCA

Hmmm, vandaag ging niet soepel, terwijl dit probleem toch eerder is langsgekomen
spoiler:
deel 1 echt brute force, deel 2 met een hashmap die bijhoud hoeveel er van elk getal op dit moment in de lijst staan. Alles u128, maar dat is volgens mij niet eens nodig.


Best wel zitten frotten om deel 1 correct te programmeren (ik kan blijkbaar niet zomaar een element van een vector pakken en die als variabele gebruiken, als dat element geen Clone implementeert in Rust :? , zelfs niet als ik expliciet clone aanroep)
En natuurlijk moet je niet, als je eerst de lengte van een getal goed hebt berekend, delen door de lengte, maar splitsen op de (helft!) van de lengte :X
De kerstborrel van gisteren was niet bevorderlijk voor de denkkracht in de morgen zullen we maar zeggen.

Ah, gevonden: hier deed het me erg aan denken.

[ Voor 7% gewijzigd door FCA op 11-12-2024 07:57 ]

Verandert z'n sig te weinig.


Acties:
  • +1 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 24-06 08:21
bakkerjangert schreef op woensdag 11 december 2024 @ 07:44:
Exact de methode die ik ook had toegepast voor deel 2 in python.
Mag ik je wijzen op defaultdict en Counter uit Pythons collections module? Bij defaultdict kan je een functie meegeven die wordt uitgevoerd wanneer een key niet bestaat, zodat je niet overal "if x not in stones" hoeft te schrijven.

Counter-objecten werken ongeveer hetzelfde, maar hebben al 0 als default-waarde, en ook een redelijk elegante manier om ze te initialiseren. Voorbeeldje

Acties:
  • 0 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 02-08 07:54
Marcj schreef op woensdag 11 december 2024 @ 07:24:
[...]

spoiler:
Dat is wel een slimme oplossing, niet aan gedacht. Wat voor limiet werkt bij jou goed dan? Bij mij lijkt 1000 ofzo het snelste te gaan.


Trouwens, die techniek is wel erg afhankelijk van de input. Ik heb voor de grap een grote input gemaakt: day11-big.txt

Zonder aanpassingen (wel 128 bits nodig) krijg ik dit:

code:
1
2
3
4
5
Executing
 ├── Input parsed in 31,199µs
 ├── Part 1 calculated in 356,364µs: ...10116
 ├── Part 2 calculated in 322,397µs: ...09224
 └── Total time: 710,035µs
Ik kwam inderdaad ook op 1000 (of 999, max. 3 digits value) uit als optimaal. Waarden met een even aantal digits worden al opgesplitst in kleinere values, dus er valt in de range [1000, 9999] denk ik weinig extra winst te boeken t.o.v. extra geheugengebruik. Op jouw testcase haal ik 446 ms: https://github.com/Robbin...ain/day11/day11_int128.cc. Ben benieuwd of er nog een andere optimalisatie mogelijk is.

Het maximum aantal steps lijkt ook weinig invloed te hebben op de tijd. Als ik het bijvoorbeeld ophoog naar 200 stappen voor part 2, dan blijft de runtime ongeveer hetzelfde.

Edit: Met precomputation van het aantal digits van values (ook tot een limiet) en machten van 10, kunnen we het proces van het splitsen van getallen met even aantal cijfers nog iets versnellen. Nu is de runtime 321ms.

Een oplossing waarbij alles in een hash map (unordered_map) wordt gecached doet er 4366 ms over bij mij voor de grote input: https://github.com/Robbin...day11/day11_int128_map.cc. Dus dat is wel significant langzamer.

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


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Marcj schreef op woensdag 11 december 2024 @ 06:30:
[...]


En daarom hergebruik in een Grid type. Dat soort fouten heb ik al veel te vaak gemaakt.
Mijn grid is read-only view op een slice, dus dat kon niet :/

[ Voor 3% gewijzigd door .oisyn op 11-12-2024 09:04 ]

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!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
Robbinb1993 schreef op woensdag 11 december 2024 @ 08:05:
Het maximum aantal steps lijkt ook weinig invloed te hebben op de tijd. Als ik het bijvoorbeeld ophoog naar 200 stappen voor part 2, dan blijft de runtime ongeveer hetzelfde.
Dat hangt ook af van de invoer. Neem bijvoorbeeld deze: loopy-numbers-1.txt. Volgens mij groeit de oplossingstijd ongeveer lineair met het aantal iteraties dat je uitvoert.

Acties:
  • 0 Henk 'm!

  • Remcoder
  • Registratie: November 2004
  • Laatst online: 11-09 15:20
Soultaker schreef op woensdag 11 december 2024 @ 09:35:
[...]

Dat hangt ook af van de invoer. Neem bijvoorbeeld deze: loopy-numbers-1.txt. Volgens mij groeit de oplossingstijd ongeveer lineair met het aantal iteraties dat je uitvoert.
119 ms tegenover 81 ms voor de echte input, dus dat valt nog reuze mee hoe het groeit.

spoiler:
85351868484553823


https://github.com/remcos...r/adventofcode/Day11.java

Acties:
  • 0 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 02-08 07:54
Soultaker schreef op woensdag 11 december 2024 @ 09:35:
[...]

Dat hangt ook af van de invoer. Neem bijvoorbeeld deze: loopy-numbers-1.txt. Volgens mij groeit de oplossingstijd ongeveer lineair met het aantal iteraties dat je uitvoert.
Inderdaad, als ik het aantal stappen verdubbel, verdubbelt de executietijd ook ongeveer voor deze test case.

1000 steps: 378ms.
2000 steps: 754ms.
4000 steps: 1484ms.

In dit geval is het verschil tussen de oplossing die alleen lage values cached en de oplossing die alles cached in een map ook kleiner. De map oplossing doet er voor 2000 steps 1277ms over.

[ Voor 17% gewijzigd door Robbinb1993 op 11-12-2024 09:53 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zucht. Er gaat iets mis in deel 2, maar ik weet niet wat. Heeft iemand zijn input en zijn antwoorden voor me zodat ik kan checken?

.edit: of, alternatief, wat is het antwoord van het voorbeeld van 125 17 voor 75 stappen?

.edit: argh jezus, ik zat het antwoord van het voorbeeld in te voeren ipv die van de daadwerkelijke puzzel input |:(
FCA schreef op woensdag 11 december 2024 @ 07:49:
Best wel zitten frotten om deel 1 correct te programmeren (ik kan blijkbaar niet zomaar een element van een vector pakken en die als variabele gebruiken, als dat element geen Clone implementeert in Rust :? , zelfs niet als ik expliciet clone aanroep)
Wat bedoel je precies? Heb je een stukje code?

[ Voor 16% gewijzigd door .oisyn op 11-12-2024 11:55 ]

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!

  • Satom
  • Registratie: Mei 2011
  • Laatst online: 13-09 18:19

Satom

Verzamel ervaringen

Dag 11 ook weer klaar, in eerste instantie had ik vanochtend een oplossing die enorm veel geheugen gebruikte O-) Maar al vrij snel bedacht ik mij dat deze enorm veel lijkt op de oplossing van dag 6, 2021, dus de boel omgeschreven en nu is het zo veel sneller! +- 15 msec voor deel 1 en +- 20 msec voor deel 2 :-)

Acties:
  • +1 Henk 'm!

  • mbe81
  • Registratie: Juni 2008
  • Laatst online: 13-09 15:00
Satom schreef op woensdag 11 december 2024 @ 12:16:
Dag 11 ook weer klaar, in eerste instantie had ik vanochtend een oplossing die enorm veel geheugen gebruikte O-)
Hier had ik ook last van; mijn proces zat op 180 GB memory usage voordat deze werd afgebroken en ik had toen nog geen antwoord... De tips hierboven hebben mij dus ook aardig geholpen ;)

Acties:
  • 0 Henk 'm!

  • HannoOttens
  • Registratie: September 2014
  • Laatst online: 22:51
Zag de bui al hangen vandaag, dus meteen maar een oplossing gemaakt die voor beide parts zou werken!
Draait in ongeveer 1ms :D

Rust

Acties:
  • 0 Henk 'm!

  • Gropah
  • Registratie: December 2007
  • Niet online

Gropah

Admin Softe Goederen

Oompa-Loompa 💩

Ik was zeker niet slim genoeg om dit meteen door te hebben. En toen ik de lengte van de input zag had ik meteen al wel door dat er iets exploderends in zou zitten.

spoiler:
Maar het omschrijven van BFS naar DFS en resultaten cachen was redelijk triviaal. Ik was meer tijd kwijt aan het herschrijven van moeilijk eigen datastructuurtje die ik had opgezet omdat ik iets anders voor deel 2 verwachtte naar longs :P

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

HannoOttens schreef op woensdag 11 december 2024 @ 15:02:
Zag de bui al hangen vandaag, dus meteen maar een oplossing gemaakt die voor beide parts zou werken!
Draait in ongeveer 1ms :D

Rust
Heh, jouw blink() is ongeveer exact dezelfde als mijn num_stones_from_number() :P

Nog een microoptimization, als je `if let Some(v) = mem.get(...) doet kun je in 1 keer testen of het elemement aanwezig is en die ophalen. Nu zit je effectief 2x te hashen en de lookup te doen.

1ms vind ik wel apart, ik doe er 12ms over. En dan deel ik de hashmap van deel 1 ook nog eens met die van deel 2.

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!

  • HannoOttens
  • Registratie: September 2014
  • Laatst online: 22:51
.oisyn schreef op woensdag 11 december 2024 @ 15:28:
[...]


Heh, jouw blink() is ongeveer exact dezelfde als mijn num_stones_from_number() :P

Nog een microoptimization, als je `if let Some(v) = mem.get(...) doet kun je in 1 keer testen of het elemement aanwezig is en die ophalen. Nu zit je effectief 2x te hashen en de lookup te doen.

1ms vind ik wel apart, ik doe er 12ms over. En dan deel ik de hashmap van deel 1 ook nog eens met die van deel 2.
Goed idee!
Ik zat trouwens eerst ook rond de 12ms, tot ik de types in mijn hashmap aanpaste naar van een u64 naar een u32 :D

Acties:
  • +1 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

@HannoOttens Oh wow, maakt dat zoveel uit? :X Ik was bang dat het getal op een steen boven de u32 uit zou komen, maar blijkbaar dus niet :)
.edit: dat is in mijn geval ook zo. Bij jou niet?

[ Voor 15% gewijzigd door .oisyn op 11-12-2024 15:40 ]

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!

  • HannoOttens
  • Registratie: September 2014
  • Laatst online: 22:51
@.oisyn Heb ik blijkbaar geluk mee gehad! :D Heb mijn sterren in ieder geval binnen.

Ik had trouwens ook een langere duration toen ik een te grote ::with_capacity deed bij mijn hashmap. Mogelijk maakt dat ook nog verschil?

[ Voor 45% gewijzigd door HannoOttens op 11-12-2024 15:45 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

HannoOttens schreef op woensdag 11 december 2024 @ 15:43:
Ik had trouwens ook een langere duration toen ik een te grote ::with_capacity deed bij mijn hashmap. Mogelijk maakt dat ook nog verschil?
De mijne had ongeveer 121k entries nodig. Als ik 'm iets groter dan dat zet heb ik een sweet spot wat tijd betreft. Veel groter maakt dat de tijd behoorlijk toeneemt idd.

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!

  • HannoOttens
  • Registratie: September 2014
  • Laatst online: 22:51
@.oisyn Wow, 121k is denk ik ook het tienvoudige van wat ik met mijn input had! Volgensmij eindigde de map bij mij met een capacity van ~15k.

Acties:
  • +1 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Damn. Als ik 'm laat beginnen met een capacity van 1 dan eindigt ie met een cap van 229.376 8)7.

Als ik 'm meteen init met die cap dan kom ik op 11ms :P

.edit: cap blijft hetzelfde als ik part1 en part2 hun eigen map geef.

[ Voor 51% gewijzigd door .oisyn op 11-12-2024 16:38 ]

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!

  • Satom
  • Registratie: Mei 2011
  • Laatst online: 13-09 18:19

Satom

Verzamel ervaringen

mbe81 schreef op woensdag 11 december 2024 @ 14:30:
[...]


Hier had ik ook last van; mijn proces zat op 180 GB memory usage voordat deze werd afgebroken en ik had toen nog geen antwoord... De tips hierboven hebben mij dus ook aardig geholpen ;)
Wauw.. ik heb nog heel even zitten twijfelen of ik mijn andere machine erbij zou pakken, die 64GB heeft. Die kon mijn oude oplossing van dag 6, 2021 wel oplossen na flink wat minuten en +- 50GB :+ Maar aan jou opmerking te zien, was dat niet de moeite waard geweest!

Acties:
  • 0 Henk 'm!

  • KabouterSuper
  • Registratie: September 2005
  • Niet online
mbe81 schreef op woensdag 11 december 2024 @ 14:30:
[...]


Hier had ik ook last van; mijn proces zat op 180 GB memory usage voordat deze werd afgebroken en ik had toen nog geen antwoord... De tips hierboven hebben mij dus ook aardig geholpen ;)
180GB? Dat is bijna valsspelen :) . Ik werk op 8GB waarvan er ongeveer 3GB beschikbaar is voor python.

When life gives you lemons, start a battery factory


Acties:
  • +1 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-09 09:39

Janoz

Moderator Devschuur®

!litemod

KabouterSuper schreef op woensdag 11 december 2024 @ 18:19:
[...]

180GB? Dat is bijna valsspelen :) . Ik werk op 8GB waarvan er ongeveer 3GB beschikbaar is voor python.
Draai jij je oplossingen op je telefoon of zo? :+

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: 02:44
Satom schreef op woensdag 11 december 2024 @ 17:36:
Wauw.. ik heb nog heel even zitten twijfelen of ik mijn andere machine erbij zou pakken, die 64GB heeft.
Dit is ook wel een leermomentje. De meeste Advent of Code problemen hebben echt niet zo'n dikke bak nodig, dus de kans is groot dat je op het verkeerde spoor zit. Natuurlijk kan het soms werken om er meer geheugen tegenaan te gooien (net zoals het bij sommige brute force oplossingen werkt om een paar minuten langer te wachten), maar het is beter om even een stap terug te doen en te proberen te beredeneren of je überhaupt in de buurt van een werkbare oplossing bent.

Bij dit probleem is het bijvoorbeeld makkelijk en behulpzaam om te debug-printen hoeveel elementen je hebt na X stappen. Bijvoorbeeld elke 5 stappen, voor de voorbeeldinvoer:

 5:          13
10:         109
15:         853
20:        6837
25:       55312
30:      445882
35:     3604697
40:    29115525
45:   235189097
50:  1900433601
55: 15358013692


Dan observeer je:

1. Na 50 stappen zit je op bijna 2 miljard elementen (met 4 bytes/element ~4 GB RAM).
2. Elke vijf stappen wordt de lijst ongeveer 8 keer zo groot.

Conclusie: om van 50 naar 75 te komen heb je ongeveer 825/5 = 85 = 215 = 32768 keer zoveel geheugen nodig als bij stap 50. Tenzij je een machine met meer dan 250 terabyte geheugen hebt is het zinloos om op deze manier door te gaan.

Acties:
  • 0 Henk 'm!

  • mbe81
  • Registratie: Juni 2008
  • Laatst online: 13-09 15:00
KabouterSuper schreef op woensdag 11 december 2024 @ 18:19:
[...]

180GB? Dat is bijna valsspelen :) . Ik werk op 8GB waarvan er ongeveer 3GB beschikbaar is voor python.
Haha, ik heb 48 GB geheugen dus er werd al flink geswapped.

Acties:
  • 0 Henk 'm!

  • mbe81
  • Registratie: Juni 2008
  • Laatst online: 13-09 15:00
Soultaker schreef op woensdag 11 december 2024 @ 19:02:
Bij dit probleem is het bijvoorbeeld makkelijk en behulpzaam om te debug-printen hoeveel elementen je hebt na X stappen.
Die output had ik ook geprint inderdaad. Ik zag al dat het kansloos was om zo verder te gaan maar wist op dat moment niet echt een andere oplossing.

In eerste instantie had ik verwacht dat recursie ook niet zo werken met zulke aantallen daar ik in het verleden wel eens stack overflows krijg als ik een fout had in mijn code en dus enorm veel functiecalls deed. Maar blijkbaar is dat in dit geval geen probleem.

Samen met de suggestie van memoization is het als de brandweer!

[ Voor 39% gewijzigd door mbe81 op 11-12-2024 19:14 ]


Acties:
  • +1 Henk 'm!

  • KabouterSuper
  • Registratie: September 2005
  • Niet online
Janoz schreef op woensdag 11 december 2024 @ 18:53:
[...]
Draai jij je oplossingen op je telefoon of zo? :+
Haha, dat zou wel sneller zijn waarschijnlijk. Ik heb een sony vaio uit 2012 die maar niet kapot wil gaan (hoewel ik wel last krijg van loslatende toetsen) . En ik heb nog een reserve vaio voor extra onderdelen, dus ik ga nog wel een paar jaar vooruit kunnen met mijn laptop. Ach, dan maar geen draaitijden in micro- of nanoseconden.

When life gives you lemons, start a battery factory


Acties:
  • 0 Henk 'm!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 07:24
Deel 1 vanochtend gedaan, maar zoals verwacht was deel 2 niet te brute forcen en ik had maar 10 min voor AoC vandaag ofzo.
Dus net maar even deel twee gedaan. Dacht eerst nog aan memoization, maar simpelweg de counts voor elke waarde bijhouden in plaats van elke individuele waarde was al voldoende om het snel te doen. Nog wel wat lopen kloten met ints en longs, maar dat hoort erbij. :P

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik zie nog wel ruimte voor betere implementaties.

spoiler:
Het ding met memoization is dat je alsnog heel veel werk dubbel doet. Als je voor een resultaat hebt voor een steen met waarde 6 met nog 10 stappen over, en je komt weer een 6 tegen maar dan met 11 stappen over, dan doe je dus al die 10 stappen opnieuw. Maar als je die 10 stappen wilt gebruiken om vervolgens 1 verder te gaan, dan moet je dus ook alle resultaten gaan opslaan, en gezien de grootte van het antwoord wordt dat ondoenlijk.

Ik heb misschien wel een idee waardoor het toch kan, maar dat moet ik nog even uitwerken.
Mugwump schreef op woensdag 11 december 2024 @ 19:50:
Nog wel wat lopen kloten met ints en longs, maar dat hoort erbij. :P
Blijkbaar maakt het ook nogal uit wat je puzzel input je hebt. @HannoOttens heeft aan 32 bits genoeg met zijn
input :P

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!

  • Satom
  • Registratie: Mei 2011
  • Laatst online: 13-09 18:19

Satom

Verzamel ervaringen

Soultaker schreef op woensdag 11 december 2024 @ 19:02:
[...]

Dit is ook wel een leermomentje. De meeste Advent of Code problemen hebben echt niet zo'n dikke bak nodig, dus de kans is groot dat je op het verkeerde spoor zit. Natuurlijk kan het soms werken om er meer geheugen tegenaan te gooien (net zoals het bij sommige brute force oplossingen werkt om een paar minuten langer te wachten), maar het is beter om even een stap terug te doen en te proberen te beredeneren of je überhaupt in de buurt van een werkbare oplossing bent.

Bij dit probleem is het bijvoorbeeld makkelijk en behulpzaam om te debug-printen hoeveel elementen je hebt na X stappen. Bijvoorbeeld elke 5 stappen, voor de voorbeeldinvoer:

 5:          13
10:         109
15:         853
20:        6837
25:       55312
30:      445882
35:     3604697
40:    29115525
45:   235189097
50:  1900433601
55: 15358013692


Dan observeer je:

1. Na 50 stappen zit je op bijna 2 miljard elementen (met 4 bytes/element ~4 GB RAM).
2. Elke vijf stappen wordt de lijst ongeveer 8 keer zo groot.

Conclusie: om van 50 naar 75 te komen heb je ongeveer 825/5 = 85 = 215 = 32768 keer zoveel geheugen nodig als bij stap 50. Tenzij je een machine met meer dan 250 terabyte geheugen hebt is het zinloos om op deze manier door te gaan.
Helemaal mee eens, daarom begin ik ook altijd met wat debug lijntjes (en de example input). Toen ik eenmaal bij dag 40 was aangekomen, had ik al weer door dat dit niet ging werken. Dat was het moment dat ik mij dag 6 van 2021 herinnerde!

Acties:
  • 0 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 13-09 11:27

FCA

OK, ik ben nog even los gegaan met verschillende implementaties.

spoiler:
Ik heb 3 implementaties naast elkaar nu:

1. Eentje waarbij ik een HashMap maak en die iteratief update (zodat elke iteratie er voor elk uniek getal er maar 1 update is)
2. De recursief + memoizatie optie, uitgebreid besproken hierboven
3. Een hybride van de 2 hierboven: doe eerst 3 stappen recursief + memoization, maar geef geen totaal terug maar een HashMap van de oplossingsvector, en doe dat 25 keer. Je kunt de cache nu vaker herbruiken. De opsplitsing in 25x3 is empirisch bepaald: je hebt makkelijke opties voor 1x75 3x25, 5x15, 15x5 en 25x3, en 75x1, en dit was de snelste optie. (75x1 is natuurlijk een suboptimale implementatie van de hashmap implementatie, en 1x75 een suboptimale implementatie van de recursieve implementatie)

Interessant genoeg heb ik voor deel 1 de volgende ordening in termen van snelheid:

rec > map > hybrid (recursive is dus de snelste)
En voor deel 2:
map > hybrid > rec (de map is dus de snelste)

En als ik naar 125 iteraties ga (25x5):
hybrid > map > rec (hybride is het snelste)

Ik heb nog even zitten denken over een meer analytische oplossing, met cycles e.d. op basis van dit soort redeneringen, maar ik kan nu even niet de energie voor opbrengen.

Verandert z'n sig te weinig.


Acties:
  • 0 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 13-09 11:27

FCA

.oisyn schreef op woensdag 11 december 2024 @ 11:42:
Zucht. Er gaat iets mis in deel 2, maar ik weet niet wat. Heeft iemand zijn input en zijn antwoorden voor me zodat ik kan checken?

.edit: of, alternatief, wat is het antwoord van het voorbeeld van 125 17 voor 75 stappen?

.edit: argh jezus, ik zat het antwoord van het voorbeeld in te voeren ipv die van de daadwerkelijke puzzel input |:(


[...]

Wat bedoel je precies? Heb je een stukje code?
Ik kan het niet reproduceren nu (waarschijnlijk deed ik iets anders doms fout met m'n brakke hoofd van vanochtend. Het probleem leek in ieder geval dat
code:
1
2
3
4
5
fn main() {
    let x = vec![vec![0], vec![1]];
    let y = x[0];
    println!("{:?}", y);
}

niet werkt:
code:
1
2
3
3 |     let y = x[0];
  |             ^^^^ move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
  |

maar de suggestie:
code:
1
2
3
4
5
fn main() {
    let x = vec![vec![0], vec![1]];
    let y = x[0].clone();
    println!("{:?}", y);
}

ook vanochtend niet leek te werken, maar nu wel :|

Verandert z'n sig te weinig.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
.oisyn schreef op woensdag 11 december 2024 @ 19:59:
Ik zie nog wel ruimte voor betere implementaties.
Ik had ook wel wat ideetjes maar niets dat praktisch tot betere performance leidde.

Bijvoorbeeld, lineaire algebra:

spoiler:
Je kunt het probleem modelleren als een sparse binaire transitie-matrix waarbij elke kolom maximaal twee enen bevat, en dan kun je k iteraties berekenen in O(n^3 log k) tijd of nog iets minder als je voor sparseness optimaliseert. Het probleem is alleen dat de matrix heel groot is en de exponent (k=75) relatief klein, dus dit is netto veel trager. Deze aanpak zou handig zijn als de set van getallen klein is en het aantal iteraties groot, maar bij dit probleem is het precies andersom.


Ook heb ik geprobeerd het te modelleren als graafprobleem:

spoiler:
Als je de getallen op stenen ziet als vertices, en de transities als edges, dan kun je in theorie iets doen als de graaf ontleden in strongly connected components, dan elke component afzonderlijk simuleren. Maar het probleem is dat de componenten van de graaf nog steeds erg groot zijn.

Bijvoorbeeld als je begint bij 100, dan krijg je een graaf met 1 component met 54 vertices waaronder 0 en 1, 1 component met 1709 vertices, en 2052 componenten met 1 vertex. Het probleem is dus dat het grootste component nog steeds vrij groot is, waardoor de decompositie weinig winst oplevert.


tl;dr: Geen van mijn ideeën leidt tot een aanpak die maar in de buurt komt van de andere opties.
Ik heb misschien wel een idee waardoor het toch kan, maar dat moet ik nog even uitwerken.
Als je iets ontdekt dat significant sneller is dan de memoization-aanpak lijkt me dat zeer interessant!
Blijkbaar maakt het ook nogal uit wat je puzzel input je hebt. @HannoOttens heeft aan 32 bits genoeg met zijn input :P
Hm, dat is wel heel bijzonder! Volgens mij kom je met alleen “100” als invoer al een steen met 409.526.509.568 tegen, wat ruim buiten het bereik van een 32-bits integer is. Is de invoerdata echt zo zwak? Of gaat het toevallig goed? @HannoOttens kun je eens testen wat jouw oplossing doet met 100 als invoer? (Correct antwoord voor deel 2, dus met 75 iteraties, is 15669924873442.)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

@FCA Maar typisch wil je dat niet, dat maakt een kopie van de hele vector. Je kunt wel een element borrowen, maar als het een mutable borrow is dan kun je verder niet meer lezen (of schrijven) van/naar de vector.

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!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 07:24
.oisyn schreef op woensdag 11 december 2024 @ 19:59:
Ik zie nog wel ruimte voor betere implementaties.

spoiler:
Het ding met memoization is dat je alsnog heel veel werk dubbel doet. Als je voor een resultaat hebt voor een steen met waarde 6 met nog 10 stappen over, en je komt weer een 6 tegen maar dan met 11 stappen over, dan doe je dus al die 10 stappen opnieuw. Maar als je die 10 stappen wilt gebruiken om vervolgens 1 verder te gaan, dan moet je dus ook alle resultaten gaan opslaan, en gezien de grootte van het antwoord wordt dat ondoenlijk.

Ik heb misschien wel een idee waardoor het toch kan, maar dat moet ik nog even uitwerken.



[...]

Blijkbaar maakt het ook nogal uit wat je puzzel input je hebt. @HannoOttens heeft aan 32 bits genoeg met zijn
input :P
Ja ik heb al een paar keer het vermoeden gehad dat ik een ongunstige input toebedeeld had gekregen. Het was bij mij zelfs zo dat ik een Long nodig had voor de counts van de individuele getallen, niet alleen voor het totaal

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 13-09 11:27

FCA

.oisyn schreef op woensdag 11 december 2024 @ 21:15:
@FCA Maar typisch wil je dat niet, dat maakt een kopie van de hele vector. Je kunt wel een element borrowen, maar als het een mutable borrow is dan kun je verder niet meer lezen (of schrijven) van/naar de vector.
Ja, dat was inderdaad duidelijk. Oplossing was om niet een vector terug te geven waar ik alleen in het eerste element geinteresseerd was, maar gewoon alleen het eerste element :)

Verandert z'n sig te weinig.


Acties:
  • +1 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mugwump schreef op woensdag 11 december 2024 @ 21:15:
[...]


Ja ik heb al een paar keer het vermoeden gehad dat ik een ongunstige input toebedeeld had gekregen. Het was bij mij zelfs zo dat ik een Long nodig had voor de counts van de individuele getallen, niet alleen voor het totaal
Ja daar heb ik het ook over ;)

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!

  • MatHack
  • Registratie: Oktober 2001
  • Niet online

MatHack

Dev by day, Gamer by night

Kreeg ook flashbacks naar 2021, dag 6.
Als we het trouwens hebben over crappy specs... ik develop AoC in een VM met 2CPU/8GB RAM, en draai daarbij ook nog eens de debug versie (zonder debugger attached) van de applicatie. :X
spoiler:
Ook hier gekozen voor tellers bijhouden + een cache van transformaties. Ik heb er uiteindelijk voor gekozen om de nummers als strings op te slaan ipv int/longs, dan hoef je alleen voor stap 3 te converten, de rest kan met strings. Nav de opmerkingen hier heb ik al wel meteen gekozen om de daadwerkelijke count van een nummer als een long bij te houden.

https://github.com/realma...de.Y2024/Solvers/Day11.cs

There's no place like 127.0.0.1


Acties:
  • +1 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 24-06 08:21
Ik heb vanochtend ook nog een tijdje zitten stoeien o.a. de ideeën die @FCA noemt, maar niets werkt echt geweldig. Het snelst is een combinatie van (een paar stappen diep) cachen daarna "handmatig" Counters optellen.
Soultaker schreef op woensdag 11 december 2024 @ 21:13:

spoiler:
Je kunt het probleem modelleren als een sparse binaire transitie-matrix waarbij elke kolom maximaal twee enen bevat,
Idem voor de aanpak met transitie-matrix (die overigens niet binair hoeft te zijn: 2424 wordt gesplitst in 2 × 24). Sowieso viel de performance van scipy.sparse en in het bijzonder scipy.sparse.linalg.matrix_power() een beetje tegen. Het bleek sneller om een kleine dense matrix te gebruiken en zelf de indices te mappen. Hier staat mijn (werkende) probeersel.

  • SPee
  • Registratie: Oktober 2001
  • Laatst online: 12-09 18:50
Mijn eerste poging was bruteforce iedere keer de nieuwe array berekenen. Dat werkte helaas niet voor deel 2.
Toen per entry recursief berekenen en alleen een aantal teruggeven. Dat gaf geen memory problemen, maar deed er alsnog te lang over. Dus een cache is wel nodig. Gelukkig ging het daarna wel goed. Ookal cache ik maar elke 5 iteraties.
Overigens geef ik een nieuwe array door in de nieuwe iteratie. Ik zie dat veel anderen alleen het getal doorgeven. Aangezien je maar 75 iteraties hebt, valt het geheugengebruik wel mee.

Overigens, geen idee of het wat uitmaakt, maar ik sorteer mijn input lijst. Qua resultaat maakt de volgorde immers niet uit.

let the past be the past.


Acties:
  • +1 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
Oef, wat ben ik lang bezig geweest met het debuggen van deel 2 vandaag. Kudo's aan de mensen die 'm in in een half uurtje opgelost hebben! (Ik ben zelf bijna een uur bezig geweest.)

Deel 1 valt nog wel mee:
spoiler:
Je kunt het oppervlak van elke plot vinden met een flood fill. Dan is het aantal ingekleurde vlakjes het oppervlakte, en het aantal vakjes dat eraan grenzen je omtrek (wel zorgen dat je correct elk paar vakjes van verschillende types telt: een enkel vakje van een ander type in het midden van de plot telt 4x mee voor de omtrek, 1 keer voor elk van de buren).


Voor deel 2:
spoiler:
Begin ik linksboven en trace ik de buitenkant van de plot, waarbij ik steeds naar links of naar rechts draai of naar voren loop. Aantal keer draaien = aantal hekstukken.


So far so good. Waar het bij mij mis ging was dat ik helaas had aangenomen dat:
spoiler:
alleen de buitenkant tracen volstaat, terwijl je ook de gaten binnenin mee moet nemen.


Duurde wel even voordat ik me dat ten eerste gerealiseerd had, en ten tweede correct opgelost had. Achteraf had ik misschien beter:
spoiler:
Alle bij deel 1 gevonden lijnstukken in een set gooien en dan stukken die in dezelfde richting lopen aan elkaar plakken tot je maximale rechte stukken hebt.

Maar ja, hindsight enzo...

Acties:
  • +2 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-09 09:39

Janoz

Moderator Devschuur®

!litemod

Soultaker schreef op donderdag 12 december 2024 @ 07:06:
Oef, wat ben ik lang bezig geweest met het debuggen van deel 2 vandaag. Kudo's aan de mensen die 'm in in een half uurtje opgelost hebben! (Ik ben zelf bijna een uur bezig geweest.)

Deel 1 valt nog wel mee:
spoiler:
Je kunt het oppervlak van elke plot vinden met een flood fill. Dan is het aantal ingekleurde vlakjes het oppervlakte, en het aantal vakjes dat eraan grenzen je omtrek (wel zorgen dat je correct elk paar vakjes van verschillende types telt: een enkel vakje van een ander type in het midden van de plot telt 4x mee voor de omtrek, 1 keer voor elk van de buren).


Voor deel 2:
spoiler:
Begin ik linksboven en trace ik de buitenkant van de plot, waarbij ik steeds naar links of naar rechts draai of naar voren loop. Aantal keer draaien = aantal hekstukken.


So far so good. Waar het bij mij mis ging was dat ik helaas had aangenomen dat:
spoiler:
alleen de buitenkant tracen volstaat, terwijl je ook de gaten binnenin mee moet nemen.
Dat kan veel simpeler :)

spoiler:
Denk voor deel 2 aan hoekpaaltjes waar het hek tussen moet en je kunt ineens heel simpel gaan patternmatchen

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: 13-09 11:27

FCA

Pittige vandaag inderdaad.
Soultaker schreef op donderdag 12 december 2024 @ 07:06:
Oef, wat ben ik lang bezig geweest met het debuggen van deel 2 vandaag. Kudo's aan de mensen die 'm in in een half uurtje opgelost hebben! (Ik ben zelf bijna een uur bezig geweest.)

Deel 1 valt nog wel mee:
spoiler:
Je kunt het oppervlak van elke plot vinden met een flood fill. Dan is het aantal ingekleurde vlakjes het oppervlakte, en het aantal vakjes dat eraan grenzen je omtrek (wel zorgen dat je correct elk paar vakjes van verschillende types telt: een enkel vakje van een ander type in het midden van de plot telt 4x mee voor de omtrek, 1 keer voor elk van de buren).
Zelfde idee gebruikt, maar kostte even, zat flink te ruzieen met de borrow checker en ander geneuzel
spoiler:
Ik wilde graag mijn region als een hashset, en natuurlijk regions kunnen afstrepen, maar dat waren teveel mutable borrows vond de Rust compiler, dus uiteindelijk flink zitten clone-en :(
Voor deel 2:
spoiler:
Begin ik linksboven en trace ik de buitenkant van de plot, waarbij ik steeds naar links of naar rechts draai of naar voren loop. Aantal keer draaien = aantal hekstukken.


So far so good. Waar het bij mij mis ging was dat ik helaas had aangenomen dat:
spoiler:
alleen de buitenkant tracen volstaat, terwijl je ook de gaten binnenin mee moet nemen.


Duurde wel even voordat ik me dat ten eerste gerealiseerd had, en ten tweede correct opgelost had. Achteraf had ik misschien beter:
spoiler:
Alle bij deel 1 gevonden lijnstukken in een set gooien en dan stukken die in dezelfde richting lopen aan elkaar plakken tot je maximale rechte stukken hebt.

Maar ja, hindsight enzo...
spoiler:
Ik ben voor een handgeschreven edge detector convolutie gegaan. Door elke region gaan en dan voor elk vierkantje checken welke buren er in zitten. Dan als de buur erboven en links er niet in zitten heb je een buitenbocht, en als de buur erboven en links ervan er wel in zitten maar linksboven niet heb je een binnenbocht. Dat x4 voor de rotaties (copy-paste + correct ( :'( ) aanpassen voor alle rotaties. Aantal bochten = aantal rechte stukken.
Eerst ook de binnenbochten vergeten, en daarna de buitenbocht check verkeerd gedaan.

Niet de snelste oplossing, nog eens rustig nadenken of er snellere opties zijn.

Verandert z'n sig te weinig.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
Janoz schreef op donderdag 12 december 2024 @ 07:32:
Dat kan veel simpeler :)

spoiler:
Denk voor deel 2 aan hoekpaaltjes waar het hek tussen moet en je kunt ineens heel simpel gaan patternmatchen
Je hebt helemaal gelijk, dat is veel simpeler. Dat verklaart ook waarom anderen zo snel waren.

Met wat puin ruimen is m'n oplossing nog wel netjes geworden, vind ik zelf: 12.py
FCA schreef op donderdag 12 december 2024 @ 07:37:
[spoiler]
Niet de snelste oplossing, nog eens rustig nadenken of er snellere opties zijn.
spoiler: deel 2
Je hoeft toch maar één keer door de hele grid te gaan om alle hoekpunten van alle regions te bepalen, of ben ik nu gek? B.v. als het vakje linksboven letter x heeft en rechtsboven en linksonder niet, dan is dit een convexe hoek; als het vakje linksboven letter x heeft en rechtsboven en linksonder ook, maar rechtsonder niet, dan is dit een concave hoek. In andere gevallen is het een recht stuk of de binnenkant van een regio.

Misschien mis ik wat edge cases hoor. Ik zal het even proberen te coden...

  • FCA
  • Registratie: April 2000
  • Laatst online: 13-09 11:27

FCA

Soultaker schreef op donderdag 12 december 2024 @ 08:20:
[...]

Je hebt helemaal gelijk, dat is veel simpeler. Dat verklaart ook waarom anderen zo snel waren.

Met wat puin ruimen is m'n oplossing nog wel netjes geworden, vind ik zelf: 12.py


[...]

spoiler: deel 2
Je hoeft toch maar één keer door de hele grid te gaan om alle hoekpunten van alle regions te bepalen, of ben ik nu gek? B.v. als het vakje linksboven letter x heeft en rechtsboven en linksonder niet, dan is dit een convexe hoek; als het vakje linksboven letter x heeft en rechtsboven en linksonder ook, maar rechtsonder niet, dan is dit een concave hoek. In andere gevallen is het een recht stuk of de binnenkant van een regio.

Misschien mis ik wat edge cases hoor. Ik zal het even proberen te coden...
Ik zag net de traagheid van mijn oplossing in de
spoiler:
floodfill
zat, waar ik talloze keren door de hele array heen ging.

Verandert z'n sig te weinig.


Acties:
  • +2 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
spoiler: dag 12 deel 2
Deel 2 kan inderdaad gewoon door 1 pass door de hele grid te maken, zie: 12-alt.py


Ik vraag me af of het zin heeft om grotere invoer te maken voor dit probleem... de efficiënte implementaties zullen allemaal O(N) zijn, hoewel er mogelijk nog wel wat verschil in performance zit tussen de ene of de andere implementation.

Acties:
  • +1 Henk 'm!

  • bakkerjangert
  • Registratie: Februari 2012
  • Laatst online: 13-09 19:44
Vandaag ook lang bezig geweest met deel 2. Het idee wat ik had was goed, maar door een domme bug redelijk wat tijd aan debugging kwijt geweest. Code in python.

spoiler:
Ik maak een lijst van alle boundaries, inclusief de richting waaruit ik kijk. Voor deel twee sort ik die per kijkrichting op x / y coördinaat en verwijder de directe buren; hiermee hou ik één boundary per zijde over. De domme bug was echter dat ik de sorting voor horizontale en verticale richting had omgedraaid. Schijnbaar komt dan uit de testuitvoer dat maar 2 van het totaal aantal gebieden het foute antwoord oplevert; daardoor dacht ik dat ik een edge-case over het hoofd had gezien en ging ik ervanuit dat de basis code juist zou moeten zijn. Niet dus.

Acties:
  • +1 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 24-06 08:21
Na flink wat nadenken en puzzelen heb ik ook iets moois bedacht! 8)

Code

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-09 09:39

Janoz

Moderator Devschuur®

!litemod

Soultaker schreef op donderdag 12 december 2024 @ 08:20:
[...]

Je hebt helemaal gelijk, dat is veel simpeler. Dat verklaart ook waarom anderen zo snel waren.

Met wat puin ruimen is m'n oplossing nog wel netjes geworden, vind ik zelf: 12.py


[...]

spoiler: deel 2
Je hoeft toch maar één keer door de hele grid te gaan om alle hoekpunten van alle regions te bepalen, of ben ik nu gek? B.v. als het vakje linksboven letter x heeft en rechtsboven en linksonder niet, dan is dit een convexe hoek; als het vakje linksboven letter x heeft en rechtsboven en linksonder ook, maar rechtsonder niet, dan is dit een concave hoek. In andere gevallen is het een recht stuk of de binnenkant van een regio.

Misschien mis ik wat edge cases hoor. Ik zal het even proberen te coden...
spoiler:
Hmm, ikzelf kijk naar het punt en ben dan eigenlijk alle 4 de hoeken aan het checken, maar je kunt natuurlijk ook alleen naar de hoek punten kijken. Het enige waar je dan op moet letten is dat een hoekpunt meer dan 1 paaltjes op kan leveren. Uiteindelijk check ik nu alle punten 4x. Voor elk aanliggende punt 1x


-----

UIteindelijk is dit wel weer een probleem wat relatief simpel is voor 'geschoolde' developers. In het wild kom je niet vaak iets van floodfills tegen terwijl dat een typisch opdrachtje is wanneer recursie en/of stacks uitgelegd worden.

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: 13-09 09:39

Janoz

Moderator Devschuur®

!litemod

Soultaker schreef op donderdag 12 december 2024 @ 09:05:
spoiler: dag 12 deel 2
Deel 2 kan inderdaad gewoon door 1 pass door de hele grid te maken, zie: 12-alt.py


Ik vraag me af of het zin heeft om grotere invoer te maken voor dit probleem... de efficiënte implementaties zullen allemaal O(N) zijn, hoewel er mogelijk nog wel wat verschil in performance zit tussen de ene of de andere implementation.
Ik kan zo ook niet iets verzinnen waardoor het sneller dan O[N] kan. Verder vermoed ik dat veel instinkers al in de echte input zit.

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


  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 02-08 07:54
Soultaker schreef op donderdag 12 december 2024 @ 09:05:
spoiler: dag 12 deel 2
Deel 2 kan inderdaad gewoon door 1 pass door de hele grid te maken, zie: 12-alt.py


Ik vraag me af of het zin heeft om grotere invoer te maken voor dit probleem... de efficiënte implementaties zullen allemaal O(N) zijn, hoewel er mogelijk nog wel wat verschil in performance zit tussen de ene of de andere implementation.
spoiler:
De oplossing met hoeken is slim bedacht en ook een stuk eenvoudiger om te implementeren dan wat ik gedaan heb. In mijn oplossing kijk ik of een aangrenzend lijnsegment al eerder is gezien tijdens de huidige floodfill (voor alle mogelijke richtingen). Als dat niet zo is, verhoog ik mijn lijncounter en markeer ik het volledige lijnsegment door naar de uiteinden te itereren. Het idee is dat een lijnsegment doorloopt zolang de direct aangrenzende cellen aan de kant waar we vandaan komen hetzelfde blijven als de karakters van het gebied dat we floodfillen, en het karakter van het lijnsegment juist niet gelijk is aan het gebied dat we floodfillen. Als zo'n aangrenzende cell dan al eerder gemarkeerd is, is de lijn al geteld. Dit is ook O(N*M), aangezien we een lijnsegment maar een keer helemaal aflopen om te markeren. Maar het duurde wel even voordat alle bugs eruit waren...

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

Acties:
  • +1 Henk 'm!

  • FCA
  • Registratie: April 2000
  • Laatst online: 13-09 11:27

FCA

Nu een implementatie waarbij:
spoiler:
1. eerst 1x door de array lopen en dan edges/corners tellen per grid point
2. Floodfill om de regio's te bepalen
3. per regio ofwel edges ofwel corners tellen
en volgens mij is sneller dan O(n) ook niet mogelijk: je moet elk punt toch minstens 1x bezoeken lijkt me.

Allebei de delen nu ~1.5ms per deel, waarvan ongeveer de helft de regiobepaling (die ik opnieuw doe voor elk deel).

Verandert z'n sig te weinig.


  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 02-08 07:54
FCA schreef op donderdag 12 december 2024 @ 10:31:
Nu een implementatie waarbij:
spoiler:
1. eerst 1x door de array lopen en dan edges/corners tellen per grid point
2. Floodfill om de regio's te bepalen
3. per regio ofwel edges ofwel corners tellen
en volgens mij is sneller dan O(n) ook niet mogelijk: je moet elk punt toch minstens 1x bezoeken lijkt me.

Allebei de delen nu ~1.5ms per deel, waarvan ongeveer de helft de regiobepaling (die ik opnieuw doe voor elk deel).
Sneller dan O(N), waarbij N = lengte*breedte is inderdaad niet mogelijk. Alleen het inlezen van de grid is al O(N). Dus het gaat dan vooral om de constante factor,
spoiler:
waarbij hoeken tellen erg snel is.

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


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Robbinb1993 schreef op donderdag 12 december 2024 @ 10:35:
[...]


Alleen het inlezen van de grid is al O(N).
Memory mapped files, die pages kunnen dan gewoon uit de cache komen :Y)

.edit: ok fair, nog steeds O(N/pagesize) = O(N)

[ Voor 21% gewijzigd door .oisyn op 12-12-2024 10:55 ]

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!

  • P_Tingen
  • Registratie: Maart 2005
  • Laatst online: 13-09 19:20

P_Tingen

omdat het KAN

Dag 11, deel 2.

Omdat ik hier al gelezen had welke richting het op moest voor deel 2 (had al door dat dat recht-toe, recht-aan niet zou gaan lukken) en ik net dag 7b (Bridge Repair) had opgelost, zag ik hier een kans.

Deel 1 had ik wel 'dom' opgelost en duurde 4,4 seconde. Met een tellertje erbij zag ik al dat elke iteratie langer duurde. Deel 2 - na wat optimalisatie - is nu klaar in 2940ms en dat is denk ik het snelste wat ik kan halen in Progress 4GL. Weer eens wat anders dan die snelle tijden ;)

https://github.com/patric...ter/2024/Day-11/day-11b.p

... en gaat over tot de orde van de dag


  • gedonie
  • Registratie: Januari 2011
  • Laatst online: 09-09 10:31
Zat bij dag 12 2de deel inderdaad even vast op de hoekbepaling. Eerst pakte hij alleen de buiten hoeken waarbij en niet de hoeken waarbij hij de vorm 'in' knikt (dus bijvoorbeeld links boven niets maar boven en links wel de vorm).

Levert wel super lelijke code op maar het berekent netjes de randen.

https://github.com/gjong/...nt/years/y2024/Day12.java

  • HannoOttens
  • Registratie: September 2014
  • Laatst online: 22:51
Oeps.. Was nog replies van gisteren aan het lezen toen ik doodleuk de spoiler over de
spoiler:
hoeken tellen oplossing
opende :F Dan hoop je maar dat je zelf tot het zelfde inzicht was gekomen :D

spoiler:
Denk dat ik wel leuke pattern matching voor mekaar heb en een simpele manier van de vlakken bij elkaar zoeken (gewoon de buren in een queue zetten en geen positie twee keer afhandelen).

Rust

Acties:
  • +1 Henk 'm!

  • HannoOttens
  • Registratie: September 2014
  • Laatst online: 22:51
@Soultaker Nog even naar de u32 vs u64 gekeken en ik zat er inderdaad naast!

Na het inleveren niet goed opgelet en er kwam doodleuk een ander antwoord uit... Omdat ik voor de performance de release build deed ook niet langer over nagedacht dat overflows dan niet meer naar voren komen 8)7

Mijn oplossing draait dan in een beschamende 15ms in plaats van de eerder geprofeteerde snelheden :D

Acties:
  • +4 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
Extra testdata voor dag 12: aoc-2024-day-12-challenge-1-and-2.zip

Om te benchmarken kun je combined-1.txt en combined-2.txt gebruiken. Er zitten wat extra bestanden bij die je kunt gebruiken om te debuggen als je niet het goede antwoord krijgt (de combined bestanden zijn simpelweg de andere bestanden aan elkaar geplakt). Ik heb daarvoor ook de oplossingen in de zip file gestopt. Natuurlijk is de uitdaging om de correcte antwoorden zelf te reproduceren!

Referentie-tijden (dit kan zeker veel sneller in een andere taal dan Python):
$ time pypy3 solve.py < combined-1.txt 
...54044
...18790

real    0m0.626s
user    0m0.565s
sys     0m0.058s

$ time pypy3 solve.py < combined-2.txt 
...62592
...00666

real    0m4.497s
user    0m4.231s
sys     0m0.253s


Overigens overweeg ik ook een carrière switch naar abstract kunstenaar:
Afbeeldingslocatie: https://i.imgur.com/nU2cosp.png
Mooi hè?

Acties:
  • +2 Henk 'm!

  • KabouterSuper
  • Registratie: September 2005
  • Niet online
Soultaker schreef op donderdag 12 december 2024 @ 13:08:
[Overigens overweeg ik ook een carrière switch naar abstract kunstenaar:
[Afbeelding]
Mooi hè?
Dream caused by floodfills around Soultakers gardens seconds before awakening

When life gives you lemons, start a battery factory


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-09 09:39

Janoz

Moderator Devschuur®

!litemod

Misschien moet ik ook maar eens een stukje graphics toevoegen aan mijn framework. Een plaatje is vaak duidelijker dan tig logregels of een bak cijfers.

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!

  • HannoOttens
  • Registratie: September 2014
  • Laatst online: 22:51
Ook even gedraait op de challenge inputs:

combined-1.txt: 444.30ms
combined-2.txt: 4.22s

[ Voor 7% gewijzigd door HannoOttens op 12-12-2024 13:56 ]


  • CrossProd
  • Registratie: November 2014
  • Laatst online: 08-09 16:33
De eerste waar ik moeite mee had dit jaar, terwijl we iets soortgelijks toch al eens eerder hebben moeten doen.

spoiler:
Voor het vinden van de areas uiteraard floodfill gebruikt. Voor het vinden van de sides in deel 2 ben ik uiteindelijk uitgekomen op twee iteraties door de map, voor horizontale en verticale sides. Als er een edge is check ik of er een edge is die ernaast of erboven zit en dan merge ik die, en anders is het een begin van een nieuwe edge. Werkt uiteindelijk wel snel.


Oplossing in Swift

Acties:
  • +1 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 12-09 19:26
Soultaker schreef op donderdag 12 december 2024 @ 13:08:
Extra testdata voor dag 12: aoc-2024-day-12-challenge-1-and-2.zip
...

Overigens overweeg ik ook een carrière switch naar abstract kunstenaar:
[Afbeelding]
Mooi hè?
Ja, echt wel weer mooie data die je gegeneerd hebt. Ik vraag me soms af waar je de tijd vandaag haalt!

Ik zat eerst te klooien met ingewikkelde algorintmes, maar nadat ik besefte dat je hekken en hoeken makkelijk kunt definieren werd het een stuk simpler! Ik heb geloof ik 80% van mijn code weer kunnen weg gooien. Hier is mijn huidige resultaat in Rust. Trouwens, het meeste complexe is een nieuwe functie in mijn Grid object die regio's met dezelfde waarden kan detecteren. Misschien nog niet het meest efficient, maar hij kan er mee door voor nu.

De challenge run:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
$ day12 < combined-1.txt
Executing
 ├── Input parsed in 54,770µs
 ├── Part 1 calculated in 18,396µs: ...54044
 ├── Part 2 calculated in 45,702µs: ...18790
 └── Total time: 118,937µs

$ day12 < combined-2.txt
Executing
 ├── Input parsed in 445,779µs
 ├── Part 1 calculated in 167,983µs: ...62592
 ├── Part 2 calculated in 415,637µs: ...00666
 └── Total time: 1,029,465µs


Niet slecht volgens mij, maar het moet denk ik nog wel wat beter moet kunnen.

Acties:
  • +6 Henk 'm!

  • Friits
  • Registratie: December 2023
  • Laatst online: 24-06 08:21
Nog even een hele andere manier van oplossen: met kernels! Deze worden vooral gebruikt in beeldherkenning (en signaalverwerking in het algemeen), en dat is wat we vandaag eigenlijk doen.

spoiler:
Convolutie met de kernel [-1, 1] levert de horizontale randen op, [-1; 1] de verticale, en [1,-1; -1,1] de hoekpunten. Aangezien het aantal hoeken altijd gelijk is aan het aantal edges, hebben we daarmee alle ingrediënten voor de antwoorden. Nog even wat optellen en vermenigvuldigen en we zijn klaar!


Code

[ Voor 31% gewijzigd door Friits op 12-12-2024 14:45 ]


Acties:
  • +1 Henk 'm!

  • Robbinb1993
  • Registratie: September 2020
  • Laatst online: 02-08 07:54
Soultaker schreef op donderdag 12 december 2024 @ 13:08:
Extra testdata voor dag 12: aoc-2024-day-12-challenge-1-and-2.zip

Om te benchmarken kun je combined-1.txt en combined-2.txt gebruiken. Er zitten wat extra bestanden bij die je kunt gebruiken om te debuggen als je niet het goede antwoord krijgt (de combined bestanden zijn simpelweg de andere bestanden aan elkaar geplakt). Ik heb daarvoor ook de oplossingen in de zip file gestopt. Natuurlijk is de uitdaging om de correcte antwoorden zelf te reproduceren!

Referentie-tijden (dit kan zeker veel sneller in een andere taal dan Python):
$ time pypy3 solve.py < combined-1.txt 
...54044
...18790

real    0m0.626s
user    0m0.565s
sys     0m0.058s

$ time pypy3 solve.py < combined-2.txt 
...62592
...00666

real    0m4.497s
user    0m4.231s
sys     0m0.253s


Overigens overweeg ik ook een carrière switch naar abstract kunstenaar:
[Afbeelding]
Mooi hè?
combined-1: 64ms.
combined-2: 614ms.

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

Acties:
  • +2 Henk 'm!

  • breew
  • Registratie: April 2014
  • Laatst online: 08:19
Paar daagjes griep gehad.. dus vanaf dag 7 niet meer bijgewerkt.. nu vrolijk verder met dag 12..

Die viel me aardig mee.
Qua snelheid vast niet vergelijkbaar met snellere loopjes.. maar qua code wel lekker kort :)
spoiler:
DEEL1:
Afbeeldingslocatie: https://tweakers.net/i/UJXuc0y5Vdub6ZO2TV7_zXE0_PE=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/eDOQrIEzdqZrGbdCfWIMIDrc.png?f=user_large
- maak een netwerk van de matrix, en behoud alleen de verbindingen tussen gelijke letters.
- de componenten in de graaf zijn de verschillende blokken
- van iedere 'letter' is de omtrek gelijk aan (4 - aantal verbindingen naar naastgelegen letters)
- sommer dit per groep, en vermenigvuldig met groetsgrootte
DEEL 2
- maak een spatial grid van vierkanten, met afmetingen van input
- haal de groepen/blokken uit het antwoord van DEEL 1
Afbeeldingslocatie: https://tweakers.net/i/zZDPlFhOzKWY9Bx-2Nc4yxRScRQ=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/GrZ1I0vQhH7GbWtpe1ALWZnl.png?f=user_large
- simplificeer per blok, waardoor je alleen polylijnen (=omtrek) overhoudt.
Afbeeldingslocatie: https://tweakers.net/i/HFcM1hA__x0NSYstp48PeX2p0hA=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/6F34rfXsSNiFu2EIUS1jOdxA.png?f=user_large
- per blok, per polylijn, kijk uit hoeveel punten de polylijn bestaat. (aantal punten - 1) is aantal lijndelen.
- sommeer per blok, en vermenigvuldig met blokgrootte

[ Voor 3% gewijzigd door breew op 12-12-2024 16:25 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02:44
Janoz schreef op donderdag 12 december 2024 @ 13:54:
Misschien moet ik ook maar eens een stukje graphics toevoegen aan mijn framework. Een plaatje is vaak duidelijker dan tig logregels of een bak cijfers.
Dat is zeker waar. Ook is het vaak behulpzaam om problemen als graaf te kunnen visualiseren. Daarmee was dag 25 van vorig jaar eigenlijk volledig op te lossen.

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-09 09:39

Janoz

Moderator Devschuur®

!litemod

Soultaker schreef op donderdag 12 december 2024 @ 16:04:
[...]

Dat is zeker waar. Ook is het vaak behulpzaam om problemen als graaf te kunnen visualiseren. Daarmee was dag 25 van vorig jaar eigenlijk volledig op te lossen.
Nou, het goed visualiseren van dag 8 van vorig jaar had ook veel kunnen helpen :D. Maar goed, vorig jaar niet heel serieus ingedoken omdat ik toen op vakantie ging.

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

Pagina: 1 ... 6 ... 10 Laatste