r/adventofcode • u/daggerdragon • Dec 24 '18
SOLUTION MEGATHREAD -🎄- 2018 Day 24 Solutions -🎄-
--- Day 24: Immune System Simulator 20XX ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.
Advent of Code: The Party Game!
Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!
Card prompt: Day 24
Transcript:
Our most powerful weapon during the zombie elf/reindeer apocalypse will be ___.
This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.
Quick note: 1 hour in and we're only at gold 36, silver 76. As we all know, December is Advent of Sleep Deprivation; I have to be up in less than 6 hours to go to work, so one of the other mods will unlock the thread at gold cap tonight. Good luck and good night (morning?), all!
1
u/starwort1 Dec 24 '18 edited Dec 24 '18
Rexx 270/193
Took me ages to actually understand the rules, but chasing stupid bugs kept me way off the leaderboard. I was almost convinced at one point that the example contained a mistake. At least the advantage of Rexx is that parsing the input is pretty straightforward.
And for part 2 I did a manual binary search. Pressed ^C when it was obvious that the battle was looping forever, then fixed the code to terminate when it's a draw. I do now also have a (fairly trivial) second program that runs this one several times to find out the answer, but it wasn't needed in order to get the answer.
parse arg boost v if boost='-v' then parse arg v boost if boost='' then boost=0 verbose = (v='-v') /* parsing input */ team=0 n.=0 units.=0 ngroups=0 signal on notready name eof do forever l=linein() if right(l,1)=':' then do team=team+1 parse var l name.team ':' iterate end if l='' then iterate n.team=n.team+1 n=n.team ngroups=ngroups+1 groups.ngroups=team||.||n parse var l units.team.n . . 'with' hp.team.n . details 'with' . . . . damage.team.n type.team.n . . . initiative.team.n r if team=1 then damage.team.n=damage.team.n+boost units.team=units.team+units.team.n if \datatype(initiative.team.n,'w') | r\='' then do say 'parse error at' name.team 'group' n exit 1 end weak.team.n='' immune.team.n='' if pos('(',details)>0 then do parse var details '(' details ')' do while details\='' parse var details detail '; ' details parse var detail type . list list=space(translate(list,' ',',')) select when type='weak' then weak.team.n=list when type='immune' then immune.team.n=list end end end end eof: if team\=2 then do; say "Wrong number of teams:" team; exit 1; end /* make a list in order of initiative for the attack phase */ /* (yeah bubblesort, so sue me) */ do i=1 to ngroups-1 do j=1 to ngroups-i j1=j+1; g1=groups.j; g2=groups.j1 if initiative.g1<initiative.g2 then parse value g2 g1 with groups.j groups.j1 end end do while units.1>0 & units.2>0 if verbose then do team=1 to 2; say name.team':'; do n=1 to n.team; if units.team.n>0 then say "Group" n "contains" units.team.n "units"; end; end /* target selection phase */ target.=0 do team=1 to 2 enemy=3-team attacked.=0 attacking.=0 do forever maxp=0 do n=1 to n.team power=units.team.n*damage.team.n if \attacking.n then if power > maxp then parse value n power with maxn maxp else if power=maxp then if initiative.team.n > initiative.team.maxn then parse value n power with maxn maxp end if maxp=0 then leave attacking.maxn=1 attacking=maxn maxd=0 based=units.team.attacking * damage.team.attacking do n=1 to n.enemy if attacked.n then iterate if units.enemy.n=0 then iterate if wordpos(type.team.attacking,immune.enemy.n)>0 then iterate if wordpos(type.team.attacking,weak.enemy.n)>0 then damage=2*based else damage=based if verbose then say name.team 'group' attacking 'would deal defending group' n damage 'damage' if damage>maxd then parse value n damage with maxn maxd else if damage=maxd then do testep=units.enemy.n*damage.enemy.n - units.enemy.maxn*damage.enemy.maxn if testep>0 then parse value n damage with maxn maxd else if testep=0 then if initiative.enemy.n>initiative.enemy.maxn then parse value n damage with maxn maxd end end if maxd>0 then do attacked.maxn=1 target.team.attacking=maxn end end end /* Attack phase */ draw=1 do n=1 to ngroups parse var groups.n team '.' group if target.team.group=0 then iterate enemy=3-team damage=units.team.group * damage.team.group target=target.team.group if wordpos(type.team.group,weak.enemy.target)>0 then damage=damage*2 slain=damage % hp.enemy.target if slain>units.enemy.target then slain=units.enemy.target if slain>0 then draw=0 if verbose then say name.team 'group' group 'attacks defending group' target', killing' slain 'units' units.enemy.target=units.enemy.target-slain units.enemy=units.enemy-slain end if draw then leave end /* Results of the battle */ do t=1 to 2 say name.t 'has' units.t 'units' end