Advent-of-Code-2023/chicken.org

9389 lines
320 KiB
Org Mode
Raw Permalink Normal View History

2023-12-10 22:58:33 +00:00
# Created 2023-12-10 Sun 23:58
2023-12-08 09:17:29 +00:00
#+title: Advent Of Code with Chicken Scheme
#+author: Daniel Ziltener
#+export_file_name: chicken.org
2023-12-09 09:42:17 +00:00
#+property: header-args:scheme :session *chicken* :comments both :exports both :prologue ";; -*- geiser-scheme-implementation: chicken -*-" :eval no-export
2023-12-08 09:17:29 +00:00
#+property: header-args:fundamental :eval no
* Prelude
I don't know why I am spending my time this way, but I am trying to get through this year's
[[https://adventofcode.com/][Advent of Code]]. I decided to use [[https://call-cc.org][Chicken Scheme]], and I am trying to use as few (if any) extensions,
for an extra challenge.
2023-12-08 09:45:19 +00:00
/*This may or may not be the original document ([[file:./chicken-src.org][=chicken-src.org=]]) or its weave for reading
([[file:./chicken.org][=chicken.org=]]). Choose wisely.*/
2023-12-08 09:17:29 +00:00
* Day 1: Trebuchet?!
** Part One
*** Quest
Something is wrong with global snow production, and you've been selected to take a look. The Elves
have even given you a map; on it, they've used stars to mark the top fifty locations that are likely
to be having problems.
You've been doing this long enough to know that to restore snow operations, you need to check all
*fifty stars* by December 25th.
Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent
calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants *one
star*. Good luck!
You try to ask why they can't just use a [[https://adventofcode.com/2015/day/1][weather machine]] ("not powerful enough") and where they're
even sending you ("the sky") and why your map looks mostly blank ("you sure ask a lot of questions")
and hang on did you just say the sky ("of course, where do you think snow comes from") when you
realize that the Elves are already loading you into a [[https://en.wikipedia.org/wiki/Trebuchet][trebuchet]] ("please hold still, we need to
strap you in").
As they're making the final adjustments, they discover that their calibration document (your puzzle
input) has been *amended* by a very young Elf who was apparently just excited to show off her art
skills. Consequently, the Elves are having trouble reading the values on the document.
The newly-improved calibration document consists of lines of text; each line originally contained a
specific *calibration value* that the Elves now need to recover. On each line, the calibration value
can be found by combining the *first digit* and the *last digit* (in that order) to form a single
*two-digit number*.
For example:
#+begin_example
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet
#+end_example
In this example, the calibration values of these four lines are =12=, =38=, =15=, and =77=. Adding
these together produces =142=.
Consider your entire calibration document. *What is the sum of all of the calibration values?*
*** Puzzle Solution
#+name: day1-solution-1
#+begin_src scheme
(import (chicken string)
(chicken irregex))
(let ((lines (string-split input "\n")))
(foldl + 0
(map
(lambda (line)
(let ((digits (irregex-extract '(/ #\0 #\9) line)))
(if (= 0 (length digits))
0
(let ((first-digit (car digits))
(last-digit (car (reverse digits))))
(string->number (string-append first-digit last-digit))))))
lines)))
#+end_src
** Part Two
*** Quest
Your calculation isn't quite right. It looks like some of the digits are actually *spelled out with
letters*: =one=, =two=, =three=, =four=, =five=, =six=, =seven=, =eight=, and =nine= *also* count as
valid "digits".
Equipped with this new information, you now need to find the real first and last digit on each
line. For example:
#+begin_example
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen
#+end_example
In this example, the calibration values are =29=, =83=, =13=, =24=, =42=, =14=, and =76=. Adding
these together produces =281=.
*What is the sum of all of the calibration values?*
*** Puzzle Solution
#+name: day1-solution-2
#+begin_src scheme
(import (chicken string)
(chicken irregex))
(define (extract-digits input-string)
(irregex-extract '(or (/ #\0 #\9)
"one"
"two"
"three"
"four"
"five"
"six"
"seven"
"eight"
"nine"
; Duplicates
"twone"
"eightwo"
"nineight"
"eighthree"
"threeight"
"fiveight"
"oneight"
"sevenine")
input-string))
(define (translate-code digit)
(case (string->symbol digit)
((|0|) "0")
((|1| one) "1")
((|2| two) "2")
((|3| three) "3")
((|4| four) "4")
((|5| five) "5")
((|6| six) "6")
((|7| seven) "7")
((|8| eight) "8")
((|9| nine) "9")
; Again, duplicates
((twone) "21")
((eightwo) "82")
((nineight) "98")
((eighthree) "83")
((threeight) "38")
((fiveight) "58")
((oneight) "18")
((sevenine) "79")
))
(let ((lines (string-split input "\n")))
(foldl + 0
(map
(lambda (line)
(let ((digits (string->list
(foldl string-append ""
(map translate-code (extract-digits line))))))
(if (= 0 (length digits))
0
(let ((first-digit (car digits))
(last-digit (car (reverse digits))))
(string->number (string first-digit last-digit))))))
lines)))
#+end_src
** Puzzle Input
Jump to [[#headline-10][day 2]].
#+name: day1-input
#+begin_src fundamental
eightqrssm9httwogqshfxninepnfrppfzhsc
one111jxlmc7tvklrmhdpsix
bptwone4sixzzppg
ninezfzseveneight5kjrjvtfjqt5nineone
58kk
5b32
1dtwo
six7two7sixtwo78
mvhsixpptztjh13sixthree2
six1bqqvrxndt
fourmk5grmqone944nbvtj
twofiveqxfivezpkvfvxt5eightjhnpl
fpfqp7three7
scmlf76ninegjzjkj97two
fivetkhfnnx22
sevenxvbcbsvxr7eighttwo
1hvhqqmrs1bgttshthg6
4bvnccbdh4onefztdrpq62vvbnvpxxvgrngnfjgfk
653spgrvd
sixctlhkjmmxh2fourfivenine37
229mjp3txmqsxxqdbnnnbrtrcctgzseven
jfourdbpcjc39bhglgnine
bvnltxdmsp7twoxzpdjdvkxeight4twothree
jlvcdrkhzh8seven3
418oneeight
53flcrlvqdeight84frmdcsixchcbc
114sixone1eight2
xrbtzbklqsl11
bhfhszrhzgrhsfd2threeseventwosevenoneseven
four9one
5p
twovhjpdxmcxshnhv5vs
qkkqeightcxcltnn7one9pmhlmvsxnine
4cbptmvp1
84xgm
bzsmqhkrdtdmhhjgrjsdfour1ninetwo61
onetwoeightgflhlgksevennine7two6
mbjhkhfour6
8cvqk6eightonethree1
qhbllbnlkr3rcsmjvztgd
18eight4
hhc6onegvkgkqs5mvsone
66bnfj
one99xvrhninefive
eight96nxcjjddmseightxvgsixfiverrzpvmgnl
rpgpczdsxpjgql39
855dnthhxld6eight
four29twosspz1
sixfiveqvrbcdr9fourlrkpkmxphlsbone
341
mhqjjg9six9nine
7pvjctsgvsix64
75twotwothreegcvssgbvhpzcnbgteight
7keight8eight
52threerhfmklssxcptmnlr4hqc4
xndfqvgxn3five
974lknineseven
rlnsix3
771m1
xvtjhq7six64threeeightgspmxgv
4sbqdxbmmzj6fiveone
onesvvch4rvhmvncnk
mkzsftp69six6
fiveptnn7
94lsgsjxrrghxxsr4
1grnvgpeightjthqmrfnszpfhfninefive9mbtf
qtsdfour2
5mfhmskpcvqbxjzzxt4lq3sevenkv
rbhjk1cdzjhtzkcbtvmfm
nine4eightpmrptkb
bfiveeight1lxzkzvbtkkgxxs38
mxcgbjqvhd1sevensevenrgp7two
fourxrdzzmjfmtr62one
sevenppqtlhvtwo7phlrbssxb
dhbnjmxg3bsgbhmlfiveseventwo
twoonemrbftgtzeightqjmjctmq55
ggk2lt586dfzqbjsvj1one
jtgpzjjtwo86seventwo
37nine4onebqvsnmvg277
hmpnzmqsfour6
xzfhgzllmcbc56vpbpbbjffmgr3jrc
5lclone
hjbvkdtmrgvpfive9sevenfive1nlzqlkfrg
htwonetgxvjdkrvjsfjjbfmcthseven29
six89bdlssd
3eight6one
vtbsix2twolzrhfr1
vhdcvtj5
167nsnmgxhtvn54fivedcbgrhm
4three1five82four
15eightonethreesixthree
dvhtsccljt51
pbnfrxblk3sevenxjcmcvhlgrghpbgdnpl8xsr3fiveoneightq
242three8
2fivehgqfxgl8kpdknxhmk5bmmsbz
fivejvjeight6fsqgtpvcb
1threelgkbhlhhlmrbvxqqgf
klmqfgfg1gnine253psn8
47eight
eight83mvdtsqppjhgjnsvngfive
7mcmzvsv6seven
56seven98three4three
pfnbthreegthreefknjm4five
2nqgrdcshfpjfpqdrvnq1twoccpmxpxvv
xtwo7threemxbtpsvjkgrfivethree2
9pkdfourfour1zjvczkhpbj
1three2
pkkbphkgqfivellrnvnkdxpql3
ppc62
one73ptfxsbbpqqgctdjhzjsjc91
nine7threefourvvk
six59542xcxqcbnrvzfbshcxxddz2
ftsfj2ninesix1hdjsrpkonelklfpltv
ninehmxgkqbmhvtlvdmdtvpeighttqfour1three
frbnineeight4168ksmjstpqvzhnn
rgnrntwohvqhgxxfkonefour4mfdr5ftgtjjv
3ninejbszdvdgznfourxpcxspqxnthlngkncvnineccq
threemjglxtp5cqmtwotwo2seventwonerkl
eightsevensevenlmbjzprggthree1eight
57nineninezdcf
cqoneighteightjnrfkplvninefivemck18mnhszhkv4
tbvdcsjsvmxtshv3fourseven4kmxvvfour9
bxcsix19six8dnqsbx
7five81ncchkdk
four4ck7rtjmjpccpeightone
fivetwo6nine1tdczktmfninelrbnnine
onetwo9twoeight5sevensix
cvvtbmninebneightsix1dnnfkgmnm
h7three3
tpnzsdm9sixtg5sixqvcqsq3
1sevenzmbcpgtfrjvq
r8757
fournineseven6fourfour
798dpbrkfourtwoxdrgqkrkmfeight7
threebvqqjcldjx4nine5
3hbl
twodndcfddkvfivermvkrfzsnqthree5
mhdcvsixmnqlvmvxmxfour3ct
25dpfsrbcllhtwothree2pthreezfhjx
dcfggnine1onetwoone
vtbmbpgffive2hdmzjzqqqc4one
zg11
txrknhvhbv183
dlvscqszz82nvtpb7tktvtgjbml
twofour5sevensmqfjrjcndmvcvqdfsrsix
446sixeight6rbrltdzf
132ncq1
4ninezdfzgvzf4four7qkzstcq
7rx5xntgxfpmvsevenzmzmbjlc3fivefive
threeseven7tshthree
gnbqhninecjnhlpcfivenine18
gjntwonenllmzgqsvq36lc45fourdrtzlctr
3tqgbfrk
zldl3zxpfbpveight
2ninetgppcvqrq
7one1sixeighttxcnhltwooneeight
bsm3hslqcr8xslndqnnvfpzvprlkt
khvptwo7kkbznndpqsevensevenvlr
sevenscneight8one4qnkc
2v
2threerjnineonev
68qhknonebtxvmqh
3btb
kcxbqzbjqt3twofourfxdlprsxkzlmflbveight
9bmdcninecjdv7
ceightwoninelkbbfxgsv9fb5n
ztwo2
7four9cpkclqxtrmpdgzxgtwo
8dghrmgprdjeight8knnb852one
2three36eightfournone2
6ztwofkzlhvjdrxtsmlbgczf
knine6ninebpmzjbkg9tttkhtgcklbfive
sevenv3
411one4483
88jvjggxqfour3zrbvbxjzmthree
fivelqcnqfvgp18t
fivejceightqlsdrmrnbzfbjskstzrllxrdlcxpjkvf1
832
sixfive77rhkjdhvbpdfjxpkmfdq66qqtfpfs
fv6svkbnsgtpznblnvkvk5
sixsevenfoursixeight486
gsbfrjpngshpmlxf2
gbmmmvdhffbbcq3
5fivehxx28
snjxttwo1zd5sixklfl
szsvdzsix3nine32nine
onervkhknmnsix3four363
1btphrrvxdeightonekdhv8
gkphmq73lfhflk66xpfive2
611four3gnjsdkvksjdxfiveeight
klbvb9zk4eightninetwo
mreight59sevengqbhnspvhqcj2six
hnvgkmljlpthsgjrzmsevensix6fcvtxddbnx5
ckfvkblhvv6gbsnlsevenktblt29three
eightfoursevendnsghkfsg8fivextnnine
5hrdqmfjq
twojcvkkjklzmfive2fourxqgdsdgzrjltwo7
onetwonvxnxnntxcthree3
threentwonine6
sprfmxlqvb9jnbzltskxppqzdscrvhpfvjjcqhxcf
sixhfour95
41fourqhpjbztknqnfpxvzc
two23sevenfgmmnszone113
one41seven57
oneninebqqklhk6gmdzddbhgzqcmxxfnmrvr
4mkpgv87eightckzjjfm
vhgdmvncxn88ldbt7464
gcczfprplf7
6eightninesxthreefive99
two69fivecjxjhgjmgvttl9
mztbzjmgxnpkfrqnrbgkgfourjjfjtone8eight
63mggldkcprlz
6sevenfourfive
1zvmrdnpzcsqqmxscn
five5tkgb8rrztmcfivebknjd
7pscpfive
eight9sixgfvhvlcnineeight
seven99fourtwojvxfrqmrdlthree
sppcgnjzeight93j
fivek7seventhree
twornbhtrlnznpctrxhqtngzdtnvfb2
sevenfivefour63five38nlrxfcjpm
qvtdcspc4zxmmhpklhcdlznqfg46lct5one
1bnndtnsfjdsevenfivetwo3k85
8five9six
3ltcc7trmmhbbbpjfive
cmbchhhczmqlp3
nctz78twodljcqvplcqg
nine4sevenpnbbztpvkbgztb
zseven9eight
fourktzscmnrvddnnzsqfnfctzpdvtwo9
nrtbgdjpm2ldcfdm5jjhx9
jq9two68kjttwo67
lnneightfourzqz6lgvxnthreeseven7
fiveglp85
ninefouronesix7k1three
3five5sevendhtmjhbh2
rbjhnmmgsvmtk8four
vtrvvjsixhnctwocvskgzt3two3
kxfive5threezgtd2
2fivemcnngtzxsgbxmvbl
eightlrlztkvhfivefour5
2twojcq7qrrbddmpsb
3twosixthreebqtoneone2
nine9six3vlmpqbgjjqdftldpq
tgrglqfxxc2onetwo76oneonex
one48one
fivesgsnrzsms6one
fiveseven1tzhxdknkseven4
3sprtonefivelxg47
twotwoseven3ninenqdvxgm
nskjpvvqeightnine93fivecngkjcd3
ltfxscllxk9pjznpnmhfmrzmqbq
4nineeight6four7
fjtpj763
four6six73htbstbbpztwofj
oneonetwo2five43three
five8bgcjnlzcgqpfkn
11mcn
9twovhkltdpkqzc65six
8fkprfkg9xfjxspqpshlfkqpnrt
4sblrf7745
lblxmbzfour6187tggqllj
dhdmlx71mbbxtvhszhsvcm
six1qbqglfsssx
164tsthbb2
8nineldrtltqfivebqnrthrm
sevenlsjbsklhxxfiveclbldxxtrdllxzthree6eight
18gnkrxfmnineone
six4threetwoeightgcn
vmknclnmnphb2czdbjmcone
eightq67
eighthnzslhbblr85eight3
3457kdzhnppqz5four8two
crcskvmhthree41
8pccnsbv8ln3
4eightonevd
pdz9threenine
3sg5gkrncz
6dxnslkl3xqlnm965twonexxn
9nlhmmkzsdbpdctd7ninec
62eightnine7nine3lrd
qbprlzczreight7threegqnrshrhc
3qlmr
three1twojgptkzgxmf
twosvdsfourone8
5sixfourzvjtkpk
six418
five523fivecbs
nineninesevenztfggvfkgkzfcm2
qnsix5dnv7three
three5twofour
hlmtnzsmlnjxdtwo6
9sixnglrctg
onecrgfq5hdldpc
nhzctlx94eight
19djvld
tzp8zzv8six1
1nsnine5sixhqxfk
33sixtwojrdvksrfsnltglggxdhbsxf
bbvtpxptrnvjqzl3rldseventhree6
2lcntfphb2lgpjbdeight
fivetwo1jjgkt9kltwo1nc
7xnmrscpfkthreejqbhlrtf4sixrbfrone
3threetqfkv1twofive
95ninejlftlxrs1nxxfsqz
hrsrszgrcl9seven8eightksdnhqsq7eight
5436ninefour
one5five
prcmxone8lhkblvr714three
92btgsllktgf7fivejhgsg2eight5
fourmm61nine558nine
bxjx2
one6onetwotjxthreefour8
threedkpnpfvgt1one3nine1
bxfour3two2sb4twondmfdpsz
11sevennrpxftwooneeightmx6
9mqxcrjxnp7hdjgqktxm
2rnjlg7mbxstzbdh
qmsixhckzone1
qzsnq6sixtwosixtwohhgbsrqgnine3
foureight7scksqtkmnfiveseven765
15oneckvshqd
41tzlxsfivebsckffdps
threefivefournine7
5fiveonefour8lhqmltwoeighttwo
four5six
mhnrspfourmflmvkc52cjkvxheightsevendtddjdcnb
vxrrlfnlqf1twoeightninesixonetwo
8xonetwo2
rveightwo79three
onebjlr9sixldqrbtwo4
f1lhrbsix
mbbkv7ffpk
8twofourmxqvkqfcjfoureightplgpmrtxm3
2rtrxjzqeighteightqtmsfnpdscpgqvxd7
nineqggljvzvxltwozsvsfournine9
ninexpmnnvqsfhnprqrqlcgfive9mtnflvttwoqlgphhb
11kbpmv1
htspdnh1xhbbh3lzcjjx1
five6fivefive5six
sxtbktj7
ncvkgvgbeightfour89ttbrjthree
xcgxzxbfnkxdqn73eight
5nine4fivesixtwotwo1
ffgzdfhn6
fourzvtfcczlxhnnx5three
threednfntx4eightwovql
sixtwoveightnine7twonineseven
seveneightcclmgknrgninemnjsrsqsevenfftmlqkch7
pvqnltjs2hghkrphnine3scngkjfcsn
62vdnbzrcrjsndqqr2
5cxhscqpgdzbrnnq1m9b
gnkclhmbjfourfivemmxpqx2qlxvsix
sevenxcp4fourdlqgpxcl
8eighttwoone
bjslbfrspcnffnine9rvnjjrvcsix2
six7tfive6hkllf56six
km3
sixtjt2threefour2vqqcxj84
9vflltwo4five
nineprprrcjt3eightmxfour
4twoninehvsbszqr
dtdmkcsd41eightfourxppqzkjb
xmdmghzdp9sevennine94
2bbjsdlxoneeight
ninefivetwonine8
68four
ninepdjpfmzxthree3dkxgttvncbr
52threesevenninefour6lfrlrsgzk
ghkczjt86bdk3czvhcone
cdjsd6jhnnnhzbzllqdjgpgnninevmcvbcxxltsix
1mxfsrninegfmgvnine14hbfnshgbprone
39four8
bxnnjqkninetwotwo58txgvrbxvq
k4bftq68seven4nineseven
seven97fivekxjnseven4fourfour
drgttpqpsevenvrkxdlmvtctsc72seven
eight298
2zsqmjskp
six5bgdkhzqt
fournlknxg35vqdqmnln6f
565rqtzdpqhlldxgnine7oneeight
3jfthree7vlkpfour1
fourgngnqtgd675vgrrjf
25nrfive
kmlbnrm5dtvqndldh
vgbzkpnltxrp5tpvb
5mbzzk3nine7cqkngz1mm
sevenfive952
4pxk8four
seven87fourlzlnineone
zxllsctgqmsevensix72
9ggkqvsrhftwobndlt
8sixsfzlfpztjtwofourqvnptkgllxcf
5dvsjvtm
29dsvjrl3pvgjqncbgcxc
9mhvrb8fbtppbhm2s
eightninel5
jltnzpcdr8one5szgf3nine88
8xzgs4chdkfour
three7vgnbtqvhthree8sixq
2onesix354jj58
175rpdmxfeightwos
gmngst7hpfvgmtfrqbb
9hd2lsxprdvtqxcv55
four13cjqkvgxvbseven8
1kqfrqsevenqgjttjrspd
7seveneight6zfmdbzdj2
9sixpfjbnthreedgbhblmr
7hdqqqkone6htzthree
hmnxstkbzlhqjpdn3three2
dpbjgmnn1
ninefivecznsbttpcvkthreeoneeight1zqtxb
6hlxdlpgrl7six
fourdhczrzd9mmmdthcngsmdqkq9fivetwofkb
7fbcrzcxjvxtqbfive168
sevenhlrkxgrggkqgd12
vzmpvhqvkpdfmthreetwo9
21cqxtjtwoljsixxbf3
bzzxkxtl3rhsrpnnzseven
threevhdqqvtwothreenine48frqsfhgsgptbbn
foureighteight3pgbcftjdbbsmcqjcrmt21
twovpfbsd42five
6foureightwofh
5185cbhgvkvpfzk1
1one3two5
seven3mdjks6kctnnchjgpnineeight
sixfivecjfkx5
sccbfqfive28bhconexmztpcftrbz
qfzhgl1nine5four59nbxhclpk
mjrvgdz3nine6gkvznv83
mfxqslvpzeight2
ztwoneeightknnjh4nine
onefivesevenfsmmhkbcplj6seven
2lfgzblvdflgxnsqfxtksbb
blmvzczjs61fourmtds
5two2
jqppjfxfour2
3five2bcrn653
86five6bseven
rzztlcbvteight135
1sjngcngjrsht3ninehninefive
81sixkrhvrhxqhn65
dkrgmnlcbjdjxblbfnp5
three85xrckdqtjqphjsjqflmt
5fmptvmz19fourmbzrttnxnk
dptwonefbqhrxtljddtkhh6four23
xfvgkfive69
cbtfrbpxphj2sevenmmzrpccnine
5twotwoseven
fivetwoeightonefive954
zxccrkvgdqtklbnhtdtdsghcseventwo6
three6vqmtchfdjxveightone
onenine39twodksvrdsxflthree
threesbpseven5zqtwobtmpgqjg1
326dgjmzzfivehkhsjrseven
dgthreeeightthreefbhbltbdjnineseven3klvx
4xkcqeighttwo2
eightonerhlnchp17
2jcmzbczstsrmbpzxpftkmznzckhv7three
7foursixbrcc6twosixgnf
4lqxfourtvxhqtlhlx7xcfxhmqzbone
2sevenz6sixtwo
nine1pv
95jzlkxn
onerzfnqhmtjpqff93lrctjgqhseveneight
5eightrdjnine3
threetwo6fourrcrq9dfmbsznshkfqmpvcb
five3hpjznhbtjonecvfgfsk9n9
2gkbqpqn31
sevenfivefgcvtpsxjprfh8nine
lvfxml6992
5threexmjjgkv8985zzjqdbtwo
eight3bkqdnbmrtb5
7sevenoneznpx
9hjg4eightrcsvdkbmldjclfqfm
9four2one4
koneightonecdfcrjkqtcsevennlvr8hbrc
seven3lthbv8
ninexzznsix5nine
ninentdd6qvkclninefivenine
four11pgmxz7pnjfiveeight
threeninefourpmtmlgllftnvxzn5twonine
four46eight9sevenfive3three
blztvfkqggcbshlzxppxgrxsr4three3
one9pvlnv
8l37
brjvlvjrhbfourxshh1vlclvrz2
5flqnkntnxkzhcftmzb9rlfzxlg
sixfourseven77onekone
6xfmdgjfeight4qzrncxdpmb4four
four28
seven74zrtpftdldc7fqlseven5
6gxjzskpkfvmmd
zkoneight99jrrmgsfpsixfiveone
9jbbdtdxjsm8szxblgjppx4tpnvqvtlrj
rsrlrcb32ngsixfourfivenine
6seven9one7threegrfqpncjthree
onebjvpzzqhvlhg1pxkvmgqvxsrglb8fourptbjs
1fch
njhs4p86n22
two1one6four1six
fourphxjkjtwo8eight
3svqrzd1fourcmlcknhvninetddpbcmbtgqpcjms
vkndzm684sixjlgkcvz4
25five
pkzt2fivetwo2zffkjqrhgfive4jpsj
sevenmpfcthreembjgbfpkdzqlr4
49four1mpldzb3
hdzddkxf1cxftflb73
zrmhdlhk2v7
25zcd
11eighteight5qcqzpvvk
38nine43
8lstwo
12sixnfbrgbhdpn1three3
8eightcd82rzkzlvthqnvhjvgfour
24jcbjplcnqbcrxs25
3fivebfkgpkglfchbmbfps
pgmvbnhskgzdmz2sixeightcjq5
cdpmrlj1one
6hxqoneightjjv
34gxbjzrtg5
pvddskbslqnrfngmcjgsdthree3
6nkjjlknp9
hflkjhgjmeightc5n1
dmkeight1223
five9three8
eight7mqfsjplfprrfpkzctgtdvrmxphm
phbs2fck4sixfourqvqbr
2bnvktn
sfvkgzone83
2threetqnthdnq32ninetwo9
sixhdkvdcmp5three23j
8615four
twosix54vrrbvzszk9
53671
threevklcphgkjsnine4eight4fmtffknglthree
sixninethreeh4dj
oneone1pmdthreesrfsssbkt8
7foureighteight3
srpvkzrqfive378
6twodnnrvfjrjv
4kpxlslqfbktwo
bvzpgrc9twotqsvdztwoseven8
xkjdltjgzbjhxkjvtwo6
five27sixsevensixtwo9nine
jk468qgkr
fourtwo89
fourthreethreedtnzbmlfhmgjr5nineseven7
44seven
two3psfive122jps
sevensevenghzmpdvrffive9nine3eight
497ftdf9five
gklfive6rnvpnvvkqheight
2hvdfiveprrdqspsix6
5m8nine
bnctbninexsixonesix8five8
xkqqlmfmrveightsix4nine93nine
6k
3foursevensix6cksix5six
7twoone
three73lfddzhd1fkxmjdzsix7twonex
sthjlrjrhd741prcsqh3rmllvjmtvgfour
4dvffpjkn
tpbttcslvz7twoneq
fourtwoninej5snfxnqzthree
n7cmsfsqd
eightssrzkxj5
239
three8five7xxthreebqrbx
zrlchvsevenfournine4ktvskhjgh3h
7fourfdjsnhdbgqjvnltzj6three
mrjsndmzkz7rszqnbhxt3fvsix1
neight85eightggtnxtgljsevenfivekz
6vknslh4onetwonrlzm
37zlrksix1skbsdkpjf6twonejtx
three2843five6
txgdvvdg959
zfjrs2zvtbqctcdqgrpfmqsjbdone5
six9eightninetwo72sxxnzvblthree
2jdpslvbnpqjpglczkmzggkfkdkx8hgpxtcz
threefive5eight5mnbllfpcsp29vlnbrntt
gfxndggbs16twozpcsckzqcj3sthsgq6
gcjjvqkvzdbcsnmqqhnzzqvj4
flcpl3btfmbbpnkjvnlmcthreetwo1eightwops
bdmeight67tvkfh2
three645qcv1zbbheight
3ninethvbxxppxgqcqrclptxczgrcneighttwofivebrqxl
25eight41
six22
pcp5
dtmgxkdqsixdhmsbj821
eightprbxpj5oneightcxj
qvrn3jbhlxjsdq
oneclvhjhr5
9nkmqpjjxxhvtpndls9
215ltwo75
threeeight16nine2mzhxnine
ktfxkmdvzprhkpdhvxhzsc68
fivesix8five
4z1eighttwofive
73twotwo4
gmjlpchdzfthreesix1vljxdqsrlxmmqs2
twofxh3
threeqzcglsdcfm4four
three1eight8
seven7dtqhr7
4xbjlxlptj8hzfjnz
37jzgxbjcggone
81fouronenine489four
eight3fiveoneseven135
stzts59zqdvrdcqrc
sixnklrjbeightn2six
bqdtntwonine1eightttzlzvzfn54xmj
sjk6
qmrbnhczj624394sevenseven
kkjdcjhfh93eight
3ptmslnconethree
cfjgdffcgvldsnvkbjqrxhxcl7fjlxdrlrrthreeseventwo
187oneseven6
fiveprnppdg2tjfbfmlvhpmkggjc
9onetwo4
fivesvjxkzzm59vtsevenhzxtkggdhr8hvjtjvv
kpxkbbxseveneight89sevenrbhqqpk
drhkpssxqvvnssq59four4
oneeight17
gteightwoone268four
eight7fourbjnlzfiveczlzppnxck
jdqpxsevenone2eight
pvh5six4hddrhfzpxfmtwo
5six56nineone2
v96k9115three
phqhhthree5ksqhfjlbfg
gpsskbfhhllnxfvjspkjndtlfour5
three5zqbnsrdthree8
b4mkfpkltlfdfive4mdqxjnb8tdpnpf3
qfivejjggrpktxponetrjzceightseven9xhdf
34cpfxc
jl9
84four
fourthree9three48
7threevgvtj2five4pbq
7kjkjc
seventfsvjbsh5smmdd3frthree
smgmzqzn5
gmtd5kvglxsixeight8twothvkprlbc5
twofour62
nine5k
hbxnpb4four4h
6sixgnmnjv4fourone1
9eightseventhree
9jpvccsvhqpnhsl8
nvcnninefour9
v237ppqbhb
78six
four165oneightxcm
9pjcsfbrghnineqzth4smx
46fpfptrq1mbqmbnktqeight
stbxvlcqz5krd1threethreeonefour
48six5seven
6bmltlrvrgpcfhjhmfiveqzfxptjtwo4zvsqqxgbrdlzsfmtzdd
jeightwo47three86twoseven
njxzmthree8fivevvchvjqdvn3foursix
83t34
oneznzqptpxbrtqxstkmz3kmtstds
1sixsfrnqd
brs7fgkbhntv5s5
twohs7m
gfljsixseventmgdvhqthree3threefive
f1twonekdh
oneone735eightnine
pfjvfspsseven9qgfrnmckxzsix94
7nineninelrcqqcgcnmmqf3
1vjdhjtrfourfive2nine278
oneone7
threelcxlqrzhdghp4zkjfivepjj
hcshggsmzpdmkvtdvdgqtfxlt8
1vdjtvpfhkhfive1
2eightstnj6three
93threeeightntjblpljbv
onermlmtncmj6pxkmhmqchzvzf
4eightfnjzfzhvg
hmjvmtwovnl8nine84
threets6
six9twofivexgz63
692five
fkgblptntvhvmlv8threethreenine
seven86
nine1n7
97two
4threebqqnmvmqleightthreefiveszppmbhxrxvpxz
6bxbmbdkxqmzeightlrqdqvrkr5threethree
llqcbpeight1vpjninekpdvzg
6qgtdqvtvkcbcskfqtq
6threegrrmxxxqkflltr3
312
hqmhsxpmkxtwosix3
rpzqtmzgdfdxcgsix1six63lxjpbxfq8
zzkbtkghmmqfourrtsixxxfjnvvccmpsd5six
13two4bxdcqzrkqtxm1mplvqxcfhcjsc
threesixqj8two
9seventhree
dtnine5twoseven6zxd
lsqbvgjnznineone7lxtvmkmflrfcqdjmjtwo
zpkjlfp6onevxtdtdzmcqjprfive
gxplqqsz412sevenninejs1
psvjsvvnrv796
69tfxkbkchvlhkjbrmone
fivehnrvtb6
eightzdlqrbzxteightptlgmcmvtwothreergcddqxf2twonepxh
343sevenxsffneightdvft
fivednmrpmvv8fiveninesevenzbggk
seventwot3hpfrzbhxlhfivetwo7zvmpmq
xnsxz8fivezhzdcbzsvp
sfzch8twoned
5rstpx
12six
gqznine5gpg
6zrmsp825seven
2493twothree
9fivemksdnmgbvx
6dvdpdpkmqpxvfive28six
dzvnrdksixonetwoonetr4
7fncndxbqj6onetwosixsixthree
7cnprcdgk2three2dvtccqnskvzfsevenxdrnqf
cxfcdvbsjqjbnxddlggjfourtnfzvtgx4twoddkkpdd
pxjgqrmdg5mpcgcdmfeight825jxxqcnfive
1tkhgtzzfrbdvnbft
hgxfive14ddcfhshfd4
onenzlhvtdgkjmjgldmddhngdv9onebkt
foureight8rzxkktk9eighteight1
478nshqhnhjrmlqbmp
ddjzzxgj75zktccgqrltfivethree
eightmcnmt5jnmnqhqdfive
rcdxshk1seven5
rdcmbznk79
2gtbskjxpmmvdclgmfjrc48one
8mqgnfive7chknsixrfourseven
4hgdxjgbn1sixseven7twosixseven
mkjslkltjd59
fourfoursixfkjrcfsfivenrtzv4eight
five8threeseven4
81821tcmfourddhmzvzfive
onesix943fivejld
5eighteight3cmvvpqmdq72vrvb
two86
nqjrpqvgqr7rjjjxglqzrmt
5kqjjvzxt
6fourvstjrlnvone3ndphzphkrnsqmkmsthreep
six8four7
two1dntwo
eightgmcgrnptrcvztbdp4three
xxbpnnztr5eightpnqeight
three9pfpnjx6rkphpjeight3five
sevendzstsjl3krspscb1
fsevenfqtxxhjzvnineninesixeight8
kznjhnxbnk7qbxjrztltv
rkeightwo6zfpvrfgqr7qxbkkg43lrjqtzjrprqttxmbrzg
mcfive77vgzxonehglbj
9319
4mzds
sevensixthree5sixdvzxkndhvjfive
9mjhfkeight88v
seven5zhdthbmrkdpdxfcp8njtqvpnjj14
8ninetwo
95tnjldjqcrzdxlm3
fourgffour8
nine821qbv6five
jbtfg83two
twozcpjrcnplnz5bdtgpdctb87lzlvqhtrjj
tr4
5foureightfourfcs
1cqjts1jgzkfm
66threetwo
jsdpkfnineeightzpjdmrvxkbhdntj9
pgcqrsix6mqrr8threeqxgkftbmzninevndn
kmvqsqhbrcnbqqgninet6
bxtstqzpqfzqnhjfb8htszvgqhpnggvqt
ninecpqpffivehg8
kxmstxkffourqmx41
scfourlkfbrjvbtwo5
qr88fivenine1lfvksgrtqseven
four6foursix
twoqmnxrjql5fourpdlstnnsfkdjgt9
4zsvbsjqv97bpxvncr
xhqlhsbqjhvdqqonesevenfive3qvrtbkhhlfbzsj9
sixeight4six5szgzcjhpj1
7vpjq9hjtrjgone
f92eight
eighteightnc8134
22onespjpxlttsqsix8eighthxdfvsdx
5ninefourgrrmxsxjfxk
threeninepmvsv763xlxjp
oneone7lzzhjqqrg
9fourtqqmhrpmkxhrvlnjvvhsevenseven
threethreetvjpnoneseven8
two46onetwoqbvntlxbrftpjf9
8one5nine1three8
three69sgdkstpqbqdz
q8rzcl
onepjmchxtlqnmrcrvm6
61fivegjjsevenqgdkq
49fxhdzfntmk6tb8dpdkknzsb
bbseven1xvqmlrhx
2j
seventwozjqszlhzxlpgphnkz2foursixfour
1sixhgvhrbonetwom
fournine8gvmrpgdxvcbdspzdcqt87bdzvxbf5
3sevennine2fzpt
threedcdlq9kcjhtmtz
86five
tpfqhqs3977
8four1cgmm12shfl58
xlkrrkpkqjtslblqfnxp7two16jzpmpkrfvdzh
243
three9hkgnmrh6lqrsx5
fivexsczpmltrmcgrvfc58
mxngrsh2sevensixthreelgrmg
ljqmflvone76
ksponeightthree2ninenine
tdsdmjznr5nine7fourtwojgjsdfsevenone
eightfive1fourseven3gsqhtv
1xfdmqtmgkmjkthree
rztwonelztpgkxzzcbn1eightttssdpone71
zthhsgvmhqsgvdponetwo9p
293rmjjjpmjchjnbdcssfrneightvdzrkbhdln
7nfkdntfourthreefzrfxmxgqone5
tkgrnhbflp7zltmbdoneeightwoh
7bspgfklffgsix4
eighthcmlrpbhjjmvbjrleightgd94
sixbgfjzgzbxsb4qsixthreehbbn
ninerhzjpjdfnsevenonenine8
38kqzjxqmmm
jngngvc412
4twosponesixdpj15five
41four2oneonekr2
cpsixjnlhkthree353seven
bknflgv1sixfivefive5
3qkhnsjqkcjmlg7gl4jthreethree
dhlngstrvbxjjll2979kjsttsfgjkc
4kkq7rqlxcldqqtwo
jfh74
lkfpcdghgq8gpgldrsnzkzzzzskrvcvsjthree
57fivefive3cxqj2
ztwone7vcd37122
4qrrhhlxgpr4
twokzfjg2sevenlnvlpzxknznpsc1
4jjbcdbfm8six6four
5eightninesixvzvf98two
8flntwomkktkpvsone78sixone
sevenzltjhkptjfjbrppm85eight
fivemfrmnqptthreepninepd5
6one9
vkqxgzmbm2b4pjqjddsbjnjcqqvm9
5443nfkv
leightwo5
8fiveeightonetwovgvhzgzfjh16eightwohlk
fivexnbhkzjfg1
chkxvgrgb1sqxsnhngnrtqsnqgjkd
96twoone5553dv
36pfltskrbcmlmnspn
4jbbrh95249
xfzspqssdfourhnmtzfive2pfzczh
onexzbzhddkqgfr2
sevenninerrlveight5nine3
eight7qvgkbk238fiveeight
sevenseveneightgtxtxkjsgdgklzzxxc3two8
tvfjhvtclm75skqdxsskqhrjkbg
45
sevenfive82
425zkhjhmk
onexdchhtxmhsevenbczrslrppneightonenbnhfmbsvdcnzjx1
zfkscdbmtwoeightrksdmgx4
lnseightnine9eight
fourhmbhlcpht53ngkbzjmfivesixg
threestrhbj9sixggczcg
9twoskgrps8
3four6xdqczgtzlzf
ldfn2
qlzjsnbzfourfdq476
tpkczdh5hdbxvvmmt3sixsix
tdpxzld5
lnveightwohdkgcvvrjs38
zz8eightstvmhvrh7hftdhkrjcneight1
9kdbcpqtx15
rbqgdbvrstgninefive4bqq2six
nine3psmkzkgnjbndrcninesevenzvcr6
eight4jfrqcbqfninedxmdtjgqgtrg6four5
3mmnineninenjjpmfivetwo
cv4znxcjthreeqqtdqmzxfknnp
8pjkm
ptwonethreegrgvseven7
onethree1bgjsix5sevengpts
96xlmmthreeeightcbdnrstvpncmr
rtc94tcninefive
onespqnnptpdbrgqsqrldstl1
qkeightwotwocjcngknkztwo7
gzjhzlf4fdglcrzckbrlkmg
3eighttwopninefour
2seven1c
17nine447qkmfour2
six6xfgqddnfpsc
mkbgbkvzdpzxfmrhdcjklxfoureightzzpn3eight
95ninevhctbgznbzz871sixoneightr
31onekmseveneight2four
mlxqgmvj2six6
2sixgvsbmrhtwofour
eight221three99two3
88xrrbjdlzrfour8plv
xdglmrpxbz5xpjxzpmvrgsixthreeseven7threebtqfkqp
lbd2onethree
seventwoseven7threesixbpld
1pstwofour8eight3dsdfrseven
gnvzm19htsbvcsfmlrmbgtstzmm3twoqzffkrrq
94nvrbbj
one71rsfbpnnbkrklmxqfive
4six1
eight48chsrmsix
vqxrnmsix98hlzdgvd3sevenninekng
12threehscqzvzcbgfive6three2zhtthr
6sixkzrnv
5gmnhhzkfmp
four35seven7onenvdsevenftnpbcj
6zxrhcxxkppkn2
dgshxchmhgtgjk281seven
lbdsmfvdsfzlp6dfpgd3
three2dpsdhfld95eightwoht
jbktdklsqkgnhnfmseven1lhdsbjksixtwo
3fdqfour
5jpljkkpmdsix
qfeightwo9threethree
hpqdx4911tzfcxlrtccqf9one
q79zspgmjpdzs63
344zk5xbthreezgbffcb
nlzmjfqxmneightxqjdnjvr21
8cxtrkpvzj21xfgbdgcvgrztwo
three18444
sntrptktwo2one1five
qxjrgfcnpcjtnfjljqnq1onehzfcqlnine
kflgzv58dbzbjjdvclgtseven
twofive4eightwozz
eightfive365
7nqnksvphhnine88
t8eight
bjd6five
khbrbtsx5jqxmbsqtf5nine3sevenskhfg6
seventlkmfhqkgxkbhqr6ncjztnfive
152one
three5cbpqkzb4eightseventgmqzflsfksix
seven32threegfddgtf
two5twofivexzkkvcqs3
tvvdgrnqlmkfour1zrcznqkhseveneight1q
92threesix89
3zbdlttpbh7fivepgxmrvbzlnfgmbkzknndfqk5
threefnhxtdbl1jtxeightwol
5vgthldgfmgdjphvcgh53dshmdkc
3nineeightwokh
57eighttddbcdsjdss
tkcgn86xfgbmzt7rksvnchnrh
five3dn5
three2eighteight15nine
49bn1zvbm57
351six6xfzfjvpz
5one5zchddj4dkksn
xfhtwonesevenfivethreepqzmrzrrfourthree5
ninetzmcgp47four
sevenbcfbpnrvkkscrjtpctdtb69bvvnvlgsmjltlvs
6threev
ninerlsbznvfn9
fourbm2
sdxd22
n7
7sixcjdsxfourfmvzrbvlnine5
threeqtbhgznine7one
ftmkmxkd9fvvlg353rp51
9zjhmpnjv5jvndz
58three59nineonesix
rmjvhrjjmkqsn6gqthreeonefivemxqhrzvffone
xsslv7gpgkbzdmr434four
pnzxp4nbtsjqctkvqncxzxzj
eightseven52five4ninekntfjrdt
4sixldsmv
pknxkqgdpnc7fivedbvhkn
qkpjhjlxone4sixpfkvhlmxmd3
four3ninerkrcvgcmbb2qm
fivenine6six1eight
69sixnine
bvjx5lg5vgrqq
21ninegnhdkcxhzkcfdksvsmdthree
zjrnmhclxhrkjpffhxkthnvj83jnshbqvx
bzfphcg9fourthreegkchdvrgsx
2ninebvgdcfxtktqjxjqvxfgjdqfhv5threegqtsfhtfxg
6rqskvckjzq2qzrnbxjmlthreeeight6hrs
sixthree6lxcrsevenseven69twonegs
2dcvcqcbpshsixone3
drkdbmv4zbjbznsqtj
eightbqfhnmvqsoneninezbrzcqkz4ftv
1eightcrcjcbdthreebscfpvznqfrj6
#+end_src
* Day 2: Cube Conundrum
** Part One
*** Quest
You're launched high into the atmosphere! The apex of your trajectory just barely reaches the
surface of a large island floating in the sky. You gently land in a fluffy pile of leaves. It's
quite cold, but you don't see much snow. An Elf runs over to greet you.
The Elf explains that you've arrived at *Snow Island* and apologizes for the lack of snow. He'll be
happy to explain the situation, but it's a bit of a walk, so you have some time. They don't get many
visitors up here; would you like to play a game in the meantime?
As you walk, the Elf shows you a small bag and some cubes which are either red, green, or blue. Each
time you play this game, he will hide a secret number of cubes of each color in the bag, and your
goal is to figure out information about the number of cubes.
To get information, once a bag has been loaded with cubes, the Elf will reach into the bag, grab a
handful of random cubes, show them to you, and then put them back in the bag. He'll do this a few
times per game.
You play several games and record the information from each game (your puzzle input). Each game is
listed with its ID number (like the =11= in =Game 11: ...=) followed by a semicolon-separated list of
subsets of cubes that were revealed from the bag (like =3 red, 5 green, 4 blue=).
For example, the record of a few games might look like this:
#+begin_example
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
#+end_example
In game 1, three sets of cubes are revealed from the bag (and then put back again). The first set is
3 blue cubes and 4 red cubes; the second set is 1 red cube, 2 green cubes, and 6 blue cubes; the
third set is only 2 green cubes.
The Elf would first like to know which games would have been possible if the bag contained *only 12
red cubes, 13 green cubes, and 14 blue cubes*?
In the example above, games 1, 2, and 5 would have been *possible* if the bag had been loaded with
that configuration. However, game 3 would have been *impossible* because at one point the Elf showed
you 20 red cubes at once; similarly, game 4 would also have been *impossible* because the Elf showed
you 15 blue cubes at once. If you add up the IDs of the games that would have been possible, you
get =8=.
Determine which games would have been possible if the bag had been loaded with only 12 red cubes, 13
green cubes, and 14 blue cubes. *What is the sum of the IDs of those games?*
*** Puzzle Solution
I decided to make the code for this as readable as possible.
I've split the process into multiple parts:
**** Record Splitting
Here, I am turning the input data into an alist with the game number as key, and the draws as value
of the entries, by using irregex matches.
#+name: day2-part1-record-splitting
#+begin_src scheme
;; Records
(define record-pattern
'(: bol
"Game "
(submatch-named game-no (+ (/ #\0 #\9)))
":"
(submatch-named draws (*? any))
eol))
(define (record-kons from-index match seed)
(cons
(cons (string->number (irregex-match-substring match 'game-no))
(draws-fold (irregex-match-substring match 'draws)))
seed))
(define (record-fold input)
(irregex-fold record-pattern record-kons '() input))
#+end_src
**** Draw Splitting
Next, as already called inside ~record-kons~, the list of draws has to be split and processed into
individual draws. Here, I simply split them.
#+name: day2-part1-draw-splitting
#+begin_src scheme
;; Draws
(define draws-pattern
'(: " " (* (~ #\;))))
(define (draws-kons from-index match seed)
(cons
(draw-fold (irregex-match-substring match))
seed))
(define (draws-fold line)
(irregex-fold draws-pattern draws-kons '() line))
#+end_src
**** Draw Processing
And as the last pre-processing step, I take apart the individual draws, and assign each amount to
its respective colour keyword.
#+name: day2-part1-draw-processing
#+begin_src scheme
;; Draw
(define draw-pattern
'(: " "
(submatch-named amount (+ (/ #\0 #\9)))
" "
(submatch-named colour (or "red" "green" "blue"))
(? ",")))
(define (draw-kons from-index match seed)
(cons
(cons (string->keyword (irregex-match-substring match 'colour))
(string->number (irregex-match-substring match 'amount)))
seed))
(define (draw-fold draw)
(irregex-fold draw-pattern draw-kons '() draw))
#+end_src
**** Main Program
I check the possibility of a game by folding over its draws, starting with a ~#t~ (true) value;
basically, it is nothing more than a recursive ~and~ statement.
#+name: day2-part1-success-check
#+begin_src scheme
;; Game success check
(define (game-possible? draws)
(foldl (lambda (seed draw)
(and seed
(>= 12 (alist-ref #:red draw eqv? 0))
(>= 13 (alist-ref #:green draw eqv? 0))
(>= 14 (alist-ref #:blue draw eqv? 0))))
#t draws))
#+end_src
Then, I put everything together in a main function, preprocessing the input and summing up all game
ids for which ~game-possible?~ returns ~#t~.
#+name: day2-part1-main-function
#+begin_src scheme
;; Main function
(define (sum-of-valid-games input)
(let ((games (record-fold input)))
(foldl
(lambda (seed game)
(let ((game-id (car game))
(draws (cdr game)))
(if (game-possible? draws)
(+ seed game-id)
seed)))
0 games)))
#+end_src
And now, everything can be put together:
#+name: day2-part1-solution
#+begin_src scheme
(import (chicken string)
(chicken keyword)
(chicken irregex))
;; Draw
(define draw-pattern
'(: " "
(submatch-named amount (+ (/ #\0 #\9)))
" "
(submatch-named colour (or "red" "green" "blue"))
(? ",")))
(define (draw-kons from-index match seed)
(cons
(cons (string->keyword (irregex-match-substring match 'colour))
(string->number (irregex-match-substring match 'amount)))
seed))
(define (draw-fold draw)
(irregex-fold draw-pattern draw-kons '() draw))
;; Draws
(define draws-pattern
'(: " " (* (~ #\;))))
(define (draws-kons from-index match seed)
(cons
(draw-fold (irregex-match-substring match))
seed))
(define (draws-fold line)
(irregex-fold draws-pattern draws-kons '() line))
;; Records
(define record-pattern
'(: bol
"Game "
(submatch-named game-no (+ (/ #\0 #\9)))
":"
(submatch-named draws (*? any))
eol))
(define (record-kons from-index match seed)
(cons
(cons (string->number (irregex-match-substring match 'game-no))
(draws-fold (irregex-match-substring match 'draws)))
seed))
(define (record-fold input)
(irregex-fold record-pattern record-kons '() input))
;; Game success check
(define (game-possible? draws)
(foldl (lambda (seed draw)
(and seed
(>= 12 (alist-ref #:red draw eqv? 0))
(>= 13 (alist-ref #:green draw eqv? 0))
(>= 14 (alist-ref #:blue draw eqv? 0))))
#t draws))
;; Main function
(define (sum-of-valid-games input)
(let ((games (record-fold input)))
(foldl
(lambda (seed game)
(let ((game-id (car game))
(draws (cdr game)))
(if (game-possible? draws)
(+ seed game-id)
seed)))
0 games)))
#+end_src
** Part Two
*** Quest
The Elf says they've stopped producing snow because they aren't getting any *water*! He isn't sure
why the water stopped; however, he can show you how to get to the water source to check it out for
yourself. It's just up ahead!
As you continue your walk, the Elf poses a second question: in each game you played, what is the
*fewest number of cubes of each color* that could have been in the bag to make the game possible?
Again consider the example games from earlier:
#+begin_example
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
#+end_example
- In game 1, the game could have been played with as few as 4 red, 2 green, and 6 blue cubes. If any
color had even one fewer cube, the game would have been impossible.
- Game 2 could have been played with a minimum of 1 red, 3 green, and 4 blue cubes.
- Game 3 must have been played with at least 20 red, 13 green, and 6 blue cubes.
- Game 4 required at least 14 red, 3 green, and 15 blue cubes.
- Game 5 needed no fewer than 6 red, 3 green, and 2 blue cubes in the bag.
The *power* of a set of cubes is equal to the numbers of red, green, and blue cubes multiplied
together. The power of the minimum set of cubes in game 1 is =48=. In games 2-5 it was =12=, =1560=,
=630=, and =36=, respectively. Adding up these five powers produces the sum *=2286=*.
For each game, find the minimum set of cubes that must have been present. *What is the sum of the
power of these sets?*
*** Puzzle Solution
Most code can be reused from the first part; only the success check and the main function have to be
rewritten to accommodate the new requirements.
The success check gets replaced by a function that multiplies the maxima together.
#+name: day2-part2-powercalc
#+begin_src scheme
(define (powercalc draws)
(* (apply max (map (lambda (draw)
(alist-ref #:red draw eqv? 1))
draws))
(apply max (map (lambda (draw)
(alist-ref #:green draw eqv? 1))
draws))
(apply max (map (lambda (draw)
(alist-ref #:blue draw eqv? 1))
draws))))
#+end_src
And the main function gets modified to sum everything up.
#+name: day2-part2-main-function
#+begin_src scheme
(define (game-set-power input)
(let ((games (record-fold input)))
(foldl + 0
(map (lambda (game)
(powercalc (cdr game)))
games))))
#+end_src
The full thing put together:
#+name: day2-part2-solution
#+begin_src scheme
(import (chicken string)
(chicken keyword)
(chicken irregex))
;; Draw
(define draw-pattern
'(: " "
(submatch-named amount (+ (/ #\0 #\9)))
" "
(submatch-named colour (or "red" "green" "blue"))
(? ",")))
(define (draw-kons from-index match seed)
(cons
(cons (string->keyword (irregex-match-substring match 'colour))
(string->number (irregex-match-substring match 'amount)))
seed))
(define (draw-fold draw)
(irregex-fold draw-pattern draw-kons '() draw))
;; Draws
(define draws-pattern
'(: " " (* (~ #\;))))
(define (draws-kons from-index match seed)
(cons
(draw-fold (irregex-match-substring match))
seed))
(define (draws-fold line)
(irregex-fold draws-pattern draws-kons '() line))
;; Records
(define record-pattern
'(: bol
"Game "
(submatch-named game-no (+ (/ #\0 #\9)))
":"
(submatch-named draws (*? any))
eol))
(define (record-kons from-index match seed)
(cons
(cons (string->number (irregex-match-substring match 'game-no))
(draws-fold (irregex-match-substring match 'draws)))
seed))
(define (record-fold input)
(irregex-fold record-pattern record-kons '() input))
(define (powercalc draws)
(* (apply max (map (lambda (draw)
(alist-ref #:red draw eqv? 1))
draws))
(apply max (map (lambda (draw)
(alist-ref #:green draw eqv? 1))
draws))
(apply max (map (lambda (draw)
(alist-ref #:blue draw eqv? 1))
draws))))
(define (game-set-power input)
(let ((games (record-fold input)))
(foldl + 0
(map (lambda (game)
(powercalc (cdr game)))
games))))
#+end_src
#+results: day2-part1-solution
: 78375
** Puzzle Input
Jump to [[#headline-22][day 3]].
#+name: day2-input
#+begin_example
Game 1: 2 blue, 4 green; 7 blue, 1 red, 14 green; 5 blue, 13 green, 1 red; 1 red, 7 blue, 11 green
Game 2: 6 blue, 3 green; 4 red, 1 green, 7 blue; 2 green
Game 3: 4 blue, 3 red; 2 blue, 4 red, 7 green; 1 blue, 6 red, 7 green; 5 green, 10 blue; 9 green, 1 blue, 6 red; 8 blue, 1 red, 12 green
Game 4: 15 blue, 4 green, 5 red; 2 red, 2 green, 5 blue; 3 green, 13 blue; 17 blue, 1 green, 5 red
Game 5: 11 green, 4 red, 3 blue; 8 blue, 6 green; 8 green, 2 red, 9 blue; 4 red, 16 blue; 8 blue, 10 red, 6 green; 9 blue, 3 red, 10 green
Game 6: 4 green, 9 red, 2 blue; 7 red, 2 green, 15 blue; 13 red, 2 green, 6 blue; 5 green, 7 blue, 6 red; 19 red, 15 blue, 4 green
Game 7: 12 blue, 5 red; 5 green, 6 blue; 5 red, 15 blue; 5 blue, 5 red, 5 green; 1 green, 11 blue, 2 red
Game 8: 6 red, 11 green; 5 red, 2 blue, 7 green; 7 red, 6 green
Game 9: 5 red, 1 blue, 11 green; 4 green, 1 blue; 8 green, 2 red; 1 green, 2 red, 2 blue; 3 green, 2 red
Game 10: 7 blue, 4 red, 11 green; 13 green, 1 red, 1 blue; 7 blue, 6 green
Game 11: 4 blue, 7 red, 2 green; 1 green, 14 red, 3 blue; 2 green, 5 red, 3 blue
Game 12: 6 green, 6 blue, 1 red; 1 green, 3 red, 2 blue; 2 blue, 6 red, 7 green
Game 13: 6 red, 10 green, 13 blue; 3 red, 12 green, 9 blue; 11 blue, 1 green; 4 red, 3 blue, 13 green; 12 green, 10 blue, 6 red; 13 blue, 3 green, 3 red
Game 14: 8 green, 1 blue, 17 red; 7 green, 11 blue, 19 red; 19 red, 9 blue, 2 green; 8 green, 20 red, 12 blue; 16 red, 3 green, 11 blue
Game 15: 3 red, 1 green, 5 blue; 9 blue, 4 green; 6 blue, 5 green, 9 red
Game 16: 13 blue, 1 red; 2 blue, 2 green; 1 green; 10 blue, 8 red; 4 red, 3 green, 9 blue
Game 17: 10 blue, 2 red; 3 green, 4 red; 6 blue, 1 red, 6 green; 5 green, 7 blue, 5 red
Game 18: 3 red, 1 green; 2 red, 5 blue; 5 blue, 2 red
Game 19: 7 green, 4 blue, 1 red; 1 green, 4 blue, 4 red; 6 blue, 8 green; 4 green, 2 blue, 1 red; 1 red, 1 blue, 2 green
Game 20: 13 green, 1 red, 1 blue; 12 green, 1 blue; 5 green, 1 blue, 2 red; 16 green, 3 red; 2 red, 9 green
Game 21: 8 red, 2 green, 2 blue; 5 red, 3 blue; 2 blue, 5 red, 2 green; 7 blue
Game 22: 9 red, 12 blue, 7 green; 7 red, 13 blue, 4 green; 9 blue, 13 red, 1 green; 3 blue, 4 red, 5 green
Game 23: 7 green, 12 red; 6 red, 7 green, 4 blue; 1 blue, 11 red, 5 green; 4 green, 2 blue, 6 red; 12 green, 6 red, 3 blue
Game 24: 11 red, 4 blue; 9 blue, 6 green, 17 red; 8 green, 2 red; 16 blue, 6 red, 2 green
Game 25: 7 red, 4 blue; 7 blue, 4 green; 10 blue, 4 red, 2 green; 6 green, 4 blue, 1 red; 10 blue, 2 red, 4 green
Game 26: 7 green, 8 red, 6 blue; 5 red, 3 green, 2 blue; 13 blue, 6 green, 5 red; 10 blue, 4 red, 8 green; 2 red, 2 blue, 1 green; 8 blue, 1 green, 4 red
Game 27: 7 green, 3 blue, 13 red; 1 green, 17 red, 1 blue; 16 red, 3 blue, 3 green; 5 green, 3 red, 5 blue; 13 red, 4 green, 8 blue; 6 blue, 2 green, 15 red
Game 28: 8 blue, 5 red, 18 green; 1 green, 6 red; 7 blue, 18 green, 5 red; 16 green, 3 red, 7 blue; 6 blue, 18 green; 8 blue, 8 green, 7 red
Game 29: 4 blue, 1 red; 6 blue, 1 red; 17 blue, 1 green
Game 30: 1 red, 2 green, 5 blue; 2 blue, 7 green, 6 red; 11 blue, 4 red, 2 green; 5 green, 6 blue, 4 red; 5 red, 8 blue, 7 green
Game 31: 10 green, 9 blue; 5 green, 9 blue, 1 red; 1 red, 8 blue
Game 32: 3 red, 5 green; 5 red, 5 blue, 14 green; 2 red, 2 green; 11 green, 3 red, 5 blue
Game 33: 7 blue, 10 green, 8 red; 18 blue, 15 green, 4 red; 6 red, 1 green; 18 blue, 8 red, 11 green
Game 34: 3 green; 2 red, 5 green; 5 blue, 3 green; 3 blue, 5 green, 1 red
Game 35: 1 blue, 5 green, 6 red; 3 green, 2 red, 3 blue; 4 red, 9 blue, 3 green; 1 green, 12 blue, 1 red
Game 36: 14 green, 3 blue, 16 red; 1 green, 2 red, 4 blue; 4 blue, 9 green, 18 red; 4 blue, 4 green, 14 red; 4 blue, 11 green
Game 37: 7 green, 2 blue, 3 red; 8 green, 9 red, 2 blue; 4 blue, 15 green, 18 red
Game 38: 11 red, 1 blue, 6 green; 6 green, 2 blue, 1 red; 6 blue, 17 red, 2 green; 17 red, 9 blue, 3 green; 7 red, 7 blue, 3 green; 3 green, 7 red, 7 blue
Game 39: 1 blue, 2 green; 1 blue, 2 green, 7 red; 1 blue, 4 red, 2 green; 1 blue, 12 red
Game 40: 1 blue, 4 red, 15 green; 12 green, 1 blue, 15 red; 15 red, 8 green
Game 41: 5 blue, 5 green, 1 red; 9 red, 8 green, 9 blue; 10 red, 10 blue, 4 green; 3 blue, 17 red, 3 green; 3 blue, 4 red, 2 green
Game 42: 2 blue, 10 red, 17 green; 6 red, 10 green, 10 blue; 3 blue, 6 green, 8 red; 9 green, 2 blue, 8 red; 13 green, 5 blue; 4 red, 18 green, 11 blue
Game 43: 8 red, 3 blue, 6 green; 2 red, 8 green, 10 blue; 5 blue, 9 red, 9 green; 1 green, 15 red, 8 blue
Game 44: 11 green, 19 red, 14 blue; 1 red, 19 green, 9 blue; 7 green, 8 red, 10 blue; 14 green, 8 blue, 15 red; 7 green, 3 red, 2 blue
Game 45: 4 green, 9 blue, 4 red; 7 blue, 13 green, 2 red; 12 green, 10 blue, 10 red
Game 46: 10 red, 2 green, 1 blue; 10 red, 10 green, 1 blue; 1 blue, 13 green; 1 blue, 2 green, 10 red; 1 blue, 7 red, 11 green; 10 red, 5 green
Game 47: 3 blue, 2 green, 12 red; 5 blue, 7 red; 5 green, 14 red; 12 red, 7 green, 5 blue
Game 48: 5 red, 1 blue, 3 green; 7 red, 8 green, 4 blue; 4 blue, 5 green, 17 red; 1 blue, 12 red
Game 49: 2 green, 7 red, 1 blue; 11 green, 5 red; 4 red, 1 blue, 1 green; 11 green, 1 blue, 7 red
Game 50: 10 red, 3 blue, 6 green; 1 blue, 5 red, 3 green; 6 blue, 11 red, 12 green; 10 green
Game 51: 18 blue, 1 green, 1 red; 15 blue; 13 blue, 11 green, 4 red; 8 red, 1 green, 18 blue; 10 green, 7 blue, 8 red
Game 52: 13 green, 15 blue; 6 blue, 4 red, 8 green; 6 red, 13 green, 11 blue; 2 red, 7 green, 13 blue; 12 green, 2 blue, 3 red; 6 red, 11 green, 1 blue
Game 53: 2 red, 2 green; 3 green, 1 blue, 1 red; 1 blue, 4 green, 7 red; 4 red, 1 blue; 4 red, 5 green, 2 blue
Game 54: 8 blue, 2 red, 5 green; 6 green, 2 blue, 3 red; 1 blue, 8 green, 4 red
Game 55: 6 green, 6 blue, 3 red; 13 green, 1 red; 2 blue, 1 red, 1 green; 14 green, 1 blue, 1 red; 1 blue, 2 red, 9 green; 9 green, 2 blue, 4 red
Game 56: 4 green, 6 blue, 1 red; 5 red, 3 blue; 6 red, 1 blue; 9 green, 5 blue, 7 red
Game 57: 5 red, 5 green, 8 blue; 11 red, 3 blue, 8 green; 7 green, 9 blue, 11 red; 3 green, 2 blue, 12 red
Game 58: 3 green, 3 red; 4 red, 1 green; 1 red, 6 green; 5 green; 5 red, 1 blue, 3 green; 3 red, 1 blue
Game 59: 2 green, 2 blue; 7 red, 18 green; 2 blue, 7 red, 16 green; 7 red, 10 green
Game 60: 3 blue, 4 red; 4 blue, 3 red, 3 green; 16 green
Game 61: 1 blue, 2 red, 8 green; 9 blue, 4 green, 12 red; 10 green, 2 red; 5 blue, 11 red, 1 green; 10 green, 3 blue, 8 red; 5 red, 2 green
Game 62: 15 red, 10 blue, 7 green; 4 blue, 9 red, 4 green; 4 red, 2 blue, 2 green; 11 green, 2 red; 8 blue, 2 green; 2 green, 8 red, 8 blue
Game 63: 2 green, 3 blue, 1 red; 7 blue, 5 red; 7 blue
Game 64: 3 green, 5 blue, 6 red; 9 green, 4 red; 13 red, 1 blue, 5 green; 4 blue, 13 red, 8 green
Game 65: 7 green, 1 blue; 1 red, 14 blue, 4 green; 8 blue, 6 red; 14 green, 4 red
Game 66: 6 red, 11 green, 7 blue; 1 blue, 6 red; 13 red, 7 blue, 3 green; 8 red, 6 blue, 15 green; 7 green, 6 blue, 4 red; 4 red, 1 blue, 20 green
Game 67: 4 blue, 9 green; 15 red, 16 green, 3 blue; 1 green, 14 red, 3 blue; 3 red, 2 blue, 3 green; 4 green, 3 blue, 12 red
Game 68: 5 green, 3 blue, 2 red; 4 green, 8 blue, 11 red; 6 red, 6 blue, 4 green; 8 red, 5 blue, 7 green; 6 blue, 6 green, 11 red; 2 blue, 3 green, 3 red
Game 69: 15 blue, 16 green, 5 red; 10 blue, 3 red, 13 green; 4 red, 5 blue, 2 green; 1 red; 11 green, 5 red, 15 blue
Game 70: 8 red, 9 blue, 12 green; 3 red, 2 blue, 14 green; 10 blue, 1 red, 18 green; 1 blue, 7 red, 16 green; 3 green, 4 red, 16 blue; 10 green, 6 red
Game 71: 12 blue, 7 red, 16 green; 2 red, 9 blue, 15 green; 1 red, 11 blue, 11 green; 15 red, 16 blue, 2 green
Game 72: 1 blue, 11 red, 6 green; 1 red, 2 blue, 5 green; 4 green, 2 red; 2 green, 12 red
Game 73: 1 blue, 1 red; 2 red, 4 blue, 2 green; 1 blue, 2 green, 10 red; 8 red
Game 74: 12 red, 1 green, 4 blue; 1 red, 5 blue, 1 green; 11 green, 16 red, 7 blue; 7 red, 1 blue, 1 green; 12 red, 11 green, 12 blue; 11 green, 6 red
Game 75: 12 green, 8 red, 3 blue; 7 red, 10 green; 1 green, 7 blue, 1 red
Game 76: 4 green, 1 red, 3 blue; 7 blue, 3 green, 3 red; 4 blue, 2 red, 3 green; 4 blue, 1 green
Game 77: 2 green, 12 blue, 10 red; 5 blue, 7 red; 2 red, 6 green; 1 blue, 2 red, 6 green
Game 78: 2 green, 4 blue, 4 red; 8 green, 10 red, 10 blue; 5 green, 8 blue, 10 red; 6 green, 2 red
Game 79: 3 green, 2 blue, 11 red; 8 red, 11 green, 1 blue; 1 blue, 16 red; 5 red, 7 green, 16 blue; 12 red, 7 green, 9 blue; 4 red, 20 blue, 12 green
Game 80: 3 red, 5 green; 2 blue, 4 green; 2 red, 12 green, 4 blue; 10 green, 1 blue, 1 red; 4 blue, 3 red
Game 81: 1 blue, 1 green, 1 red; 5 green, 3 red, 1 blue; 1 blue, 6 green; 1 green; 1 red, 5 green, 2 blue; 1 blue, 1 red, 3 green
Game 82: 7 green, 10 blue, 3 red; 10 green, 12 red, 12 blue; 18 red, 8 green, 14 blue; 3 red, 3 green, 10 blue; 3 red, 1 blue, 5 green; 1 green, 8 blue
Game 83: 9 red, 3 blue; 14 blue, 8 red, 3 green; 14 blue, 5 green, 4 red
Game 84: 2 blue, 3 red, 6 green; 11 green, 2 red, 1 blue; 17 green, 3 blue, 3 red; 1 red, 1 blue; 1 red, 2 blue, 19 green
Game 85: 3 green, 2 blue, 3 red; 4 red, 5 blue, 8 green; 15 green, 1 red, 9 blue; 12 green, 3 blue, 2 red
Game 86: 15 green, 7 red, 10 blue; 2 blue, 2 red, 1 green; 4 red, 1 green, 9 blue; 7 red, 14 blue, 5 green
Game 87: 1 green, 3 blue, 1 red; 2 blue, 1 green; 1 blue, 2 green, 1 red
Game 88: 2 green, 6 blue, 5 red; 5 blue, 2 red; 3 red, 13 blue; 9 blue, 10 red, 1 green
Game 89: 6 green, 10 red, 2 blue; 7 red, 1 blue, 8 green; 4 blue, 3 red, 5 green; 4 green, 4 blue, 10 red
Game 90: 8 red, 7 blue; 4 green, 3 red, 1 blue; 5 blue, 2 green
Game 91: 15 green, 14 red; 12 red, 16 green, 2 blue; 8 red, 10 green; 1 green, 6 red; 8 green, 12 red
Game 92: 4 blue, 4 green, 9 red; 1 blue, 17 green; 1 green; 15 green, 3 blue, 12 red; 11 red, 1 blue, 7 green; 7 blue, 13 red, 8 green
Game 93: 10 blue, 12 red; 10 blue, 11 green, 8 red; 1 blue, 11 green, 7 red; 10 blue, 15 red, 5 green; 11 red, 8 green, 9 blue; 10 green, 3 blue
Game 94: 1 blue, 2 red; 4 red, 1 green, 5 blue; 3 red, 2 green; 2 green, 2 blue; 1 red, 5 blue, 1 green; 4 blue, 1 red, 2 green
Game 95: 1 red, 1 blue, 3 green; 2 green, 6 blue; 1 green, 13 blue, 1 red; 3 green, 15 blue
Game 96: 16 blue, 7 green, 5 red; 5 green, 5 blue, 6 red; 3 green, 17 blue, 10 red; 13 blue, 2 red, 1 green
Game 97: 12 red; 1 blue, 6 red, 1 green; 9 red, 2 blue, 1 green; 1 green, 2 blue, 1 red; 15 red, 1 blue; 1 blue
Game 98: 11 red, 6 blue, 13 green; 4 blue, 2 red, 12 green; 2 blue, 8 green, 10 red
Game 99: 2 red, 1 blue; 4 green; 7 green, 1 blue, 1 red; 5 green, 2 red; 1 blue, 2 red, 9 green; 2 green, 3 red
Game 100: 7 red, 11 blue; 10 red, 5 blue, 1 green; 7 red, 1 green, 13 blue; 9 red; 9 red, 19 blue; 9 red, 9 blue
#+end_example
* Day 3: Gear Ratios
Get the puzzle solution as [[file:./day3.scm][tangled .scm file]].
** Part One
*** Quest
You and the Elf eventually reach a [[https://en.wikipedia.org/wiki/Gondola_lift][gondola lift]] station; he says the gondola lift will take you up
to the *water source*, but this is as far as he can bring you. You go inside.
It doesn't take long to find the gondolas, but there seems to be a problem: they're not moving.
"Aaah!"
You turn around to see a slightly-greasy Elf with a wrench and a look of surprise. "Sorry, I wasn't
expecting anyone! The gondola lift isn't working right now; it'll still be a while before I can fix
it." You offer to help.
The engineer explains that an engine part seems to be missing from the engine, but nobody can figure
out which one. If you can *add up all the part numbers* in the engine schematic, it should be easy
to work out which part is missing.
The engine schematic (your puzzle input) consists of a visual representation of the engine. There
are lots of numbers and symbols you don't really understand, but apparently *any number adjacent to
a symbol*, even diagonally, is a "part number" and should be included in your sum. (Periods (=.=) do
not count as a symbol.)
Here is an example engine schematic:
#+begin_example
467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..
#+end_example
In this schematic, two numbers are *not* part numbers because they are not adjacent to a symbol:
=114= (top right) and =58= (middle right). Every other number is adjacent to a symbol and so *is* a
part number; their sum is *=4361=*.
Of course, the actual engine schematic is much larger. *What is the sum of all of the part numbers
in the engine schematic?*
*** Puzzle Solution
**** Records
#+name: day3-part1-records
#+begin_src scheme
(define-record part-number number line start-col end-col)
(define-record part-symbol sym line start-col end-col)
(define-record buffer-char char line col)
#+end_src
**** Indexing the Input
#+name: day3-part1-indexing
#+begin_src scheme
(define (index-input input #!optional (indexed-input '()) (line-index 0) (col-index 0))
(if (= 0 (length input))
(reverse indexed-input)
(let ((next-char (car input))
(new-rest-input (cdr input)))
(if (eqv? #\newline next-char)
(index-input new-rest-input
indexed-input
(+ line-index 1)
0)
(index-input new-rest-input
(cons (make-buffer-char next-char line-index col-index)
indexed-input)
line-index
(+ col-index 1))))))
#+end_src
**** Tokenizing the Indexed Input
#+name: day3-part1-number-char-p
#+begin_src scheme
(define (number-char? c)
(case (buffer-char-char c)
((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) #t)
(else #f)))
#+end_src
#+name: day3-part1-finalize-token
#+begin_src scheme
(define (finalize-token buffer)
(let* ((rev-buffer (reverse buffer))
(line (buffer-char-line (car buffer)))
(start-col (buffer-char-col (car buffer)))
(end-col (buffer-char-col (car rev-buffer))))
(if (number-char? (car buffer))
(make-part-number (string->number
(apply string (map buffer-char-char buffer)))
line start-col end-col)
(make-part-symbol (string->symbol
(apply string (map buffer-char-char buffer)))
line start-col end-col))))
#+end_src
#+name: day3-part1-compatible-with-buffer-p
#+begin_src scheme
(define (compatible-with-buffer? buffer char)
(and
(not (eqv? #\. (buffer-char-char char)))
(or (= 0 (length buffer))
(and (number-char? (car buffer))
(number-char? char))
(and (not (number-char? (car buffer)))
(not (number-char? char))))))
#+end_src
#+name: day3-part1-tokenize-indexed-input
#+begin_src scheme
(define (tokenize-indexed-input indexed-input #!optional (token-buffer '()) (part-nums '()) (part-syms '()))
(if (= 0 (length indexed-input))
(values (reverse part-nums)
(reverse part-syms))
(let ((next-char (car indexed-input)))
(cond
((compatible-with-buffer? token-buffer (car indexed-input))
(tokenize-indexed-input (cdr indexed-input)
(cons (car indexed-input) token-buffer)
part-nums part-syms))
((= 0 (length token-buffer))
(tokenize-indexed-input
(cdr indexed-input)
(if (eqv? #\. (buffer-char-char (car indexed-input)))
token-buffer (list (car indexed-input)))
part-nums part-syms))
(else
(let ((token (finalize-token (reverse token-buffer))))
(tokenize-indexed-input
(cdr indexed-input)
(if (eqv? #\. (buffer-char-char next-char)) '() (list (car indexed-input)))
(if (part-number? token) (cons token part-nums) part-nums)
(if (part-symbol? token) (cons token part-syms) part-syms))))))))
#+end_src
**** Checking for Part Neighbours
#+name: day3-part1-neighbours-p
#+begin_src scheme
(define (neighbours? part-num part-sym)
(let ((part-num-line (part-number-line part-num))
(col-min (- (part-number-start-col part-num) 1))
(col-max (+ (part-number-end-col part-num) 1)))
(and (>= (part-symbol-line part-sym) (- part-num-line 1))
(<= (part-symbol-line part-sym) (+ part-num-line 1))
(>= (part-symbol-start-col part-sym) col-min)
(<= (part-symbol-start-col part-sym) col-max)
(>= (part-symbol-end-col part-sym) col-min)
(<= (part-symbol-end-col part-sym) col-max))))
#+end_src
**** Folding Everything Together
#+name: day3-part1-real-part-number-p
#+begin_src scheme
(define (is-real-part-number? part-num part-syms)
(and (< 0 (length part-syms))
(or (neighbours? part-num (car part-syms))
(is-real-part-number? part-num (cdr part-syms)))))
#+end_src
#+name: day3-part1-fold
#+begin_src scheme
(define (fold-part-numbers part-nums part-syms)
(foldl (lambda (output input)
(if (is-real-part-number? input part-syms)
(+ output (part-number-number input))
output))
0 part-nums))
#+end_src
#+name: day3-part1-calc
#+begin_src scheme
(let-values (((part-nums part-syms) (tokenize-indexed-input (index-input (string->list input)))))
(fold-part-numbers part-nums part-syms))
#+end_src
#+results: day3-part1-calc-full
: 509115
** Part Two
*** Quest
The engineer finds the missing part and installs it in the engine! As the engine springs to life,
you jump in the closest gondola, finally ready to ascend to the water source.
You don't seem to be going very fast, though. Maybe something is still wrong? Fortunately, the
gondola has a phone labeled "help", so you pick it up and the engineer answers.
Before you can explain the situation, she suggests that you look out the window. There stands the
engineer, holding a phone in one hand and waving with the other. You're going so slowly that you
haven't even left the station. You exit the gondola.
The missing part wasn't the only issue - one of the gears in the engine is wrong. A *gear* is any
=*= symbol that is adjacent to *exactly two part numbers*. Its *gear ratio* is the result of
multiplying those two numbers together.
This time, you need to find the gear ratio of every gear and add them all up so that the engineer
can figure out which gear needs to be replaced.
Consider the same engine schematic again:
#+begin_example
467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..
#+end_example
In this schematic, there are *two* gears. The first is in the top left; it has part numbers =467=
and =35=, so its gear ratio is =16345=. The second gear is in the lower right; its gear ratio is
=451490=. (The =*= adjacent to =617= is *not* a gear because it is only adjacent to one part
number.) Adding up all of the gear ratios produces *=467835=*.
*What is the sum of all of the gear ratios in your engine schematic?*
*** Puzzle Solution
**** Gather Symbol Neighbours
#+name: day3-part2-sym-neighbour-count
#+begin_src scheme
(define (gather-neighbours part-sym part-nums)
(foldl (lambda (output input)
(if (neighbours? input part-sym)
(cons input output)
output))
(list) part-nums))
#+end_src
**** Put Everything Together
#+name: day3-part2-filter
#+begin_src scheme
(define (filter-gear-candidates part-syms)
(foldl (lambda (output input)
(if (eqv? '* (part-symbol-sym input))
(cons input output) output))
(list) part-syms))
#+end_src
#+name: day3-part2-fold
#+begin_src scheme
(define (calc-gear-ratio gears)
(foldl (lambda (output input)
(if (= 2 (length input))
(+ output (apply * (map part-number-number input)))
output))
0 gears))
#+end_src
#+name: day3-part2-calc
#+begin_src scheme
(let-values (((part-nums part-syms) (tokenize-indexed-input (index-input (string->list input)))))
(let ((gear-candidates (map (lambda (x) (gather-neighbours x part-nums)) (filter-gear-candidates part-syms))))
(calc-gear-ratio gears)))
#+end_src
#+results: day3-part2-calc-full
: 75220503
** Puzzle Input
Jump to [[#headline-37][day 4]].
#+name: day3-input
#+begin_src org
.....664...998........343...............851............................2............414.....................3....................948.164....
......*..................*617....885...*....................-......250.........536..........470...#..................../4......=.....*......
...407...570..218................-.....654........776.....920.........*753...........566......*..347.....61.-979..786........935...42.......
.......%....*...$..311.102..........................*.907.....723...............622-....*..354..............................................
.....266..............*....987.554...........&....288...#......#.......................69......41..........486..-...........................
.849................................&........781...........978......724*..196..../767................725..../...892.....*355.....815.390....
....*......@.....*988......%........704...............*......&...........*...................826.....................243.......#....*.......
...796......729.9.........490..721....................438.=....272..54&...926..481..............*..523......&.785...........766.......*493..
........281.........706...........=.666.......505.........579.*................./...669.........73...*...639...*.......479.........514......
...........*...386.......375..................................525.926..$120............&.580.........457........325.......*829..............
.....758..662.......937....%...661.24......749*323...444.............*.............583....*.........................................223.....
.......*........665....*...........*................@.................154......965..*....119.......620*............347.................*470.
........391.........183.........75..783../....................209.312............*...362........./.....667..........*....77.................
...379=..........................$......261..228........907......*.......+591...178.........227.704........@771..667..........268......543..
.......................#.....................*..........*....................................-........*581...........101........*.....*.....
................471...545..135........432..178....$225..143...973#..322............2.................................*...........239...985..
......728*612...*.........*.....65....................................*...........*................&..............527....255+../............
..255.........435.304....854...................-............=........261......&...749....+......196....694......................779..271.374
......604.........*.....................708.....922.......76..82*554......991..19........456............*..582.........597@.................
.................374..*........*707........................................*....................609...52....%.................483...........
..../..................739......................$..........649...973.*511.861..20%.................=.....................148....*......343..
...978.................................282&...401......961....-.*.........................................499%.........../.....347..........
.................+..174..315.-819.................841.....*66......820.836......8....60....456........*........434..........................
....62%.......908......./.................770....../..................*.....852......&.....*........317...%......@.......+.......691........
........793......../......411......963.......*594..................@........@......*.......45.............729...........306.148....*..@.....
626.......$......35..........*........*...........................77.134........584.....23....35................589........./...482..853....
.......................366..668.........................238...........*..265.........*..........*...........&......*...471..................
..741.............679.................@.807...76....185*...........211..%.........507....178..583....*.561...521..620...*....865.$247.494...
.....*.....383.....%..183..876......179..$..................254.........................$..........697.*..............935...*...............
...50..390..*.........*.........917.........904/..50+.........................96...............960......701...............464....*.......947
.........*..53........270..........*647.342......................778............$..$684..+279...*....#.........................393..........
......151.......490...........352*.........*........................#............................594.732.........11....#....................
........................$.........306....805..................832...................859..../.#53.........953*228...*....217.................
......37....349....391.739.......................................*286..........558......516.......647........................%........847...
..346.../....*......&.......855.........732....586...353.................43....*..............598.&...798.719.........671.....881...........
..........561................=..........................*..........52....*.....727............./.....$....*..........*......................
999*..........746...158........534............927.....587.....521......511...........448%...89...........52..557......211..356.344...116....
........*.....................%........732....*..............*...............................*..................*806.......$.....*..*.......
.....575.515.......922..........410.......*................564...............+503...........297................................132.667......
.../.............-..#.....69*82....*.......842......248..&.......630.@........................................500...........................
..916.........944...................586.................647.......*...21....&419..........=....699.......766...%.......152.......315*101....
......*436...........987#.....*....................188.............81.............87..-..109......*.........-..........*....349.............
...553..........570-.......442.197.......115...590....*.......284.......478...459..#.6.........946...............945-..192............292...
22.......+..............................%......../...865........*......*........*..........900......950.......................*449...$......
.......780..........435...*................................371...588...727.....213.....496.............-.845*..../173......688..............
713........923..../.*......289....38.....408.552.141*476..*..................................619....6........238...................633......
...*821.......*..57.8............../..46*......*..........38.........%..................$...*.......*....201......=.............61...-..%86.
...........361......../12..39.51............903..................380..659........905+.28....256.............*......215.....=.../............
...-..577.......553...............749.246.........34....................................................311..282........894.................
.960.....@...........661.....558...&......239*..........482......574=..269..........289..../...............*.................323............
...........292................%.................#........../............*......452/.-......132.....=..342.721..335.....426....*.....516.....
................967.......=.......900...........925..........476.252/...861.....................891.....*.........*315.&.....130...=........
..955..........=........584.......*...-................600............$..........940.=348...............733...754...........................
.....*..123.....................76...36...430-......&...............524.........*............706..............#.....*.....849*......162*129.
..543.....*........903..290.........................42.......................649...$............+...78.*648......180.979......353...........
...........91.642.../....*........443/.........206...........#.......219............134............*..............................798..344..
......759................144..............................455........*...906...............195......924....502.405....802.400.......*.......
.812..............-..........394.............$771.245..............116........................*.+.........#....../...*.....*...448...883....
..................784................................*.....&.................809.......616..109.496.................89.....592...*..........
...596........671......527..483.197......-965.231.918.......921.452-.538.......*..763.........................162............../..479../685.
......*....46...#......*......*.@.............................................839.*......172.....................*374........927............
.....383............649.....783..........=981.........44..159.....94...............769......*..............#..........*.............748*993.
..................................................607.+...*......*.......................755..810........539.......728.98.....425...........
......32......35....99...233..............275.337.&......437..630...........423.84...........-............................163........578....
................+.....*.....+.....334.......*.-................................*..................110.....358....115..566....*648.......*...
....................471............*......384....81...190.606..=714....673.198.......57..#761........=..........*.....*..................618
..........847.755..................963..........*........*................*......251*....................#592.222....107...991..557.........
....236-.....*.................569.....311....584.............*958..........923%........................................./.......*....=.....
................../.835...................*........157*324.840......../415...................408...........212......-..573.549.770.995......
............312.34..............&.377...287.461..................+.................33*555...*................@.315.720......%...............
.......614.*.................309.....*........*..758............811..........................259.................+..................-627....
.........*.....*.....757.................684.527..*.......408.........999...............524..............570...............995..............
...835..415.345.822...............495.....*.......138...........966....*..................#...............*....560.........*................
...#.................806..954......*.......51...........+.......*.....910..436.477..............*150.....510...*.....#....537...........434.
......................*...-........871.743.........643...234...844............*....705..959..360................454..402..........984.......
....................491.................+..675...........................$........*........-................................487...*...876...
....191........%559.......................*........250..................965......556..&...........521.......365.......994%.%....923.....$...
.....*........................238..257...631..........*....*.....&...........346......366...150....*........*...............................
.....532....584....800.......*.................603.452..155.42..272..267.295*.....52...........*....672..743...830.....395.......862........
...............#....*.....347...................*......................@.......................487...................................671*973
......=340.......&..667...................*......413.........................576*888......706.......487..502..........22....................
................649..........&./426....286.............149........690..............................&..........765.....*..............321....
389........304/............200...................660...*.............*253...........129..#30.........................710.../................
...@..............408.............258*246....136.....614..531..-.....................*.........253&..........421...........939.....+.357....
.....%..............*...........................*............*..313..+418.47...931...329............974.........=...847..........166.*......
834..6.............346....505....164............833........66.....................*.......367..95......*211..............-............888...
.........535....=......+.....$.......770......+....................................5.......*.....*36..................547...+...............
.....115.*...471......863.............#.....75..364...........=842..974......722........581............$..........588.......557....760......
987..=...780...............$...................*......................................+......869.......591.......&................-.........
........................15.484..........640...768.@710.353.......=.585......&91....996..712..=...............548...680........661...939.....
...630...........186=...*......575.....*................#.....662..$.................................+......*.........+........../.....*....
.........116*235........138...*....................644....................*853...............210...719......503.....................453.....
.....................=.........480..%................=...........429...478.....695.....789..$..........19&............216...................
......506.........101...189.........232....951.........706....43...*.......943.........%...........935.......160..........+20..152.16.......
..............789...........654...............*648.............*...........*....=.............398...*........*................*.............
..............*.........509...@.....$...............746.....645...........607..336.................488....285....$..944......298.$..........
..........23...642.374.............913................*.327....................................................263.....*182......822........
......94....*......*.......942*.............596....285.....*..............177...........86...................................477......702...
..243..+.....220.838.637.......481....301..+...............717...................394......................782/.......*..........%.872.*.....
.........../.........%...../...........$...........239...........209......*........-...............153............100.700...........*..708..
............499.........235..........................*....939*......*..227.293.-.....805.785.........#..250.................423....954......
.......570........................................837..@......748..56..........782.....*....*..........*......552...........................
872%..*......%.......88*484....805....178...704........282............387...........562....614..559...750..*...........@.....417......762...
......745.....3...98....................*..*...............................@....329........................130.......134....$...........*...
.814.............%......829.268........220...441.316.............*740......607........*831..............*......................529.......410
......=...687...........*.....*................*...*..........369.....332..........798...............956.932......................=.........
.....856.*............858....283.........43.594...292................*....*.604*.........217....................44*.....676*.........752.571
..........489....................951...................83...........262.243........681....*.................373....493...........-...@......
349................................*..................@.....................444.......*......../951..810.......#.......184....227...........
.................958..574....313...312...909....204/....................674*...........146...........=...=..................................
.....*.438...512*.....*.....*...........*.............484&.25..........................................851...........534@.$720.719..........
...254.*...........167..@...7............22....681...........*684........7.696.135.207.......177............749*670............*.....681....
..........733...........659.........527............645*215.........850.....*..........*.........*....822........................787.........
..37*58.....*.................562....*........232..........610.321*.....148.......416............514.....703......54...................310..
..........638....223.........*........296............452....................152....#...678..........................*...+...692.........*...
..911...........*.........594.......*......589........*..........186........................219...........344.927.324.525..*............753.
.....*..144.247.493...............351.........*....994...........*......738..107.......235...*....937.......-.*...........171....634........
....756..*..../.....626..131+.@..............770..........70...11........*...............*..533...*...181......861..................*.......
.........755...................637./15.....................=.........217..407......146...........402.#..................11...436..535.......
..........................&592.............367.636...........830........*..........*..........................................+.........%...
..........420*.27....954..........314.............=...........*......791...$.......718........828.....9@..449...................868...110...
..................*..........835...&...417*...........895......747..........785.........128....*..80........*.....................*.........
........475@...285...700.............*.....846....561...*.723.............................&.436...*......728................&....389........
....................*.............610.266...........@.351.*..........308...931...490...............50........*487.....958.500...............
..................335...736.....................285.......294..510*....*........*.....103.....139.........920...........=...................
.............*...........*..........343............*..692..........57.741.....@..314...*.....*......*835......738.=............582.....295..
...437....215..........185...............58.......654...&.....603..........505.......97...224..@..........766.....508.....+317....#.........
...............................52.............1...........777........704........372.............23....652...=...........@...............620.
............83..481..917......*........36$...../......=...=.............*...471*.....171.680.............*.......635...28...127.....272.....
...262.183..*......*..=..56*.72...................812.317.......454.....1.............*.............................*.........*.......*.....
....*........299..246...........190#...........%...+..............*.224..............664......897....407.155*....407...........406..581.....
......691.................869..........439.....385....@.........26.....*........863.......402*.........-.............*28...332..............
........*.......159*638......*....38....*..209......578.963........592..875......*...................*.....$......596........-..............
......90................424.640.....*.272.................$..........*.........134...........624..158.907..964.................291..........
................410....&..........972.......................$..305..683..743........551.338.&..................................*............
...........................%..........213.................164.....*.......+..........*........751..............................10....710.387
......%................&....314........-..376.......833*.......494..821...........829......%.....#........582..............&............*...
......87...318......472...........%449.....=............720.........%.................257...29...........*.........-.....656................
..666........*....*.....920.....................................................&......*........................759..........875$...........
......138....366..797...........584.......247.........................427..206..843...618.....530......................................172..
#+end_src
* Day 4: Scratchcards
Get the puzzle solution as [[file:./day4.scm][tangled .scm file]].
** Part One
*** Quest
The gondola takes you up. Strangely, though, the ground doesn't seem to be coming with you; you're
not climbing a mountain. As the circle of Snow Island recedes below you, an entire new landmass
suddenly appears above you! The gondola carries you to the surface of the new island and lurches
into the station.
As you exit the gondola, the first thing you notice is that the air here is much *warmer* than it was
on Snow Island. It's also quite *humid*. Is this where the water source is?
The next thing you notice is an Elf sitting on the floor across the station in what seems to be a
pile of colorful square cards.
"Oh! Hello!" The Elf excitedly runs over to you. "How may I be of service?" You ask about water
sources.
"I'm not sure; I just operate the gondola lift. That does sound like something we'd have, though -
this is *Island Island*, after all! I bet the *gardener* would know. He's on a different island,
though - er, the small kind surrounded by water, not the floating kind. We really need to come up
with a better naming scheme. Tell you what: if you can help me with something quick, I'll let you
*borrow my boat* and you can go visit the gardener. I got all these [[https://en.wikipedia.org/wiki/Scratchcard][scratchcards]] as a gift, but I
can't figure out what I've won."
The Elf leads you over to the pile of colorful cards. There, you discover dozens of scratchcards,
all with their opaque covering already scratched off. Picking one up, it looks like each card has
two lists of numbers separated by a vertical bar (=|=): a list of *winning numbers* and then a list
of *numbers you have*. You organize the information into a table (your puzzle input).
As far as the Elf has been able to figure out, you have to figure out which of the *numbers you
have* appear in the list of *winning numbers*. The first match makes the card worth *one point* and
each match after the first *doubles* the point value of that card.
For example:
#+begin_example
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
#+end_example
In the above example, card 1 has five winning numbers (=41=, =48=, =83=, =86=, and =17=) and eight
numbers you have (=83=, =86=, =6=, =31=, =17=, =9=, =48=, and =53=). Of the numbers you have, four
of them (=48=, =83=, =17=, and =86=) are winning numbers! That means card 1 is worth *=8=* points (1
for the first match, then doubled three times for each of the three matches after the first).
Card 2 has two winning numbers (=32= and =61=), so it is worth *=2=* points.
Card 3 has two winning numbers (=1= and =21=), so it is worth *=2=* points.
Card 4 has one winning number (=84=), so it is worth *=1=* point.
Card 5 has no winning numbers, so it is worth no points.
Card 6 has no winning numbers, so it is worth no points.
So, in this example, the Elf's pile of scratchcards is worth *=13=* points.
Take a seat in the large pile of colorful cards. *How many points are they worth in total?*
*** Puzzle Solution
**** A Record For The Start
Records are always useful, so let's create one to represent an individual card. We want to store the
card's id (it might be useful in part 2), the winning numbers, and the card's numbers.
Since it could potentially be relevant, I also add a slot for the matches.
/UPDATE: I also added a slot for the number of copies of the scratch card - relevant for part 2./
#+name: day4-part1-scratchcard
#+begin_src scheme
(define-record scratchcard id winning-numbers card-numbers match-numbers copies)
#+end_src
**** Parsing The Input
We know the drill by now, we have to take apart the input strings, and parse them into an easy
format for us - in our case, this is the ~scratchcard~ record.
For that, I first create the pattern for a card.
#+name: day4-part1-card-irregex
#+begin_src scheme
(define card-irregex
'(: bol
(* whitespace)
"Card"
(+ whitespace)
(submatch-named card-no (+ numeric))
": "
(submatch-named winning-numbers-str (+ (or numeric whitespace)))
" | "
(submatch-named card-numbers-str (+ (or numeric whitespace)))
eol))
#+end_src
The pattern is then used to extract every scratch card which is then being parsed in a fold
statement.
#+name: day4-part1-card-fold
#+begin_src scheme
(define (input->cards input-str)
(irregex-fold card-irregex
(lambda (from-index match seed)
(cons
(make-scratchcard
(string->number (irregex-match-substring match 'card-no))
(map string->number
(string-split (irregex-match-substring match 'winning-numbers-str)))
(map string->number
(string-split (irregex-match-substring match 'card-numbers-str)))
'() 1)
seed))
'() input-str))
#+end_src
**** Processing The Cards
I compare every card number with every winning number on a card, and put every card number
with at least one match into the special slot of the record. Note that this is a non-functional
operation, and thus modifies the original record! That is also the reason why the procedure
name ends with an ~!~.
#+name: day4-part1-card-matching
#+begin_src scheme
(define (calc-card-matches card)
(let ((winning-nums (scratchcard-winning-numbers card))
(card-nums (scratchcard-card-numbers card)))
(for-each (lambda (card-num)
(when (foldl (lambda (matches? winning-num)
(or matches?
(= card-num winning-num)))
#f winning-nums)
(scratchcard-match-numbers-set!
card (cons card-num (scratchcard-match-numbers card)))))
card-nums)))
#+end_src
As a next step, I calculate the points for each card.
#+name: day4-part1-card-points
#+begin_src scheme
(define (card-points card)
(let ((match-nums (scratchcard-match-numbers card)))
(foldl (lambda (points num)
(if (= 0 points)
1
(* points 2)))
0 match-nums)))
#+end_src
And now, we can put everything together and sum up the points:
#+name: day4-part1-calc
#+begin_src scheme
(foldl
(lambda (sum card)
(calc-card-matches card)
(+ sum
(card-points card)))
0 (input->cards input))
#+end_src
#+results: day4-part1-calc-full
: 23441
** Part Two
*** Quest
Just as you're about to report your findings to the Elf, one of you realizes that the rules have
actually been printed on the back of every card this whole time.
There's no such thing as "points". Instead, scratchcards only cause you to *win more scratchcards*
equal to the number of winning numbers you have.
Specifically, you win *copies* of the scratchcards below the winning card equal to the number of
matches. So, if card 10 were to have 5 matching numbers, you would win one copy each of cards 11,
12, 13, 14, and 15.
Copies of scratchcards are scored like normal scratchcards and have the *same card number* as the
card they copied. So, if you win a copy of card 10 and it has 5 matching numbers, it would then win
a copy of the same cards that the original card 10 won: cards 11, 12, 13, 14, and 15. This process
repeats until none of the copies cause you to win any more cards. (Cards will never make you copy a
card past the end of the table.)
This time, the above example goes differently:
#+begin_example
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
#+end_example
- Card 1 has four matching numbers, so you win one copy each of the next four cards: cards 2, 3, 4,
and 5.
- Your original card 2 has two matching numbers, so you win one copy each of cards 3 and 4.
- Your copy of card 2 also wins one copy each of cards 3 and 4.
- Your four instances of card 3 (one original and three copies) have two matching numbers, so you
win *four* copies each of cards 4 and 5.
- Your eight instances of card 4 (one original and seven copies) have one matching number, so you
win *eight* copies of card 5.
- Your fourteen instances of card 5 (one original and thirteen copies) have no matching numbers and
win no more cards.
- Your one instance of card 6 (one original) has no matching numbers and wins no more cards.
Once all of the originals and copies have been processed, you end up with *=1=* instance of card 1,
*=2=* instances of card 2, *=4=* instances of card 3, *=8=* instances of card 4, *=14=* instances of
card 5, and *=1=* instance of card 6. In total, this example pile of scratchcards causes you to
ultimately have *=30=* scratchcards!
Process all of the original and copied scratchcards until no more scratchcards are won. Including
the original set of scratchcards, *how many total scratchcards do you end up with?*
*** Puzzle Solution
#+name: day4-part2-card-alist
#+begin_src scheme
(define (card-alist cards)
(foldl (lambda (alist card)
(calc-card-matches card)
(alist-update (scratchcard-id card)
card
alist))
'() (reverse cards)))
#+end_src
#+name: day4-part2-gen-copies
#+begin_src scheme
(define (generate-copies cardlist #!optional (index 1))
(let ((index-card (alist-ref index cardlist)))
(if index-card
(let* ((matches (scratchcard-match-numbers index-card))
(copies (scratchcard-copies index-card))
(copy-indexes (foldl (lambda (indexes match)
(cons (+ 1 index (length indexes))
indexes))
(list) matches)))
(for-each (lambda (card-id)
(let ((target-card (alist-ref card-id cardlist)))
(scratchcard-copies-set!
target-card
(+ (scratchcard-copies target-card) copies))))
copy-indexes)
(generate-copies
cardlist
(+ index 1)))
cardlist)))
#+end_src
#+name: day4-part2-count-scratchcards
#+begin_src scheme
(define (count-scratchcards cardlist)
(foldl + 0 (map (compose scratchcard-copies cdr) cardlist)))
#+end_src
#+name: day4-part2-calc
#+begin_src scheme
(let ((cardlist (card-alist (input->cards input))))
(generate-copies cardlist)
(count-scratchcards cardlist))
#+end_src
#+results: day4-part2-calc-full
: 5923918
** Puzzle Input
Jump to [[#headline-48][day 5]].
#+name: day4-input
#+begin_src org
Card 1: 33 56 23 64 92 86 94 7 59 13 | 86 92 64 43 10 70 16 55 79 33 56 8 7 25 82 14 31 96 94 13 99 29 69 75 23
Card 2: 61 66 75 1 27 38 93 90 34 43 | 94 46 62 49 35 88 45 70 15 22 20 86 56 38 64 98 50 6 79 11 13 93 92 60 16
Card 3: 57 7 33 56 85 6 88 34 80 8 | 92 42 7 60 61 51 40 6 67 35 3 25 87 2 98 75 97 54 10 68 73 83 4 62 56
Card 4: 79 85 94 74 15 62 84 88 76 56 | 56 9 22 57 4 92 62 79 84 64 72 55 34 88 66 15 45 18 76 73 85 94 8 78 74
Card 5: 57 94 99 25 52 67 69 31 26 78 | 94 52 31 83 70 45 40 67 89 11 81 24 25 61 26 72 50 12 27 69 91 57 55 34 78
Card 6: 5 96 3 19 98 25 13 59 94 8 | 36 55 22 76 86 19 10 8 59 9 87 40 2 71 13 98 12 77 3 70 5 25 34 41 88
Card 7: 35 52 84 36 72 53 76 88 41 14 | 57 34 14 39 44 71 51 1 67 30 16 77 23 66 45 74 37 55 38 69 33 31 98 72 36
Card 8: 7 70 72 13 23 1 48 18 40 94 | 48 70 93 99 20 23 17 40 72 35 21 7 71 3 42 59 87 55 18 41 94 1 13 22 90
Card 9: 40 2 46 38 86 16 62 78 29 13 | 26 46 47 29 99 51 25 57 66 86 62 2 22 70 41 3 78 13 74 15 16 90 43 40 38
Card 10: 35 71 99 87 81 58 5 83 55 73 | 90 34 71 10 96 38 39 29 69 93 35 51 86 12 76 91 80 36 17 59 64 68 58 15 82
Card 11: 35 89 27 73 65 46 39 86 81 90 | 86 90 50 35 73 31 92 65 18 81 30 37 21 76 89 56 64 71 49 12 27 82 16 32 29
Card 12: 15 77 35 41 38 93 63 30 39 18 | 90 69 65 93 13 4 64 51 72 57 96 91 75 14 58 94 28 38 63 97 86 84 50 15 21
Card 13: 10 82 16 85 74 38 95 51 54 94 | 66 29 85 73 54 8 51 14 56 74 46 42 10 67 16 59 23 7 95 48 94 6 82 68 88
Card 14: 77 53 62 72 97 7 36 96 67 28 | 30 24 28 44 39 77 15 88 92 4 60 66 11 21 20 42 55 53 6 12 95 87 37 58 85
Card 15: 89 74 36 8 27 73 90 60 48 56 | 56 45 74 78 39 7 15 6 89 88 8 76 90 16 22 36 17 10 99 79 71 59 46 96 49
Card 16: 82 64 99 10 32 65 20 78 29 31 | 49 59 4 78 22 18 95 82 54 72 39 41 35 14 98 1 84 92 58 64 28 83 50 7 65
Card 17: 25 1 40 66 84 24 19 17 10 46 | 22 40 8 87 17 38 6 95 36 51 15 93 18 73 56 9 13 57 63 10 78 37 48 1 84
Card 18: 18 14 27 40 80 47 9 65 22 5 | 90 59 72 36 33 31 93 55 75 3 56 37 27 87 10 23 47 19 99 85 35 48 18 62 69
Card 19: 63 16 71 14 1 89 61 55 62 44 | 32 5 64 82 94 77 11 90 54 47 49 29 97 78 57 68 92 33 44 28 59 30 72 18 8
Card 20: 60 21 85 8 35 66 70 36 2 58 | 10 37 36 64 72 98 60 19 55 45 30 33 31 94 90 49 71 57 81 17 91 29 68 86 39
Card 21: 4 25 18 6 56 62 97 1 83 30 | 42 66 83 75 14 50 26 24 90 36 46 87 49 84 53 65 80 17 92 70 19 95 9 27 32
Card 22: 53 91 82 19 43 83 65 46 4 85 | 97 67 90 39 16 1 54 64 10 77 99 71 28 94 30 45 84 95 21 35 13 61 29 11 33
Card 23: 65 66 83 69 23 16 13 3 29 68 | 6 54 27 65 16 68 13 69 29 14 91 23 37 61 39 74 66 77 83 11 26 40 92 3 49
Card 24: 43 97 61 35 69 20 65 3 23 79 | 3 69 20 80 98 92 18 61 91 96 86 88 19 25 43 97 17 79 47 55 11 35 23 77 65
Card 25: 94 30 47 27 2 80 76 75 82 67 | 28 12 96 27 2 20 4 29 58 18 93 75 62 38 30 72 94 80 76 91 47 14 67 82 46
Card 26: 51 47 45 64 9 53 16 80 61 94 | 88 28 84 45 61 51 70 18 4 21 94 62 5 53 32 10 20 86 47 46 43 9 66 83 80
Card 27: 31 5 15 38 10 61 33 92 26 47 | 60 49 54 69 1 99 85 29 95 34 84 81 36 11 57 67 14 55 90 51 17 7 37 35 48
Card 28: 25 69 85 59 82 16 6 17 49 62 | 80 17 62 69 16 46 87 29 59 64 97 85 45 30 6 82 47 75 25 43 72 14 2 23 49
Card 29: 58 97 36 33 62 27 74 38 68 23 | 51 20 85 47 44 67 48 25 39 36 17 61 52 22 79 6 64 57 95 56 71 33 98 34 42
Card 30: 74 96 56 34 64 54 26 22 62 59 | 32 74 61 7 34 47 83 94 27 26 66 54 87 75 56 65 49 13 64 70 96 62 53 22 59
Card 31: 26 6 14 82 12 60 16 4 92 87 | 16 33 76 55 54 39 27 26 17 83 6 18 94 77 3 40 81 92 1 69 25 19 71 99 2
Card 32: 15 3 33 16 13 65 8 44 40 96 | 22 15 46 89 16 50 6 33 53 24 96 40 8 35 97 13 3 55 43 14 65 66 34 60 44
Card 33: 41 61 28 60 85 69 87 62 91 18 | 49 88 84 73 20 45 75 99 27 25 3 65 66 30 50 54 97 57 76 96 2 6 39 5 18
Card 34: 12 72 20 48 49 77 38 86 68 92 | 6 56 30 68 95 87 42 16 59 10 7 22 82 74 2 71 19 48 50 1 40 37 24 80 72
Card 35: 97 86 21 45 10 30 63 8 36 91 | 33 31 67 77 29 24 10 79 21 25 12 71 30 1 68 56 46 94 51 64 8 14 45 4 41
Card 36: 90 75 80 95 49 87 2 88 50 42 | 77 85 53 76 52 72 32 42 79 65 50 25 19 14 37 11 35 63 29 75 49 98 96 54 95
Card 37: 19 84 30 59 86 49 31 40 14 50 | 20 92 36 43 82 18 86 47 73 30 84 19 99 5 48 34 68 63 61 46 53 75 16 28 45
Card 38: 39 47 28 13 75 89 76 93 15 14 | 36 94 51 97 49 16 66 60 72 30 52 5 3 17 23 7 58 14 63 87 54 8 56 13 35
Card 39: 70 22 9 80 89 51 43 64 57 37 | 23 39 5 27 98 11 29 73 72 10 63 79 59 58 46 96 2 86 50 19 67 41 95 66 82
Card 40: 94 95 1 39 64 63 54 19 17 38 | 44 53 12 92 11 34 42 67 93 36 6 3 29 60 7 62 85 4 33 83 2 9 10 82 51
Card 41: 69 12 36 48 67 7 52 89 63 73 | 11 61 81 93 47 20 27 31 66 64 45 38 2 59 46 5 73 7 87 22 6 52 36 10 54
Card 42: 17 93 3 90 91 59 6 57 54 65 | 22 17 99 16 6 77 38 46 43 59 41 47 12 2 86 4 40 56 80 82 11 98 23 20 85
Card 43: 1 68 36 70 24 83 86 94 52 7 | 38 9 64 12 10 60 92 81 77 98 59 23 79 91 65 28 13 15 6 69 24 40 19 16 99
Card 44: 3 45 25 7 57 67 62 36 40 44 | 51 23 88 52 68 11 89 84 59 54 10 77 73 96 46 44 17 85 91 12 80 74 5 27 39
Card 45: 14 68 88 27 44 83 37 22 65 7 | 78 61 91 48 92 21 52 49 77 74 46 24 33 28 36 89 53 39 93 23 72 95 2 63 67
Card 46: 20 59 75 43 98 38 85 46 74 57 | 3 34 11 7 98 64 52 89 43 41 87 57 19 56 37 68 20 2 99 91 23 17 74 48 78
Card 47: 87 20 73 47 82 37 3 68 29 65 | 15 53 58 25 62 13 31 59 11 63 2 89 30 71 35 36 82 37 75 67 17 12 34 90 19
Card 48: 63 11 55 53 44 7 3 41 60 40 | 73 61 87 91 46 60 51 31 11 32 7 44 41 78 55 14 59 3 63 53 74 94 62 65 40
Card 49: 30 62 35 9 40 51 68 55 79 97 | 53 87 77 97 63 11 52 67 51 35 68 79 99 98 5 9 40 37 19 49 30 16 55 75 62
Card 50: 66 80 74 99 63 84 35 26 83 67 | 43 92 52 67 63 84 16 21 88 23 31 22 24 49 59 99 75 47 66 80 1 83 91 95 70
Card 51: 68 99 70 39 79 10 81 27 46 80 | 70 17 46 68 61 50 43 48 79 81 12 32 65 1 27 39 80 99 58 8 19 10 41 4 73
Card 52: 37 86 40 43 66 14 63 2 19 50 | 96 50 27 43 64 83 13 92 63 86 37 19 2 40 58 66 3 31 59 14 62 61 67 54 53
Card 53: 78 33 11 45 12 22 19 38 87 74 | 2 50 63 33 97 8 58 99 48 22 4 45 11 60 74 21 69 78 87 29 12 39 19 18 38
Card 54: 11 51 64 21 19 87 70 80 55 95 | 11 69 53 94 24 96 87 59 95 76 23 19 68 47 51 74 70 55 32 77 80 64 21 36 78
Card 55: 92 99 88 93 1 26 13 4 61 11 | 71 92 99 61 76 56 46 89 4 67 3 45 22 81 19 33 50 26 93 28 13 72 1 11 88
Card 56: 11 65 76 35 97 63 16 57 92 53 | 96 30 65 82 76 59 63 97 35 40 16 98 86 79 41 11 78 95 10 88 29 28 64 5 74
Card 57: 32 5 1 8 43 15 25 79 96 71 | 25 49 31 90 39 77 27 83 15 56 41 5 1 26 58 33 34 79 62 8 96 32 92 43 71
Card 58: 65 20 54 93 18 31 97 99 94 86 | 89 46 12 27 23 42 43 88 75 73 35 49 95 9 37 66 50 62 51 48 11 17 26 1 41
Card 59: 62 38 28 4 59 53 16 89 52 35 | 27 47 52 12 35 86 59 8 39 31 81 55 95 79 37 89 58 14 30 80 68 87 43 84 56
Card 60: 8 89 16 22 75 94 34 67 78 62 | 84 81 29 51 10 70 91 95 32 34 46 12 67 66 68 99 74 87 92 78 90 13 76 18 27
Card 61: 27 92 80 94 87 2 75 26 22 79 | 36 34 76 84 22 48 52 86 79 46 81 80 87 78 27 95 70 51 35 49 9 89 75 8 67
Card 62: 89 10 56 52 80 76 46 31 69 24 | 73 6 53 98 17 65 44 16 83 45 92 41 94 3 81 99 26 61 43 67 2 93 36 28 29
Card 63: 38 74 68 99 88 4 42 87 58 31 | 39 99 22 11 16 50 52 53 85 34 67 76 55 42 45 8 89 43 2 20 75 4 97 28 70
Card 64: 22 38 75 7 35 62 49 30 10 32 | 1 54 59 40 12 74 46 51 37 21 72 57 97 82 31 25 87 47 29 43 67 88 19 9 8
Card 65: 21 69 41 76 88 73 4 77 34 93 | 92 53 25 78 81 84 8 49 77 41 28 70 12 88 91 45 29 15 86 46 32 96 57 34 54
Card 66: 42 60 7 35 31 50 13 61 9 19 | 53 18 80 69 78 88 24 56 29 62 49 95 64 81 11 42 17 40 34 28 6 98 70 54 91
Card 67: 36 50 47 89 18 54 9 25 92 91 | 87 59 85 42 62 37 26 21 52 4 90 19 75 23 67 33 35 49 69 79 14 80 46 97 98
Card 68: 92 43 44 34 29 75 6 1 8 31 | 88 85 55 9 1 95 14 97 67 42 22 72 89 19 90 35 74 96 58 5 57 51 47 37 69
Card 69: 59 43 21 14 5 85 20 12 1 7 | 40 11 63 87 72 34 83 86 94 31 66 3 24 98 82 39 65 35 51 77 67 18 2 47 90
Card 70: 24 83 87 85 3 48 99 11 21 33 | 76 92 16 81 61 86 83 14 57 44 74 41 98 63 96 38 89 65 32 11 48 51 53 23 19
Card 71: 57 77 65 66 16 50 49 39 55 87 | 3 45 97 44 31 14 25 70 13 72 16 41 2 66 88 69 57 26 54 95 80 10 65 28 86
Card 72: 3 80 44 10 43 90 71 20 17 85 | 86 53 46 72 74 3 91 99 19 55 94 2 65 4 36 26 29 16 95 48 11 24 90 76 78
Card 73: 71 11 88 6 54 78 97 30 91 92 | 52 86 23 91 78 54 97 66 11 44 30 8 93 71 16 92 21 83 84 88 34 6 33 26 9
Card 74: 87 88 97 95 33 72 21 39 60 66 | 65 68 95 84 97 32 72 21 43 74 23 55 1 96 92 87 25 66 60 16 33 59 39 98 88
Card 75: 40 81 51 37 56 61 25 84 82 4 | 82 84 43 7 23 61 14 38 63 5 27 85 48 71 56 99 30 96 29 40 18 37 77 13 16
Card 76: 40 46 25 27 39 47 33 37 36 7 | 13 39 9 80 34 38 8 7 60 48 92 71 5 40 10 41 37 21 67 29 25 43 69 28 2
Card 77: 25 10 9 74 66 52 6 22 41 3 | 32 24 86 5 47 22 6 23 3 69 56 40 28 52 54 17 95 53 68 39 60 74 71 99 4
Card 78: 59 18 58 51 88 8 92 27 82 79 | 97 86 8 11 79 28 88 70 48 80 42 37 87 2 92 95 55 59 82 40 50 27 51 68 63
Card 79: 51 97 54 22 64 44 80 27 96 47 | 93 72 29 23 96 1 54 66 51 24 22 62 87 97 35 27 44 77 79 64 3 37 47 45 80
Card 80: 64 67 54 24 8 4 35 89 15 23 | 67 12 13 77 45 15 54 92 89 9 96 95 25 24 99 4 81 52 46 35 69 64 23 79 8
Card 81: 34 25 84 7 23 12 54 30 20 1 | 49 26 82 7 13 75 89 58 53 67 93 46 8 97 32 86 11 72 28 54 98 56 1 45 55
Card 82: 87 24 17 63 67 65 43 97 38 95 | 8 40 49 43 15 36 88 11 83 29 46 7 62 31 51 23 69 67 66 39 54 72 35 80 65
Card 83: 12 57 85 81 48 97 45 5 72 11 | 68 98 58 29 8 22 9 30 49 51 67 47 74 13 40 65 94 44 91 34 92 82 14 33 61
Card 84: 95 33 18 64 24 92 27 29 57 53 | 56 19 14 79 60 36 6 12 75 71 26 87 4 58 54 16 52 31 98 17 85 40 61 41 77
Card 85: 42 71 23 49 53 96 88 48 60 95 | 66 18 98 88 58 7 12 11 89 37 13 1 6 28 45 47 30 31 55 57 17 97 77 99 4
Card 86: 44 31 35 2 49 88 26 98 43 42 | 19 46 70 1 92 12 3 11 30 74 33 38 95 17 24 75 9 28 83 32 40 65 62 10 29
Card 87: 98 23 88 50 4 73 92 5 11 24 | 85 14 59 94 41 69 5 99 46 22 27 61 77 7 60 95 58 6 30 24 44 92 10 88 23
Card 88: 39 61 4 84 2 6 33 53 85 42 | 3 77 16 69 11 76 48 80 95 15 12 10 83 78 19 57 30 56 52 46 58 88 55 35 13
Card 89: 27 97 32 38 46 3 62 40 58 89 | 6 91 80 72 21 56 24 50 82 54 74 97 60 73 47 96 13 38 84 12 9 69 14 3 41
Card 90: 80 50 8 55 93 29 3 87 84 27 | 38 83 96 69 76 28 18 87 32 45 89 48 82 91 70 6 25 24 73 42 19 49 34 51 93
Card 91: 10 40 8 20 83 79 47 2 69 12 | 31 79 74 71 87 57 41 36 7 22 76 42 82 72 16 78 3 67 43 52 26 85 39 25 14
Card 92: 72 76 71 8 20 13 48 25 81 47 | 33 94 7 85 64 93 53 31 10 21 92 50 70 23 1 99 2 12 18 97 66 45 57 51 55
Card 93: 50 21 56 54 41 32 77 19 93 13 | 36 88 97 56 53 99 68 26 13 21 9 86 77 41 50 3 16 75 98 48 24 62 8 32 93
Card 94: 52 39 66 88 19 43 80 53 33 3 | 66 34 43 41 65 92 80 50 72 86 94 69 52 53 39 67 83 16 25 19 99 93 11 33 6
Card 95: 22 38 17 63 68 51 79 72 81 61 | 79 63 38 71 81 1 78 13 68 33 21 51 12 57 53 67 97 22 62 72 61 2 9 17 73
Card 96: 83 96 2 47 21 68 50 78 19 29 | 77 66 37 59 36 96 74 16 80 84 65 87 90 58 89 48 42 47 68 85 35 49 56 40 19
Card 97: 72 8 69 10 3 33 79 4 99 65 | 26 99 96 10 31 33 8 58 38 4 40 69 6 97 80 79 98 65 20 57 73 3 81 5 72
Card 98: 43 67 24 40 95 3 27 1 89 39 | 24 87 37 1 26 72 19 95 43 89 32 3 27 5 55 40 25 71 69 67 39 74 56 93 35
Card 99: 68 24 93 30 34 20 27 89 37 50 | 93 77 86 17 4 30 60 37 98 24 68 34 14 39 8 31 18 50 48 10 20 12 27 78 70
Card 100: 68 45 61 38 58 50 27 87 9 96 | 3 23 52 54 76 49 34 8 81 78 11 38 33 15 26 40 37 67 94 51 24 5 30 97 31
Card 101: 23 16 99 80 29 13 81 67 27 22 | 94 53 95 19 66 31 96 3 60 28 38 30 35 47 44 68 75 82 56 18 5 50 36 78 64
Card 102: 17 2 85 30 78 23 93 46 88 92 | 18 44 84 92 13 62 48 46 53 31 52 17 93 78 29 51 99 39 30 23 91 5 81 2 33
Card 103: 35 21 66 81 40 75 50 88 14 6 | 16 25 61 81 13 6 17 77 38 66 98 41 45 54 23 19 99 21 49 32 51 35 8 47 65
Card 104: 29 37 46 77 92 53 81 20 9 96 | 94 81 75 8 24 78 68 48 4 5 98 16 30 57 3 10 14 70 36 33 91 64 47 18 87
Card 105: 15 2 31 71 99 30 26 61 79 32 | 21 49 58 16 67 94 5 75 4 69 96 51 28 53 17 89 25 85 1 12 83 82 10 33 6
Card 106: 51 24 14 80 10 38 53 55 41 32 | 69 66 91 73 65 12 36 75 45 90 46 58 80 57 74 28 39 37 95 22 30 62 7 32 1
Card 107: 26 78 66 42 54 69 51 95 17 52 | 64 69 20 75 87 30 11 42 60 47 85 46 80 36 40 7 94 68 33 21 31 83 89 10 82
Card 108: 82 2 99 56 80 38 54 47 20 29 | 23 56 40 97 5 81 37 4 69 48 91 64 58 73 32 61 54 78 77 43 67 14 17 68 15
Card 109: 97 80 18 44 73 53 15 50 47 48 | 30 41 82 36 43 86 95 56 33 4 89 47 28 59 27 31 92 12 93 32 60 74 99 26 75
Card 110: 4 58 43 91 66 59 69 73 37 94 | 35 3 65 27 77 52 44 38 86 79 2 32 56 84 10 60 18 24 49 64 61 78 93 99 22
Card 111: 52 86 22 5 18 14 7 92 65 56 | 50 86 28 52 14 48 56 93 5 22 80 76 65 25 92 2 78 7 45 49 70 47 18 15 53
Card 112: 10 36 28 87 20 7 93 15 65 53 | 27 93 36 83 87 46 24 1 86 43 28 7 89 4 32 20 38 14 15 67 57 29 69 40 10
Card 113: 27 38 49 70 32 56 22 11 43 10 | 25 75 85 29 63 83 35 95 65 15 84 49 87 27 74 43 11 13 46 10 72 56 22 70 57
Card 114: 91 82 29 32 44 84 51 67 94 11 | 51 69 55 28 89 74 8 96 93 35 42 33 73 44 3 31 36 68 38 11 94 46 29 12 82
Card 115: 88 46 87 97 52 18 20 96 2 3 | 17 36 23 42 67 93 72 24 10 89 87 8 66 48 25 50 61 32 59 52 84 2 35 99 65
Card 116: 50 23 72 60 40 77 97 90 98 70 | 3 76 97 92 72 11 28 60 30 29 35 45 70 62 84 55 57 87 22 14 38 69 51 25 86
Card 117: 31 4 58 33 86 7 47 25 62 87 | 44 36 7 4 73 84 25 58 65 14 23 96 55 31 27 87 77 17 9 15 47 22 98 69 62
Card 118: 71 33 83 75 28 82 56 94 21 42 | 1 21 43 28 13 86 19 82 58 48 89 94 71 91 41 95 27 79 73 93 75 31 66 30 83
Card 119: 38 69 51 58 93 60 13 66 90 71 | 44 94 98 53 49 69 9 74 24 57 71 45 12 78 18 56 88 68 85 42 35 1 47 17 2
Card 120: 44 82 72 71 73 16 39 5 93 81 | 57 21 8 33 3 69 54 47 26 70 53 10 5 44 77 31 29 87 24 19 93 37 80 65 84
Card 121: 90 63 79 82 91 85 98 70 14 28 | 66 71 82 27 2 29 44 73 76 18 47 3 55 64 34 25 6 88 81 8 30 19 75 1 31
Card 122: 80 4 6 16 18 20 23 35 50 90 | 50 25 27 1 70 12 60 19 96 37 57 82 69 89 45 87 23 26 75 90 48 42 30 78 54
Card 123: 32 6 8 96 56 86 73 18 71 92 | 35 64 83 21 15 95 49 80 33 93 11 45 29 78 68 5 60 63 86 67 57 91 42 51 97
Card 124: 72 84 64 25 99 28 40 98 96 59 | 31 50 67 35 94 3 10 95 85 38 46 45 80 42 6 62 97 52 7 92 83 44 55 65 21
Card 125: 13 63 2 53 48 38 88 14 5 58 | 49 50 91 75 40 66 34 71 24 52 28 26 55 19 25 73 98 56 11 41 96 21 85 67 29
Card 126: 55 36 33 58 17 53 39 6 21 52 | 88 30 68 84 61 14 17 97 7 19 99 54 45 56 52 35 92 50 85 36 24 70 27 29 75
Card 127: 96 37 56 99 84 12 10 70 93 55 | 85 77 82 60 74 20 51 27 92 12 59 98 91 81 56 31 6 53 4 10 89 84 90 69 55
Card 128: 63 44 56 61 88 65 33 85 81 55 | 58 28 88 75 33 89 20 8 61 37 6 9 19 92 46 17 35 94 29 62 76 41 55 57 80
Card 129: 86 99 43 13 11 17 67 9 50 33 | 47 67 6 69 11 5 13 98 96 89 57 40 61 79 33 80 15 42 62 92 59 86 10 65 44
Card 130: 4 71 54 22 81 7 25 19 29 50 | 91 16 36 54 51 19 50 80 83 7 81 64 61 30 85 72 79 9 13 12 67 59 4 31 20
Card 131: 87 91 50 20 3 77 14 47 97 76 | 71 87 8 34 78 27 32 61 33 89 62 52 72 17 60 16 42 51 64 49 66 86 22 30 59
Card 132: 68 17 4 26 8 14 41 57 21 31 | 98 31 75 47 9 48 30 65 36 40 70 57 77 72 76 3 21 42 68 24 96 7 23 17 10
Card 133: 46 32 98 75 52 49 80 60 9 47 | 87 3 69 96 29 80 54 98 53 49 66 88 35 75 58 40 93 73 42 2 30 90 1 76 22
Card 134: 23 8 93 17 5 21 9 19 13 82 | 71 37 95 91 65 43 27 44 36 24 98 99 2 74 20 88 49 17 76 80 46 57 79 94 81
Card 135: 81 28 19 5 22 75 18 74 51 13 | 32 66 55 62 17 60 96 70 23 37 34 67 14 84 24 76 16 47 94 56 38 65 25 97 98
Card 136: 72 8 16 42 50 75 57 39 82 41 | 86 82 57 11 62 92 79 78 1 41 3 64 15 12 46 31 89 45 63 91 81 47 96 27 10
Card 137: 64 70 10 41 33 73 22 62 9 21 | 25 47 90 79 14 97 80 34 33 40 4 6 64 28 83 91 73 63 37 44 98 42 5 12 62
Card 138: 87 14 61 6 27 82 35 8 54 56 | 95 36 51 60 98 78 30 83 19 58 72 4 88 10 77 69 96 8 87 74 27 92 65 75 35
Card 139: 4 16 59 44 74 86 33 5 95 60 | 14 2 34 29 44 26 12 70 66 47 67 52 85 71 95 7 11 4 30 77 40 96 36 98 6
Card 140: 12 86 6 69 88 43 13 55 81 10 | 19 71 6 51 72 46 2 97 3 67 56 74 90 42 86 28 32 52 98 17 38 76 77 49 10
Card 141: 29 72 27 68 17 7 45 64 49 26 | 35 11 29 26 66 14 41 52 6 42 92 5 99 39 24 59 75 12 83 51 78 58 28 81 93
Card 142: 41 63 11 16 15 59 97 34 40 23 | 39 85 37 84 30 20 77 60 36 19 42 61 11 67 10 21 99 87 32 66 48 1 28 5 9
Card 143: 47 14 63 53 73 40 7 50 15 21 | 69 96 26 94 38 9 10 79 78 48 82 66 59 57 12 37 74 1 92 98 88 42 31 39 23
Card 144: 36 88 96 60 86 29 1 57 37 46 | 99 47 22 57 3 60 29 87 86 36 58 30 40 37 1 33 88 49 46 11 96 80 9 8 82
Card 145: 54 66 15 59 79 52 73 14 23 8 | 50 8 20 14 92 72 98 80 85 77 42 49 59 58 18 91 90 17 21 97 1 19 53 84 2
Card 146: 36 80 57 90 97 28 76 52 77 45 | 41 14 46 8 84 91 20 57 52 99 37 67 3 55 10 87 25 18 43 77 97 80 78 85 74
Card 147: 64 12 80 55 49 67 78 28 20 10 | 20 43 1 78 83 39 80 38 24 54 75 49 94 22 26 67 71 97 64 28 12 45 10 55 89
Card 148: 57 96 75 17 53 63 60 8 95 27 | 8 60 2 82 19 5 24 98 27 93 80 86 63 97 17 53 99 59 70 14 78 96 95 57 75
Card 149: 50 95 82 20 27 47 80 48 13 49 | 87 77 20 82 88 74 94 48 13 99 30 65 47 27 11 49 80 61 71 50 34 62 85 18 95
Card 150: 52 14 22 54 43 3 1 99 73 39 | 42 97 89 92 58 8 60 80 82 5 28 17 35 79 40 50 61 56 53 75 95 25 83 31 15
Card 151: 44 9 3 78 73 55 32 59 70 24 | 75 23 91 37 81 66 24 59 70 38 25 55 54 9 3 73 32 44 89 39 78 64 83 12 7
Card 152: 37 29 16 15 24 41 40 99 21 87 | 37 78 68 17 95 60 69 44 55 21 66 96 82 65 87 29 23 36 4 20 15 52 94 75 74
Card 153: 72 80 39 77 71 29 83 10 7 93 | 10 51 52 12 1 22 65 62 33 32 34 11 13 55 72 57 76 96 85 95 90 3 64 47 31
Card 154: 89 66 34 86 8 75 50 98 56 71 | 74 39 16 68 56 27 5 2 58 97 75 34 90 91 8 71 95 66 50 98 60 92 6 9 35
Card 155: 23 84 27 71 33 15 96 25 14 57 | 11 31 46 14 77 88 27 60 59 93 3 96 48 71 33 15 5 6 23 79 89 82 57 25 84
Card 156: 10 25 83 53 73 33 56 29 95 24 | 22 29 11 32 41 74 4 43 46 38 78 16 91 12 73 54 62 10 25 47 52 65 7 28 63
Card 157: 97 31 12 42 32 23 29 72 98 99 | 64 41 3 57 25 76 46 80 75 47 73 87 91 95 82 55 31 35 51 60 16 8 78 77 66
Card 158: 90 46 61 13 33 59 12 25 30 49 | 29 57 31 46 1 64 93 43 94 21 87 83 23 67 91 52 92 85 71 78 36 79 62 5 58
Card 159: 75 92 63 61 69 53 1 74 51 27 | 3 87 65 74 10 59 54 42 22 95 26 24 67 91 33 55 92 77 98 79 43 82 13 12 27
Card 160: 50 38 97 82 73 27 91 79 74 41 | 69 71 34 94 55 40 23 84 10 25 14 67 7 46 48 6 37 91 12 66 16 17 26 22 9
Card 161: 57 19 25 38 12 76 89 95 10 33 | 31 63 68 46 42 79 94 60 7 44 36 56 91 23 35 85 41 87 71 58 82 54 11 9 81
Card 162: 17 54 37 84 85 46 99 51 86 7 | 32 38 4 66 49 7 9 23 76 35 51 85 52 30 45 19 89 6 82 5 58 91 87 72 50
Card 163: 44 4 10 46 38 87 52 83 85 16 | 79 42 21 58 75 3 25 56 7 50 69 57 27 84 38 39 89 70 59 78 93 85 8 96 72
Card 164: 76 26 66 23 89 37 87 9 34 81 | 84 43 14 21 13 20 95 97 3 33 18 88 81 78 16 86 58 48 90 6 61 11 68 62 64
Card 165: 15 54 48 34 18 25 85 23 82 43 | 79 49 95 24 9 96 58 27 2 8 77 3 90 71 86 78 31 80 28 81 26 69 57 29 17
Card 166: 23 94 29 56 27 33 51 55 79 98 | 85 7 89 74 69 15 19 2 97 5 27 88 43 80 86 62 78 76 67 63 30 20 65 1 37
Card 167: 69 37 95 7 53 80 16 82 11 27 | 22 75 5 93 47 62 76 49 2 89 9 50 21 85 34 90 38 86 45 42 18 25 33 98 99
Card 168: 95 12 30 74 21 24 80 64 17 67 | 86 8 98 19 37 48 75 56 16 31 20 40 29 83 79 73 71 27 59 43 65 61 57 78 81
Card 169: 80 8 4 83 15 47 93 2 41 25 | 69 80 93 30 75 16 25 74 61 15 56 67 47 4 85 44 2 87 19 92 70 95 41 94 81
Card 170: 91 25 44 98 29 80 63 26 72 88 | 7 57 3 38 17 44 70 75 88 92 54 14 80 26 8 40 98 55 39 32 72 29 61 63 86
Card 171: 74 37 39 87 31 6 8 38 76 32 | 67 83 34 96 68 64 69 82 54 74 63 12 25 85 9 35 50 87 59 33 60 11 20 32 84
Card 172: 45 96 3 16 97 2 98 27 51 34 | 63 82 10 95 6 5 14 24 57 69 98 23 51 3 43 91 79 35 20 36 48 44 90 84 70
Card 173: 83 69 34 6 8 44 42 33 28 5 | 86 32 56 57 3 19 91 43 80 29 78 8 93 47 73 34 85 77 48 65 83 11 2 15 26
Card 174: 22 30 18 86 72 57 26 29 38 69 | 37 21 80 26 61 68 52 33 15 74 69 9 66 81 17 40 99 78 23 65 43 1 95 79 24
Card 175: 91 47 88 2 62 39 21 4 48 49 | 14 65 12 4 51 21 42 6 79 17 57 10 7 55 98 70 47 49 5 90 18 67 58 62 54
Card 176: 76 7 72 24 57 19 70 41 67 87 | 37 59 36 95 90 28 8 58 93 97 40 57 18 80 69 66 13 54 87 27 86 62 76 84 19
Card 177: 61 23 95 38 1 85 28 51 49 53 | 6 34 38 33 16 39 64 57 10 11 80 78 60 18 12 27 5 75 28 36 25 63 88 74 8
Card 178: 22 69 42 55 54 52 58 11 89 70 | 54 75 5 88 74 97 64 59 94 82 16 76 58 20 23 90 28 47 67 38 66 51 42 83 52
Card 179: 51 45 20 68 69 24 54 52 73 89 | 88 3 64 5 72 1 39 17 53 79 97 8 83 49 50 77 70 76 90 18 59 15 29 61 10
Card 180: 68 10 39 93 62 32 1 20 90 99 | 40 31 38 23 63 27 94 85 87 36 53 67 56 5 72 13 22 6 89 25 35 64 41 57 65
Card 181: 43 76 19 35 75 71 27 13 23 5 | 56 21 87 50 30 46 2 47 85 16 44 73 3 68 38 59 92 17 65 48 22 32 42 52 83
Card 182: 77 3 61 97 96 84 27 48 52 40 | 9 54 65 43 7 20 29 86 73 67 87 82 42 14 55 33 39 71 1 81 69 31 92 74 75
Card 183: 10 52 76 84 82 14 93 34 60 73 | 81 34 75 67 23 82 68 47 73 1 52 45 25 10 6 37 84 93 21 60 79 89 76 14 18
Card 184: 39 91 94 34 71 86 36 2 65 74 | 46 37 91 79 74 59 65 66 34 30 40 73 36 16 64 57 92 71 2 78 94 89 77 86 39
Card 185: 76 22 70 57 85 51 44 43 84 14 | 80 22 29 66 75 1 97 72 21 38 76 13 27 33 69 65 74 7 11 84 53 98 77 17 82
Card 186: 59 49 71 34 66 23 52 79 32 28 | 59 2 32 93 70 96 86 71 1 3 10 28 49 51 66 79 61 24 23 19 46 52 7 34 42
Card 187: 3 31 77 49 45 15 47 6 20 25 | 25 67 88 20 49 6 46 45 9 98 24 2 59 70 77 99 22 13 31 53 91 15 3 74 47
Card 188: 84 19 66 65 53 61 38 25 83 91 | 24 64 43 66 11 72 53 94 86 39 28 97 18 70 68 52 5 7 30 55 38 9 85 34 31
Card 189: 86 22 88 18 87 28 63 92 5 16 | 33 90 71 18 88 39 28 22 26 14 68 1 52 93 56 87 49 77 92 19 86 63 5 16 72
Card 190: 67 83 94 44 66 25 9 98 21 51 | 55 97 76 81 85 68 40 94 66 41 51 45 69 44 50 37 63 83 87 39 2 96 98 95 13
Card 191: 92 89 36 65 6 72 46 23 84 19 | 94 51 99 1 3 88 77 35 90 68 72 87 44 25 69 37 2 42 59 22 58 73 61 43 33
Card 192: 52 49 74 40 2 89 54 87 21 79 | 50 58 54 24 79 27 74 72 62 67 46 89 52 38 83 40 49 29 26 77 87 12 5 21 2
Card 193: 32 59 96 29 80 7 54 3 39 83 | 83 21 80 98 13 54 87 43 29 96 62 75 53 68 88 65 59 33 3 32 67 39 10 77 7
Card 194: 40 12 79 91 84 54 1 74 56 38 | 31 78 38 9 25 46 10 99 54 11 2 97 5 84 37 77 27 1 50 91 43 72 12 96 56
Card 195: 80 34 51 81 55 65 49 71 8 44 | 81 71 83 92 8 51 80 53 30 55 44 2 43 16 24 69 18 57 31 49 65 47 91 79 3
Card 196: 12 22 77 95 49 1 48 8 84 47 | 61 64 63 42 55 13 96 70 73 41 92 10 58 6 86 30 14 23 91 66 87 72 9 27 51
Card 197: 90 30 14 35 11 20 99 79 56 2 | 75 59 40 15 80 36 97 44 17 77 20 10 50 29 33 39 55 32 85 71 43 26 35 24 82
Card 198: 92 98 86 34 64 32 74 17 26 53 | 32 75 97 22 66 89 74 17 8 31 69 52 41 53 34 77 45 46 68 2 96 86 95 93 21
Card 199: 32 31 52 80 2 47 1 13 89 9 | 28 32 87 9 96 7 20 12 73 60 46 78 24 69 55 58 64 14 38 97 16 92 52 79 82
Card 200: 1 8 31 4 53 15 45 22 73 13 | 22 10 73 9 81 74 83 2 11 53 15 45 46 21 62 43 69 50 32 67 41 48 5 25 24
Card 201: 45 37 26 53 80 1 20 35 68 33 | 6 51 77 11 41 53 56 18 25 27 13 42 48 14 79 16 81 59 99 29 86 78 3 15 17
Card 202: 86 56 57 83 11 19 52 69 36 17 | 65 72 11 95 73 49 25 75 15 5 84 35 18 71 44 99 26 52 9 60 45 22 14 19 94
Card 203: 76 23 26 70 12 48 60 11 72 64 | 90 56 99 59 64 62 15 84 71 11 85 93 98 33 46 86 53 39 5 60 81 43 3 78 14
Card 204: 23 75 70 14 95 84 61 9 66 77 | 79 8 1 64 50 41 32 93 58 15 33 10 28 72 82 16 77 65 25 43 39 49 13 23 83
Card 205: 2 99 53 15 32 6 16 69 21 14 | 96 98 24 66 6 47 4 54 45 46 42 13 75 11 80 18 34 35 93 79 65 37 40 92 91
Card 206: 74 30 29 66 68 2 3 34 79 87 | 63 45 88 78 98 27 97 32 38 75 9 11 71 93 55 69 56 20 12 82 81 41 80 23 94
#+end_src
* Day 5: If You Give A Seed A Fertilizer
Get the puzzle solution as [[file:./day5.scm][tangled .scm file]].
** Part One
*** Quest
You take the boat and find the gardener right where you were told he would be: managing a giant
"garden" that looks more to you like a farm.
"A water source? Island Island *is* the water source!" You point out that Snow Island isn't
receiving any water.
"Oh, we had to stop the water because we *ran out of sand* to [[https://en.wikipedia.org/wiki/Sand_filter][filter]] it with! Can't make snow with
dirty water. Don't worry, I'm sure we'll get more sand soon; we only turned off the water a few
days... weeks... oh no." His face sinks into a look of horrified realization.
"I've been so busy making sure everyone here has food that I completely forgot to check why we
stopped getting more sand! There's a ferry leaving soon that is headed over in that direction - it's
much faster than your boat. Could you please go check it out?"
You barely have time to agree to this request when he brings up another. "While you wait for the
ferry, maybe you can help us with our *food production problem*. The latest Island Island [[https://en.wikipedia.org/wiki/Almanac][Almanac]]
just arrived and we're having trouble making sense of it."
The almanac (your puzzle input) lists all of the seeds that need to be planted. It also lists what
type of soil to use with each kind of seed, what type of fertilizer to use with each kind of soil,
what type of water to use with each kind of fertilizer, and so on. Every type of seed, soil,
fertilizer and so on is identified with a number, but numbers are reused by each category - that is,
soil =123= and fertilizer =123= aren't necessarily related to each other.
For example:
#+begin_example
seeds: 79 14 55 13
seed-to-soil map:
50 98 2
52 50 48
soil-to-fertilizer map:
0 15 37
37 52 2
39 0 15
fertilizer-to-water map:
49 53 8
0 11 42
42 0 7
57 7 4
water-to-light map:
88 18 7
18 25 70
light-to-temperature map:
45 77 23
81 45 19
68 64 13
temperature-to-humidity map:
0 69 1
1 0 69
humidity-to-location map:
60 56 37
56 93 4
#+end_example
The almanac starts by listing which seeds need to be planted: seeds =79=, =14=, =55=, and =13=.
The rest of the almanac contains a list of *maps* which describe how to convert numbers from a
*source category* into numbers in a *destination category*. That is, the section that starts with
~seed-to-soil map:~ describes how to convert a *seed number* (the source) to a *soil number* (the
destination). This lets the gardener and his team know which soil to use with which seeds, which
water to use with which fertilizer, and so on.
Rather than list every source number and its corresponding destination number one by one, the maps
describe entire *ranges* of numbers that can be converted. Each line within a map contains three
numbers: the *destination range start*, the *source range start*, and the *range length*.
Consider again the example ~seed-to-soil map~:
#+begin_example
50 98 2
52 50 48
#+end_example
The first line has a *destination range start* of =50=, a *source range start* of =98=, and a *range
length* of =2=. This line means that the source range starts at =98= and contains two values: =98=
and =99=. The destination range is the same length, but it starts at =50=, so its two values are
=50= and =51=. With this information, you know that seed number =98= corresponds to soil number =50=
and that seed number =99= corresponds to soil number =51=.
The second line means that the source range starts at =50= and contains =48= values: =50=, =51=,
..., =96=, =97=. This corresponds to a destination range starting at =52= and also containing =48=
values: =52=, =53=, ..., =98=, =99=. So, seed number =53= corresponds to soil number =55=.
Any source numbers that *aren't mapped* correspond to the *same* destination number. So, seed number
=10= corresponds to soil number =10=.
So, the entire list of seed numbers and their corresponding soil numbers looks like this:
#+begin_example
seed soil
0 0
1 1
... ...
48 48
49 49
50 52
51 53
... ...
96 98
97 99
98 50
99 51
#+end_example
With this map, you can look up the soil number required for each initial seed number:
- Seed number =79= corresponds to soil number =81=.
- Seed number =14= corresponds to soil number =14=.
- Seed number =55= corresponds to soil number =57=.
- Seed number =13= corresponds to soil number =13=.
The gardener and his team want to get started as soon as possible, so they'd like to know the
closest location that needs a seed. Using these maps, find *the lowest location number that
corresponds to any of the initial seeds*. To do this, you'll need to convert each seed number
through other categories until you can find its corresponding *location number*. In this example,
the corresponding types are:
- Seed =79=, soil =81=, fertilizer =81=, water =81=, light =74=, temperature =78=, humidity =78=,
*location =82=*.
- Seed =14=, soil =14=, fertilizer =53=, water =49=, light =42=, temperature =42=, humidity =43=,
*location =43=*.
- Seed =55=, soil =57=, fertilizer =57=, water =53=, light =46=, temperature =82=, humidity =82=,
*location =86=*.
- Seed =13=, soil =13=, fertilizer =52=, water =41=, light =34=, temperature =34=, humidity =35=,
*location =35=*.
So, the lowest location number in this example is *=35=*.
*What is the lowest location number that corresponds to any of the initial seed numbers?*
*** Puzzle Solution
**** Mapping Record
#+name: day5-part1-mapping-record
#+begin_src scheme
(define-record entity type id)
(define-record mapping-entry from-type to-type from-start from-end to-start to-end)
#+end_src
**** Data Extraction
***** Irregexes
#+name: day5-part1-seed-irregex
#+begin_src scheme
(define seed-irregex
'(: (* whitespace)
"seeds: "
(submatch-named seed-numbers (+ (or numeric whitespace)))))
#+end_src
#+name: day5-part1-mapping-irregex
#+begin_src scheme
(define mapping-irregex
'(: (submatch-named mapping-from (+ alphabetic))
"-to-"
(submatch-named mapping-to (+ alphabetic))
" map:"
(submatch-named mapping-vals (+ (or numeric whitespace)))))
#+end_src
#+name: day5-part1-mapping-nums-irregex
#+begin_src scheme
(define mapping-nums-irregex
'(: (* whitespace)
(submatch-named to-range (+ numeric))
(* whitespace)
(submatch-named from-range (+ numeric))
(* whitespace)
(submatch-named range-size (+ numeric))))
#+end_src
***** Data Reading
A list of seed numbers:
#+name: day5-part1-seeds-list
#+begin_src scheme
(define (input->seeds-list input)
(let ((seeds-str (irregex-match-substring
(irregex-search seed-irregex input)
'seed-numbers)))
(map string->number (string-split seeds-str))))
#+end_src
And a mapping from input type (e.g. ~#:soil~) to the mappings to the next type:
#+name: day5-part1-mapping-alist
#+begin_src scheme
(define (input->mapping-alist input)
(irregex-fold mapping-irregex
(lambda (from-index match seed)
(let ((map-from-key (string->keyword (irregex-match-substring match 'mapping-from)))
(map-to-key (string->keyword (irregex-match-substring match 'mapping-to)))
(mapping-vals-str (irregex-match-substring match 'mapping-vals)))
(cons
(cons
map-from-key
(irregex-fold mapping-nums-irregex
(lambda (from-index match seed)
(let ((from-start (string->number
(irregex-match-substring match 'from-range)))
(to-start (string->number
(irregex-match-substring match 'to-range)))
(range-size (string->number
(irregex-match-substring match 'range-size))))
(cons
(make-mapping-entry
map-from-key map-to-key
from-start (fx- (fx+ from-start range-size) 1)
to-start (fx- (fx+ to-start range-size) 1))
seed)))
'() mapping-vals-str))
seed)))
'() input))
#+end_src
**** Processing The Data
#+name: day5-part1-map-entity-forward
#+begin_src scheme
(define (map-entity-forward entity mapping-alist)
(let ((maplist (alist-ref (entity-type entity) mapping-alist)))
(if maplist
(let ((default-target-type (mapping-entry-to-type (car maplist))))
(or
(foldl (lambda (new-entity mapping-entry)
(if (and (fx>= (entity-id entity)
(mapping-entry-from-start mapping-entry))
(fx<= (entity-id entity)
(mapping-entry-from-end mapping-entry)))
(make-entity (mapping-entry-to-type mapping-entry)
(fx+ (mapping-entry-to-start mapping-entry)
(fx- (entity-id entity)
(mapping-entry-from-start mapping-entry))))
new-entity))
#f maplist)
(make-entity default-target-type (entity-id entity))))
#f)))
#+end_src
#+name: day5-part1-map-entity-forward-fully
#+begin_src scheme
(define (map-entity-forward-fully entity mapping-alist)
(let ((new-entity (map-entity-forward entity mapping-alist)))
(if new-entity
(map-entity-forward-fully new-entity mapping-alist)
entity)))
#+end_src
**** Solution
#+name: day5-part1-calc
#+begin_src scheme
(let ((seeds (map (cut make-entity #:seed <>) (input->seeds-list input)))
(mapping-alist (input->mapping-alist input)))
(apply min (map (compose
entity-id
(cut map-entity-forward-fully <> mapping-alist))
seeds)))
#+end_src
#+results: day5-part1-calc-full
: 1181555926
** Part Two
*** Quest
Everyone will starve if you only plant such a small number of seeds. Re-reading the almanac, it
looks like the ~seeds:~ line actually describes ranges of seed numbers.
The values on the initial ~seeds:~ line come in pairs. Within each pair, the first value is the
*start* of the range and the second value is the *length* of the range. So, in the first line of the
example above:
~seeds: 79 14 55 13~
This line describes two ranges of seed numbers to be planted in the garden. The first range starts
with seed number =79= and contains =14= values: =79=, =80=, ..., =91=, =92=. The second range starts
with seed number =55= and contains =13= values: =55=, =56=, ..., =66=, =67=.
Now, rather than considering four seed numbers, you need to consider a total of *27* seed numbers.
In the above example, the lowest location number can be obtained from seed number *82*, which
corresponds to soil =84=, fertilizer =84=, water =84=, light =77=, temperature =45=, humidity =46=,
and *location =46=*. So, the lowest location number is *=46=*.
Consider all of the initial seed numbers listed in the ranges on the first line of the
almanac. *What is the lowest location number that corresponds to any of the initial seed numbers?*
*** Puzzle Solution
All that is needed is to "expand" the seed numbers before continuing. Since we are dealing with such
a huge number of seeds, I use ~delay-force~ to delay calculation of the later ones until they're
actually needed.
#+name: day5-part2-expand-seeds
#+begin_src scheme
(define (expand-seed existing-seeds start size)
(let ((max (- (+ start size) 1)))
(do ((seedlist (cons start existing-seeds)
(cons (+ (car seedlist) 1)
seedlist)))
((< (- max 2) (car seedlist))
seedlist))))
(define (expand-seeds seed-nums #!optional (existing-seeds '()))
(if (< 2 (length seed-nums))
(expand-seeds (cddr seed-nums)
(delay-force (expand-seed existing-seeds
(car seed-nums)
(cadr seed-nums))))
(expand-seed existing-seeds (car seed-nums) (cadr seed-nums))))
#+end_src
After that, it is /almost/ identical to part 1, but we have to replace the ~foldl~ with a recursive
function that handles the promises.
#+name: day5-part2-fold-seeds
#+begin_src scheme
(define (fold-seeds seeds mapping-alist #!optional (minimum most-positive-fixnum))
(let* ((seeds (if (promise? seeds) (force seeds) seeds))
(seeds-available? (not (eqv? '() seeds))))
(if seeds-available?
(let ((location-entity-id ((compose entity-id
(cut map-entity-forward-fully <> mapping-alist)
(cut make-entity #:seed <>))
(car seeds))))
(fold-seeds (cdr seeds)
mapping-alist
(min minimum location-entity-id)))
minimum)))
#+end_src
#+name: day5-part2-calc
#+begin_src scheme
(let ((seeds (expand-seeds (input->seeds-list input)))
(mapping-alist (input->mapping-alist input)))
(fold-seeds seeds mapping-alist))
#+end_src
#+results: day5-part2-calc-full
: 37806486
*** The Optimized Solution
For the optimized solution using ranges, a new record type is needed: ~ranged-entity~.
#+begin_src scheme
(define-record ranged-entity type from-id to-id)
#+end_src
To map the ~ranged-entity~ onto the next step, it has to be split up according to the
~mapping-entry~ ranges.
There are different types of splitting, and when they apply:
- The beginning of ~ranged-entity~ lies lower than the ~mapping-entry~: the part lower has to be
extracted into a 1:1-mapping for the next step type.
#+begin_src scheme
(define (extract-dangling-entity-part ranged-entity type mapping-entry)
(let ((mapping-entry-lower-bound (mapping-entry-from-start mapping-entry)))
(values (make-ranged-entity type
(ranged-entity-from-id ranged-entity)
(- mapping-entry-lower-bound 1))
(make-ranged-entity (ranged-entity-type ranged-entity)
mapping-entry-lower-bound
(ranged-entity-to-id ranged-entity)))))
#+end_src
- The beginning of ~ranged-entity~ is somewhere inside ~mapping-entry~: the part inside the
~mapping-entity~'s range has to be extracted and the ids shifted accordingly.
#+begin_src scheme
(define (extract-matching-entity-part ranged-entity type mapping-entry)
(let* ((mapping-entry-lower-bound (mapping-entry-from-start mapping-entry))
(mapping-entry-upper-bound (mapping-entry-from-end mapping-entry))
(mapping-entry-target-start (mapping-entry-to-start mapping-entry))
(ranged-entity-lower-bound (ranged-entity-from-id ranged-entity))
(ranged-entity-upper-bound (ranged-entity-to-id ranged-entity))
(start-offset (- ranged-entity-lower-bound mapping-entry-lower-bound))
(first-index (max ranged-entity-lower-bound mapping-entry-lower-bound))
(last-index (min ranged-entity-upper-bound mapping-entry-upper-bound))
(range-size (- last-index first-index))
(matches-mapping? (= ranged-entity-upper-bound mapping-entry-upper-bound))
(exceeds-mapping? (> ranged-entity-upper-bound mapping-entry-upper-bound)))
(values (make-ranged-entity type
(+ mapping-entry-target-start start-offset)
(+ mapping-entry-target-start start-offset range-size))
(if exceeds-mapping?
(make-ranged-entity (ranged-entity-type ranged-entity)
(+ mapping-entry-upper-bound 1)
ranged-entity-upper-bound)
#f))))
#+end_src
- There is just ~ranged-entity~ left, with nothing else: then it gets a new type, and is otherwise
passed on 1:1.
#+begin_src scheme
(define (map-dangling-entity ranged-entity type)
(values (make-ranged-entity type
(ranged-entity-from-id ranged-entity)
(ranged-entity-to-id ranged-entity))
#f))
#+end_src
This behemoth determines which of the functions above to call.
#+begin_src scheme
(define (map-ranged-entity-forward ranged-entity type level-mappings)
(let ((processed-ranged-entity #f)
(remaining-ranged-entity #f)
(retry? #f))
(cond
((eqv? '() ranged-entity) '())
((eqv? '() level-mappings)
(let-values (((processed-ranged-entity* remaining-ranged-entity*)
(map-dangling-entity ranged-entity type)))
(set! processed-ranged-entity processed-ranged-entity*)
(set! remaining-ranged-entity remaining-ranged-entity*)))
((and (>= (ranged-entity-from-id ranged-entity)
(mapping-entry-from-start (car level-mappings)))
(<= (ranged-entity-from-id ranged-entity)
(mapping-entry-from-end (car level-mappings))))
(let-values
(((processed-ranged-entity* remaining-ranged-entity*)
(extract-matching-entity-part ranged-entity type (car level-mappings))))
(set! processed-ranged-entity processed-ranged-entity*)
(set! remaining-ranged-entity remaining-ranged-entity*)))
((> (ranged-entity-from-id ranged-entity)
(mapping-entry-from-end (car level-mappings)))
(set! retry? #t))
(else
(let-values
(((processed-ranged-entity* remaining-ranged-entity*)
(extract-dangling-entity-part ranged-entity type (car level-mappings))))
(set! processed-ranged-entity processed-ranged-entity*)
(set! remaining-ranged-entity remaining-ranged-entity*))))
(if retry?
(map-ranged-entity-forward ranged-entity type (cdr level-mappings))
(if remaining-ranged-entity
(cons processed-ranged-entity
(map-ranged-entity-forward remaining-ranged-entity type (cdr level-mappings)))
(list processed-ranged-entity)))))
#+end_src
Here, the mapping is being done.
#+begin_src scheme
(define (map-ranged-entity-forward-fully ranged-entity mapping-alist)
(let ((mappings (alist-ref (ranged-entity-type ranged-entity) mapping-alist)))
(if (and (not (eqv? '() mappings))
mappings)
(let* ((mappings-alist (map (lambda (x)
(cons (mapping-entry-from-start x) x))
mappings))
(sorted-mapping-ids (sort (map car mappings-alist) <))
(sorted-mappings (map (cut alist-ref <> mappings-alist) sorted-mapping-ids))
(new-type (mapping-entry-to-type (car sorted-mappings)))
(new-entities (map-ranged-entity-forward ranged-entity new-type sorted-mappings)))
(foldl append '() (map (cut map-ranged-entity-forward-fully <> mapping-alist)
new-entities)))
(list ranged-entity))))
(define (seeds-list->ranged-entities seeds)
(if (<= 2 (length seeds))
(cons (make-ranged-entity #:seed (car seeds)
(- (+ (car seeds) (cadr seeds)) 1))
(seeds-list->ranged-entities (cddr seeds)))
'()))
#+end_src
And here, it is all put together.
#+begin_src scheme
(define (calc-part-2-optimized)
(let ((seeds (seeds-list->ranged-entities (input->seeds-list input)))
(mapping-alist (input->mapping-alist input)))
(foldl min most-positive-fixnum
(map ranged-entity-from-id
(foldl append '()
(map (cut map-ranged-entity-forward-fully <> mapping-alist)
seeds))))))
#+end_src
** Puzzle Input
Jump to [[#headline-63][day 6]].
#+name: day5-input
#+begin_src org
seeds: 364807853 408612163 302918330 20208251 1499552892 200291842 3284226943 16030044 2593569946 345762334 3692780593 17215731 1207118682 189983080 2231594291 72205975 3817565407 443061598 2313976854 203929368
seed-to-soil map:
2069473506 3732587455 1483883
3235691256 2348990120 6550341
3547561069 1392195671 747406227
3264251584 3734071338 283309485
391285622 257757572 195552540
1645243555 3166958320 377191689
335002083 512210869 56283539
3242241597 897735089 22009987
77244511 0 257757572
989159646 4172023334 122943962
605476380 3544150009 188437446
0 568494408 18343754
2700122696 4050276683 121746651
2022435244 2139601898 47038262
2227672101 919745076 95840269
1112103608 2633818373 533139947
826809686 2186640160 162349960
3100147259 762191092 135543997
18343754 453310112 58900757
2323512370 1015585345 282396986
2605909356 1297982331 94213340
2821869347 2355540461 278277912
793913826 4017380823 32895860
2070957389 605476380 156714712
soil-to-fertilizer map:
2700214958 2743391193 363795571
1484584575 1440072796 24660284
927520818 435059068 191969051
1588488926 1434420334 5652462
1423277199 141187887 5443857
1594141388 1350997453 83422881
1986188257 3933008893 120750463
1509244859 146631744 79093544
3712482038 4220862006 74105290
3948206286 1986188257 277570873
291046304 281588807 153470261
1119489869 918224946 303787330
1677564269 1321192605 29804848
2309878676 2336743687 390336282
3079951473 3306332300 449116691
444516565 1222012276 99180329
543696894 1464733080 383823924
3895169406 3771389935 53036880
3529068164 4053759356 167102650
0 627178642 291046304
3696170814 2727079969 16311224
3855550220 3824426815 39619186
2106938720 3107186764 199145536
1428721056 225725288 55863519
1707369117 0 64378064
1771747181 64378064 76809823
3064010529 3755448991 15940944
2306084256 2332949267 3794420
4225777159 2263759130 69190137
3786587328 3864046001 68962892
1588338403 627028119 150523
fertilizer-to-water map:
2299879115 39069388 7889905
514481680 504392888 101474410
3448524168 0 25428313
13641075 1832356728 472401611
0 25428313 13641075
1842445520 108629584 395763304
486042686 3445513487 28438994
2307769020 2304758339 1140755148
2238208824 46959293 61670291
615956090 605867298 1226489430
water-to-light map:
1318826171 2010420436 223477535
2278894745 2233897971 671603259
988189854 447584401 27746374
2132052210 300741866 146842535
0 1279660741 97125596
3531244480 3147213622 507810286
257581844 3816963790 101424269
1298609589 3918388059 20216582
3317726838 1072550929 21856732
3065323607 1254863909 4121973
97125596 1094407661 160456248
359006113 1057194484 15356445
374362558 1636971609 104335413
4039054766 475330775 9209679
1038424317 1376786337 260185272
878530050 3938604641 109659804
1784016098 3738041092 78922698
3152462764 0 165264074
1862938796 1741307022 269113414
497536930 676201364 380993120
3069445580 3655023908 83017184
2950498004 165264074 114825603
1015936228 1258985882 1835900
478697971 1260821782 18838959
1017772128 280089677 20652189
1542303706 2905501230 241712392
3339583570 484540454 191660910
light-to-temperature map:
2827696039 489007811 183207687
1480301347 3744628626 306791400
695239418 130668965 358338846
1297125534 2232912413 183175813
3979319170 1917264287 315648126
3010903726 948848843 968415444
130668965 2663473525 564570453
1053578264 4051420026 243547270
2303677395 672215498 276633345
1787092747 3228043978 516584648
2580310740 2416088226 247385299
temperature-to-humidity map:
4161466647 3871737509 133500649
2423686895 2864370860 72123408
1983529997 0 320533964
3184295196 2695571092 41928210
0 822932241 605870242
3557076981 3267347843 604389666
3226223406 2936494268 330853575
2495810303 2737499302 126871558
1108268519 1428802483 491674128
605870242 320533964 502398277
2622681861 2423686895 271884197
2894566058 4005238158 289729138
1599942647 1920476611 383587350
humidity-to-location map:
2945628300 1864953738 334378942
3467273713 3579654586 715312710
975015905 1356290883 508662855
1483678760 2498980024 1080674562
3443998409 2199332680 23275304
3280007242 2222607984 163991167
4182586423 2386599151 112380873
2564353322 975015905 381274978
#+end_src
* Day 6: Wait For It
Get the puzzle solution as [[file:./day6.scm][tangled .scm file]].
** Part One
*** Quest
The ferry quickly brings you across Island Island. After asking around, you discover that there is
indeed normally a large pile of sand somewhere near here, but you don't see anything besides lots of
water and the small island where the ferry has docked.
As you try to figure out what to do next, you notice a poster on a wall near the ferry dock. "Boat
races! Open to the public! Grand prize is an all-expenses-paid trip to *Desert Island*!" That must
be where the sand comes from! Best of all, the boat races are starting in just a few minutes.
You manage to sign up as a competitor in the boat races just in time. The organizer explains that
it's not really a traditional race - instead, you will get a fixed amount of time during which your
boat has to travel as far as it can, and you win if your boat goes the farthest.
As part of signing up, you get a sheet of paper (your puzzle input) that lists the *time* allowed
for each race and also the best *distance* ever recorded in that race. To guarantee you win the
grand prize, you need to make sure you *go farther in each race* than the current record holder.
The organizer brings you over to the area where the boat races are held. The boats are much smaller
than you expected - they're actually *toy boats*, each with a big button on top. Holding down the
button *charges the boat*, and releasing the button *allows the boat to move*. Boats move faster if
their button was held longer, but time spent holding the button counts against the total race
time. You can only hold the button at the start of the race, and boats don't move until the button
is released.
For example:
#+begin_example
Time: 7 15 30
Distance: 9 40 200
#+end_example
This document describes three races:
- The first race lasts 7 milliseconds. The record distance in this race is 9 millimeters.
- The second race lasts 15 milliseconds. The record distance in this race is 40 millimeters.
- The third race lasts 30 milliseconds. The record distance in this race is 200 millimeters.
Your toy boat has a starting speed of *zero millimeters per millisecond*. For each whole millisecond
you spend at the beginning of the race holding down the button, the boat's speed increases by *one
millimeter per millisecond*.
So, because the first race lasts 7 milliseconds, you only have a few options:
- Don't hold the button at all (that is, hold it for *=0= milliseconds*) at the start of the
race. The boat won't move; it will have traveled *=0= millimeters* by the end of the race.
- Hold the button for *=1= millisecond* at the start of the race. Then, the boat will travel at a
speed of =1= millimeter per millisecond for =6= milliseconds, reaching a total distance traveled
of *=6 millimeters=.
- Hold the button for *=2= milliseconds*, giving the boat a speed of =2= millimeters per
millisecond. It will then get =5= milliseconds to move, reaching a total distance of *=10=
millimeters*.
- Hold the button for *=3= milliseconds*. After its remaining =4= milliseconds of travel time, the
boat will have gone *=12= millimeters=.
- Hold the button for *=4= milliseconds*. After its remaining =3= milliseconds of travel time, the
boat will have gone *=12= millimeters*.
- Hold the button for *=5= milliseconds*, causing the boat to travel a total of *=10= millimeters*.
- Hold the button for *=6= milliseconds*, causing the boat to travel a total of *=6= millimeters*.
- Hold the button for *=7= milliseconds*. That's the entire duration of the race. You never let go
of the button. The boat can't move until you let go of the button. Please make sure you let go of
the button so the boat gets to move. *=0= millimeters*.
Since the current record for this race is =9= millimeters, there are actually *=4=* different ways
you could win: you could hold the button for =2=, =3=, =4=, or =5= milliseconds at the start of the
race.
In the second race, you could hold the button for at least =4= milliseconds and at most =11=
milliseconds and beat the record, a total of *=8=* different ways to win.
In the third race, you could hold the button for at least =11= milliseconds and no more than =19=
milliseconds and still beat the record, a total of *=9=* ways you could win.
To see how much margin of error you have, determine the *number of ways you can beat the record* in
each race; in this example, if you multiply these values together, you get *=288=* (=4= * =8= *
=9=).
Determine the number of ways you could beat the record in each race. *What do you get if you
multiply these numbers together?*
*** Puzzle Solution
**** Data Extraction
First, we need to define the record for the race data.
#+name: day6-part1-race-record
#+begin_src scheme
(define-record race time-limit record-distance winning-distances losing-distances)
#+end_src
The solution starts with the usual data extraction using ~irregex~.
#+name: day6-part1-input-extraction-irregex
#+begin_src scheme
(define input-extraction-irregex
'(: "Time:"
(submatch-named time-vals (+ (or numeric whitespace)))
"Distance:"
(submatch-named distance-vals (+ (or numeric whitespace)))))
#+end_src
Next, the data is converted into ~race~ records.
#+name: day6-part1-input--race-records
#+begin_src scheme
(define (input->race-records input)
(let ((match (irregex-search input-extraction-irregex
input)))
(map (lambda (time distance)
(make-race time distance #f #f))
(map string->number (string-split (irregex-match-substring match 'time-vals)))
(map string->number (string-split (irregex-match-substring match 'distance-vals))))))
#+end_src
**** Race Calculations
#+name: day6-part1-get-distance
#+begin_src scheme
(define (get-distance race hold-time)
(let ((time-remaining (- (race-time-limit race) hold-time)))
(* time-remaining hold-time)))
#+end_src
#+name: day6-part1-calc-race-distances
#+begin_src scheme
(define (calc-race-distances race
#!optional (hold-time 1) (winning-distances '()) (losing-distances '()))
(let* ((record-distance (race-record-distance race))
(new-distance (get-distance race hold-time))
(is-new-record? (> new-distance record-distance)))
(cond
((= new-distance 0)
(begin
(race-winning-distances-set! race winning-distances)
(race-losing-distances-set! race losing-distances)
race))
(else
(calc-race-distances
race (+ hold-time 1)
(if is-new-record? (cons new-distance winning-distances) winning-distances)
(if is-new-record? losing-distances (cons new-distance losing-distances)))))))
#+end_src
**** Getting The Result
#+name: day6-part1-calc-fn
#+begin_src scheme
(import (chicken string)
(chicken irregex))
(define input "
Time: 58 81 96 76
Distance: 434 1041 2219 1218")
(define-record race time-limit record-distance winning-distances losing-distances)
(define input-extraction-irregex
'(: "Time:"
(submatch-named time-vals (+ (or numeric whitespace)))
"Distance:"
(submatch-named distance-vals (+ (or numeric whitespace)))))
(define (input->race-records input)
(let ((match (irregex-search input-extraction-irregex
input)))
(map (lambda (time distance)
(make-race time distance #f #f))
(map string->number (string-split (irregex-match-substring match 'time-vals)))
(map string->number (string-split (irregex-match-substring match 'distance-vals))))))
(define (get-distance race hold-time)
(let ((time-remaining (- (race-time-limit race) hold-time)))
(* time-remaining hold-time)))
(define (calc-race-distances race
#!optional (hold-time 1) (winning-distances '()) (losing-distances '()))
(let* ((record-distance (race-record-distance race))
(new-distance (get-distance race hold-time))
(is-new-record? (> new-distance record-distance)))
(cond
((= new-distance 0)
(begin
(race-winning-distances-set! race winning-distances)
(race-losing-distances-set! race losing-distances)
race))
(else
(calc-race-distances
race (+ hold-time 1)
(if is-new-record? (cons new-distance winning-distances) winning-distances)
(if is-new-record? losing-distances (cons new-distance losing-distances)))))))
(define (calc-part-1)
(foldl *
1 (map (compose length race-winning-distances)
(map calc-race-distances (input->race-records input)))))
#+end_src
#+results:
: 1159152
** Part Two
*** Quest
As the race is about to start, you realize the piece of paper with race times and record distances
you got earlier actually just has very bad [[https://en.wikipedia.org/wiki/Kerning][kerning]]. There's really *only one race* - ignore the
spaces between the numbers on each line.
So, the example from before:
#+begin_example
Time: 7 15 30
Distance: 9 40 200
#+end_example
...now instead means this:
#+begin_example
Time: 71530
Distance: 940200
#+end_example
Now, you have to figure out how many ways there are to win this single race. In this example, the
race lasts for *=71530= milliseconds* and the record distance you need to beat is *=940200=
millimeters*. You could hold the button anywhere from =14= to =71516= milliseconds and beat the
record, a total of =71503= ways!
*How many ways can you beat the record in this one much longer race?*
*** Puzzle Solution
**** Code Changes
The ~input->race-records~ function has to be rewritten:
#+name: day6-part2-input--race-record
#+begin_src scheme
(define (input->race-record input)
(let* ((match (irregex-search input-extraction-irregex input))
(time-val ((compose string->number
(cut foldl string-append "" <>)
string-split
(cut irregex-match-substring <> 'time-vals))
match))
(distance-val ((compose string->number
(cut foldl string-append "" <>)
string-split
(cut irregex-match-substring <> 'distance-vals))
match)))
(make-race time-val distance-val #f #f)))
#+end_src
And instead of keeping a list of all winning and losing distances, I use a counter.
#+name: day6-part2-calc-race-distances
#+begin_src scheme
(define (calc-race-distances-with-counter race
#!optional (hold-time 1) (winning-distances 0) (losing-distances 0))
(let* ((record-distance (race-record-distance race))
(new-distance (get-distance race hold-time))
(is-new-record? (> new-distance record-distance)))
(cond
((= new-distance 0)
(begin
(race-winning-distances-set! race winning-distances)
(race-losing-distances-set! race losing-distances)
race))
(else
(calc-race-distances-with-counter
race (+ hold-time 1)
(if is-new-record? (+ 1 winning-distances) winning-distances)
(if is-new-record? losing-distances (+ 1 losing-distances)))))))
#+end_src
**** Race Variant Results
#+name: day6-part2-calc-fn
#+begin_src scheme
(import (chicken string)
(chicken irregex))
(define input "
Time: 58 81 96 76
Distance: 434 1041 2219 1218")
(define-record race time-limit record-distance winning-distances losing-distances)
(define input-extraction-irregex
'(: "Time:"
(submatch-named time-vals (+ (or numeric whitespace)))
"Distance:"
(submatch-named distance-vals (+ (or numeric whitespace)))))
(define (input->race-record input)
(let* ((match (irregex-search input-extraction-irregex input))
(time-val ((compose string->number
(cut foldl string-append "" <>)
string-split
(cut irregex-match-substring <> 'time-vals))
match))
(distance-val ((compose string->number
(cut foldl string-append "" <>)
string-split
(cut irregex-match-substring <> 'distance-vals))
match)))
(make-race time-val distance-val #f #f)))
(define (get-distance race hold-time)
(let ((time-remaining (- (race-time-limit race) hold-time)))
(* time-remaining hold-time)))
(define (calc-race-distances-with-counter race
#!optional (hold-time 1) (winning-distances 0) (losing-distances 0))
(let* ((record-distance (race-record-distance race))
(new-distance (get-distance race hold-time))
(is-new-record? (> new-distance record-distance)))
(cond
((= new-distance 0)
(begin
(race-winning-distances-set! race winning-distances)
(race-losing-distances-set! race losing-distances)
race))
(else
(calc-race-distances-with-counter
race (+ hold-time 1)
(if is-new-record? (+ 1 winning-distances) winning-distances)
(if is-new-record? losing-distances (+ 1 losing-distances)))))))
(define (calc-part-2)
(race-winning-distances
(calc-race-distances-with-counter (input->race-record input))))
#+end_src
#+results:
: 41513103
** Puzzle Input
Jump to [[#headline-76][day 7]].
#+name: day6-input
#+begin_src org
Time: 58 81 96 76
Distance: 434 1041 2219 1218
#+end_src
* Day 7: Camel Cards
Get the puzzle solution as [[file:./day7.scm][tangled .scm file]].
** Part One
*** Quest
Your all-expenses-paid trip turns out to be a one-way, five-minute ride in an [[https://en.wikipedia.org/wiki/Airship][airship]]. (At least
it's a *cool* airship!) It drops you off at the edge of a vast desert and descends back to Island
Island.
"Did you bring the parts?"
You turn around to see an Elf completely covered in white clothing, wearing goggles, and riding a
large [[https://en.wikipedia.org/wiki/Dromedary][camel]].
"Did you bring the parts?" she asks again, louder this time. You aren't sure what parts she's
looking for; you're here to figure out why the sand stopped.
"The parts! For the sand, yes! Come with me; I will show you." She beckons you onto the camel.
After riding a bit across the sands of Desert Island, you can see what look like very large rocks
covering half of the horizon. The Elf explains that the rocks are all along the part of Desert
Island that is directly above Island Island, making it hard to even get there. Normally, they use
big machines to move the rocks and filter the sand, but the machines have broken down because Desert
Island recently stopped receiving the parts they need to fix the machines.
You've already assumed it'll be your job to figure out why the parts stopped when she asks if you
can help. You agree automatically.
Because the journey will take a few days, she offers to teach you the game of *Camel Cards*. Camel
Cards is sort of similar to [[https://en.wikipedia.org/wiki/List_of_poker_hands][poker]] except it's designed to be easier to play while riding a camel.
In Camel Cards, you get a list of *hands*, and your goal is to order them based on the *strength* of
each hand. A hand consists of *five cards* labeled one of =A=, =K=, =Q=, =J=, =T=, =9=, =8=, =7=,
=6=, =5=, =4=, =3=, or =2=. The relative strength of each card follows this order, where =A= is the
highest and =2= is the lowest.
Every hand is exactly one *type*. From strongest to weakest, they are:
- *Five of a kind*, where all five cards have the same label: =AAAAA=
- *Four of a kind*, where four cards have the same label and one card has a different label: =AA8AA=
- *Full house*, where three cards have the same label, and the remaining two cards share a different
label: =23332=
- *Three of a kind*, where three cards have the same label, and the remaining two cards are each
different from any other card in the hand: =TTT98=
- *Two pair*, where two cards share one label, two other cards share a second label, and the
remaining card has a third label: =23432=
- *One pair*, where two cards share one label, and the other three cards have a different label from
the pair and each other: =A23A4=
- *High card*, where all cards' labels are distinct: =23456=
Hands are primarily ordered based on type; for example, every *full house* is stronger than any
*three of a kind*.
If two hands have the same type, a second ordering rule takes effect. Start by comparing the *first
card in each hand*. If these cards are different, the hand with the stronger first card is
considered stronger. If the first card in each hand have the *same label*, however, then move on to
considering the *second card in each hand*. If they differ, the hand with the higher second card
wins; otherwise, continue with the third card in each hand, then the fourth, then the fifth.
So, =33332= and =2AAAA= are both *four of a kind* hands, but =33332= is stronger because its first
card is stronger. Similarly, =77888= and =77788= are both a *full house*, but =77888= is stronger
because its third card is stronger (and both hands have the same first and second card).
To play Camel Cards, you are given a list of hands and their corresponding *bid* (your puzzle
input). For example:
#+begin_example
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483
#+end_example
This example shows five hands; each hand is followed by its *bid* amount. Each hand wins an amount
equal to its bid multiplied by its *rank*, where the weakest hand gets rank 1, the second-weakest
hand gets rank 2, and so on up to the strongest hand. Because there are five hands in this example,
the strongest hand will have rank 5 and its bid will be multiplied by 5.
So, the first step is to put the hands in order of strength:
- =32T3K= is the only *one pair* and the other hands are all a stronger type, so it gets rank *1*.
- =KK677= and =KTJJT= are both *two pair*. Their first cards both have the same label, but the
second card of =KK677= is stronger (=K= vs =T=), so =KTJJT= gets rank *2* and =KK677= gets rank
*3*.
- =T55J5= and =QQQJA= are both *three of a kind*. =QQQJA= has a stronger first card, so it gets rank
*5* and =T55J5= gets rank *4*.
Now, you can determine the total winnings of this set of hands by adding up the result of
multiplying each hand's bid with its rank (=765= * 1 + =220= * 2 + =28= * 3 + =684= * 4 + =483= *
5). So the *total winnings* in this example are *=6440=*.
Find the rank of every hand in your set. *What are the total winnings?*
*** Puzzle Solution
Because the journey will take a few days, she offers to teach you the game of *Camel Cards*. Camel
Cards is sort of similar to [[https://en.wikipedia.org/wiki/List_of_poker_hands][poker]] except it's designed to be easier to play while riding a camel.
In Camel Cards, you get a list of *hands*, and your goal is to order them based on the *strength* of
each hand. A hand consists of *five cards* labeled one of =A=, =K=, =Q=, =J=, =T=, =9=, =8=, =7=,
=6=, =5=, =4=, =3=, or =2=. The relative strength of each card follows this order, where =A= is the
highest and =2= is the lowest.
#+name: day7-part1-cards
#+begin_src scheme
(define cards `((#:A . ,(make-card #:A 13))
(#:K . ,(make-card #:K 12))
(#:Q . ,(make-card #:Q 11))
(#:J . ,(make-card #:J 10))
(#:T . ,(make-card #:T 9))
(#:9 . ,(make-card #:9 8))
(#:8 . ,(make-card #:8 7))
(#:7 . ,(make-card #:7 6))
(#:6 . ,(make-card #:6 5))
(#:5 . ,(make-card #:5 4))
(#:4 . ,(make-card #:4 3))
(#:3 . ,(make-card #:3 2))
(#:2 . ,(make-card #:2 1))))
#+end_src
The hands are separated into types.
#+name: day7-part1-types
#+begin_src scheme
(define (calc-card-frequencies cardlist #!optional (frequencies '()))
(if (eqv? '() cardlist)
(sort (map cdr frequencies) >)
(let* ((card-label (card-label (car cardlist)))
(card-old-frequency (alist-ref card-label frequencies eqv? 0)))
(calc-card-frequencies (cdr cardlist)
(alist-update card-label (+ 1 card-old-frequency) frequencies)))))
(define (calc-hand-type hand)
(let ((frequencies (calc-card-frequencies (hand-cards hand))))
(cond ;; Insert the comparisons from below here
))
hand)
#+end_src
For the sake of brevity, there is a shortcut function to get a type for a hand of cards, to be used
in the following examples:
#+name: day7-part1-type-sample-noweb
#+begin_src scheme
(define (get-type-for-cards #!rest card-labels)
(hand-type-label
(hand-type-rec
(calc-hand-type (make-hand (map (cut alist-ref <> cards) card-labels) #f #f #f)))))
#+end_src
Every hand is exactly one *type*. From strongest to weakest, they are:
- *Five of a kind*, where all five cards have the same label: =AAAAA=;
src_scheme{(get-type-for-cards #:A #:A #:A #:A #:A)} =#:five-of-a-kind=
#+name: day7-part1-five-of-a-kind
#+begin_src scheme
((= 5 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:five-of-a-kind hand-types)))
#+end_src
- *Four of a kind*, where four cards have the same label and one card has a different label: =AA8AA=;
src_scheme{(get-type-for-cards #:A #:A #:8 #:A #:A)} =#:four-of-a-kind=
#+name: day7-part1-four-of-a-kind
#+begin_src scheme
((= 4 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:four-of-a-kind hand-types)))
#+end_src
- *Full house*, where three cards have the same label, and the remaining two cards share a different
label: =23332=;
src_scheme{(get-type-for-cards #:2 #:3 #:3 #:3 #:2)} =#:full-house=
#+name: day7-part1-full-house
#+begin_src scheme
((and (= 3 (car frequencies))
(= 2 (cadr frequencies)))
(hand-type-rec-set! hand (alist-ref #:full-house hand-types)))
#+end_src
- *Three of a kind*, where three cards have the same label, and the remaining two cards are each
different from any other card in the hand: =TTT98=;
src_scheme{(get-type-for-cards #:T #:T #:T #:9 #:8)} =#:three-of-a-kind=
#+name: day7-part1-three-of-a-kind
#+begin_src scheme
((= 3 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:three-of-a-kind hand-types)))
#+end_src
- *Two pair*, where two cards share one label, two other cards share a second label, and the
remaining card has a third label: =23432=;
src_scheme{(get-type-for-cards #:2 #:3 #:4 #:3 #:2)} =#:two-pair=
#+name: day7-part1-two-pair
#+begin_src scheme
((and (= 2 (car frequencies))
(= 2 (cadr frequencies)))
(hand-type-rec-set! hand (alist-ref #:two-pair hand-types)))
#+end_src
- *One pair*, where two cards share one label, and the other three cards have a different label from
the pair and each other: =A23A4=;
src_scheme{(get-type-for-cards #:A #:2 #:3 #:A #:4)} =#:one-pair=
#+name: day7-part1-one-pair
#+begin_src scheme
((= 2 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:one-pair hand-types)))
#+end_src
- *High card*, where all cards' labels are distinct: =23456=;
src_scheme{(get-type-for-cards #:2 #:3 #:4 #:5 #:6)} =#:high-card=
#+name: day7-part1-high-card
#+begin_src scheme
((= 1 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:high-card hand-types)))
#+end_src
Hands are primarily ordered based on type; for example, every *full house* is stronger than any
*three of a kind*.
#+name: day7-part1-hand-types
#+begin_src scheme
(define hand-types `((#:five-of-a-kind . ,(make-hand-type #:five-of-a-kind 7))
(#:four-of-a-kind . ,(make-hand-type #:four-of-a-kind 6))
(#:full-house . ,(make-hand-type #:full-house 5))
(#:three-of-a-kind . ,(make-hand-type #:three-of-a-kind 4))
(#:two-pair . ,(make-hand-type #:two-pair 3))
(#:one-pair . ,(make-hand-type #:one-pair 2))
(#:high-card . ,(make-hand-type #:high-card 1))))
#+end_src
If two hands have the same type, a second ordering rule takes effect. Start by comparing the *first
card in each hand*. If these cards are different, the hand with the stronger first card is
considered stronger. If the first card in each hand have the *same label*, however, then move on to
considering the *second card in each hand*. If they differ, the hand with the higher second card
wins; otherwise, continue with the third card in each hand, then the fourth, then the fifth.
#+name: day7-part1-hand-comparison
#+begin_src scheme
(define (card> card-a card-b)
(> (card-weight card-a) (card-weight card-b)))
(define (hand-cards> cards-a cards-b)
(or (card> (car cards-a) (car cards-b))
(and (< 1 (length cards-a))
(= (card-weight (car cards-a)) (card-weight (car cards-b)))
(hand-cards> (cdr cards-a) (cdr cards-b)))))
(define (hands> hand-a hand-b)
(let ((type-weight-a (hand-type-weight (hand-type-rec hand-a)))
(type-weight-b (hand-type-weight (hand-type-rec hand-b)))
(cards-a (hand-cards hand-a))
(cards-b (hand-cards hand-b)))
(or (> type-weight-a type-weight-b)
(and (= type-weight-a type-weight-b)
(hand-cards> cards-a cards-b)))))
#+end_src
So, =33332= and =2AAAA= are both *four of a kind* hands, but =33332= is stronger because its first
card is stronger. Similarly, =77888= and =77788= are both a *full house*, but =77888= is stronger
because its third card is stronger (and both hands have the same first and second card).
#+begin_src scheme
(hands> (make-hand (map (cut alist-ref <> cards) '(#:3 #:3 #:3 #:3 #:2))
0
(alist-ref #:four-of-a-kind hand-types) #f)
(make-hand (map (cut alist-ref <> cards) '(#:2 #:A #:A #:A #:A))
0
(alist-ref #:four-of-a-kind hand-types) #f))
#+end_src
#+results:
: #t
To play Camel Cards, you are given a list of hands and their corresponding *bid* (your puzzle
input). For example:
#+begin_example
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483
#+end_example
Better sample input from [[https://old.reddit.com/r/adventofcode/comments/18cr4xr/2023_day_7_better_example_input_not_a_spoiler/][u/LxsterGames]] on Reddit:
#+name: day7-part1-hand-input-example
#+begin_example
2345A 1
Q2KJJ 13
Q2Q2Q 19
T3T3J 17
T3Q33 11
2345J 3
J345A 2
32T3K 5
T55J5 29
KK677 7
KTJJT 34
QQQJA 31
JJJJJ 37
JAAAA 43
AAAAJ 59
AAAAA 61
2AAAA 23
2JJJJ 53
JJJJ2 41
#+end_example
#+name: day7-part1-data-regex
#+begin_src scheme
(define camel-card-irregex
'(: (submatch-named cards (+ (or (/ #\A #\Z) (/ #\0 #\9))))
" "
(submatch-named bid (+ (/ #\0 #\9)))))
#+end_src
#+name: day7-part1-data-extraction
#+begin_src scheme
(define (cardstr->cards cardstr)
(map (compose (cut alist-ref <> cards)
string->keyword
string)
(string->list cardstr)))
(define (input->hands input)
(irregex-fold camel-card-irregex
(lambda (from-index match seed)
(let ((cardstr (irregex-match-substring match 'cards))
(bidstr (irregex-match-substring match 'bid)))
(cons
(make-hand (cardstr->cards cardstr)
(string->number bidstr) #f #f)
seed)))
'() input))
#+end_src
This example shows five hands; each hand is followed by its *bid* amount. Each hand wins an amount
equal to its bid multiplied by its *rank*, where the weakest hand gets rank 1, the second-weakest
hand gets rank 2, and so on up to the strongest hand. Because there are five hands in this example,
the strongest hand will have rank 5 and its bid will be multiplied by 5.
#+name: day7-part1-hand-ranking
#+begin_src scheme
(define (rank-hands sorted-hands #!optional (index 1))
(when (not (eqv? '() sorted-hands))
(hand-rank-set! (car sorted-hands) index)
(rank-hands (cdr sorted-hands) (+ index 1))))
#+end_src
So, the first step is to put the hands in order of strength:
- =32T3K= is the only *one pair* and the other hands are all a stronger type, so it gets rank *1*.
- =KK677= and =KTJJT= are both *two pair*. Their first cards both have the same label, but the
second card of =KK677= is stronger (=K= vs =T=), so =KTJJT= gets rank *2* and =KK677= gets rank
*3*.
- =T55J5= and =QQQJA= are both *three of a kind*. =QQQJA= has a stronger first card, so it gets rank
*5* and =T55J5= gets rank *4*.
#+begin_src scheme
(let ((hands (input->hands input)))
(map calc-hand-type hands)
(rank-hands (reverse (sort hands hands>)))
(append '(("Cards" "Hand Type" "Rank" "Bid" "Bid*Rank"))
(map (lambda (hand)
(let ((card-labels (map card-label (hand-cards hand)))
(hand-rank (hand-rank hand))
(hand-bid (hand-bid hand))
(hand-type (hand-type-label (hand-type-rec hand))))
(list (apply string-append (map keyword->string card-labels))
hand-type hand-rank hand-bid
(* hand-bid hand-rank))))
(sort hands hands>))
`(("Total" "" "" "" ,(total-winnings hands)))))
#+end_src
#+results:
| Cards | Hand Type | Rank | Bid | Bid*Rank |
| AAAAA | five-of-a-kind | 19 | 61 | 1159 |
| JJJJJ | five-of-a-kind | 18 | 37 | 666 |
| AAAAJ | four-of-a-kind | 17 | 59 | 1003 |
| JAAAA | four-of-a-kind | 16 | 43 | 688 |
| JJJJ2 | four-of-a-kind | 15 | 41 | 615 |
| 2AAAA | four-of-a-kind | 14 | 23 | 322 |
| 2JJJJ | four-of-a-kind | 13 | 53 | 689 |
| Q2Q2Q | full-house | 12 | 19 | 228 |
| QQQJA | three-of-a-kind | 11 | 31 | 341 |
| T55J5 | three-of-a-kind | 10 | 29 | 290 |
| T3Q33 | three-of-a-kind | 9 | 11 | 99 |
| KK677 | two-pair | 8 | 7 | 56 |
| KTJJT | two-pair | 7 | 34 | 238 |
| T3T3J | two-pair | 6 | 17 | 102 |
| Q2KJJ | one-pair | 5 | 13 | 65 |
| 32T3K | one-pair | 4 | 5 | 20 |
| J345A | high-card | 3 | 2 | 6 |
| 2345A | high-card | 2 | 1 | 2 |
| 2345J | high-card | 1 | 3 | 3 |
| Total | | | | 6592 |
Now, you can determine the total winnings of this set of hands by adding up the result of
multiplying each hand's bid with its rank (=765= * 1 + =220= * 2 + =28= * 3 + =684= * 4 + =483= *
5). So the *total winnings* in this example are *=6440=*.
#+name: day7-part1-total-winnings
#+begin_src scheme
(define (total-winnings hands)
(foldl (lambda (total hand)
(let ((bid (hand-bid hand))
(rank (hand-rank hand)))
(+ total (* bid rank))))
0 hands))
#+end_src
Find the rank of every hand in your set. *What are the total winnings?*
#+name: day7-part1-calc-fn
#+begin_src scheme
(import (chicken string)
(chicken keyword)
(chicken sort)
(chicken irregex))
(define-record card label weight)
(define-record hand cards bid type-rec rank)
(define-record hand-type label weight)
(define input "
3Q373 470
K53JT 351
A9JK9 856
2T333 515
867T4 541
58K22 253
5JA6J 994
K4A4K 865
94377 519
92J2Q 901
J7676 389
2KK36 938
JQ2KK 987
Q7A82 509
TTTA5 243
72J27 502
AKKKA 387
23222 674
55335 161
AA655 73
QKKQA 686
5J2T5 680
666AT 385
ATA3A 761
TTT8J 364
98A2T 282
59A44 260
6T9QJ 130
T7TKQ 721
9274T 656
T9AJ4 182
A2222 259
TQKJ7 67
4J844 560
AAATA 636
9J36J 546
QJQQQ 119
249TT 295
877J7 221
4KA23 116
929Q2 929
99JQQ 445
Q9QJ8 432
4Q7TJ 963
4J2J8 783
5J657 257
88788 183
KKK7K 909
KK396 637
J45AT 117
84448 806
A2698 820
A9AA5 320
A3934 19
Q45Q5 392
78686 254
A55A5 701
98A4K 655
5AJ88 95
AK3KK 55
773KK 33
J9J9J 356
2KAKK 563
655K5 287
55T56 475
54444 308
5J5QA 811
QKA76 792
2K288 42
JTKA2 694
88668 889
8TQ64 212
23QQ2 261
8K8K5 365
JKKAA 234
3J894 880
667Q2 817
888T4 599
T5Q83 315
3QK29 670
JK4KK 322
75T8T 144
AAA7K 291
7T333 495
A49K4 448
JJ3J3 251
5999J 278
38438 890
6K3Q9 122
TTT99 93
94775 240
K8QJ3 369
59674 107
267J4 355
QTQTQ 187
46J44 961
Q7AK2 580
69969 609
876A5 474
A3866 642
Q3QQA 526
JAA88 425
35Q9K 986
QQTQJ 550
54535 357
2J222 639
QK5J7 743
222Q2 191
T4T44 855
QTQQ2 338
JA7A2 300
AAAJ2 508
4J455 23
A77AA 339
5KK25 899
252J2 737
7QJ76 888
K46QK 795
A4T3J 640
8A8K8 176
AA5AA 41
J2Q24 958
58855 632
333J3 610
74474 807
K3AAA 78
JJ222 765
44224 688
76733 361
5845K 181
TT4T2 974
23J33 102
QQJ6Q 34
Q9AQQ 150
22747 717
KAA5A 121
7AA7J 286
J786T 780
3K8TT 32
A6KAA 25
9A362 166
A29Q2 499
6688K 57
KKQKA 947
999JJ 975
6A666 927
TTT3K 658
JQQ7T 467
8A247 934
7JK8J 712
KK39K 612
6666Q 17
77Q37 868
A66AJ 169
KKKKJ 535
7Q7JJ 591
K9848 646
46888 931
A86A8 326
743TA 527
QKK67 977
KKJ6K 471
AAJ7A 571
55292 330
3A222 390
6453J 109
JKKKA 403
4J9T5 21
K7A5K 486
6TT34 793
3479Q 60
44624 443
6KK3K 164
4447J 112
QQ27Q 452
JAK65 522
Q5Q5Q 354
J5Q6A 540
68999 711
3QJ4Q 155
A6AAA 314
222KK 767
55T9A 373
T5T57 913
TTTTA 794
8J258 190
3Q87J 489
AAQAQ 950
Q4JJ4 588
6T64T 9
636K5 228
AA222 248
7KJ35 616
26646 507
44A4J 829
23323 904
TA265 135
JJQT9 136
KATJ8 644
J2862 713
4JQ28 152
Q3K2T 56
6Q232 812
9A622 885
KJKKJ 773
3859T 374
99333 101
TKTTK 205
3333A 35
5A4AQ 548
T4944 967
43353 813
423JK 869
T99T7 219
3AAAA 394
T65Q6 740
J9243 352
6656J 496
444K4 574
Q8T6K 98
AQ55K 917
7QQJ7 605
TJ5TT 615
68JQ5 852
7A3J2 745
369AK 217
57755 343
A8844 61
Q76QQ 698
36333 774
237Q7 12
KT694 283
88286 154
4T552 990
Q9J54 759
K6697 350
A3A33 937
AA9AA 246
QQ7KK 748
TT4A6 380
4J992 845
A66AA 573
5QQ2Q 28
86J37 214
2A443 362
Q9QKK 654
44434 964
77773 74
44355 235
9QK75 863
3AJ33 766
T2TJT 53
44494 860
883A9 309
QQ59Q 360
A88A8 584
A83A4 395
7J9TA 299
55955 833
QJK35 188
4656A 514
8KTQ4 554
56J47 985
J272J 184
9J999 671
72295 31
53555 264
4A537 750
7A4JJ 875
QK834 463
88KKA 570
QQ9JK 906
6Q646 858
53336 359
QJ8QJ 587
424TJ 607
KTKK6 285
Q5AQQ 84
899A8 542
K8TKK 250
4JA4A 705
6J75J 896
888K8 312
5583J 660
6T335 614
Q757T 945
3AKKA 629
KK946 825
3393Q 406
7J288 367
49999 907
99729 837
66265 384
K47JQ 263
2AJ4K 566
TTKKA 186
8J877 418
56844 666
JTTTT 531
6TJ94 26
JQ5J5 344
7J772 85
33747 510
KJA2A 729
333TQ 578
JQAT4 955
75766 834
QQ6QQ 980
32K33 306
TTTJ6 231
2QTTT 213
999AQ 608
33353 202
Q8Q8Q 756
KK555 490
746K8 691
98A75 853
JQ858 816
KK9KK 536
9T999 933
TA8A8 39
8558J 919
J8KQK 15
73Q2K 503
2K2KJ 585
JK9K5 903
TJ7T7 545
J723T 453
KT895 583
TTTKT 123
39535 393
K4K88 893
43KK6 821
6AA8J 504
972TA 597
7J736 592
536A8 63
J23Q3 402
83K9Q 405
28337 396
9T558 776
7AA78 946
QTT24 441
26QT3 401
AJQAQ 953
6T6AJ 304
JK5KK 162
2JJ2J 484
73773 6
8J864 630
78782 557
6TJ52 424
487JQ 830
8J698 82
AJAAA 866
228J8 204
622J4 823
6J2QJ 79
22K22 232
A86A6 444
83K8Q 965
JK586 944
JA848 465
8888A 45
2T28T 803
73J73 450
27272 857
7A777 544
A998J 679
46466 458
KJ233 192
4453J 378
TQQJT 451
A3K5J 512
888Q6 968
6AA66 841
QQ222 883
3K5A3 233
JA4AA 379
62288 778
44456 51
4A644 862
55647 981
A77A7 327
KQ3A3 687
QQ7Q7 976
T4A2T 293
46226 628
Q59Q5 348
36AJ2 984
54433 532
JJQ24 831
7455J 381
78845 218
72AQ5 276
52T22 618
99399 68
36AA3 118
69669 839
33Q5J 785
TJ766 626
T28J4 556
T883Q 142
73928 932
TJ884 494
AJ36Q 485
9Q999 324
T725Q 267
22622 88
92364 685
97792 789
J673K 620
99943 625
77JJ7 921
8828Q 572
7777J 353
TAAJT 926
99T29 787
AQ4J4 520
9J559 5
J3T94 706
K9KK9 918
KK252 439
79925 97
TT47T 497
848T4 126
6TTT6 426
K8825 925
888J8 62
K5K85 972
AAKKA 449
J5555 663
89J99 27
4Q444 922
A9A99 397
5A555 163
8J3K8 662
29989 645
95222 751
Q4Q4Q 193
555K5 982
74AJ8 735
KKQ6K 668
7676Q 916
A28T7 784
K57KK 388
A4J4J 115
2K442 229
33TT3 956
TT6TA 741
TT782 131
TJ5JQ 238
TQ7T7 415
29KQQ 598
A8AAT 676
46A28 650
6698K 696
6J969 158
6694A 271
QTQ5T 498
Q2QQQ 613
2A7QJ 210
6T466 683
QJ575 799
Q63Q3 822
Q9J28 848
TTTT7 7
KA9AA 854
K2JJT 859
28228 179
K29KJ 429
JJ8JJ 222
A99A5 457
QQTTT 983
43KK2 134
984JJ 1
97J97 892
2AAA8 689
9Q77J 819
98TJK 517
56KA5 71
7J66J 294
55855 335
TTT8T 596
33663 407
7J774 911
3JQ55 564
QQQ7Q 329
85668 120
KK333 301
Q3553 867
7K557 988
Q8488 400
96J99 643
29224 714
T8ATA 346
99J93 462
K83J3 697
3KQJ4 653
5KJQ2 824
4JJ3A 897
56248 727
JJ666 702
355T5 245
45KAK 553
88AAA 236
K55J5 581
AJJ49 65
A8Q3J 197
AAAKQ 529
55976 707
77776 930
A9995 227
K7J7K 912
29K99 244
4Q464 80
22972 195
666JQ 189
26278 241
79288 601
5454A 427
JTAKQ 138
88833 549
84J54 215
AATAK 114
58959 145
8ATTJ 431
QJ26K 265
A3JA3 81
T8T4J 242
4T3A3 37
44777 871
JQ542 561
A97Q9 693
A76T4 412
28T4A 481
T485A 861
78286 303
K6776 52
T8TKQ 754
KJ938 957
Q444Q 840
25A89 455
58588 673
K8858 634
K8KJ8 170
K6KKK 851
53353 140
2T2K6 593
QQAQA 48
TT6J6 305
922J2 920
AA22K 22
J555Q 725
TTAAT 781
2244J 171
A95K7 436
2J299 651
78AAA 321
2KKK2 690
2J565 649
77J5K 77
T999T 762
J4445 879
J888Q 873
J884J 1000
98898 413
29299 442
QKQ3Q 678
A652A 993
55272 898
KA5K5 664
8KJAQ 147
Q56QJ 734
K77J3 739
J7677 661
T5569 206
2AA2J 757
TJTJT 342
T2TTT 682
88J82 363
9KK78 700
AT4T4 730
86968 736
99995 207
7A3J4 172
8KK87 991
TKKJJ 16
J7532 165
J9888 996
9AJTA 92
43T78 310
93J77 317
J4424 805
43J86 703
952TJ 127
54363 146
8T2J7 435
88848 832
TAAAQ 791
8228T 256
699QT 815
KQQQK 30
T82J3 49
36222 4
AK288 86
6792A 194
2Q22T 667
J3545 270
9QJK4 280
QQ22Q 371
K9247 446
A422A 943
765K3 469
9J5A6 874
4A4QA 775
8Q8Q8 124
T8Q62 850
8Q8Q5 747
6KT88 738
82888 722
3TQQQ 349
2J3TT 539
7TQ59 72
8998T 733
JQJT3 414
82428 589
92856 423
89833 54
79T4A 523
95839 979
TJJT5 936
33839 29
37433 511
TKJ2T 681
JT973 633
Q8Q8J 971
Q5555 440
K8886 24
Q75A4 43
3AQ33 298
T446T 719
577J5 753
KJTKT 167
52528 8
25222 641
QJ2T8 621
A8JQJ 316
7T7A7 772
KQQTQ 141
83734 758
6Q66Q 434
QJ6Q2 638
AAA7A 196
57555 203
4QJQ4 216
82J5Q 763
A73A3 940
46AJQ 559
T4936 103
89Q29 262
7872T 466
A5J58 274
AAAQA 290
37399 844
A759Q 328
TJ9TT 273
77887 268
64A2J 978
6T76Q 110
QQ467 742
9J7Q5 422
4K6Q3 91
336K3 826
6K63Q 382
23552 105
243AA 505
Q887J 764
2J92A 749
68A3Q 416
7T8T8 199
225J5 404
24774 153
T7T77 870
3J393 347
Q5Q8J 128
7Q777 796
QKKKK 617
86686 108
44KT4 75
56858 622
5AJK4 960
3245Q 311
36536 370
6644Q 11
JKAAA 104
T2426 579
J3399 83
33933 602
A299J 777
26J22 224
8666J 594
J3J38 669
3AJ84 239
52Q8T 877
QJQQK 779
QJ6T8 797
43339 399
9AJ74 476
T499Q 13
2TAKA 928
T3K78 809
2923K 201
J8858 798
T8888 818
98399 168
8T266 555
23A57 652
3KKK3 113
22T22 460
AJJAA 106
7QKA8 464
QQ8TQ 368
99A99 341
62Q5A 223
J9T47 568
Q7388 894
69662 744
96J2T 323
2A779 89
Q2874 269
77797 948
5359A 864
AJ9K4 482
Q3Q44 567
JT958 665
A38J3 438
J4666 296
428J5 501
38K8K 410
6T979 709
3533T 284
2285A 910
933T6 882
K6666 786
56Q32 992
5J752 198
AJJQJ 600
KK5KK 3
38T94 180
67QTJ 69
J6636 200
229J8 493
QJTQ3 247
5KQ5K 149
654AT 528
T84T4 878
Q23QQ 905
QQQ74 325
4JTQQ 408
T4T78 340
3T5T5 551
3J3J3 391
88844 631
TTT9T 810
57775 935
A777J 604
4555T 2
A5J8T 942
22AJJ 506
22323 997
A3323 624
84442 516
2T992 76
J7T76 828
J8552 995
KTKK3 886
33853 782
53233 129
44J4J 372
KQQT2 480
K5649 576
3J63K 760
2J666 827
6JT68 318
45Q64 849
49884 801
9KTTK 902
66737 952
5Q8J4 708
57Q92 724
627J7 331
K22J6 473
4T444 923
J4444 552
78J8J 491
4K328 477
4AA3A 808
7A34Q 437
AQ888 428
8TA99 768
AA9A9 143
9K5AT 211
77722 40
TQTTT 941
Q2A4K 492
236T9 677
J8686 746
J585K 64
TJKQT 582
T3TTJ 157
22266 38
KT5TK 692
QJQQJ 908
4K623 279
7JJJ7 173
64A66 524
J7AJ8 417
K43Q3 769
T662T 148
54J2J 488
K6485 44
J6666 970
J26J9 209
8337Q 334
A27A4 319
A7T78 132
K777A 842
KKK4K 249
99K9K 430
8745K 151
Q2QTJ 433
QKQ76 525
25Q2Q 533
5QK6J 800
77T77 558
5K323 939
33KK4 590
K8A52 111
ATQJ6 569
ATK89 50
4433A 836
3KKKQ 891
46TK4 538
5249Q 447
2462K 675
8JT6T 336
466J7 459
7K7KK 838
544Q4 959
58773 483
823J5 999
2TKA5 752
AKJ58 386
7T833 99
KQ88Q 659
KJ3A4 790
K9595 307
3K3J4 534
3838T 220
32522 720
366Q3 500
J8868 989
T7KTK 376
JQQQA 14
42555 409
5T5T5 648
4KK4Q 383
K7777 884
736A3 543
343Q3 366
TJ856 237
JJ555 46
K5QQQ 275
QAQQ7 672
8KTJQ 731
QQQ3Q 47
J257Q 575
6Q3QQ 87
QKK43 924
TTATJ 998
K44K5 771
37895 881
48823 521
KKK74 456
99J79 139
J4542 635
AJ96K 954
K8937 411
5J355 895
96967 185
333T3 562
TAJ77 755
J38A8 487
AAT79 313
A6Q73 398
386JA 10
J35Q8 623
27758 969
3K3KJ 966
7928Q 627
AAA4A 59
2AA52 478
848J8 133
55225 843
TTQT9 619
3Q79K 255
27AK8 58
TKTKK 272
KTTAT 333
55666 802
47748 454
Q3T56 699
63T3T 302
8754Q 723
4J86T 358
8TTQ9 226
5523J 125
88588 606
58AAA 208
TK273 137
4Q7KQ 160
29292 577
Q333Q 611
22TT2 716
A55AA 258
64822 468
22228 847
2242T 788
JA26Q 472
8JAAA 174
K5Q8A 175
Q5AT4 732
J4434 530
76666 337
9998Q 547
9T2J9 100
3Q982 90
7727Q 281
92944 973
K2597 814
K444K 36
26KJ6 292
34K38 962
5A378 225
636J9 375
TTTT4 420
A66TA 461
69QK5 345
76293 479
66966 804
A3383 297
T82TT 657
2QJJQ 156
K2JK3 94
K6K66 252
K58QJ 876
6J979 513
92647 718
QQ9Q9 586
862Q5 20
5465K 915
KQ44Q 595
T66T6 288
TJT7T 710
5JT8K 159
KJTK3 603
KKJTQ 949
67776 914
J4323 177
22229 704
96999 178
8AJKA 70
69T69 419
65556 770
87738 537
547J4 835
44766 421
3355J 684
2K266 647
5TTT5 266
3T3TT 332
88JJ8 96
QQ5K3 887
K7JKK 377
J8Q2Q 66
2KKJ6 230
TTKQT 277
22Q92 18
JTTTK 695
J993Q 846
88898 728
88T87 715
Q74J4 872
4T999 951
T997Q 289
92QA9 726
AJ394 900
TT2T2 518
JJJJJ 565")
(define cards `((#:A . ,(make-card #:A 13))
(#:K . ,(make-card #:K 12))
(#:Q . ,(make-card #:Q 11))
(#:J . ,(make-card #:J 10))
(#:T . ,(make-card #:T 9))
(#:9 . ,(make-card #:9 8))
(#:8 . ,(make-card #:8 7))
(#:7 . ,(make-card #:7 6))
(#:6 . ,(make-card #:6 5))
(#:5 . ,(make-card #:5 4))
(#:4 . ,(make-card #:4 3))
(#:3 . ,(make-card #:3 2))
(#:2 . ,(make-card #:2 1))))
(define (calc-card-frequencies cardlist #!optional (frequencies '()))
(if (eqv? '() cardlist)
(sort (map cdr frequencies) >)
(let* ((card-label (card-label (car cardlist)))
(card-old-frequency (alist-ref card-label frequencies eqv? 0)))
(calc-card-frequencies (cdr cardlist)
(alist-update card-label (+ 1 card-old-frequency) frequencies)))))
(define (calc-hand-type hand)
(let ((frequencies (calc-card-frequencies (hand-cards hand))))
(cond ;; Insert the comparisons from below here
((= 5 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:five-of-a-kind hand-types))) ((= 4 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:four-of-a-kind hand-types))) ((and (= 3 (car frequencies))
(= 2 (cadr frequencies)))
(hand-type-rec-set! hand (alist-ref #:full-house hand-types))) ((= 3 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:three-of-a-kind hand-types))) ((and (= 2 (car frequencies))
(= 2 (cadr frequencies)))
(hand-type-rec-set! hand (alist-ref #:two-pair hand-types))) ((= 2 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:one-pair hand-types))) ((= 1 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:high-card hand-types)))))
hand)
(define hand-types `((#:five-of-a-kind . ,(make-hand-type #:five-of-a-kind 7))
(#:four-of-a-kind . ,(make-hand-type #:four-of-a-kind 6))
(#:full-house . ,(make-hand-type #:full-house 5))
(#:three-of-a-kind . ,(make-hand-type #:three-of-a-kind 4))
(#:two-pair . ,(make-hand-type #:two-pair 3))
(#:one-pair . ,(make-hand-type #:one-pair 2))
(#:high-card . ,(make-hand-type #:high-card 1))))
(define (card> card-a card-b)
(> (card-weight card-a) (card-weight card-b)))
(define (hand-cards> cards-a cards-b)
(or (card> (car cards-a) (car cards-b))
(and (< 1 (length cards-a))
(= (card-weight (car cards-a)) (card-weight (car cards-b)))
(hand-cards> (cdr cards-a) (cdr cards-b)))))
(define (hands> hand-a hand-b)
(let ((type-weight-a (hand-type-weight (hand-type-rec hand-a)))
(type-weight-b (hand-type-weight (hand-type-rec hand-b)))
(cards-a (hand-cards hand-a))
(cards-b (hand-cards hand-b)))
(or (> type-weight-a type-weight-b)
(and (= type-weight-a type-weight-b)
(hand-cards> cards-a cards-b)))))
(define camel-card-irregex
'(: (submatch-named cards (+ (or (/ #\A #\Z) (/ #\0 #\9))))
" "
(submatch-named bid (+ (/ #\0 #\9)))))
(define (cardstr->cards cardstr)
(map (compose (cut alist-ref <> cards)
string->keyword
string)
(string->list cardstr)))
(define (input->hands input)
(irregex-fold camel-card-irregex
(lambda (from-index match seed)
(let ((cardstr (irregex-match-substring match 'cards))
(bidstr (irregex-match-substring match 'bid)))
(cons
(make-hand (cardstr->cards cardstr)
(string->number bidstr) #f #f)
seed)))
'() input))
(define (rank-hands sorted-hands #!optional (index 1))
(when (not (eqv? '() sorted-hands))
(hand-rank-set! (car sorted-hands) index)
(rank-hands (cdr sorted-hands) (+ index 1))))
(define (total-winnings hands)
(foldl (lambda (total hand)
(let ((bid (hand-bid hand))
(rank (hand-rank hand)))
(+ total (* bid rank))))
0 hands))
(define (calc-part-1)
(let ((hands (input->hands input)))
(map calc-hand-type hands)
(rank-hands (reverse (sort hands hands>)))
(total-winnings hands)))
#+end_src
#+results:
: 251216224
** Part Two
*** Quest
To make things a little more interesting, the Elf introduces one additional rule. Now, =J= cards are
[[https://en.wikipedia.org/wiki/Joker_(playing_card)][jokers]] - wildcards that can act like whatever card would make the hand the strongest type possible.
To balance this, *=J cards are now the weakest* individual cards, weaker even than =2=. The other
cards stay in the same order: =A=, =K=, =Q=, =T=, =9=, =8=, =7=, =6=, =5=, =4=, =3=, =2=, =J=.
#+name: day7-part2-cards
#+begin_src scheme
(define p2-cards `((#:A . ,(make-card #:A 13))
(#:K . ,(make-card #:K 12))
(#:Q . ,(make-card #:Q 11))
(#:T . ,(make-card #:T 10))
(#:9 . ,(make-card #:9 9))
(#:8 . ,(make-card #:8 8))
(#:7 . ,(make-card #:7 7))
(#:6 . ,(make-card #:6 6))
(#:5 . ,(make-card #:5 5))
(#:4 . ,(make-card #:4 4))
(#:3 . ,(make-card #:3 3))
(#:2 . ,(make-card #:2 2))
(#:J . ,(make-card #:J 1))))
#+end_src
/In addition, the ~cardstr->cards~ and, subsequently, ~input->hands~ functions have to be adjusted
to use this new list./
#+name: day7-part2-data-extraction
#+begin_src scheme
(define (p2-cardstr->cards cardstr)
(map (compose (cut alist-ref <> p2-cards)
string->keyword
string)
(string->list cardstr)))
(define (p2-input->hands input)
(irregex-fold camel-card-irregex
(lambda (from-index match seed)
(let ((cardstr (irregex-match-substring match 'cards))
(bidstr (irregex-match-substring match 'bid)))
(cons
(make-hand (p2-cardstr->cards cardstr)
(string->number bidstr) #f #f)
seed)))
'() input))
#+end_src
=J= cards can pretend to be whatever card is best for the purpose of determining hand type; for
example, =QJJQ2= is now considered *four of a kind*. However, for the purpose of breaking ties
between two hands of the same type, =J= is always treated as =J=, not the card it's pretending to
be: =JKKK2= is weaker than =QQQQ2= because =J= is weaker than =Q=.
#+name: day7-part2-types
#+begin_src scheme
(define (add-joker frequencies joker-freq)
(let* ((joker-account joker-freq)
(new-freqs (map (lambda (freq)
(cond
((eqv? #:J (car freq)) freq)
((< 5 (+ joker-account (cdr freq)))
(set! joker-account (- 5 (cdr freq)))
(cons (car freq) 5))
(else
(let ((newval (+ joker-account (cdr freq))))
(set! joker-account 0)
(cons (car freq) newval)))))
frequencies)))
(alist-update #:J joker-account new-freqs)))
(define (p2-calc-card-frequencies cardlist #!optional (frequencies '()))
(if (eqv? '() cardlist)
(let* ((joker-freq (alist-ref #:J frequencies eqv? 0))
(new-freqs (add-joker (sort frequencies (lambda (x y) (> (cdr x) (cdr y)))) joker-freq)))
(sort (map cdr new-freqs) >))
(let* ((card-label (card-label (car cardlist)))
(card-old-frequency (alist-ref card-label frequencies eqv? 0)))
(p2-calc-card-frequencies (cdr cardlist)
(alist-update card-label (+ 1 card-old-frequency) frequencies)))))
(define (p2-calc-hand-type hand)
(let ((frequencies (p2-calc-card-frequencies (hand-cards hand))))
(cond ;; Insert the comparisons from part 1 here
))
hand)
#+end_src
Now, the above example goes very differently:
#+begin_example
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483
#+end_example
- =32T3K= is still the only *one pair*; it doesn't contain any jokers, so its strength doesn't increase.
- =KK677= is now the only *two pair*, making it the second-weakest hand.
- =T55J5=, =KTJJT=, and =QQQJA= are now all *four of a kind*! =T55J5= gets rank 3, =QQQJA= gets rank
4, and =KTJJT= gets rank 5.
/We again take the Reddit example from above, since it covers corner cases./
#+begin_src scheme
(let ((hands (p2-input->hands input)))
(map p2-calc-hand-type hands)
(rank-hands (reverse (sort hands hands>)))
(append '(("Cards" "Hand Type" "Rank" "Bid" "Bid*Rank"))
(map (lambda (hand)
(let ((card-labels (map card-label (hand-cards hand)))
(hand-rank (hand-rank hand))
(hand-bid (hand-bid hand))
(hand-type (hand-type-label (hand-type-rec hand))))
(list (apply string-append (map keyword->string card-labels))
hand-type hand-rank hand-bid
(* hand-bid hand-rank))))
(sort hands hands>))
`(("Total" "" "" "" ,(total-winnings hands)))))
#+end_src
#+results:
| Cards | Hand Type | Rank | Bid | Bid*Rank |
| AAAAA | five-of-a-kind | 19 | 61 | 1159 |
| AAAAJ | five-of-a-kind | 18 | 59 | 1062 |
| 2JJJJ | five-of-a-kind | 17 | 53 | 901 |
| JAAAA | five-of-a-kind | 16 | 43 | 688 |
| JJJJ2 | five-of-a-kind | 15 | 41 | 615 |
| JJJJJ | five-of-a-kind | 14 | 37 | 518 |
| KTJJT | four-of-a-kind | 13 | 34 | 442 |
| QQQJA | four-of-a-kind | 12 | 31 | 372 |
| T55J5 | four-of-a-kind | 11 | 29 | 319 |
| 2AAAA | four-of-a-kind | 10 | 23 | 230 |
| Q2Q2Q | full-house | 9 | 19 | 171 |
| T3T3J | full-house | 8 | 17 | 136 |
| Q2KJJ | three-of-a-kind | 7 | 13 | 91 |
| T3Q33 | three-of-a-kind | 6 | 11 | 66 |
| KK677 | two-pair | 5 | 7 | 35 |
| 32T3K | one-pair | 4 | 5 | 20 |
| 2345J | one-pair | 3 | 3 | 9 |
| J345A | one-pair | 2 | 2 | 4 |
| 2345A | high-card | 1 | 1 | 1 |
| Total | | | | 6839 |
With the new joker rule, the total winnings in this example are *=5905=*.
Using the new joker rule, find the rank of every hand in your set. *What are the new total
winnings?*
#+name: day7-part2-calc-fn
#+begin_src scheme
(import (chicken string)
(chicken keyword)
(chicken sort)
(chicken irregex))
(define-record card label weight)
(define-record hand cards bid type-rec rank)
(define-record hand-type label weight)
(define input "
3Q373 470
K53JT 351
A9JK9 856
2T333 515
867T4 541
58K22 253
5JA6J 994
K4A4K 865
94377 519
92J2Q 901
J7676 389
2KK36 938
JQ2KK 987
Q7A82 509
TTTA5 243
72J27 502
AKKKA 387
23222 674
55335 161
AA655 73
QKKQA 686
5J2T5 680
666AT 385
ATA3A 761
TTT8J 364
98A2T 282
59A44 260
6T9QJ 130
T7TKQ 721
9274T 656
T9AJ4 182
A2222 259
TQKJ7 67
4J844 560
AAATA 636
9J36J 546
QJQQQ 119
249TT 295
877J7 221
4KA23 116
929Q2 929
99JQQ 445
Q9QJ8 432
4Q7TJ 963
4J2J8 783
5J657 257
88788 183
KKK7K 909
KK396 637
J45AT 117
84448 806
A2698 820
A9AA5 320
A3934 19
Q45Q5 392
78686 254
A55A5 701
98A4K 655
5AJ88 95
AK3KK 55
773KK 33
J9J9J 356
2KAKK 563
655K5 287
55T56 475
54444 308
5J5QA 811
QKA76 792
2K288 42
JTKA2 694
88668 889
8TQ64 212
23QQ2 261
8K8K5 365
JKKAA 234
3J894 880
667Q2 817
888T4 599
T5Q83 315
3QK29 670
JK4KK 322
75T8T 144
AAA7K 291
7T333 495
A49K4 448
JJ3J3 251
5999J 278
38438 890
6K3Q9 122
TTT99 93
94775 240
K8QJ3 369
59674 107
267J4 355
QTQTQ 187
46J44 961
Q7AK2 580
69969 609
876A5 474
A3866 642
Q3QQA 526
JAA88 425
35Q9K 986
QQTQJ 550
54535 357
2J222 639
QK5J7 743
222Q2 191
T4T44 855
QTQQ2 338
JA7A2 300
AAAJ2 508
4J455 23
A77AA 339
5KK25 899
252J2 737
7QJ76 888
K46QK 795
A4T3J 640
8A8K8 176
AA5AA 41
J2Q24 958
58855 632
333J3 610
74474 807
K3AAA 78
JJ222 765
44224 688
76733 361
5845K 181
TT4T2 974
23J33 102
QQJ6Q 34
Q9AQQ 150
22747 717
KAA5A 121
7AA7J 286
J786T 780
3K8TT 32
A6KAA 25
9A362 166
A29Q2 499
6688K 57
KKQKA 947
999JJ 975
6A666 927
TTT3K 658
JQQ7T 467
8A247 934
7JK8J 712
KK39K 612
6666Q 17
77Q37 868
A66AJ 169
KKKKJ 535
7Q7JJ 591
K9848 646
46888 931
A86A8 326
743TA 527
QKK67 977
KKJ6K 471
AAJ7A 571
55292 330
3A222 390
6453J 109
JKKKA 403
4J9T5 21
K7A5K 486
6TT34 793
3479Q 60
44624 443
6KK3K 164
4447J 112
QQ27Q 452
JAK65 522
Q5Q5Q 354
J5Q6A 540
68999 711
3QJ4Q 155
A6AAA 314
222KK 767
55T9A 373
T5T57 913
TTTTA 794
8J258 190
3Q87J 489
AAQAQ 950
Q4JJ4 588
6T64T 9
636K5 228
AA222 248
7KJ35 616
26646 507
44A4J 829
23323 904
TA265 135
JJQT9 136
KATJ8 644
J2862 713
4JQ28 152
Q3K2T 56
6Q232 812
9A622 885
KJKKJ 773
3859T 374
99333 101
TKTTK 205
3333A 35
5A4AQ 548
T4944 967
43353 813
423JK 869
T99T7 219
3AAAA 394
T65Q6 740
J9243 352
6656J 496
444K4 574
Q8T6K 98
AQ55K 917
7QQJ7 605
TJ5TT 615
68JQ5 852
7A3J2 745
369AK 217
57755 343
A8844 61
Q76QQ 698
36333 774
237Q7 12
KT694 283
88286 154
4T552 990
Q9J54 759
K6697 350
A3A33 937
AA9AA 246
QQ7KK 748
TT4A6 380
4J992 845
A66AA 573
5QQ2Q 28
86J37 214
2A443 362
Q9QKK 654
44434 964
77773 74
44355 235
9QK75 863
3AJ33 766
T2TJT 53
44494 860
883A9 309
QQ59Q 360
A88A8 584
A83A4 395
7J9TA 299
55955 833
QJK35 188
4656A 514
8KTQ4 554
56J47 985
J272J 184
9J999 671
72295 31
53555 264
4A537 750
7A4JJ 875
QK834 463
88KKA 570
QQ9JK 906
6Q646 858
53336 359
QJ8QJ 587
424TJ 607
KTKK6 285
Q5AQQ 84
899A8 542
K8TKK 250
4JA4A 705
6J75J 896
888K8 312
5583J 660
6T335 614
Q757T 945
3AKKA 629
KK946 825
3393Q 406
7J288 367
49999 907
99729 837
66265 384
K47JQ 263
2AJ4K 566
TTKKA 186
8J877 418
56844 666
JTTTT 531
6TJ94 26
JQ5J5 344
7J772 85
33747 510
KJA2A 729
333TQ 578
JQAT4 955
75766 834
QQ6QQ 980
32K33 306
TTTJ6 231
2QTTT 213
999AQ 608
33353 202
Q8Q8Q 756
KK555 490
746K8 691
98A75 853
JQ858 816
KK9KK 536
9T999 933
TA8A8 39
8558J 919
J8KQK 15
73Q2K 503
2K2KJ 585
JK9K5 903
TJ7T7 545
J723T 453
KT895 583
TTTKT 123
39535 393
K4K88 893
43KK6 821
6AA8J 504
972TA 597
7J736 592
536A8 63
J23Q3 402
83K9Q 405
28337 396
9T558 776
7AA78 946
QTT24 441
26QT3 401
AJQAQ 953
6T6AJ 304
JK5KK 162
2JJ2J 484
73773 6
8J864 630
78782 557
6TJ52 424
487JQ 830
8J698 82
AJAAA 866
228J8 204
622J4 823
6J2QJ 79
22K22 232
A86A6 444
83K8Q 965
JK586 944
JA848 465
8888A 45
2T28T 803
73J73 450
27272 857
7A777 544
A998J 679
46466 458
KJ233 192
4453J 378
TQQJT 451
A3K5J 512
888Q6 968
6AA66 841
QQ222 883
3K5A3 233
JA4AA 379
62288 778
44456 51
4A644 862
55647 981
A77A7 327
KQ3A3 687
QQ7Q7 976
T4A2T 293
46226 628
Q59Q5 348
36AJ2 984
54433 532
JJQ24 831
7455J 381
78845 218
72AQ5 276
52T22 618
99399 68
36AA3 118
69669 839
33Q5J 785
TJ766 626
T28J4 556
T883Q 142
73928 932
TJ884 494
AJ36Q 485
9Q999 324
T725Q 267
22622 88
92364 685
97792 789
J673K 620
99943 625
77JJ7 921
8828Q 572
7777J 353
TAAJT 926
99T29 787
AQ4J4 520
9J559 5
J3T94 706
K9KK9 918
KK252 439
79925 97
TT47T 497
848T4 126
6TTT6 426
K8825 925
888J8 62
K5K85 972
AAKKA 449
J5555 663
89J99 27
4Q444 922
A9A99 397
5A555 163
8J3K8 662
29989 645
95222 751
Q4Q4Q 193
555K5 982
74AJ8 735
KKQ6K 668
7676Q 916
A28T7 784
K57KK 388
A4J4J 115
2K442 229
33TT3 956
TT6TA 741
TT782 131
TJ5JQ 238
TQ7T7 415
29KQQ 598
A8AAT 676
46A28 650
6698K 696
6J969 158
6694A 271
QTQ5T 498
Q2QQQ 613
2A7QJ 210
6T466 683
QJ575 799
Q63Q3 822
Q9J28 848
TTTT7 7
KA9AA 854
K2JJT 859
28228 179
K29KJ 429
JJ8JJ 222
A99A5 457
QQTTT 983
43KK2 134
984JJ 1
97J97 892
2AAA8 689
9Q77J 819
98TJK 517
56KA5 71
7J66J 294
55855 335
TTT8T 596
33663 407
7J774 911
3JQ55 564
QQQ7Q 329
85668 120
KK333 301
Q3553 867
7K557 988
Q8488 400
96J99 643
29224 714
T8ATA 346
99J93 462
K83J3 697
3KQJ4 653
5KJQ2 824
4JJ3A 897
56248 727
JJ666 702
355T5 245
45KAK 553
88AAA 236
K55J5 581
AJJ49 65
A8Q3J 197
AAAKQ 529
55976 707
77776 930
A9995 227
K7J7K 912
29K99 244
4Q464 80
22972 195
666JQ 189
26278 241
79288 601
5454A 427
JTAKQ 138
88833 549
84J54 215
AATAK 114
58959 145
8ATTJ 431
QJ26K 265
A3JA3 81
T8T4J 242
4T3A3 37
44777 871
JQ542 561
A97Q9 693
A76T4 412
28T4A 481
T485A 861
78286 303
K6776 52
T8TKQ 754
KJ938 957
Q444Q 840
25A89 455
58588 673
K8858 634
K8KJ8 170
K6KKK 851
53353 140
2T2K6 593
QQAQA 48
TT6J6 305
922J2 920
AA22K 22
J555Q 725
TTAAT 781
2244J 171
A95K7 436
2J299 651
78AAA 321
2KKK2 690
2J565 649
77J5K 77
T999T 762
J4445 879
J888Q 873
J884J 1000
98898 413
29299 442
QKQ3Q 678
A652A 993
55272 898
KA5K5 664
8KJAQ 147
Q56QJ 734
K77J3 739
J7677 661
T5569 206
2AA2J 757
TJTJT 342
T2TTT 682
88J82 363
9KK78 700
AT4T4 730
86968 736
99995 207
7A3J4 172
8KK87 991
TKKJJ 16
J7532 165
J9888 996
9AJTA 92
43T78 310
93J77 317
J4424 805
43J86 703
952TJ 127
54363 146
8T2J7 435
88848 832
TAAAQ 791
8228T 256
699QT 815
KQQQK 30
T82J3 49
36222 4
AK288 86
6792A 194
2Q22T 667
J3545 270
9QJK4 280
QQ22Q 371
K9247 446
A422A 943
765K3 469
9J5A6 874
4A4QA 775
8Q8Q8 124
T8Q62 850
8Q8Q5 747
6KT88 738
82888 722
3TQQQ 349
2J3TT 539
7TQ59 72
8998T 733
JQJT3 414
82428 589
92856 423
89833 54
79T4A 523
95839 979
TJJT5 936
33839 29
37433 511
TKJ2T 681
JT973 633
Q8Q8J 971
Q5555 440
K8886 24
Q75A4 43
3AQ33 298
T446T 719
577J5 753
KJTKT 167
52528 8
25222 641
QJ2T8 621
A8JQJ 316
7T7A7 772
KQQTQ 141
83734 758
6Q66Q 434
QJ6Q2 638
AAA7A 196
57555 203
4QJQ4 216
82J5Q 763
A73A3 940
46AJQ 559
T4936 103
89Q29 262
7872T 466
A5J58 274
AAAQA 290
37399 844
A759Q 328
TJ9TT 273
77887 268
64A2J 978
6T76Q 110
QQ467 742
9J7Q5 422
4K6Q3 91
336K3 826
6K63Q 382
23552 105
243AA 505
Q887J 764
2J92A 749
68A3Q 416
7T8T8 199
225J5 404
24774 153
T7T77 870
3J393 347
Q5Q8J 128
7Q777 796
QKKKK 617
86686 108
44KT4 75
56858 622
5AJK4 960
3245Q 311
36536 370
6644Q 11
JKAAA 104
T2426 579
J3399 83
33933 602
A299J 777
26J22 224
8666J 594
J3J38 669
3AJ84 239
52Q8T 877
QJQQK 779
QJ6T8 797
43339 399
9AJ74 476
T499Q 13
2TAKA 928
T3K78 809
2923K 201
J8858 798
T8888 818
98399 168
8T266 555
23A57 652
3KKK3 113
22T22 460
AJJAA 106
7QKA8 464
QQ8TQ 368
99A99 341
62Q5A 223
J9T47 568
Q7388 894
69662 744
96J2T 323
2A779 89
Q2874 269
77797 948
5359A 864
AJ9K4 482
Q3Q44 567
JT958 665
A38J3 438
J4666 296
428J5 501
38K8K 410
6T979 709
3533T 284
2285A 910
933T6 882
K6666 786
56Q32 992
5J752 198
AJJQJ 600
KK5KK 3
38T94 180
67QTJ 69
J6636 200
229J8 493
QJTQ3 247
5KQ5K 149
654AT 528
T84T4 878
Q23QQ 905
QQQ74 325
4JTQQ 408
T4T78 340
3T5T5 551
3J3J3 391
88844 631
TTT9T 810
57775 935
A777J 604
4555T 2
A5J8T 942
22AJJ 506
22323 997
A3323 624
84442 516
2T992 76
J7T76 828
J8552 995
KTKK3 886
33853 782
53233 129
44J4J 372
KQQT2 480
K5649 576
3J63K 760
2J666 827
6JT68 318
45Q64 849
49884 801
9KTTK 902
66737 952
5Q8J4 708
57Q92 724
627J7 331
K22J6 473
4T444 923
J4444 552
78J8J 491
4K328 477
4AA3A 808
7A34Q 437
AQ888 428
8TA99 768
AA9A9 143
9K5AT 211
77722 40
TQTTT 941
Q2A4K 492
236T9 677
J8686 746
J585K 64
TJKQT 582
T3TTJ 157
22266 38
KT5TK 692
QJQQJ 908
4K623 279
7JJJ7 173
64A66 524
J7AJ8 417
K43Q3 769
T662T 148
54J2J 488
K6485 44
J6666 970
J26J9 209
8337Q 334
A27A4 319
A7T78 132
K777A 842
KKK4K 249
99K9K 430
8745K 151
Q2QTJ 433
QKQ76 525
25Q2Q 533
5QK6J 800
77T77 558
5K323 939
33KK4 590
K8A52 111
ATQJ6 569
ATK89 50
4433A 836
3KKKQ 891
46TK4 538
5249Q 447
2462K 675
8JT6T 336
466J7 459
7K7KK 838
544Q4 959
58773 483
823J5 999
2TKA5 752
AKJ58 386
7T833 99
KQ88Q 659
KJ3A4 790
K9595 307
3K3J4 534
3838T 220
32522 720
366Q3 500
J8868 989
T7KTK 376
JQQQA 14
42555 409
5T5T5 648
4KK4Q 383
K7777 884
736A3 543
343Q3 366
TJ856 237
JJ555 46
K5QQQ 275
QAQQ7 672
8KTJQ 731
QQQ3Q 47
J257Q 575
6Q3QQ 87
QKK43 924
TTATJ 998
K44K5 771
37895 881
48823 521
KKK74 456
99J79 139
J4542 635
AJ96K 954
K8937 411
5J355 895
96967 185
333T3 562
TAJ77 755
J38A8 487
AAT79 313
A6Q73 398
386JA 10
J35Q8 623
27758 969
3K3KJ 966
7928Q 627
AAA4A 59
2AA52 478
848J8 133
55225 843
TTQT9 619
3Q79K 255
27AK8 58
TKTKK 272
KTTAT 333
55666 802
47748 454
Q3T56 699
63T3T 302
8754Q 723
4J86T 358
8TTQ9 226
5523J 125
88588 606
58AAA 208
TK273 137
4Q7KQ 160
29292 577
Q333Q 611
22TT2 716
A55AA 258
64822 468
22228 847
2242T 788
JA26Q 472
8JAAA 174
K5Q8A 175
Q5AT4 732
J4434 530
76666 337
9998Q 547
9T2J9 100
3Q982 90
7727Q 281
92944 973
K2597 814
K444K 36
26KJ6 292
34K38 962
5A378 225
636J9 375
TTTT4 420
A66TA 461
69QK5 345
76293 479
66966 804
A3383 297
T82TT 657
2QJJQ 156
K2JK3 94
K6K66 252
K58QJ 876
6J979 513
92647 718
QQ9Q9 586
862Q5 20
5465K 915
KQ44Q 595
T66T6 288
TJT7T 710
5JT8K 159
KJTK3 603
KKJTQ 949
67776 914
J4323 177
22229 704
96999 178
8AJKA 70
69T69 419
65556 770
87738 537
547J4 835
44766 421
3355J 684
2K266 647
5TTT5 266
3T3TT 332
88JJ8 96
QQ5K3 887
K7JKK 377
J8Q2Q 66
2KKJ6 230
TTKQT 277
22Q92 18
JTTTK 695
J993Q 846
88898 728
88T87 715
Q74J4 872
4T999 951
T997Q 289
92QA9 726
AJ394 900
TT2T2 518
JJJJJ 565")
(define p2-cards `((#:A . ,(make-card #:A 13))
(#:K . ,(make-card #:K 12))
(#:Q . ,(make-card #:Q 11))
(#:T . ,(make-card #:T 10))
(#:9 . ,(make-card #:9 9))
(#:8 . ,(make-card #:8 8))
(#:7 . ,(make-card #:7 7))
(#:6 . ,(make-card #:6 6))
(#:5 . ,(make-card #:5 5))
(#:4 . ,(make-card #:4 4))
(#:3 . ,(make-card #:3 3))
(#:2 . ,(make-card #:2 2))
(#:J . ,(make-card #:J 1))))
(define (add-joker frequencies joker-freq)
(let* ((joker-account joker-freq)
(new-freqs (map (lambda (freq)
(cond
((eqv? #:J (car freq)) freq)
((< 5 (+ joker-account (cdr freq)))
(set! joker-account (- 5 (cdr freq)))
(cons (car freq) 5))
(else
(let ((newval (+ joker-account (cdr freq))))
(set! joker-account 0)
(cons (car freq) newval)))))
frequencies)))
(alist-update #:J joker-account new-freqs)))
(define (p2-calc-card-frequencies cardlist #!optional (frequencies '()))
(if (eqv? '() cardlist)
(let* ((joker-freq (alist-ref #:J frequencies eqv? 0))
(new-freqs (add-joker (sort frequencies (lambda (x y) (> (cdr x) (cdr y)))) joker-freq)))
(sort (map cdr new-freqs) >))
(let* ((card-label (card-label (car cardlist)))
(card-old-frequency (alist-ref card-label frequencies eqv? 0)))
(p2-calc-card-frequencies (cdr cardlist)
(alist-update card-label (+ 1 card-old-frequency) frequencies)))))
(define (p2-calc-hand-type hand)
(let ((frequencies (p2-calc-card-frequencies (hand-cards hand))))
(cond ;; Insert the comparisons from part 1 here
((= 5 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:five-of-a-kind hand-types))) ((= 4 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:four-of-a-kind hand-types))) ((and (= 3 (car frequencies))
(= 2 (cadr frequencies)))
(hand-type-rec-set! hand (alist-ref #:full-house hand-types))) ((= 3 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:three-of-a-kind hand-types))) ((and (= 2 (car frequencies))
(= 2 (cadr frequencies)))
(hand-type-rec-set! hand (alist-ref #:two-pair hand-types))) ((= 2 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:one-pair hand-types))) ((= 1 (car frequencies))
(hand-type-rec-set! hand (alist-ref #:high-card hand-types)))))
hand)
(define hand-types `((#:five-of-a-kind . ,(make-hand-type #:five-of-a-kind 7))
(#:four-of-a-kind . ,(make-hand-type #:four-of-a-kind 6))
(#:full-house . ,(make-hand-type #:full-house 5))
(#:three-of-a-kind . ,(make-hand-type #:three-of-a-kind 4))
(#:two-pair . ,(make-hand-type #:two-pair 3))
(#:one-pair . ,(make-hand-type #:one-pair 2))
(#:high-card . ,(make-hand-type #:high-card 1))))
(define (card> card-a card-b)
(> (card-weight card-a) (card-weight card-b)))
(define (hand-cards> cards-a cards-b)
(or (card> (car cards-a) (car cards-b))
(and (< 1 (length cards-a))
(= (card-weight (car cards-a)) (card-weight (car cards-b)))
(hand-cards> (cdr cards-a) (cdr cards-b)))))
(define (hands> hand-a hand-b)
(let ((type-weight-a (hand-type-weight (hand-type-rec hand-a)))
(type-weight-b (hand-type-weight (hand-type-rec hand-b)))
(cards-a (hand-cards hand-a))
(cards-b (hand-cards hand-b)))
(or (> type-weight-a type-weight-b)
(and (= type-weight-a type-weight-b)
(hand-cards> cards-a cards-b)))))
(define camel-card-irregex
'(: (submatch-named cards (+ (or (/ #\A #\Z) (/ #\0 #\9))))
" "
(submatch-named bid (+ (/ #\0 #\9)))))
(define (p2-cardstr->cards cardstr)
(map (compose (cut alist-ref <> p2-cards)
string->keyword
string)
(string->list cardstr)))
(define (p2-input->hands input)
(irregex-fold camel-card-irregex
(lambda (from-index match seed)
(let ((cardstr (irregex-match-substring match 'cards))
(bidstr (irregex-match-substring match 'bid)))
(cons
(make-hand (p2-cardstr->cards cardstr)
(string->number bidstr) #f #f)
seed)))
'() input))
(define (rank-hands sorted-hands #!optional (index 1))
(when (not (eqv? '() sorted-hands))
(hand-rank-set! (car sorted-hands) index)
(rank-hands (cdr sorted-hands) (+ index 1))))
(define (total-winnings hands)
(foldl (lambda (total hand)
(let ((bid (hand-bid hand))
(rank (hand-rank hand)))
(+ total (* bid rank))))
0 hands))
(define (calc-part-2)
(let ((hands (p2-input->hands input)))
(map p2-calc-hand-type hands)
(rank-hands (reverse (sort hands hands>)))
(total-winnings hands)))
#+end_src
#+results:
: 250825971
** Thoughts About Today's Puzzle
At first, when reading the description, I thought I'd miss not having extensions a lot for today's
puzzle. But ultimately, I think it was fine witout. Sure, the code might have been a bit shorter
here and there, but that's about it.
I also came across the conscious realization about what feels intuitively right, but maybe is not;
Scheme is not evaluating code depth-first. Consider the following two examples:
#+name: day7-thoughts-a
#+begin_src scheme
(let ((A '((#:X . 5) (#:Y . 10)))
(X-buf 5))
(alist-update #:X X-buf
(map (lambda (a)
(cond ((eqv? #:X (car a)) a)
(else
(let ((new-Y X-buf))
(set! X-buf 0)
(cons (car a) new-Y)))))
A)))
#+end_src
#+results: day7-thoughts-a
#+name: day7-thoughts-b
#+begin_src scheme
(let* ((A '((#:X . 5) (#:Y . 10)))
(X-buf 5)
(new-A (map (lambda (a)
(cond ((eqv? #:X (car a)) a)
(else
(let ((new-Y X-buf))
(set! X-buf 0)
(cons (car a) new-Y)))))
A)))
(alist-update #:X X-buf new-A))
#+end_src
The first example evaluates as =((#:X . 5) (#:Y . 5))=
, because Scheme evaluates left-to-right, and only nested-first as soon as it encounters a list. But
would it really be unintuitive if it was depth-first? In that case, the first example would evaluate
to the same result as the second: =((#:X . 0) (#:Y . 5))=
** Puzzle Input
Jump to [[#headline-83][day 8]].
#+name: day7-input
#+begin_src fundamental
3Q373 470
K53JT 351
A9JK9 856
2T333 515
867T4 541
58K22 253
5JA6J 994
K4A4K 865
94377 519
92J2Q 901
J7676 389
2KK36 938
JQ2KK 987
Q7A82 509
TTTA5 243
72J27 502
AKKKA 387
23222 674
55335 161
AA655 73
QKKQA 686
5J2T5 680
666AT 385
ATA3A 761
TTT8J 364
98A2T 282
59A44 260
6T9QJ 130
T7TKQ 721
9274T 656
T9AJ4 182
A2222 259
TQKJ7 67
4J844 560
AAATA 636
9J36J 546
QJQQQ 119
249TT 295
877J7 221
4KA23 116
929Q2 929
99JQQ 445
Q9QJ8 432
4Q7TJ 963
4J2J8 783
5J657 257
88788 183
KKK7K 909
KK396 637
J45AT 117
84448 806
A2698 820
A9AA5 320
A3934 19
Q45Q5 392
78686 254
A55A5 701
98A4K 655
5AJ88 95
AK3KK 55
773KK 33
J9J9J 356
2KAKK 563
655K5 287
55T56 475
54444 308
5J5QA 811
QKA76 792
2K288 42
JTKA2 694
88668 889
8TQ64 212
23QQ2 261
8K8K5 365
JKKAA 234
3J894 880
667Q2 817
888T4 599
T5Q83 315
3QK29 670
JK4KK 322
75T8T 144
AAA7K 291
7T333 495
A49K4 448
JJ3J3 251
5999J 278
38438 890
6K3Q9 122
TTT99 93
94775 240
K8QJ3 369
59674 107
267J4 355
QTQTQ 187
46J44 961
Q7AK2 580
69969 609
876A5 474
A3866 642
Q3QQA 526
JAA88 425
35Q9K 986
QQTQJ 550
54535 357
2J222 639
QK5J7 743
222Q2 191
T4T44 855
QTQQ2 338
JA7A2 300
AAAJ2 508
4J455 23
A77AA 339
5KK25 899
252J2 737
7QJ76 888
K46QK 795
A4T3J 640
8A8K8 176
AA5AA 41
J2Q24 958
58855 632
333J3 610
74474 807
K3AAA 78
JJ222 765
44224 688
76733 361
5845K 181
TT4T2 974
23J33 102
QQJ6Q 34
Q9AQQ 150
22747 717
KAA5A 121
7AA7J 286
J786T 780
3K8TT 32
A6KAA 25
9A362 166
A29Q2 499
6688K 57
KKQKA 947
999JJ 975
6A666 927
TTT3K 658
JQQ7T 467
8A247 934
7JK8J 712
KK39K 612
6666Q 17
77Q37 868
A66AJ 169
KKKKJ 535
7Q7JJ 591
K9848 646
46888 931
A86A8 326
743TA 527
QKK67 977
KKJ6K 471
AAJ7A 571
55292 330
3A222 390
6453J 109
JKKKA 403
4J9T5 21
K7A5K 486
6TT34 793
3479Q 60
44624 443
6KK3K 164
4447J 112
QQ27Q 452
JAK65 522
Q5Q5Q 354
J5Q6A 540
68999 711
3QJ4Q 155
A6AAA 314
222KK 767
55T9A 373
T5T57 913
TTTTA 794
8J258 190
3Q87J 489
AAQAQ 950
Q4JJ4 588
6T64T 9
636K5 228
AA222 248
7KJ35 616
26646 507
44A4J 829
23323 904
TA265 135
JJQT9 136
KATJ8 644
J2862 713
4JQ28 152
Q3K2T 56
6Q232 812
9A622 885
KJKKJ 773
3859T 374
99333 101
TKTTK 205
3333A 35
5A4AQ 548
T4944 967
43353 813
423JK 869
T99T7 219
3AAAA 394
T65Q6 740
J9243 352
6656J 496
444K4 574
Q8T6K 98
AQ55K 917
7QQJ7 605
TJ5TT 615
68JQ5 852
7A3J2 745
369AK 217
57755 343
A8844 61
Q76QQ 698
36333 774
237Q7 12
KT694 283
88286 154
4T552 990
Q9J54 759
K6697 350
A3A33 937
AA9AA 246
QQ7KK 748
TT4A6 380
4J992 845
A66AA 573
5QQ2Q 28
86J37 214
2A443 362
Q9QKK 654
44434 964
77773 74
44355 235
9QK75 863
3AJ33 766
T2TJT 53
44494 860
883A9 309
QQ59Q 360
A88A8 584
A83A4 395
7J9TA 299
55955 833
QJK35 188
4656A 514
8KTQ4 554
56J47 985
J272J 184
9J999 671
72295 31
53555 264
4A537 750
7A4JJ 875
QK834 463
88KKA 570
QQ9JK 906
6Q646 858
53336 359
QJ8QJ 587
424TJ 607
KTKK6 285
Q5AQQ 84
899A8 542
K8TKK 250
4JA4A 705
6J75J 896
888K8 312
5583J 660
6T335 614
Q757T 945
3AKKA 629
KK946 825
3393Q 406
7J288 367
49999 907
99729 837
66265 384
K47JQ 263
2AJ4K 566
TTKKA 186
8J877 418
56844 666
JTTTT 531
6TJ94 26
JQ5J5 344
7J772 85
33747 510
KJA2A 729
333TQ 578
JQAT4 955
75766 834
QQ6QQ 980
32K33 306
TTTJ6 231
2QTTT 213
999AQ 608
33353 202
Q8Q8Q 756
KK555 490
746K8 691
98A75 853
JQ858 816
KK9KK 536
9T999 933
TA8A8 39
8558J 919
J8KQK 15
73Q2K 503
2K2KJ 585
JK9K5 903
TJ7T7 545
J723T 453
KT895 583
TTTKT 123
39535 393
K4K88 893
43KK6 821
6AA8J 504
972TA 597
7J736 592
536A8 63
J23Q3 402
83K9Q 405
28337 396
9T558 776
7AA78 946
QTT24 441
26QT3 401
AJQAQ 953
6T6AJ 304
JK5KK 162
2JJ2J 484
73773 6
8J864 630
78782 557
6TJ52 424
487JQ 830
8J698 82
AJAAA 866
228J8 204
622J4 823
6J2QJ 79
22K22 232
A86A6 444
83K8Q 965
JK586 944
JA848 465
8888A 45
2T28T 803
73J73 450
27272 857
7A777 544
A998J 679
46466 458
KJ233 192
4453J 378
TQQJT 451
A3K5J 512
888Q6 968
6AA66 841
QQ222 883
3K5A3 233
JA4AA 379
62288 778
44456 51
4A644 862
55647 981
A77A7 327
KQ3A3 687
QQ7Q7 976
T4A2T 293
46226 628
Q59Q5 348
36AJ2 984
54433 532
JJQ24 831
7455J 381
78845 218
72AQ5 276
52T22 618
99399 68
36AA3 118
69669 839
33Q5J 785
TJ766 626
T28J4 556
T883Q 142
73928 932
TJ884 494
AJ36Q 485
9Q999 324
T725Q 267
22622 88
92364 685
97792 789
J673K 620
99943 625
77JJ7 921
8828Q 572
7777J 353
TAAJT 926
99T29 787
AQ4J4 520
9J559 5
J3T94 706
K9KK9 918
KK252 439
79925 97
TT47T 497
848T4 126
6TTT6 426
K8825 925
888J8 62
K5K85 972
AAKKA 449
J5555 663
89J99 27
4Q444 922
A9A99 397
5A555 163
8J3K8 662
29989 645
95222 751
Q4Q4Q 193
555K5 982
74AJ8 735
KKQ6K 668
7676Q 916
A28T7 784
K57KK 388
A4J4J 115
2K442 229
33TT3 956
TT6TA 741
TT782 131
TJ5JQ 238
TQ7T7 415
29KQQ 598
A8AAT 676
46A28 650
6698K 696
6J969 158
6694A 271
QTQ5T 498
Q2QQQ 613
2A7QJ 210
6T466 683
QJ575 799
Q63Q3 822
Q9J28 848
TTTT7 7
KA9AA 854
K2JJT 859
28228 179
K29KJ 429
JJ8JJ 222
A99A5 457
QQTTT 983
43KK2 134
984JJ 1
97J97 892
2AAA8 689
9Q77J 819
98TJK 517
56KA5 71
7J66J 294
55855 335
TTT8T 596
33663 407
7J774 911
3JQ55 564
QQQ7Q 329
85668 120
KK333 301
Q3553 867
7K557 988
Q8488 400
96J99 643
29224 714
T8ATA 346
99J93 462
K83J3 697
3KQJ4 653
5KJQ2 824
4JJ3A 897
56248 727
JJ666 702
355T5 245
45KAK 553
88AAA 236
K55J5 581
AJJ49 65
A8Q3J 197
AAAKQ 529
55976 707
77776 930
A9995 227
K7J7K 912
29K99 244
4Q464 80
22972 195
666JQ 189
26278 241
79288 601
5454A 427
JTAKQ 138
88833 549
84J54 215
AATAK 114
58959 145
8ATTJ 431
QJ26K 265
A3JA3 81
T8T4J 242
4T3A3 37
44777 871
JQ542 561
A97Q9 693
A76T4 412
28T4A 481
T485A 861
78286 303
K6776 52
T8TKQ 754
KJ938 957
Q444Q 840
25A89 455
58588 673
K8858 634
K8KJ8 170
K6KKK 851
53353 140
2T2K6 593
QQAQA 48
TT6J6 305
922J2 920
AA22K 22
J555Q 725
TTAAT 781
2244J 171
A95K7 436
2J299 651
78AAA 321
2KKK2 690
2J565 649
77J5K 77
T999T 762
J4445 879
J888Q 873
J884J 1000
98898 413
29299 442
QKQ3Q 678
A652A 993
55272 898
KA5K5 664
8KJAQ 147
Q56QJ 734
K77J3 739
J7677 661
T5569 206
2AA2J 757
TJTJT 342
T2TTT 682
88J82 363
9KK78 700
AT4T4 730
86968 736
99995 207
7A3J4 172
8KK87 991
TKKJJ 16
J7532 165
J9888 996
9AJTA 92
43T78 310
93J77 317
J4424 805
43J86 703
952TJ 127
54363 146
8T2J7 435
88848 832
TAAAQ 791
8228T 256
699QT 815
KQQQK 30
T82J3 49
36222 4
AK288 86
6792A 194
2Q22T 667
J3545 270
9QJK4 280
QQ22Q 371
K9247 446
A422A 943
765K3 469
9J5A6 874
4A4QA 775
8Q8Q8 124
T8Q62 850
8Q8Q5 747
6KT88 738
82888 722
3TQQQ 349
2J3TT 539
7TQ59 72
8998T 733
JQJT3 414
82428 589
92856 423
89833 54
79T4A 523
95839 979
TJJT5 936
33839 29
37433 511
TKJ2T 681
JT973 633
Q8Q8J 971
Q5555 440
K8886 24
Q75A4 43
3AQ33 298
T446T 719
577J5 753
KJTKT 167
52528 8
25222 641
QJ2T8 621
A8JQJ 316
7T7A7 772
KQQTQ 141
83734 758
6Q66Q 434
QJ6Q2 638
AAA7A 196
57555 203
4QJQ4 216
82J5Q 763
A73A3 940
46AJQ 559
T4936 103
89Q29 262
7872T 466
A5J58 274
AAAQA 290
37399 844
A759Q 328
TJ9TT 273
77887 268
64A2J 978
6T76Q 110
QQ467 742
9J7Q5 422
4K6Q3 91
336K3 826
6K63Q 382
23552 105
243AA 505
Q887J 764
2J92A 749
68A3Q 416
7T8T8 199
225J5 404
24774 153
T7T77 870
3J393 347
Q5Q8J 128
7Q777 796
QKKKK 617
86686 108
44KT4 75
56858 622
5AJK4 960
3245Q 311
36536 370
6644Q 11
JKAAA 104
T2426 579
J3399 83
33933 602
A299J 777
26J22 224
8666J 594
J3J38 669
3AJ84 239
52Q8T 877
QJQQK 779
QJ6T8 797
43339 399
9AJ74 476
T499Q 13
2TAKA 928
T3K78 809
2923K 201
J8858 798
T8888 818
98399 168
8T266 555
23A57 652
3KKK3 113
22T22 460
AJJAA 106
7QKA8 464
QQ8TQ 368
99A99 341
62Q5A 223
J9T47 568
Q7388 894
69662 744
96J2T 323
2A779 89
Q2874 269
77797 948
5359A 864
AJ9K4 482
Q3Q44 567
JT958 665
A38J3 438
J4666 296
428J5 501
38K8K 410
6T979 709
3533T 284
2285A 910
933T6 882
K6666 786
56Q32 992
5J752 198
AJJQJ 600
KK5KK 3
38T94 180
67QTJ 69
J6636 200
229J8 493
QJTQ3 247
5KQ5K 149
654AT 528
T84T4 878
Q23QQ 905
QQQ74 325
4JTQQ 408
T4T78 340
3T5T5 551
3J3J3 391
88844 631
TTT9T 810
57775 935
A777J 604
4555T 2
A5J8T 942
22AJJ 506
22323 997
A3323 624
84442 516
2T992 76
J7T76 828
J8552 995
KTKK3 886
33853 782
53233 129
44J4J 372
KQQT2 480
K5649 576
3J63K 760
2J666 827
6JT68 318
45Q64 849
49884 801
9KTTK 902
66737 952
5Q8J4 708
57Q92 724
627J7 331
K22J6 473
4T444 923
J4444 552
78J8J 491
4K328 477
4AA3A 808
7A34Q 437
AQ888 428
8TA99 768
AA9A9 143
9K5AT 211
77722 40
TQTTT 941
Q2A4K 492
236T9 677
J8686 746
J585K 64
TJKQT 582
T3TTJ 157
22266 38
KT5TK 692
QJQQJ 908
4K623 279
7JJJ7 173
64A66 524
J7AJ8 417
K43Q3 769
T662T 148
54J2J 488
K6485 44
J6666 970
J26J9 209
8337Q 334
A27A4 319
A7T78 132
K777A 842
KKK4K 249
99K9K 430
8745K 151
Q2QTJ 433
QKQ76 525
25Q2Q 533
5QK6J 800
77T77 558
5K323 939
33KK4 590
K8A52 111
ATQJ6 569
ATK89 50
4433A 836
3KKKQ 891
46TK4 538
5249Q 447
2462K 675
8JT6T 336
466J7 459
7K7KK 838
544Q4 959
58773 483
823J5 999
2TKA5 752
AKJ58 386
7T833 99
KQ88Q 659
KJ3A4 790
K9595 307
3K3J4 534
3838T 220
32522 720
366Q3 500
J8868 989
T7KTK 376
JQQQA 14
42555 409
5T5T5 648
4KK4Q 383
K7777 884
736A3 543
343Q3 366
TJ856 237
JJ555 46
K5QQQ 275
QAQQ7 672
8KTJQ 731
QQQ3Q 47
J257Q 575
6Q3QQ 87
QKK43 924
TTATJ 998
K44K5 771
37895 881
48823 521
KKK74 456
99J79 139
J4542 635
AJ96K 954
K8937 411
5J355 895
96967 185
333T3 562
TAJ77 755
J38A8 487
AAT79 313
A6Q73 398
386JA 10
J35Q8 623
27758 969
3K3KJ 966
7928Q 627
AAA4A 59
2AA52 478
848J8 133
55225 843
TTQT9 619
3Q79K 255
27AK8 58
TKTKK 272
KTTAT 333
55666 802
47748 454
Q3T56 699
63T3T 302
8754Q 723
4J86T 358
8TTQ9 226
5523J 125
88588 606
58AAA 208
TK273 137
4Q7KQ 160
29292 577
Q333Q 611
22TT2 716
A55AA 258
64822 468
22228 847
2242T 788
JA26Q 472
8JAAA 174
K5Q8A 175
Q5AT4 732
J4434 530
76666 337
9998Q 547
9T2J9 100
3Q982 90
7727Q 281
92944 973
K2597 814
K444K 36
26KJ6 292
34K38 962
5A378 225
636J9 375
TTTT4 420
A66TA 461
69QK5 345
76293 479
66966 804
A3383 297
T82TT 657
2QJJQ 156
K2JK3 94
K6K66 252
K58QJ 876
6J979 513
92647 718
QQ9Q9 586
862Q5 20
5465K 915
KQ44Q 595
T66T6 288
TJT7T 710
5JT8K 159
KJTK3 603
KKJTQ 949
67776 914
J4323 177
22229 704
96999 178
8AJKA 70
69T69 419
65556 770
87738 537
547J4 835
44766 421
3355J 684
2K266 647
5TTT5 266
3T3TT 332
88JJ8 96
QQ5K3 887
K7JKK 377
J8Q2Q 66
2KKJ6 230
TTKQT 277
22Q92 18
JTTTK 695
J993Q 846
88898 728
88T87 715
Q74J4 872
4T999 951
T997Q 289
92QA9 726
AJ394 900
TT2T2 518
JJJJJ 565
#+end_src
* Day 8: Haunted Wasteland
2023-12-09 09:42:17 +00:00
Get the puzzle solution as [[file:./day8.scm][tangled .scm file]].
2023-12-08 09:17:29 +00:00
** Part One
2023-12-08 09:45:19 +00:00
*** Quest
You're still riding a camel across Desert Island when you spot a sandstorm quickly approaching. When you turn to warn the Elf, she disappears before your eyes! To be fair, she had just finished warning you about *ghosts* a few minutes ago.
One of the camel's pouches is labeled "maps" - sure enough, it's full of documents (your puzzle input) about how to navigate the desert. At least, you're pretty sure that's what they are; one of the documents contains a list of left/right instructions, and the rest of the documents seem to describe some kind of *network* of labeled nodes.
It seems like you're meant to use the *left/right* instructions to *navigate the network*. Perhaps if you have the camel follow the same instructions, you can escape the haunted wasteland!
After examining the maps for a bit, two nodes stick out: =AAA= and =ZZZ=. You feel like =AAA= is where you are now, and you have to follow the left/right instructions until you reach =ZZZ=.
This format defines each node of the network individually. For example:
2023-12-09 09:42:17 +00:00
#+name: day8-part1-example1
2023-12-08 09:45:19 +00:00
#+begin_example
RL
AAA = (BBB, CCC)
BBB = (DDD, EEE)
CCC = (ZZZ, GGG)
DDD = (DDD, DDD)
EEE = (EEE, EEE)
GGG = (GGG, GGG)
ZZZ = (ZZZ, ZZZ)
#+end_example
2023-12-09 09:42:17 +00:00
2023-12-08 09:45:19 +00:00
Starting with =AAA=, you need to *look up the next element* based on the next left/right instruction in your input. In this example, start with =AAA= and go *right* (=R=) by choosing the right element of =AAA=, *=CCC=*. Then, =L= means to choose the *left* element of =CCC=, *=ZZZ=*. By following the left/right instructions, you reach =ZZZ= in *=2=* steps.
Of course, you might not find =ZZZ= right away. If you run out of left/right instructions, repeat the whole sequence of instructions as necessary: =RL= really means =RLRLRLRLRLRLRLRL...= and so on. For example, here is a situation that takes *=6=* steps to reach =ZZZ=:
2023-12-09 09:42:17 +00:00
#+name: day8-part1-example2
2023-12-08 09:45:19 +00:00
#+begin_example
LLR
AAA = (BBB, BBB)
BBB = (AAA, ZZZ)
ZZZ = (ZZZ, ZZZ)
#+end_example
Starting at =AAA=, follow the left/right instructions. *How many steps are required to reach =ZZZ=*?
2023-12-09 09:42:17 +00:00
*** Puzzle Solution
**** Data Definition and Extraction
#+name: day8-part1-records
#+begin_src scheme
(define-record node name left right)
(define-record direction side)
(define-record directions-ring entries entry length index)
#+end_src
#+name: day8-part1-irregex
#+begin_src scheme
(define alnum '(+ (or (/ #\A #\Z)
(/ #\0 #\9))))
(define node-irregex
`(: bol
(* whitespace)
(submatch-named node-name ,alnum)
" = ("
(submatch-named left ,alnum)
", "
(submatch-named right ,alnum)
")"
(* whitespace)
eol))
(define directions-irregex
'(+ (or #\L #\R)))
#+end_src
#+name: day8-part1-input--directions
#+begin_src scheme
(define (input->directions input)
(let* ((directions-str (car (irregex-extract directions-irregex input)))
(directions (map (compose make-direction string->symbol string) (string->list directions-str))))
(make-directions-ring directions
(car directions)
(length directions)
0)))
#+end_src
#+name: day8-part1-input--nodes-alist
#+begin_src scheme
(define (input->nodes-alist input)
(irregex-fold node-irregex
(lambda (from-index match seed)
(alist-update
(string->symbol (irregex-match-substring match 'node-name))
(make-node (string->symbol (irregex-match-substring match 'node-name))
(string->symbol (irregex-match-substring match 'left))
(string->symbol (irregex-match-substring match 'right)))
seed))
'() input))
#+end_src
**** Navigation
#+name: day8-part1-move-forward
#+begin_src scheme
(define (move-forward directions-ring)
(let ((entries (directions-ring-entries directions-ring))
(len (directions-ring-length directions-ring))
(index (directions-ring-index directions-ring)))
(directions-ring-index-set! directions-ring
(or (and (< index (- len 1))
(+ index 1))
0))
(directions-ring-entry-set! directions-ring
(list-ref entries (directions-ring-index directions-ring)))
directions-ring))
#+end_src
#+name: day8-part1-move
#+begin_src scheme
(define (move node direction nodes-alist)
(let* ((side (direction-side direction))
(next-sym (if (eqv? 'L side)
(node-left node)
(node-right node))))
(alist-ref next-sym nodes-alist)))
#+end_src
#+name: day8-part1-navigate
#+begin_src scheme
(define (navigate nodes-alist directions start-sym target-sym
#!optional (current-sym start-sym) (counter 0))
(if (eqv? current-sym target-sym)
counter
(let ((next-sym (node-name
(move (alist-ref current-sym nodes-alist)
(directions-ring-entry directions)
nodes-alist))))
(navigate nodes-alist
(move-forward directions)
start-sym target-sym
next-sym
(+ counter 1)))))
#+end_src
**** Calculate The Route
#+name: day8-part1-calc-fn
#+begin_src scheme
(import (chicken irregex)
(chicken sort)
(chicken string)
(chicken type)
(chicken format))
(define-record node name left right)
(define-record direction side)
(define-record directions-ring entries entry length index)
(define alnum '(+ (or (/ #\A #\Z)
(/ #\0 #\9))))
(define node-irregex
`(: bol
(* whitespace)
(submatch-named node-name ,alnum)
" = ("
(submatch-named left ,alnum)
", "
(submatch-named right ,alnum)
")"
(* whitespace)
eol))
(define directions-irregex
'(+ (or #\L #\R)))
(define (input->directions input)
(let* ((directions-str (car (irregex-extract directions-irregex input)))
(directions (map (compose make-direction string->symbol string) (string->list directions-str))))
(make-directions-ring directions
(car directions)
(length directions)
0)))
(define (input->nodes-alist input)
(irregex-fold node-irregex
(lambda (from-index match seed)
(alist-update
(string->symbol (irregex-match-substring match 'node-name))
(make-node (string->symbol (irregex-match-substring match 'node-name))
(string->symbol (irregex-match-substring match 'left))
(string->symbol (irregex-match-substring match 'right)))
seed))
'() input))
(define (move-forward directions-ring)
(let ((entries (directions-ring-entries directions-ring))
(len (directions-ring-length directions-ring))
(index (directions-ring-index directions-ring)))
(directions-ring-index-set! directions-ring
(or (and (< index (- len 1))
(+ index 1))
0))
(directions-ring-entry-set! directions-ring
(list-ref entries (directions-ring-index directions-ring)))
directions-ring))
(define (move node direction nodes-alist)
(let* ((side (direction-side direction))
(next-sym (if (eqv? 'L side)
(node-left node)
(node-right node))))
(alist-ref next-sym nodes-alist)))
(define (navigate nodes-alist directions start-sym target-sym
#!optional (current-sym start-sym) (counter 0))
(if (eqv? current-sym target-sym)
counter
(let ((next-sym (node-name
(move (alist-ref current-sym nodes-alist)
(directions-ring-entry directions)
nodes-alist))))
(navigate nodes-alist
(move-forward directions)
start-sym target-sym
next-sym
(+ counter 1)))))
(define (calc-part-1)
(let ((directions (input->directions input))
(nodes-alist (input->nodes-alist input)))
(navigate nodes-alist directions 'AAA 'ZZZ)))
#+end_src
#+results:
: 19631
2023-12-08 09:17:29 +00:00
** Part Two
2023-12-09 09:42:17 +00:00
*** Quest
The sandstorm is upon you and you aren't any closer to escaping the wasteland. You had the camel follow the instructions, but you've barely left your starting position. It's going to take *significantly more steps* to escape!
What if the map isn't for people - what if the map is for *ghosts*? Are ghosts even bound by the laws of spacetime? Only one way to find out.
After examining the maps a bit longer, your attention is drawn to a curious fact: the number of nodes with names ending in =A= is equal to the number ending in =Z=! If you were a ghost, you'd probably just *start at every node that ends with A* and follow all of the paths at the same time until they all simultaneously end up at nodes that end with =Z=.
For example:
#+name: day8-part2-example1
#+begin_example
LR
11A = (11B, XXX)
11B = (XXX, 11Z)
11Z = (11B, XXX)
22A = (22B, XXX)
22B = (22C, 22C)
22C = (22Z, 22Z)
22Z = (22B, 22B)
XXX = (XXX, XXX)
#+end_example
=6=
Here, there are two starting nodes, =11A= and =22A= (because they both end with =A=). As you follow each left/right instruction, use that instruction to *simultaneously* navigate away from both nodes you're currently on. Repeat this process until *all* of the nodes you're currently on end with =Z=. (If only some of the nodes you're on end with =Z=, they act like any other node and you continue as normal.) In this example, you would proceed as follows:
- Step 0: You are at =11A= and =22A=.
- Step 1: You choose all of the *left* paths, leading you to =11B= and =22B=.
- Step 2: You choose all of the *right* paths, leading you to *=11Z=* and =22C=.
- Step 3: You choose all of the *left* paths, leading you to =11B= and *=22Z=*.
- Step 4: You choose all of the *right* paths, leading you to *=11Z=* and =22B=.
- Step 5: You choose all of the *left* paths, leading you to =11B= and =22C=.
- Step 6: You choose all of the *right* paths, leading you to *=11Z=* and *=22Z=*.
So, in this example, you end up entirely on nodes that end in =Z= after *=6=* steps.
Simultaneously start on every node that ends with =A=. *How many steps does it take before you're only on nodes that end with =Z=?*
*** Puzzle Solution
#+name: day8-part2-calc-next-sym
#+begin_src scheme
(define (calc-next-sym sym direction nodes-alist)
(let ((side (direction-side direction))
(node (alist-ref sym nodes-alist)))
(if (eqv? 'L side)
(node-left node) (node-right node))))
#+end_src
#+name: day8-part2-navigate
#+begin_src scheme
(define (p2-navigate nodes-alist directions start-sym
#!optional (current-sym start-sym) (counter 0))
(if (eqv? #\Z
((compose car reverse string->list symbol->string) current-sym))
(begin
(print "Found end point of " start-sym ": " current-sym ", steps: " counter)
counter)
(let ((next-sym (calc-next-sym current-sym (directions-ring-entry directions) nodes-alist)))
(p2-navigate nodes-alist
(move-forward directions)
start-sym next-sym
(+ counter 1)))))
#+end_src
#+name: day8-part2-find-start-points
#+begin_src scheme
(define (find-start-points sym-list)
(foldl (lambda (start-points sym)
(if (eqv? #\A ((compose car reverse string->list symbol->string) sym))
(cons sym start-points) start-points))
'() sym-list))
#+end_src
#+name: day8-part2-lcm
#+begin_src scheme
(: p2-lcm ((list-of integer) integer -> integer))
(define (p2-lcm numbers #!optional (factor 2))
(let ((multiple (* (car numbers) factor)))
(if (= 0 (foldl (lambda (x n) (+ x (modulo multiple n))) 0 numbers))
multiple
(p2-lcm numbers (+ factor 1)))))
#+end_src
#+name: day8-part2-calc-fn
#+begin_src scheme
(import (chicken irregex)
(chicken sort)
(chicken string)
(chicken type)
(chicken format)) (define-record node name left right)
(define-record direction side)
(define-record directions-ring entries entry length index) (define alnum '(+ (or (/ #\A #\Z)
(/ #\0 #\9))))
(define node-irregex
`(: bol
(* whitespace)
(submatch-named node-name ,alnum)
" = ("
(submatch-named left ,alnum)
", "
(submatch-named right ,alnum)
")"
(* whitespace)
eol))
(define directions-irregex
'(+ (or #\L #\R))) (define (input->directions input)
(let* ((directions-str (car (irregex-extract directions-irregex input)))
(directions (map (compose make-direction string->symbol string) (string->list directions-str))))
(make-directions-ring directions
(car directions)
(length directions)
0))) (define (input->nodes-alist input)
(irregex-fold node-irregex
(lambda (from-index match seed)
(alist-update
(string->symbol (irregex-match-substring match 'node-name))
(make-node (string->symbol (irregex-match-substring match 'node-name))
(string->symbol (irregex-match-substring match 'left))
(string->symbol (irregex-match-substring match 'right)))
seed))
'() input)) (define (move-forward directions-ring)
(let ((entries (directions-ring-entries directions-ring))
(len (directions-ring-length directions-ring))
(index (directions-ring-index directions-ring)))
(directions-ring-index-set! directions-ring
(or (and (< index (- len 1))
(+ index 1))
0))
(directions-ring-entry-set! directions-ring
(list-ref entries (directions-ring-index directions-ring)))
directions-ring)) (define (move node direction nodes-alist)
(let* ((side (direction-side direction))
(next-sym (if (eqv? 'L side)
(node-left node)
(node-right node))))
(alist-ref next-sym nodes-alist))) (define (calc-next-sym sym direction nodes-alist)
(let ((side (direction-side direction))
(node (alist-ref sym nodes-alist)))
(if (eqv? 'L side)
(node-left node) (node-right node)))) (define (p2-navigate nodes-alist directions start-sym
#!optional (current-sym start-sym) (counter 0))
(if (eqv? #\Z
((compose car reverse string->list symbol->string) current-sym))
(begin
(print "Found end point of " start-sym ": " current-sym ", steps: " counter)
counter)
(let ((next-sym (calc-next-sym current-sym (directions-ring-entry directions) nodes-alist)))
(p2-navigate nodes-alist
(move-forward directions)
start-sym next-sym
(+ counter 1))))) (define (find-start-points sym-list)
(foldl (lambda (start-points sym)
(if (eqv? #\A ((compose car reverse string->list symbol->string) sym))
(cons sym start-points) start-points))
'() sym-list)) (: p2-lcm ((list-of integer) integer -> integer))
(define (p2-lcm numbers #!optional (factor 2))
(let ((multiple (* (car numbers) factor)))
(if (= 0 (foldl (lambda (x n) (+ x (modulo multiple n))) 0 numbers))
multiple
(p2-lcm numbers (+ factor 1)))))
(define (calc-part-2)
(let* ((directions (input->directions input))
(nodes-alist (input->nodes-alist input))
(start-points (find-start-points (map car nodes-alist))))
(apply lcm
(sort (map (cut p2-navigate nodes-alist directions <>) start-points) >))))
#+end_src
#+results:
: 21003205388413
2023-12-08 09:17:29 +00:00
** Puzzle Input
2023-12-09 09:42:17 +00:00
2023-12-09 15:24:00 +00:00
Jump to [[#headline-95][day 9]].
2023-12-09 09:42:17 +00:00
#+name: day8-input
#+begin_src fundamental
LRRLRRRLRLRLLRRLRLRLLRLRLRLLLLRRRLLRRRLRRRLRRRLLRLLRLRRLRLRLRRRLLLLRRLRLRRLRRLLRRRLRRLRLRRLRRLRRLRRLRLLRRLRRLLLLRLRLRRLLRRLLRRLRLLRLRRLRRLRRLRRRLRRLLLRRLRRRLRLRRRLLRLRRLRRRLRRLLRRRLRRLRLLRRLLRRLRRLRRRLRRLLRRLRRRLRLRLRLRLRLRRLRRLLRRRLRLRRLRRRLRLRLRLRLRLRRRLRRLRRRLLRRLRLLRRRLRRLRLLLLRRRLRRLRRRR
DRM = (DLQ, BGR)
PKD = (TNC, DKH)
FSM = (LKS, KPG)
NDS = (KGD, HNX)
KQQ = (DPF, GKD)
SBX = (DDL, MGH)
GCV = (KMG, GLP)
PCT = (JXN, XDR)
KHR = (QPK, FPQ)
FCK = (GLS, GGP)
MKR = (XPQ, TJX)
PFP = (RPR, LPS)
XPC = (SSS, FRX)
PTJ = (LSC, CND)
GVJ = (NRL, SHV)
QNF = (MBQ, GSR)
TMK = (DVM, BJM)
KTG = (QVG, LLX)
JMK = (BKF, XDK)
JQV = (DCM, RLT)
VFH = (FDD, GML)
XPN = (FKG, CXG)
GDX = (GRV, BPP)
GVP = (JLP, XNJ)
TCB = (RVR, QXQ)
DLP = (XDK, BKF)
FQG = (RMH, QHR)
XDD = (SMK, HMN)
TLL = (TVV, FXX)
NPT = (NGC, FQM)
XQK = (PQG, QTK)
DMQ = (RVS, KNQ)
QKR = (SJD, PLH)
XNV = (SJB, GCV)
SRP = (CDK, JFK)
FRP = (FFD, XPC)
PVC = (XVD, MGD)
DPP = (BFQ, XDD)
CNV = (LQC, JJH)
LLH = (CFP, BGF)
XCK = (VDX, GFC)
KGD = (LSF, FNK)
MJA = (FXB, QVX)
QLH = (KRM, KVD)
QCR = (TKN, RNB)
PSR = (FBL, HKJ)
MGK = (BVC, HVL)
PVK = (JRN, SMV)
JTD = (VNS, FGJ)
PMD = (HGN, NBM)
DRF = (CPR, RTX)
HJL = (CBR, VDR)
PPB = (GDX, DXB)
DVR = (LLT, GVJ)
JRN = (RLD, RSL)
NXM = (RBN, NVD)
RLV = (FRM, FJB)
SJB = (KMG, GLP)
KJM = (XJH, LQX)
GRB = (HHL, RGD)
LQC = (BMC, XSH)
NRB = (NQD, RFT)
SQH = (QJT, JXX)
JLX = (RJL, HHH)
HVR = (XPN, JFM)
FVD = (RXS, RHH)
KSX = (TCB, GDK)
GKJ = (TQF, HQJ)
HQL = (BMR, PBX)
QFP = (NJM, FSB)
TPH = (NXT, RKN)
SRL = (LSP, LFV)
SDL = (MGL, PSK)
MFX = (FSM, LQF)
RFT = (FLV, GMS)
BTG = (DRS, PVC)
HLR = (DSB, DPP)
DXB = (BPP, GRV)
NHS = (HQG, GVP)
GKK = (DCM, RLT)
MJT = (JNR, PGC)
KDS = (FFD, XPC)
TSS = (BGX, QQX)
FKC = (NBN, SJP)
HHQ = (GVP, HQG)
JKF = (QRR, GFD)
CXG = (SDD, TMN)
GCG = (TCC, TDT)
NQX = (DMQ, DPM)
GHX = (BJQ, CHJ)
JQC = (HNQ, RJF)
QBB = (GNH, XSC)
BJG = (VMH, FCN)
VMS = (KRX, VLQ)
GSF = (NQM, KBH)
JQQ = (PKD, GNB)
KFG = (BGX, QQX)
TTV = (SNB, JQF)
CXJ = (CND, LSC)
GGP = (PBH, XNG)
FCV = (NLP, QJK)
NSB = (KSX, SLL)
JBH = (RGK, NSS)
CQH = (HJL, FKR)
VRX = (HKJ, FBL)
HJZ = (QVX, FXB)
RLD = (BJP, RLV)
HHH = (PNJ, HPJ)
LSC = (NRP, DCF)
BVM = (RCG, QLL)
KGN = (PRB, MLT)
NTV = (MRQ, NHQ)
VXT = (VFH, MBX)
RLG = (MJQ, RNL)
JVX = (HJQ, FNV)
XGH = (HHK, JXT)
NHC = (HPX, LGG)
VPC = (XCL, HPQ)
HKJ = (RQC, TMK)
PGQ = (FTX, MNP)
MPF = (KNM, BJG)
MFT = (DRS, PVC)
XNG = (RCS, JNH)
RMH = (GHD, MPF)
PFM = (PGQ, XHJ)
TRN = (TCP, TCP)
NHP = (JMG, VGP)
JSK = (JBG, PVM)
FSB = (MGK, HTD)
BPR = (VFH, MBX)
RHM = (LHD, PTF)
PRV = (RJL, HHH)
GNC = (HVR, PSV)
PSV = (JFM, XPN)
KMG = (KDR, RTV)
RKL = (DPP, DSB)
GLN = (QJT, JXX)
FNK = (XXP, QDR)
JDP = (HVR, PSV)
HHD = (VPC, MDS)
XHJ = (MNP, FTX)
XVJ = (RGG, BCB)
DRH = (CDK, JFK)
BMC = (TTQ, KHR)
TCT = (JQD, QBB)
BCS = (HLV, MKR)
LFV = (GTL, NSX)
JCS = (JQC, NDG)
SBJ = (PHS, QMN)
HPZ = (DQD, PFP)
BFM = (PMD, JGB)
QBL = (KVC, TXK)
RGD = (NXH, KQQ)
PBX = (LBP, FPK)
FDD = (TCX, CSN)
RJT = (CQG, JSQ)
BMR = (FPK, LBP)
RBN = (DRF, VJB)
PHB = (NXR, LPM)
BPN = (PPX, PPX)
KVC = (NSF, TQK)
PXB = (GJH, JHM)
BCB = (NTR, KKB)
KXM = (NHS, HHQ)
VTT = (NCB, HCR)
SHP = (LQX, XJH)
RCG = (CLL, TCT)
LHG = (GSF, PRJ)
XCL = (JLX, PRV)
LXB = (RHH, RXS)
FKZ = (TJS, BJB)
NNH = (CFD, XMX)
NTD = (NCX, PVK)
DCF = (JHJ, VMN)
GJH = (JTD, CJD)
VBS = (CDQ, LFQ)
MGL = (GGB, QNN)
TXK = (NSF, TQK)
HRX = (QFP, BJR)
GMS = (GKJ, TNF)
RGA = (PFP, DQD)
KTS = (GSF, PRJ)
TPP = (VPC, MDS)
JNV = (BHV, XQK)
DXL = (HDP, KTG)
MBR = (GRS, GTG)
KVJ = (LPH, NGG)
HRG = (RNL, MJQ)
XHL = (JXF, FVH)
MMC = (FHM, HNF)
HGC = (SHT, HBF)
LPS = (NTV, CGR)
FKR = (CBR, VDR)
BHV = (PQG, QTK)
BKF = (SRP, DRH)
JMA = (BJB, TJS)
MPT = (HRX, VSD)
QHL = (NRB, HJG)
PDG = (KJM, SHP)
HFT = (HHQ, NHS)
SJD = (GPM, PPB)
NSF = (NRX, SRL)
MXG = (JVJ, BMF)
PHD = (BQK, VKV)
VBH = (TXK, KVC)
NJM = (HTD, MGK)
TVV = (LLH, HFB)
RPS = (GGQ, SNK)
HPR = (LJS, DJR)
FDR = (QKT, GRX)
LLT = (SHV, NRL)
VQC = (DPM, DMQ)
MJQ = (CLD, FCV)
BFG = (GJH, JHM)
GFS = (PMP, VXL)
LBP = (HRF, GRB)
BXC = (MFS, NRM)
CFD = (QMQ, HPR)
HPN = (JQC, NDG)
BBJ = (JTL, QQK)
VVL = (CDN, STB)
HFB = (CFP, BGF)
NNG = (XVP, CQH)
QKM = (KDS, FRP)
VJB = (CPR, RTX)
KQB = (XCK, BSF)
LKS = (LDJ, MXG)
GTL = (FVD, LXB)
PJS = (BGV, MLM)
KNM = (FCN, VMH)
FCN = (VGR, KHV)
RPJ = (XKD, BPM)
GLP = (KDR, RTV)
NXL = (VTS, SDL)
XDX = (MPT, FXH)
KRX = (DCD, DHH)
CTP = (CRQ, DPL)
SRG = (SKH, SLF)
QVX = (NDC, NPL)
XVK = (SNB, JQF)
RBT = (NSD, SBJ)
RXS = (FKC, JSS)
SFX = (PRB, MLT)
SRS = (FVH, JXF)
NRL = (RLG, HRG)
QKK = (PBX, BMR)
DPL = (PTQ, DBH)
PFD = (JQV, GKK)
VGR = (KMX, DVR)
FQX = (LHD, PTF)
LXT = (RHM, FQX)
JHV = (MBR, PHJ)
JNN = (VKG, SLT)
XDK = (DRH, SRP)
JBR = (BDR, GFS)
BNM = (VKG, SLT)
CJD = (VNS, FGJ)
FPK = (HRF, GRB)
PBH = (JNH, RCS)
FGV = (FDR, TMD)
LSF = (XXP, QDR)
RBM = (VHG, BDL)
TNF = (HQJ, TQF)
TRM = (JHT, BCG)
GBH = (XMJ, JFF)
DBH = (DSS, RQL)
PGB = (BXR, DXL)
QFR = (TDT, TCC)
HHL = (NXH, KQQ)
HGN = (BFG, PXB)
PXC = (BPN, BPN)
NDF = (VQC, NQX)
GSK = (BVV, SBX)
TCM = (VBS, HCN)
HTD = (BVC, HVL)
SHD = (MHG, HNG)
LQX = (QVF, LBV)
MSF = (FDF, VLP)
NRP = (VMN, JHJ)
TQF = (BXC, JCR)
MBX = (GML, FDD)
JCR = (MFS, NRM)
NTR = (PCN, RNT)
JHJ = (XMT, NPT)
SQX = (CDN, STB)
CSN = (GBJ, PGB)
GDJ = (GBM, GCJ)
XGL = (HJQ, FNV)
PLD = (BFL, BFL)
NRX = (LFV, LSP)
TFF = (HGQ, MJT)
JVJ = (TMS, HPK)
BSF = (VDX, GFC)
GML = (CSN, TCX)
BFJ = (GFD, QRR)
FGJ = (PGF, VMS)
TQK = (SRL, NRX)
GQD = (MDD, HLQ)
TJX = (XCG, DJH)
GRR = (LPM, NXR)
PTQ = (DSS, DSS)
HHK = (KLD, NNG)
FBR = (KXM, HFT)
RLT = (JMK, DLP)
PHL = (QHR, RMH)
DVM = (JTP, KDM)
MNF = (RPJ, RMF)
RMF = (BPM, XKD)
GGQ = (MFT, BTG)
CLD = (NLP, QJK)
NMR = (FNL, LXT)
CLX = (TRP, GMD)
QMQ = (DJR, LJS)
KDR = (PKC, NRF)
KKG = (VHG, BDL)
FBQ = (TPP, HHD)
QVV = (LNR, GSK)
VKV = (MFX, FDL)
HJG = (NQD, RFT)
XVD = (VXT, BPR)
NCX = (SMV, JRN)
QLN = (CDJ, TDK)
GFC = (CKR, LNC)
HGQ = (JNR, PGC)
NDG = (RJF, HNQ)
CBC = (NSD, SBJ)
BQK = (FDL, MFX)
VGV = (HGC, TQG)
VGP = (RJT, KPK)
VMN = (XMT, NPT)
PSH = (NSS, RGK)
PPL = (FXH, MPT)
DCD = (SBR, DTS)
MDD = (MQX, FQT)
XCG = (XVK, TTV)
LFQ = (SNS, VBL)
JHT = (FMN, HMC)
KNQ = (QKM, DPS)
PVM = (CHL, GLT)
JMG = (KPK, RJT)
XKD = (GQJ, NXL)
DGG = (CCB, CQX)
HNF = (MNC, FKZ)
QTL = (PSH, JBH)
RNL = (CLD, FCV)
BDR = (PMP, VXL)
GKH = (KXM, HFT)
RQC = (DVM, BJM)
GSR = (PPL, XDX)
JQD = (GNH, XSC)
GRS = (RTN, MPH)
BPP = (GBH, KQX)
XVP = (HJL, FKR)
PKZ = (NMR, KJK)
SLT = (BVM, KMJ)
XHA = (KJK, NMR)
BQQ = (FDR, TMD)
GGC = (CXJ, PTJ)
NBM = (PXB, BFG)
RQL = (BBH, NLT)
KJK = (FNL, LXT)
PSK = (GGB, QNN)
FQT = (DRL, NDS)
SJT = (VQC, NQX)
QHT = (GFS, BDR)
QJT = (PJS, DNG)
SVT = (PDG, GSS)
MBQ = (PPL, XDX)
VHL = (PVM, JBG)
QCJ = (JKK, JSR)
NQH = (LKQ, FBG)
XNJ = (QNF, LPL)
PQV = (CKJ, JHV)
FHM = (MNC, MNC)
FPN = (DLQ, BGR)
BJR = (NJM, FSB)
HPQ = (PRV, JLX)
KMJ = (QLL, RCG)
FTX = (TSM, PDR)
JXT = (KLD, NNG)
DPS = (KDS, FRP)
KKB = (RNT, PCN)
XCB = (TDM, HXC)
TCP = (PFP, DQD)
CDK = (NDF, SJT)
HCR = (HSP, PFD)
SNK = (BTG, MFT)
TKN = (QTL, HPL)
GSS = (KJM, SHP)
NRF = (SVT, RGV)
FLV = (GKJ, TNF)
QPK = (FPN, DRM)
RNB = (QTL, HPL)
HPJ = (XGL, JVX)
NSD = (QMN, PHS)
JXF = (DQV, XPX)
PRJ = (KBH, NQM)
XMT = (NGC, FQM)
JLP = (QNF, LPL)
RND = (HLV, MKR)
QRR = (GPQ, GLL)
LNR = (BVV, SBX)
PQG = (TXR, NTD)
JXX = (PJS, DNG)
QQX = (VTT, XKV)
RRJ = (GLS, GGP)
MLM = (VCD, BTQ)
QVG = (TMM, CTP)
KRM = (MSF, HVT)
XKV = (HCR, NCB)
LJX = (RNB, TKN)
CCB = (NXM, QSG)
RJF = (FQP, VDH)
XBN = (BJQ, CHJ)
JHM = (JTD, CJD)
SMV = (RSL, RLD)
PDR = (GHX, XBN)
JFK = (NDF, SJT)
HCN = (LFQ, CDQ)
SLL = (TCB, GDK)
VBL = (JBR, QHT)
SMK = (RBM, KKG)
GDK = (QXQ, RVR)
KQX = (XMJ, JFF)
LKQ = (HLN, VTD)
JSQ = (QXG, CLX)
FFD = (FRX, SSS)
NRM = (XBP, NQH)
SBR = (PQQ, SRG)
BKR = (MHG, HNG)
QQK = (GQK, STS)
HVL = (DLF, QLH)
NHT = (PTJ, CXJ)
GLL = (TLL, LRR)
GLS = (PBH, XNG)
NHB = (QQK, JTL)
PFS = (KFG, TSS)
PCN = (PFS, QFB)
CJV = (BFL, PKZ)
JFM = (FKG, CXG)
GFD = (GLL, GPQ)
MDS = (XCL, HPQ)
FXH = (VSD, HRX)
DQD = (RPR, LPS)
HPX = (RRJ, FCK)
JNR = (SQQ, SQQ)
BGR = (PQV, DKS)
BRN = (BSF, XCK)
RVS = (QKM, DPS)
PLH = (GPM, PPB)
XSM = (QFS, GQD)
TTH = (TQG, HGC)
KBJ = (KTS, LHG)
RKN = (PCX, NSB)
TPK = (PFM, RFN)
MNC = (BJB, TJS)
PMM = (GRR, PHB)
QKT = (BNK, QKR)
HQG = (JLP, XNJ)
RRD = (JGB, PMD)
CPR = (TGM, VXS)
GGM = (GCJ, GBM)
HBF = (FQG, PHL)
NXH = (DPF, GKD)
TMD = (GRX, QKT)
FBL = (RQC, TMK)
GNB = (DKH, TNC)
LQF = (LKS, KPG)
BKN = (TRN, TRN)
QJK = (BLT, XVJ)
HLV = (TJX, XPQ)
XPX = (TPK, HQN)
BJP = (FJB, FRM)
GHD = (KNM, BJG)
XMX = (HPR, QMQ)
FNV = (NHT, GGC)
JGB = (HGN, NBM)
PKH = (HHK, JXT)
JXN = (VRR, VRR)
CHJ = (TLF, QSN)
XBP = (LKQ, FBG)
QTK = (TXR, NTD)
PKC = (SVT, RGV)
JNH = (MGV, MPJ)
FXB = (NDC, NPL)
XHQ = (KTS, LHG)
MFS = (NQH, XBP)
FQM = (XJB, TXN)
QNN = (JQQ, GBG)
GBG = (PKD, GNB)
TMN = (GRC, BCV)
HMN = (KKG, RBM)
DHH = (SBR, DTS)
KPG = (LDJ, MXG)
FDL = (LQF, FSM)
FXX = (LLH, HFB)
VSD = (BJR, QFP)
HVT = (FDF, VLP)
FRM = (CBB, GMX)
GQK = (QVV, QBV)
CKJ = (PHJ, MBR)
JJH = (XSH, BMC)
SQQ = (PLD, PLD)
KPK = (JSQ, CQG)
VLP = (HHT, MMC)
NLP = (XVJ, BLT)
VTS = (MGL, PSK)
DTS = (SRG, PQQ)
VCD = (GDJ, GGM)
VRR = (HLR, RKL)
VXS = (BKN, SRB)
GMD = (PSR, VRX)
PFK = (HXC, TDM)
SJP = (VSM, NNH)
TDK = (SRS, XHL)
KRS = (GCV, SJB)
MRQ = (CJK, PQD)
XJB = (JRK, RPS)
BGF = (QCR, LJX)
MLT = (MMF, DGG)
TCC = (MNF, KKL)
QMN = (GLN, SQH)
GQJ = (VTS, SDL)
BFQ = (SMK, HMN)
NSS = (JPQ, HXV)
MHG = (VGV, TTH)
KBH = (GPL, XCV)
DRL = (KGD, HNX)
HMC = (QDF, RGR)
QSN = (FBR, GKH)
SDD = (GRC, BCV)
TGH = (BPN, SSQ)
HNG = (TTH, VGV)
RHH = (FKC, JSS)
DQA = (MVV, LQJ)
QFB = (KFG, TSS)
TQG = (SHT, HBF)
KDM = (QKK, HQL)
XHV = (PLD, CJV)
PQD = (TPH, PTN)
SSS = (SQX, VVL)
GPM = (DXB, GDX)
KLD = (CQH, XVP)
LRR = (FXX, TVV)
HPL = (JBH, PSH)
TMS = (BQQ, FGV)
MMF = (CCB, CQX)
DLQ = (PQV, DKS)
PHJ = (GTG, GRS)
TLF = (GKH, FBR)
FJB = (CBB, GMX)
PTF = (PSF, PHD)
NPL = (RTG, QHL)
XMJ = (XHQ, KBJ)
PMP = (TRM, PJK)
JPQ = (KLM, TCM)
BCG = (FMN, HMC)
DRS = (MGD, XVD)
RGT = (PKH, XGH)
TGM = (BKN, BKN)
BPM = (GQJ, NXL)
VDX = (CKR, LNC)
XJH = (QVF, LBV)
MGD = (BPR, VXT)
RGR = (JSK, VHL)
SNS = (QHT, JBR)
SRB = (TRN, DVK)
NRQ = (LQC, JJH)
PSF = (BQK, VKV)
BMF = (TMS, HPK)
LGG = (FCK, RRJ)
HPK = (FGV, BQQ)
QBV = (GSK, LNR)
FNF = (PHB, GRR)
GLT = (JDP, GNC)
DKS = (JHV, CKJ)
RGV = (GSS, PDG)
HQN = (PFM, RFN)
GKD = (BFJ, JKF)
HXC = (HPN, JCS)
MGH = (BVB, FBQ)
LBV = (XCB, PFK)
LHD = (PHD, PSF)
CDQ = (SNS, VBL)
BTQ = (GGM, GDJ)
HMS = (CBC, RBT)
VTD = (CNV, NRQ)
JBG = (GLT, CHL)
LCB = (NGG, LPH)
FKG = (SDD, TMN)
BVV = (DDL, MGH)
RGG = (KKB, NTR)
FBG = (HLN, VTD)
KMX = (GVJ, LLT)
HRF = (HHL, RGD)
DGM = (QFS, GQD)
LPM = (QFR, GCG)
QXQ = (BCS, RND)
BGV = (BTQ, VCD)
BGX = (XKV, VTT)
XDR = (VRR, ZZZ)
BJM = (JTP, KDM)
RFN = (PGQ, XHJ)
DDL = (FBQ, BVB)
XCV = (JNN, BNM)
TCX = (GBJ, PGB)
QXG = (TRP, GMD)
VKG = (BVM, KMJ)
RSL = (RLV, BJP)
CDN = (QLN, CNM)
RVR = (BCS, RND)
BBH = (BXJ, BXJ)
BXR = (KTG, HDP)
DJH = (XVK, TTV)
DVK = (TCP, HPZ)
SLF = (TFF, KQV)
DJR = (SFX, KGN)
HHT = (FHM, FHM)
JSR = (JXM, JNV)
DSB = (BFQ, XDD)
DPM = (RVS, KNQ)
HJQ = (NHT, GGC)
ZZZ = (RKL, HLR)
RJL = (HPJ, PNJ)
BJQ = (TLF, QSN)
HQJ = (BXC, JCR)
FQP = (HMS, SRH)
PGF = (VLQ, KRX)
LQJ = (FNF, PMM)
JXM = (BHV, XQK)
PNJ = (JVX, XGL)
STB = (CNM, QLN)
BBS = (JXN, JXN)
KKL = (RMF, RPJ)
SHV = (HRG, RLG)
FPQ = (FPN, DRM)
GBJ = (DXL, BXR)
QHR = (GHD, MPF)
MDG = (JKK, JSR)
CRQ = (PTQ, DBH)
BVB = (TPP, HHD)
GRC = (RGT, VDD)
SKH = (TFF, KQV)
DHZ = (LQJ, MVV)
LSP = (NSX, GTL)
MPJ = (QBL, VBH)
TDT = (KKL, MNF)
TXN = (JRK, RPS)
HSP = (GKK, JQV)
JTL = (STS, GQK)
GBM = (QCJ, MDG)
HDP = (LLX, QVG)
GMX = (KQB, BRN)
PJK = (JHT, BCG)
NDC = (RTG, QHL)
LPL = (GSR, MBQ)
VLQ = (DCD, DHH)
QLL = (CLL, TCT)
RTV = (NRF, PKC)
DKH = (BBJ, NHB)
NGC = (XJB, TXN)
CNM = (CDJ, TDK)
XXP = (BSP, NHC)
FNL = (RHM, FQX)
NBN = (VSM, NNH)
XSC = (BFM, RRD)
VXL = (PJK, TRM)
VSM = (XMX, CFD)
NQM = (GPL, XCV)
HLN = (CNV, NRQ)
GCJ = (QCJ, MDG)
FDF = (HHT, HHT)
PQQ = (SKH, SLF)
KVD = (MSF, HVT)
QSG = (NVD, RBN)
RGK = (HXV, JPQ)
NXR = (GCG, QFR)
QDR = (BSP, NHC)
TDM = (HPN, JCS)
MQX = (NDS, DRL)
JRK = (GGQ, SNK)
VMH = (VGR, KHV)
RPR = (NTV, CGR)
CFP = (LJX, QCR)
CLL = (JQD, QBB)
LLX = (CTP, TMM)
PRB = (DGG, MMF)
FVH = (XPX, DQV)
JKK = (JNV, JXM)
KLM = (VBS, HCN)
NHQ = (CJK, PQD)
BJB = (BKR, SHD)
CQX = (NXM, QSG)
KHV = (DVR, KMX)
SRH = (CBC, RBT)
DQV = (TPK, HQN)
NQD = (GMS, FLV)
PHS = (GLN, SQH)
GPL = (JNN, BNM)
JSS = (SJP, NBN)
CGR = (MRQ, NHQ)
PGC = (SQQ, XHV)
GPQ = (LRR, TLL)
HXV = (TCM, KLM)
BFL = (KJK, NMR)
PPX = (FXB, QVX)
AAA = (HLR, RKL)
DSS = (BBH, BBH)
VDD = (PKH, XGH)
NCB = (PFD, HSP)
SSQ = (PPX, HJZ)
DNG = (MLM, BGV)
CDJ = (XHL, SRS)
TNC = (NHB, BBJ)
QDF = (VHL, JSK)
GTG = (MPH, RTN)
FRX = (SQX, VVL)
MVV = (FNF, PMM)
QFS = (HLQ, MDD)
MNP = (PDR, TSM)
LDJ = (BMF, JVJ)
NSX = (FVD, LXB)
RNT = (PFS, QFB)
TJS = (SHD, BKR)
HNQ = (VDH, FQP)
BLT = (BCB, RGG)
KQV = (HGQ, MJT)
PTN = (NXT, RKN)
VDR = (BBS, PCT)
RCS = (MPJ, MGV)
GRX = (BNK, QKR)
JFF = (XHQ, KBJ)
RTG = (NRB, HJG)
CND = (DCF, NRP)
DCM = (JMK, DLP)
XPQ = (XCG, DJH)
RTX = (TGM, VXS)
DPF = (BFJ, JKF)
LNC = (PXC, TGH)
PCX = (SLL, KSX)
BSP = (HPX, LGG)
VHG = (LCH, NHP)
GRV = (KQX, GBH)
NGG = (DGM, XSM)
XSH = (TTQ, KHR)
MRH = (KVJ, LCB)
TXR = (NCX, PVK)
NVD = (VJB, DRF)
TTQ = (FPQ, QPK)
CKR = (PXC, PXC)
BVC = (DLF, QLH)
VDH = (SRH, HMS)
JQF = (SKC, MRH)
CBB = (BRN, KQB)
FMN = (RGR, QDF)
SHT = (FQG, PHL)
NLT = (BXJ, DHZ)
MPH = (KRS, XNV)
BXJ = (MVV, LQJ)
CHL = (JDP, GNC)
TSM = (XBN, GHX)
DLF = (KRM, KVD)
BCV = (RGT, VDD)
HNX = (FNK, LSF)
LJS = (SFX, KGN)
STS = (QBV, QVV)
SKC = (KVJ, LCB)
BNK = (SJD, PLH)
RTN = (KRS, XNV)
JTP = (QKK, HQL)
LCH = (VGP, JMG)
CBR = (BBS, BBS)
VNS = (VMS, PGF)
CQG = (CLX, QXG)
HLQ = (MQX, FQT)
TMM = (CRQ, DPL)
BDL = (NHP, LCH)
TRP = (VRX, PSR)
MGV = (VBH, QBL)
GNH = (BFM, RRD)
NXT = (NSB, PCX)
SNB = (SKC, MRH)
LPH = (XSM, DGM)
GGB = (GBG, JQQ)
CJK = (PTN, TPH)
QVF = (PFK, XCB)
#+end_src
2023-12-09 15:24:00 +00:00
* Day 9: Mirage Maintenance
Get the puzzle solution as [[file:./day9.scm][tangled .scm file]].
** Part One
*** Quest
You ride the camel through the sandstorm and stop where the ghost's maps told you to stop. The sandstorm subsequently subsides, somehow seeing you standing at an *oasis*!
The camel goes to get some water and you stretch your neck. As you look up, you discover what must be yet another giant floating island, this one made of metal! That must be where the *parts to fix the sand machines* come from.
There's even a [[https://en.wikipedia.org/wiki/Hang_gliding][hang glider]] partially buried in the sand here; once the sun rises and heats up the sand, you might be able to use the glider and the hot air to get all the way up to the metal island!
While you wait for the sun to rise, you admire the oasis hidden here in the middle of Desert Island. It must have a delicate ecosystem; you might as well take some ecological readings while you wait. Maybe you can report any environmental instabilities you find to someone so the oasis can be around for the next sandstorm-worn traveler.
You pull out your handy *Oasis And Sand Instability Sensor* and analyze your surroundings. The OASIS produces a report of many values and how they are changing over time (your puzzle input). Each line in the report contains the *history* of a single value. For example:
#+name: day9-part1-example1
#+begin_example
0 3 6 9 12 15
1 3 6 10 15 21
10 13 16 21 30 45
#+end_example
To best protect the oasis, your environmental report should include a *prediction of the next value* in each history. To do this, start by making a new sequence from the *difference at each step* of your history. If that sequence is *not* all zeroes, repeat this process, using the sequence you just generated as the input sequence. Once all of the values in your latest sequence are zeroes, you can extrapolate what the next value of the original history should be.
In the above dataset, the first history is =0 3 6 9 12 15=. Because the values increase by =3= each step, the first sequence of differences that you generate will be =3 3 3 3 3=. Note that this sequence has one fewer value than the input sequence because at each step it considers two numbers from the input. Since these values aren't *all zero*, repeat the process: the values differ by =0= at each step, so the next sequence is =0 0 0 0=. This means you have enough information to extrapolate the history! Visually, these sequences can be arranged like this:
#+begin_example
0 3 6 9 12 15
3 3 3 3 3
0 0 0 0
#+end_example
To extrapolate, start by adding a new zero to the end of your list of zeroes; because the zeroes represent differences between the two values above them, this also means there is now a placeholder in every sequence above it:
#+begin_example
0 3 6 9 12 15 B
3 3 3 3 3 A
0 0 0 0 0
#+end_example
You can then start filling in placeholders from the bottom up. =A= needs to be the result of increasing =3= (the value to its left) by =0= (the value below it); this means =A= must be *=3=*:
#+begin_example
0 3 6 9 12 15 B
3 3 3 3 3 3
0 0 0 0 0
#+end_example
Finally, you can fill in =B=, which needs to be the result of increasing =15= (the value to its left) by =3= (the value below it), or *=18=*:
#+begin_example
0 3 6 9 12 15 18
3 3 3 3 3 3
0 0 0 0 0
#+end_example
So, the next value of the first history is *=18=*.
Finding all-zero differences for the second history requires an additional sequence:
#+begin_example
1 3 6 10 15 21
2 3 4 5 6
1 1 1 1
0 0 0
#+end_example
Then, following the same process as before, work out the next value in each sequence from the bottom up:
#+begin_example
1 3 6 10 15 21 28
2 3 4 5 6 7
1 1 1 1 1
0 0 0 0
#+end_example
So, the next value of the second history is *=28=*.
The third history requires even more sequences, but its next value can be found the same way:
#+begin_example
10 13 16 21 30 45 68
3 3 5 9 15 23
0 2 4 6 8
2 2 2 2
0 0 0
#+end_example
So, the next value of the third history is *=68=*.
If you find the next value for each history in this example and add them together, you get *=114=*.
Analyze your OASIS report and extrapolate the next value for each history. *What is the sum of these extrapolated values?*
*** Puzzle Solution
**** Data Extraction
#+name: day9-part1-datalist
#+begin_src scheme
(define (input->list input)
(map
(lambda (x)
(map string->number (string-split x)))
(string-split input "\n")))
#+end_src
**** Calculation
#+name: day9-part1-diff
#+begin_src scheme
(define (diff input)
(if (= 1 (length input))
'()
(cons (- (cadr input) (car input))
(diff (cdr input)))))
#+end_src
#+name: day9-part1-extrapolate
#+begin_src scheme
(define (extrapolate data)
(append data
(list
(if (foldl (lambda (out in) (and out (= 0 in)))
#t data)
0
(+ (car (reverse data))
(car (reverse (extrapolate (diff data)))))))))
#+end_src
#+name: day9-part1-calc-fn
#+begin_src scheme
(import (chicken irregex)
(chicken string)
(chicken type)
(chicken format)) (define (input->list input)
(map
(lambda (x)
(map string->number (string-split x)))
(string-split input "\n"))) (define (diff input)
(if (= 1 (length input))
'()
(cons (- (cadr input) (car input))
(diff (cdr input))))) (define (extrapolate data)
(append data
(list
(if (foldl (lambda (out in) (and out (= 0 in)))
#t data)
0
(+ (car (reverse data))
(car (reverse (extrapolate (diff data)))))))))
(define (calc-part-1)
(foldl + 0 (map (compose car reverse extrapolate)
(input->list input))))
#+end_src
#+results:
: 2174807968
** Part Two
*** Quest
Of course, it would be nice to have *even more history* included in your report. Surely it's safe to just *extrapolate backwards* as well, right?
For each history, repeat the process of finding differences until the sequence of differences is entirely zero. Then, rather than adding a zero to the end and filling in the next values of each previous sequence, you should instead add a zero to the *beginning* of your sequence of zeroes, then fill in new *first* values for each previous sequence.
In particular, here is what the third example history looks like when extrapolating back in time:
#+begin_example
5 10 13 16 21 30 45
5 3 3 5 9 15
-2 0 2 4 6
2 2 2 2
0 0 0
#+end_example
Adding the new values on the left side of each sequence from bottom to top eventually reveals the new left-most history value: *=5=*.
Doing this for the remaining example data above results in previous values of *=-3=* for the first history and *=0=* for the second history. Adding all three new values together produces *=2=*.
Analyze your OASIS report again, this time extrapolating the *previous* value for each history. *What is the sum of these extrapolated values?*
#+name: day9-part2-calc-fn
#+begin_src scheme
(import (chicken irregex)
(chicken string)
(chicken type)
(chicken format)) (define (input->list input)
(map
(lambda (x)
(map string->number (string-split x)))
(string-split input "\n"))) (define (diff input)
(if (= 1 (length input))
'()
(cons (- (cadr input) (car input))
(diff (cdr input))))) (define (extrapolate data)
(append data
(list
(if (foldl (lambda (out in) (and out (= 0 in)))
#t data)
0
(+ (car (reverse data))
(car (reverse (extrapolate (diff data)))))))))
(define (calc-part-2)
(foldl + 0 (map (compose car reverse extrapolate reverse)
(input->list input))))
#+end_src
#+results:
: 1208
** Puzzle Input
2023-12-10 22:58:33 +00:00
Jump to [[#headline-104][day 10]].
2023-12-09 15:24:00 +00:00
#+name: day9-input
#+begin_src fundamental
3 10 23 46 99 234 563 1310 2904 6131 12351 23745 43470 75464 123501 189097 268370 349700 418439 484617 669380
16 41 77 119 171 265 488 1017 2162 4417 8519 15515 26837 44385 70618 108653 162372 236537 336913 470399 645167
20 45 91 182 351 648 1157 2027 3543 6296 11556 22009 43088 85209 167316 322244 604526 1101399 1947905 3347136 5596837
24 50 87 141 223 341 487 621 653 420 -352 -2121 -5670 -12365 -24598 -46505 -85074 -151786 -264963 -453031 -758943
13 31 76 172 351 645 1075 1649 2399 3508 5604 10347 21558 47460 105396 232221 507493 1104469 2398816 5191706 11149877
11 26 41 56 71 86 101 116 131 146 161 176 191 206 221 236 251 266 281 296 311
15 29 51 84 133 204 310 490 840 1545 2898 5314 9419 16451 29509 56732 118481 262393 593397 1331440 2919341
15 25 37 52 92 226 605 1507 3400 7055 13792 26042 48618 91547 176291 349138 709201 1464905 3043603 6296140 12864564
7 10 18 37 73 132 220 343 507 718 982 1305 1693 2152 2688 3307 4015 4818 5722 6733 7857
15 38 84 178 356 676 1258 2368 4561 8898 17252 32718 60142 106784 183130 303868 489043 765406 1167972 1741802 2544024
6 1 -1 4 18 43 88 187 448 1186 3263 8896 23446 59130 142286 326871 718410 1514791 3073295 6017268 11401122
15 29 41 54 79 135 249 456 799 1329 2105 3194 4671 6619 9129 12300 16239 21061 26889 33854 42095
19 32 61 116 209 354 567 866 1271 1804 2489 3352 4421 5726 7299 9174 11387 13976 16981 20444 24409
6 20 44 78 122 176 240 314 398 492 596 710 834 968 1112 1266 1430 1604 1788 1982 2186
16 30 54 91 153 265 478 906 1811 3777 8045 17148 36139 75040 153808 312341 630150 1263728 2514908 4951321 9611313
13 38 88 174 309 517 845 1386 2334 4116 7690 15178 31151 65158 136598 283958 582099 1174186 2329820 4549050 8744617
24 34 44 54 64 74 84 94 104 114 124 134 144 154 164 174 184 194 204 214 224
9 13 27 63 139 273 489 854 1568 3142 6746 14925 33112 72770 157638 335518 699411 1423691 2823509 5448867 10228929
10 10 27 74 165 327 637 1304 2826 6271 13771 29395 60703 121520 236914 452294 850626 1586416 2955103 5536876 10493273
4 -2 1 20 72 195 466 1039 2234 4749 10146 21906 47613 103336 222285 471798 986484 2032184 4127207 8266676 16326242
26 37 48 59 70 81 92 103 114 125 136 147 158 169 180 191 202 213 224 235 246
22 29 39 66 134 284 585 1149 2150 3851 6669 11402 19995 37786 79284 181567 433019 1031652 2399292 5400601 11759053
15 30 58 119 247 501 993 1937 3727 7076 13313 25067 47809 93158 185649 376132 767743 1565630 3171448 6361747 12621939
3 6 9 15 33 80 178 345 578 825 942 630 -654 -3819 -10303 -22286 -42963 -76888 -130401 -212151 -333729
17 25 47 101 219 463 964 2011 4225 8871 18399 37384 74212 144276 276417 526495 1006445 1945905 3819619 7602107 15258621
18 29 46 68 95 128 169 221 288 375 488 634 821 1058 1355 1723 2174 2721 3378 4160 5083
7 14 23 38 77 194 511 1260 2835 5854 11231 20258 34697 56882 89831 137368 204255 296334 420679 585758 801605
22 38 69 135 264 494 877 1486 2430 3889 6192 9989 16665 29438 56335 117945 266418 629260 1504963 3562351 8239882
26 53 99 180 322 573 1030 1882 3470 6365 11465 20112 34230 56485 90468 140902 213874 317093 460175 654956 915834
15 23 35 61 122 257 543 1142 2402 5056 10594 21958 44885 90585 181120 360055 713057 1406833 2761469 5383323 10407444
10 8 4 13 68 227 585 1295 2609 4966 9184 16876 31349 59530 115990 231038 466366 944412 1903010 3799003 7512836
5 16 47 115 252 511 974 1776 3164 5606 9944 17535 30228 49864 76748 106236 122251 86280 -79663 -517365 -1464656
15 24 45 100 222 456 857 1485 2397 3636 5217 7110 9220 11364 13245 14423 14283 12000 6501 -3576 -19926
9 28 63 129 262 526 1024 1924 3520 6369 11584 21431 40508 78061 152598 301239 598775 1196146 2396433 4800625 9578422
9 8 16 61 188 456 945 1788 3243 5820 10478 18907 33910 59900 103527 174450 286269 457632 713532 1086809 1619872
17 36 59 89 150 315 760 1851 4280 9300 19180 38125 74110 142422 272337 519607 989951 1883736 3581545 6807641 12938466
7 20 46 97 195 378 708 1274 2191 3626 5945 10183 19205 40164 89187 199648 435935 915304 1841256 3552893 6595927
10 5 -5 -20 -40 -65 -95 -130 -170 -215 -265 -320 -380 -445 -515 -590 -670 -755 -845 -940 -1040
12 15 14 8 -5 -33 -80 -91 201 1614 6181 18353 47069 109209 235297 479044 933854 1762589 3253152 5924174 10725971
17 28 54 115 241 485 951 1856 3664 7364 15036 30992 64033 131772 268582 539580 1064191 2054280 3873614 7127525 12794077
3 18 41 76 144 297 646 1422 3108 6716 14355 30387 63785 132963 275685 569338 1172097 2405486 4917217 9995922 20165782
-2 -11 -18 -18 -9 20 110 363 996 2452 5649 12567 27667 61305 137695 312640 711010 1601959 3542704 7641380 16018623
10 26 64 139 273 495 841 1354 2084 3088 4430 6181 8419 11229 14703 18940 24046 30134 37324 45743 55525
14 24 44 81 144 259 502 1068 2419 5602 12910 29200 64433 138451 289794 591687 1180468 2305044 4410912 8279435 15253110
-5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25
7 8 28 92 250 591 1258 2478 4629 8371 14868 26113 45312 77128 127213 199638 289163 362090 313624 -120434 -1536674
13 23 37 68 128 234 434 866 1882 4303 9920 22420 48995 102986 208023 404246 757331 1371199 2405455 4098788 6799762
12 20 25 36 65 121 199 260 198 -210 -1375 -3992 -9165 -18565 -34625 -60776 -101728 -163800 -255303 -386980 -572507
19 27 30 35 72 205 554 1345 3019 6463 13486 27773 56756 115227 232224 463967 917739 1795083 3468214 6612095 12427528
22 31 33 30 26 34 98 328 956 2458 5868 13557 30990 70339 157357 343649 727458 1487369 2934979 5594648 10321002
-2 -8 -10 11 87 272 656 1383 2671 4828 8253 13407 20738 30548 42801 56891 71420 84080 91792 91331 80761
-9 -10 -2 28 101 258 583 1236 2495 4806 8840 15556 26269 42722 67161 102412 151959 220022 311634 432716 590149
9 22 58 135 291 603 1213 2361 4425 7968 13792 22999 37059 57885 87915 130201 188505 267402 372390 510007 687955
11 16 36 88 195 396 773 1496 2887 5512 10331 18975 34281 61306 109164 194191 345147 611416 1075470 1871226 3210351
11 25 42 61 81 101 120 137 151 161 166 165 157 141 116 81 35 -23 -94 -179 -279
12 13 27 81 215 482 948 1692 2806 4395 6577 9483 13257 18056 24050 31422 40368 51097 63831 78805 96267
23 47 91 161 263 403 587 821 1111 1463 1883 2377 2951 3611 4363 5213 6167 7231 8411 9713 11143
22 40 68 119 215 382 647 1044 1639 2599 4375 8181 17211 39616 95503 232744 561299 1324998 3046759 6814429 14831782
5 8 13 32 102 306 802 1860 3907 7580 13787 23776 39212 62262 95688 142948 208305 296944 415097 570176 770914
24 34 52 87 143 225 368 713 1661 4151 10156 23609 52208 110966 229042 462397 916262 1783392 3406732 6378571 11692653
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
10 25 42 73 160 391 917 1966 3841 6888 11440 17797 26403 38542 58109 95332 173740 342203 694526 1399873 2748242
7 15 40 93 196 393 767 1475 2827 5458 10690 21284 43001 87846 180779 373417 771448 1588223 3247376 6576762 13174273
17 21 36 70 134 258 514 1042 2075 3959 7164 12282 20008 31100 46314 66310 91525 122009 157220 195774 235146
5 24 67 143 257 409 605 887 1384 2378 4378 8235 15481 29448 58482 123927 277779 638304 1456805 3235439 6924821
-4 -13 -31 -65 -116 -170 -189 -102 204 893 2189 4385 7852 13048 20527 30948 45084 63831 88217 119411 158732
9 3 -7 -13 14 145 522 1405 3256 6883 13661 25826 46797 81415 135892 217132 330915 478219 648689 809941 891008
19 26 42 77 157 335 694 1332 2321 3644 5135 6474 7319 7702 8947 15807 41799 122946 352368 962939 2513289
24 43 72 128 246 498 1023 2081 4170 8292 16532 33246 67397 137051 277976 560104 1119120 2217113 4358724 8512176 16525692
14 25 36 59 130 316 725 1526 2997 5655 10608 20453 41406 88013 192938 426237 931696 1993231 4154260 8432537 16713850
19 44 81 141 261 519 1064 2184 4456 9055 18341 36886 73134 141888 267766 489635 865785 1479206 2441737 3895019 6005051
22 27 31 48 113 303 773 1810 3906 7845 14799 26457 45305 75383 124229 207355 357574 642911 1198799 2282910 4364441
7 12 24 52 116 259 557 1127 2133 3790 6366 10182 15610 23069 33019 45953 62387 82848 107860 137928 173520
-1 6 29 91 228 492 956 1715 2874 4511 6600 8876 10621 10347 5349 -8902 -39559 -97428 -198265 -364383 -626614
22 27 43 86 173 322 552 883 1336 1933 2697 3652 4823 6236 7918 9897 12202 14863 17911 21378 25297
4 3 -4 -8 14 95 281 653 1380 2815 5646 11114 21310 39563 70931 122807 205652 333867 526816 810012 1216478
10 9 17 50 133 301 600 1088 1836 2929 4467 6566 9359 12997 17650 23508 30782 39705 50533 63546 79049
7 0 -9 -20 -21 30 229 772 2060 4936 11193 24608 52958 111845 231915 472723 950241 1893280 3761743 7495716 15035137
10 21 26 38 82 205 499 1145 2494 5204 10445 20164 37385 66582 114525 193166 329149 591406 1162719 2509549 5757819
10 25 54 96 157 254 412 662 1069 1849 3673 8304 19770 46342 103661 219442 440276 841153 1538440 2707168 4603611
23 38 61 112 231 499 1075 2262 4625 9194 17795 33562 61693 110523 192997 328636 546099 886454 1407281 2187740 3334747
13 24 59 145 330 706 1458 2953 5896 11603 22474 42792 80027 146887 264431 466642 806951 1367306 2270493 3696539 5904160
10 18 27 42 73 135 248 437 732 1168 1785 2628 3747 5197 7038 9335 12158 15582 19687 24558 30285
0 20 69 166 341 646 1172 2068 3551 5883 9275 13668 18357 21505 19801 8917 -13953 -43392 -52008 34010 375042
17 15 9 -5 -24 -12 147 721 2238 5664 12732 26593 53145 103800 201325 392204 772513 1540933 3104557 6284571 12706664
0 10 34 77 151 285 557 1156 2479 5267 10785 21054 39148 69576 118778 195775 313026 487560 742468 1108859 1628405
12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92
11 29 57 92 131 171 209 242 267 281 281 264 227 167 81 -34 -181 -363 -583 -844 -1149
-1 -1 3 23 82 226 539 1155 2271 4195 7529 13721 26479 55018 120964 272252 610107 1340413 2870991 5996513 12252244
9 6 -1 -16 -41 -72 -95 -73 97 692 2391 6721 16930 39768 89256 194718 417549 884978 1855267 3838446 7811229
6 5 4 13 52 160 422 1028 2379 5254 11059 22216 42852 80173 147371 269868 498718 939273 1812188 3582057 7224622
13 33 75 152 286 523 960 1788 3352 6226 11298 19857 33671 55042 86821 132363 195399 279799 389197 526446 692868
10 19 30 59 134 295 594 1095 1874 3019 4630 6819 9710 13439 18154 24015 31194 39875 50254 62539 76950
19 27 43 89 213 499 1078 2146 3995 7063 12009 19819 31949 50511 78508 120124 181075 269027 394087 569373 811669
-2 -3 -11 -28 -41 -2 197 748 1943 4177 7952 13966 23563 40276 74198 153035 348067 832077 2003716 4746046 10948462
19 30 60 123 242 466 905 1799 3642 7387 14763 28740 54183 98741 174022 297110 492485 794412 1249870 1922097 2894832
0 7 27 81 213 494 1027 1968 3587 6398 11380 20291 36062 63297 109090 184848 310794 526609 914641 1646749 3072763
17 32 58 111 237 524 1118 2263 4402 8395 15926 30177 56831 105418 190966 336018 573779 955502 1571274 2606855 4486445
15 20 35 78 181 404 862 1782 3631 7396 15165 31276 64500 132042 266623 528588 1025907 1946124 3605771 6524482 11532963
20 46 93 176 318 563 997 1767 3094 5303 8946 15186 26784 50386 101536 215309 468375 1024083 2223578 4768355 10082757
3 8 24 64 151 325 657 1282 2478 4835 9568 19016 37316 71128 130115 226735 375087 589848 890362 1324626 2047999
7 15 32 60 103 162 237 361 716 1925 5685 16012 41518 99340 221600 465601 929365 1774603 3259782 5786628 9964185
1 -7 -17 -33 -67 -146 -322 -676 -1284 -2080 -2510 -817 7300 31141 89649 220744 501079 1088781 2315289 4877757 10228491
12 27 59 115 218 416 793 1483 2697 4796 8487 15311 28807 57252 120069 262580 589026 1333781 3008755 6696087 14606600
24 40 71 124 198 282 369 512 975 2574 7361 19879 49309 112942 241541 487311 935370 1719812 3045675 5218374 8682432
17 18 13 -6 -37 -53 13 283 949 2288 4677 8608 14703 23729 36613 54457 78553 110398 151709 204438 270787
-1 2 12 38 91 184 332 552 863 1286 1844 2562 3467 4588 5956 7604 9567 11882 14588 17726 21339
23 39 66 122 249 520 1037 1931 3386 5729 9665 16795 30647 58615 115552 230558 460253 915439 1815044 3593968 7113449
-7 -2 9 33 88 203 418 784 1363 2228 3463 5163 7434 10393 14168 18898 24733 31834 40373 50533 62508
16 25 31 42 72 146 325 770 1883 4604 11028 25668 57977 127225 271612 564742 1144514 2262427 4365693 8231006 15178118
17 35 59 94 145 217 318 474 786 1597 3911 10355 27266 69022 166670 384444 850191 1809395 3717867 7395824 14276711
12 13 17 24 34 47 63 82 104 129 157 188 222 259 299 342 388 437 489 544 602
0 -1 -6 -19 -44 -85 -146 -231 -344 -489 -670 -891 -1156 -1469 -1834 -2255 -2736 -3281 -3894 -4579 -5340
5 16 32 70 173 428 985 2069 3988 7168 12293 20696 35238 62028 113480 213375 404799 762064 1407990 2538234 4454699
7 13 34 89 211 458 932 1814 3444 6520 12583 25131 52010 110221 235027 496322 1026725 2067887 4044160 7676197 14151365
10 22 35 46 52 50 37 10 -34 -98 -185 -298 -440 -614 -823 -1070 -1358 -1690 -2069 -2498 -2980
15 28 60 130 266 504 891 1497 2434 3877 6097 9579 15462 26884 52455 114159 263677 613630 1393790 3047140 6387030
28 36 49 85 173 364 756 1547 3145 6394 13039 26691 54844 113093 233903 484671 1004561 2078906 4288030 8801645 17953478
10 18 18 5 -11 9 153 589 1610 3694 7578 14343 25505 43105 69789 108867 164338 240866 343690 478449 650901
3 8 13 30 83 220 536 1207 2543 5096 9920 19187 37529 74714 150587 303628 605011 1180704 2244943 4149356 7453119
6 23 53 112 234 491 1028 2127 4326 8646 17029 33173 64095 123050 235114 448303 856506 1647425 3201837 6293946 12482396
13 34 69 132 260 532 1099 2246 4522 8985 17614 33936 63893 116917 207086 354152 584375 932072 1446071 2214064 3438654
13 30 52 89 161 302 580 1153 2402 5216 11564 25606 55842 119333 250156 516518 1055280 2140619 4317945 8659852 17246368
7 18 31 46 63 82 103 126 151 178 207 238 271 306 343 382 423 466 511 558 607
21 48 101 194 354 639 1161 2117 3836 6861 12108 21193 37129 65854 119643 224743 438199 883902 1827123 3822840 7999884
11 13 22 57 146 334 718 1536 3347 7361 16032 34149 70916 144028 287775 569230 1120532 2202854 4331783 8519402 16733123
-2 11 51 137 300 602 1181 2348 4786 9941 20756 42992 87522 174193 338136 639750 1179934 2122363 3724473 6377975 10657624
7 13 28 51 73 73 14 -154 -459 -781 -510 2274 12653 42918 121184 309218 738163 1677669 3664992 7737833 15840617
-9 -16 -23 -13 49 221 596 1330 2694 5150 9448 16766 29011 49657 86117 156061 303173 634244 1402195 3183669 7243449
20 35 56 83 116 155 200 251 308 371 440 515 596 683 776 875 980 1091 1208 1331 1460
7 1 4 39 141 367 815 1651 3143 5701 9922 16639 26973 42387 64741 96347 140023 199145 277696 380311 512317
24 45 72 111 185 351 727 1527 3112 6095 11590 21775 41076 78559 152743 301440 602189 1214813 2469043 5041085 10300040
-5 -4 2 13 38 109 306 798 1900 4149 8435 16316 30843 58592 114261 230351 476543 997368 2084774 4318733 8843090
12 18 27 47 95 215 513 1216 2769 5998 12388 24553 47010 87411 158436 280606 486338 825634 1373873 2242259 3591569
4 24 68 149 287 515 885 1474 2390 3778 5826 8771 12905 18581 26219 36312 49432 66236 87472 113985 146723
0 -10 -20 -25 -20 0 40 105 200 330 500 715 980 1300 1680 2125 2640 3230 3900 4655 5500
-8 -10 3 58 204 518 1123 2244 4337 8347 16210 31856 63266 126690 255089 514413 1033714 2058624 4042777 7798770 14739772
15 18 30 58 120 251 502 934 1613 2627 4196 7075 13729 31293 78265 198410 487727 1143860 2552398 5431564 11066378
8 15 48 121 259 521 1037 2071 4138 8229 16234 31705 61201 116694 220077 412042 770044 1444583 2730844 5205533 9978815
10 20 46 90 164 317 671 1465 3113 6296 12131 22494 40621 72173 127030 222177 386164 665764 1135620 1911866 3170930
18 23 24 32 80 243 671 1651 3722 7886 16006 31591 61405 118835 230952 453097 898238 1794181 3591256 7158078 14125706
29 51 92 167 309 595 1178 2335 4553 8686 16235 29845 54198 97633 175070 313184 559297 996161 1765722 3106111 5407527
12 12 4 -21 -76 -178 -348 -611 -996 -1536 -2268 -3233 -4476 -6046 -7996 -10383 -13268 -16716 -20796 -25581 -31148
0 9 35 98 232 488 936 1674 2877 4958 8966 17413 35803 75231 156529 316559 617390 1159247 2098285 3670420 6222642
13 21 32 49 85 182 447 1112 2635 5878 12439 25300 50113 97733 189126 364748 702329 1350459 2591722 4960343 9458373
9 19 39 86 189 395 789 1533 2933 5553 10424 19471 36446 68985 133049 262273 527277 1075055 2208489 4544904 9327119
19 36 72 149 295 545 946 1563 2481 3802 5652 8243 12077 18443 30510 55765 111767 240144 540160 1245849 2894059
15 29 72 172 384 804 1583 2941 5181 8703 14018 21762 32710 47790 68097 94907 129691 174129 230124 299816 385596
25 35 55 98 193 403 842 1697 3271 6073 10991 19594 34619 60709 105478 180989 305741 507271 825487 1316858 2059597
6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46
8 11 15 32 76 169 370 839 1956 4538 10240 22298 46904 95789 191261 376486 737120 1447065 2863661 5719920 11499172
-8 -2 13 45 122 303 686 1418 2735 5097 9533 18373 36617 74274 150096 297232 571434 1062560 1910237 3324669 5613700
13 23 33 43 53 63 73 83 93 103 113 123 133 143 153 163 173 183 193 203 213
18 43 77 122 190 318 594 1204 2519 5250 10708 21215 40721 75691 136335 238263 404656 669053 1078863 1699720 2620808
8 16 28 42 62 98 176 371 883 2196 5408 12934 30042 68225 152478 336535 733710 1577404 3336844 6934362 14147986
8 18 25 29 27 19 31 159 645 2027 5484 13657 32508 75226 169850 373203 794966 1637312 3257507 6263301 11653801
6 24 56 106 178 279 424 638 944 1313 1529 884 -2444 -12568 -37949 -94582 -209847 -424059 -779987 -1274723 -1714327
-2 13 45 110 245 522 1077 2173 4319 8468 16321 30775 56579 101338 177239 304520 519289 891865 1569433 2872703 5509044
17 26 47 86 160 319 683 1500 3231 6668 13091 24470 43718 75001 124111 198908 309837 470526 698471 1015814 1450220
-3 -1 8 31 81 182 388 841 1902 4409 10163 22832 49615 104267 212544 421952 819143 1560767 2927518 5416973 9898961
13 20 38 80 163 311 565 1001 1756 3062 5289 9000 15024 24557 39306 61697 95175 144632 217008 322120 473785
28 39 47 63 118 277 660 1478 3107 6261 12404 24678 49842 102075 210163 430999 875464 1759681 3509315 6974263 13868272
20 37 63 92 127 189 323 614 1250 2702 6132 14201 32571 72666 156840 328295 670484 1345532 2670978 5274306 10406489
12 14 31 87 219 479 939 1706 2953 4972 8273 13827 23743 43064 84079 175767 383139 845371 1850192 3980360 8406944
-8 -12 -15 -8 21 80 174 332 700 1782 4988 13797 36140 89197 208948 469000 1017273 2146494 4427414 8955718 17799720
9 20 36 52 63 64 50 16 -43 -132 -256 -420 -629 -888 -1202 -1576 -2015 -2524 -3108 -3772 -4521
22 38 71 131 225 358 542 820 1318 2363 4763 10452 23873 54719 123012 268101 564392 1149494 2277273 4423811 8507611
15 25 48 99 193 350 610 1062 1889 3437 6341 11804 22265 42999 85871 177948 380787 832437 1835974 4039605 8789881
-3 12 53 138 295 568 1034 1838 3254 5784 10314 18356 32418 56560 97213 164360 273203 446468 717531 1134582 1766081
9 18 48 126 296 625 1223 2292 4229 7838 14770 28423 55712 110379 218873 430309 832633 1577898 2920516 5273516 9289232
12 23 37 57 99 199 425 903 1868 3751 7323 13958 26187 48985 92882 181485 369228 781655 1702709 3754963 8254611
24 48 95 177 306 499 786 1221 1896 2958 4629 7229 11202 17145 25840 38289 55752 79788 112299 155577 212354
4 5 7 10 14 19 25 32 40 49 59 70 82 95 109 124 140 157 175 194 214
7 9 13 26 70 197 515 1225 2669 5389 10197 18256 31172 51097 80843 124007 185107 269729 384685 538182 740002
15 28 44 60 73 80 78 64 35 -12 -80 -172 -291 -440 -622 -840 -1097 -1396 -1740 -2132 -2575
17 38 65 108 202 432 975 2169 4632 9480 18737 36101 68345 127819 236819 435057 792171 1428238 2546689 4485974 7798892
20 30 44 71 137 292 617 1231 2305 4124 7316 13509 26907 57623 128106 284692 617246 1291102 2597120 5027743 9389545
9 14 29 68 169 402 877 1761 3321 6024 10750 19215 34763 63774 118054 218728 402353 730210 1302027 2275734 3895261
9 23 39 56 72 89 136 336 1061 3246 8987 22668 53123 117887 251707 523689 1071642 2169768 4358940 8690267 17165991
16 30 59 112 213 412 806 1582 3108 6124 12128 24119 47957 94734 184721 353659 662384 1210994 2158945 3752554 6361325
7 12 38 108 255 520 957 1664 2871 5128 9648 18872 37335 72924 138631 254916 452807 777876 1295242 2095764 3303599
3 10 35 103 265 612 1288 2502 4539 7770 12661 19781 29809 43540 61890 85900 116739 155706 204231 263875 336329
16 29 53 95 170 319 639 1343 2894 6296 13677 29364 61728 126168 249707 477790 884004 1583583 2751717 4647853 7647358
16 40 69 105 168 319 707 1653 3787 8255 17021 33324 62443 113114 200286 350512 612477 1077901 1924644 3509430 6572577
0 11 34 77 173 410 979 2241 4814 9681 18315 32806 55976 91537 144597 223435 344712 546499 917076 1652791 3165715
9 14 36 80 146 231 333 456 625 941 1740 3982 10126 26022 64897 155516 358321 796136 1710316 3559564 7187714
11 36 85 172 312 525 853 1393 2354 4170 7765 15200 31175 66259 143335 309641 658037 1362816 2737597 5325692 10036938
6 9 16 38 98 240 543 1150 2342 4719 9594 19762 40874 83726 167865 327018 616966 1126613 1993140 3422286 5714962
16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
16 22 28 34 40 46 52 58 64 70 76 82 88 94 100 106 112 118 124 130 136
-3 0 10 37 93 197 388 759 1537 3240 6939 14638 29755 57639 105989 184948 306525 482848 722568 1024515 1367449
10 20 28 37 65 165 456 1173 2761 6065 12705 25772 51038 98940 187675 347830 629068 1109498 1908474 3203695 5253615
24 40 59 86 145 285 584 1165 2249 4287 8253 16271 32930 67962 141480 293768 602766 1213994 2389815 4587764 8581295
14 24 49 96 172 302 575 1237 2854 6572 14505 30286 59820 112282 201407 347123 577582 931648 1461905 2238252 3352156
-1 14 44 89 149 224 314 419 539 674 824 989 1169 1364 1574 1799 2039 2294 2564 2849 3149
14 15 17 21 40 117 357 989 2491 5837 12960 27569 56511 111931 214554 398493 718076 1257283 2142491 3559341 5774666
4 14 44 117 269 547 1003 1682 2609 3791 5262 7215 10313 16436 30590 65824 155350 380532 931308 2228761 5160433
12 9 6 3 0 -3 -6 -9 -12 -15 -18 -21 -24 -27 -30 -33 -36 -39 -42 -45 -48
20 35 54 78 121 218 424 801 1386 2126 2773 2790 1505 -770 1178 28420 145017 519925 1559927 4182072 10352394
#+end_src
2023-12-10 22:58:33 +00:00
* Day 10: Pipe Maze
Get the puzzle solution as [[file:./day10.scm][tangled .scm file]].
** Part One
*** Quest
You use the hang glider to ride the hot air from Desert Island all the way up to the floating metal island. This island is surprisingly cold and there definitely aren't any thermals to glide on, so you leave your hang glider behind.
You wander around for a while, but you don't find any people or animals. However, you do occasionally find signposts labeled "[[https://en.wikipedia.org/wiki/Hot_spring][Hot Springs]]" pointing in a seemingly consistent direction; maybe you can find someone at the hot springs and ask them where the desert-machine parts are made.
The landscape here is alien; even the flowers and trees are made of metal. As you stop to admire some metal grass, you notice something metallic scurry away in your peripheral vision and jump into a big pipe! It didn't look like any animal you've ever seen; if you want a better look, you'll need to get ahead of it.
Scanning the area, you discover that the entire field you're standing on is densely packed with pipes; it was hard to tell at first because they're the same metallic silver color as the "ground". You make a quick sketch of all of the surface pipes you can see (your puzzle input).
The pipes are arranged in a two-dimensional grid of *tiles*:
- =|= is a *vertical pipe* connecting north and south.
- =-= is a *horizontal pipe* connecting east and west.
- =L= is a *90-degree bend* connecting north and east.
- =J= is a *90-degree bend* connecting north and west.
- =7= is a *90-degree bend* connecting south and west.
- =F= is a *90-degree bend* connecting south and east.
- =.= is *ground*; there is no pipe in this tile.
- =S= is the *starting position* of the animal; there is a pipe on this tile, but your sketch doesn't show what shape the pipe has.
Based on the acoustics of the animal's scurrying, you're confident the pipe that contains the animal is *one large, continuous loop*.
For example, here is a square loop of pipe:
#+begin_example
.....
.F-7.
.|.|.
.L-J.
.....
#+end_example
If the animal had entered this loop in the northwest corner, the sketch would instead look like this:
#+begin_example
.....
.S-7.
.|.|.
.L-J.
.....
#+end_example
In the above diagram, the =S= tile is still a 90-degree =F= bend: you can tell because of how the adjacent pipes connect to it.
Unfortunately, there are also many pipes that *aren't connected to the loop*! This sketch shows the same loop as above:
#+begin_example
-L|F7
7S-7|
L|7||
-L-J|
L|-JF
#+end_example
In the above diagram, you can still figure out which pipes form the main loop: they're the ones connected to =S=, pipes those pipes connect to, pipes *those* pipes connect to, and so on. Every pipe in the main loop connects to its two neighbors (including =S=, which will have exactly two pipes connecting to it, and which is assumed to connect back to those two pipes).
Here is a sketch that contains a slightly more complex main loop:
#+begin_example
..F7.
.FJ|.
SJ.L7
|F--J
LJ...
#+end_example
Here's the same example sketch with the extra, non-main-loop pipe tiles also shown:
#+begin_example
7-F7-
.FJ|7
SJLL7
|F--J
LJ.LJ
#+end_example
If you want to *get out ahead of the animal*, you should find the tile in the loop that is *farthest* from the starting position. Because the animal is in the pipe, it doesn't make sense to measure this by direct distance. Instead, you need to find the tile that would take the longest number of steps *along the loop* to reach from the starting point - regardless of which way around the loop the animal went.
In the first example with the square loop:
#+begin_example
.....
.S-7.
.|.|.
.L-J.
.....
#+end_example
You can count the distance each tile in the loop is from the starting point like this:
#+begin_example
.....
.012.
.1.3.
.234.
.....
#+end_example
In this example, the farthest point from the start is =4= steps away.
Here's the more complex loop again:
#+begin_example
..F7.
.FJ|.
SJ.L7
|F--J
LJ...
#+end_example
Here are the distances for each tile on that loop:
#+begin_example
..45.
.236.
01.78
14567
23...
#+end_example
Find the single giant loop starting at =S=. *How many steps along the loop does it take to get from the starting position to the point farthest from the starting position?*
*** Puzzle Solution
**** Data Structures
#+begin_src scheme
(define-record tile goes-north? goes-east? goes-south? goes-west? start?)
(define (char->tile c)
(case c
((#\|) (make-tile #t #f #t #f #f))
((#\-) (make-tile #f #t #f #t #f))
((#\L) (make-tile #t #t #f #f #f))
((#\J) (make-tile #t #f #f #t #f))
((#\7) (make-tile #f #f #t #t #f))
((#\F) (make-tile #f #t #t #f #f))
((#\.) (make-tile #f #f #f #f #f))
((#\S) (make-tile #f #f #f #f #t))))
#+end_src
**** Load Data
#+begin_src scheme
(define (input->grid input)
(map (compose (cut map char->tile <>)
string->list
(cut foldl string-append "" <>)
string-split)
(string-split input "\n")))
#+end_src
**** Prepare Data
#+begin_src scheme
(define (get-tile grid x y)
(list-ref (list-ref grid y) x))
(define (get-start-loc grid #!optional (x 0) (y 0))
(let ((tile (get-tile grid x y)))
(if (tile-start? tile)
(values x y)
(if (= (+ 1 x) (length (car grid)))
(get-start-loc grid 0 (+ y 1))
(get-start-loc grid (+ x 1) y)))))
#+end_src
#+begin_src scheme
(define (update-start-loc grid x y)
(let ((S (get-tile grid x y)))
(when (and (< 0 y)
(tile-goes-south? (get-tile grid x (- y 1))))
(tile-goes-north?-set! S #t))
(when (and (< (+ 1 y) (length (car grid)))
(tile-goes-north? (get-tile grid x (+ y 1))))
(tile-goes-south?-set! S #t))
(when (and (< 0 x)
(tile-goes-east? (get-tile grid (- x 1) y)))
(tile-goes-west?-set! S #t))
(when (and (< (+ 1 x) (length grid))
(tile-goes-west? (get-tile grid (+ x 1) y)))
(tile-goes-east?-set! S #t))))
#+end_src
#+begin_src scheme
(define x car)
(define y cdr)
(define (get-paths grid x y)
`((#:e . (and (< (+ x 1) (length (car grid)))
(tile-goes-west? (get-tile (+ x 1) y))))
(#:s . (and (< (+ y 1) (length grid))
(tile-goes-north? (get-tile x (+ y 1)))))
(#:w . (and (< 0 x)
(tile-goes-east? (get-tile (- x 1) y))))
(#:n . (and (< 0 y)
(tile-goes-south? (get-tile x (- y 1)))))))
(define (get-valid-paths paths #!optional (valid-paths (list)))
(if (= 0 (length paths)) valid-paths
(get-valid-paths (cdr paths)
(if (cdar paths)
(alist-update (caar paths) (cdar paths) valid-paths)
valid-paths))))
(define (move-forward grid past-loc cur-loc)
(let ((tile (get-tile grid (x cur-loc) (y cur-loc)))
(delta-x (- (x cur-loc) (x past-loc)))
(delta-y (- (y cur-loc) (y past-loc)))
(valid-paths (get-valid-paths (get-paths grid (x cur-loc) (y cur-loc)))))
(values cur-loc
(cond ((= -50 (car past-loc))
(case (caar valid-paths)
((#:n) (cons (x cur-loc) (- (y cur-loc) 1)))
((#:e) (cons (+ (x cur-loc) 1) (y cur-loc)))
((#:s) (cons (x cur-loc) (+ (y cur-loc) 1)))
((#:w) (cons (- (x cur-loc) 1) (y cur-loc)))))
((and (tile-goes-north? tile)
(alist-ref #:n valid-paths)
(not (= (cdr past-loc) (- (cdr cur-loc) 1))))
(cons (x cur-loc) (- (y cur-loc) 1)))
((and (tile-goes-east? tile)
(alist-ref #:e valid-paths)
(not (= (car past-loc) (+ (car cur-loc) 1))))
(cons (+ (x cur-loc) 1) (y cur-loc)))
((and (tile-goes-south? tile)
(alist-ref #:s valid-paths)
(not (= (cdr past-loc) (+ (cdr cur-loc) 1))))
(cons (x cur-loc) (+ (y cur-loc) 1)))
((and (tile-goes-west? tile)
(alist-ref #:w valid-paths)
(not (= (car past-loc) (- (car cur-loc) 1))))
(cons (- (x cur-loc) 1) (y cur-loc)))))))
#+end_src
#+begin_src scheme
(define (count-steps grid start-loc
#!optional (last-loc (cons -50 -50)) (cur-loc start-loc) (count 0))
(if (and (> count 0)
(= (car start-loc) (car cur-loc))
(= (cdr start-loc) (cdr cur-loc)))
count
(let-values (((cur-loc new-loc) (move-forward grid last-loc cur-loc)))
(count-steps grid start-loc cur-loc new-loc (+ count 1)))))
#+end_src
**** Calculation
#+name: day10-part1-calc-fn
#+begin_src scheme
(define (calc-part-1)
(let ((grid (input->grid input)))
(let-values (((start-x start-y) (get-start-loc grid)))
(update-start-loc grid start-x start-y)
(/ (count-steps grid (cons start-x start-y)) 2))))
#+end_src
#+results:
: 7145
** Part Two
*** Quest
*** Puzzle Solution
**** Calculation
#+name: day10-part2-calc-fn
#+begin_src scheme
#+end_src
** Puzzle Input
#+name: day10-input
#+begin_src fundamental
.F7FFJ7L-7.F-7.F7|F-L-7F7F|7.F7F7FJ.FLFF-77.FFF7-|FL-7LF-7F7FF--77.-777F-LJFFL7FJ.|-L7-FF-FJ77F7F7F-7F.|F7JF-L-J--|-F7|F-LF--77..J..F---.F7-
|7LJJ-||.FF-7.|||J-|LL|-J7JFF77LFFJ.7J|L|LJ7F7J|-77||7LL7||L7L7FJFF|F-7|7-|FFJFJ|-|.L7.|.7.|F7-|F7J-JFFJFLJL|J7L|FF77J.-7LJF|LJ7||FFJF-JF-7J
L7J|JJF-L|J.L7.LJF77.LF7JL-J|.L.7J-FF7|FJ7LF||LJLL.LJ-J|||L7L-JL7-J7JFL|L7FF--F-|.|F-L|F7-.L7J|L|.J.L||7||7.|.F7--J|J-|F|7||7-LF--JJ.L-JF-J-
.LFF--|.|LFJ7||.||7-7||J.F|F|-J-|.|L|L-7L-J|.-77.|F.|.FFJL-JF---J7-FJL7L---J|J.JJFF77LJ-J.FFJ.-.|J7F.|L--J7-FJL-F-7J.|JLF7FL7|7F7LL----7J7|7
..7JJFJF|J.L-7-F7JJL|-L.|F-FJ7J7L|7-L7FJ7L77J|JL--|FF7-L--7FJF7F7L7J-L-7|J|-L.FL-J.L|-J.L|7L-|LFJ|LF-FJLJ7FJ.|7LL-J-J77-L-|JL--J7JLF|-FJL---
FFJ.L7LJ7.|J|..LJ|FFLF--J|.JF7L|L-J.L||F-7F7JF7..7-|||-F7FJ|FJ||L-7LLL7FJ.F7|-|.FL|JL|F7.FJF-J-F-7FJ.L|.FF|7F|7L|||.F||7|LL7|.LLF7.L77|J.LL.
7J7|.F7.LJ|F7--J-L7J7.F|..F.7J-LFJ.F7|LJFJ||FJ|-||FF||FJ|L7||FJ|F-J7..J|F|.F7-|FLL|F-F-7F7||F|.J-L||7.L-J7LJ|J|.7JF7|7JL|LJ-L7L7|J-||JL|JJ--
LF-JFJ|LJJ|.F-F.|LL.|F77J.LJ||.FF7F||L-7|7|||FJ-F7F7||L7|F|||L7|L7F7-|LFF7FJL7F77|L--L7|||F-7JL7L|.F7-FL--JFLJFFFJL7LJ-FF-|-L77F77.JJ|FJJF.|
LF7L7LF.||F.L-|77|.|LFL|7FF-|7-FJL7||F7|L-J|||F7||||||FJL-JLJFJ|FJ|L7J-FJ|L7FJ||7FJ||FJLJLJFJ|J7.F-J|.|F7|JLJJ|..FLFJL7JL7.-.|F.|F-JF-L..|F7
-LJ7||L-F7|7.FLJ-J.F77.77|7JF77L-7LJ||LJF7FJ|||||LJLJLJF-7F-7L7|L-JFJLFL7|FJL7|L77--7L-7F--JFF7-F77L|FFFJJ77|FFF77||-LL7F|.F7-J-FJ.LF-|-|7.|
JFFL77|.L-|L-J-|7FLFJL7LFF7-||F-7L-7||F-JLJFJ|||L-7F7F7L7LJLL7||F--J|FF-J||F-J|FJ7|FF7FJL-7JFF7F777FF77||.F-7-FJL-77-F7F-7-LJ-|FF-L-|F77J|FJ
FJ7L|L--F7|F7|7FJ-|..||.L||FJ|L7|F7|||L---7L7LJ|F7LJLJL-JF7-FJLJL7F7F7L7FJ||F7||JF-7||L7F-J-FJ|||F7F7JL77.L7|7L7F-J--LLL7L7FJLJ7|JJ.L|.7-FFJ
L7|F7.|-|L-JLFF-JF-7FF--7|LJFJF|||LJLJF---JFJF-J|L7F--7F-JL7L7F--J|||L7|L-JLJLJL7L7|||FJL7-LL7||||LJL7F-7F7||F-JL7J|FJ|-|FJ7JFFF7FFF-|-|--L7
L-J-7-7-|JJL-JF-77F|7L-7LJF-JLFJ||F--7L-7F-JFJF7L7|L7FJL--7|FJL7F7|LJFJ|F-------JL|LJLJF7|F7L|||||F7FJL7LJLJ|L7F-JLF7F--J|F77F7||7JL7L.L7.JJ
F..L|J.F|LJ.FF77-LF--7L|F7L7F7L7LJL-7L--JL-7L7|L7||FJL7.F7||L-7||||F-JL||F7F--7LF7L--7FJLJ|L-JLJ|LJ|L-7|F--7L7|L--7||L--7LJL7||||F7.--JJJJJ.
-77JF--F--FLJF7.LFL-7|LLJL7LJ|JL-7F-JF7.F7FL7||FJ||L7FJFJLJL--J|||||F-7|||||F7|FJ|FF7||7F7L7F7F7L7FJF-JLJF7L7||F-7||L--7L-7FJ|||LJL7F|7||L77
L|7-|J.|.F--L|LJ-7F-J|F7|FL7FJF-7||F-JL7||F-J|||FJL-JL7L------7||LJ||FJ||||||LJL7L7||||FJL7LJLJ|FJ|FJF7F7|L7|LJ|F||L--7L7.|L-JLJF7FJFLFFJ|.F
..JJ||7LLJ.7--7|L-L-7|||-F-JL7L7LJLJF-7|||L-7LJ|L7F---JF--7F7FJ||F-J|L7|LJLJL7F7L7||||||F-J7F7FJ|FJ|FJ|||L7|L-7L7LJ-F7|FJFJF7F7FJLJF-.FJLL77
J.|.L.-7L|77-F7-77LFJ||L7L7F7L7L-7F-JJLJ|L7JL-7|FJ|F7F7L-7|||L7|||JFJFJ|F--7FJ||7|||||LJL7F7||L7|L7LJFJ||FJL-7L7L7F7|LJ|L|FJ||||JJLL77JFJ.77
|.FL|-LLFL---|.FF7.L7||FJ7LJL7L7FJL-77F7|FJF--J|L7LJ||L-7|LJL7||||FJFJF|L-7LJL||FJLJ||F--J||||FJL7L-7L7|||F--JJL7LJ|L-7L7|L7||LJJ.|-FJ-LF7FJ
FFJ||--LFJ|JFLF7||F-JLJ|F7F-7L7||F--JFJLJL7L--7|FJF-JL-7|L--7LJLJ|L7|F7|F-JF7FJ||F-7LJL-7L||||L-7L7FJFJ|LJ|FF7F7L7FJF7|FJ|FJ|L7-7-F7F7.LJ7|.
FL.J|JLF.FLFF7||||L---7||||FJFJLJL--7|F7F7L7F7|||FJF7F7||FF7L--7FJFJLJLJL--JLJFJLJ||F--7|FJ||L7FJFJL7|FJF7L7|LJL7|L7|LJL-JL7L-J7J|LLJ-7..F7-
J-7-J-FF.|JFJLJLJL-7LFJ||LJL7L-7F--7|||LJL7||LJ|||FJ|||||FJL---J|||F----7F-7F-JF7F7||F7LJ|FJ|FJ|FJ7FJ|L-JL7||F--J|FJ|F---7FJF7F7-|.||J.7F-7J
L-J-|.F|.L-L----7F7L7L7|L7F7|F7||F7LJLJLF7|||F-J||L7|||||L7F---7|FJ|LF-7LJ-LJ7FJ||||||L7-|L7||.||F7|FJ7F7L|LJL-7FJL-J|7F7LJ||||L-7-LJ|..|7|7
|FLFJF|J7L7|F7F7LJL7L-JL7LJ|LJ||LJL7F77FJLJLJL-7||FJLJ||L7LJJF-JLJFJFJFJF----7L7LJLJ||FJFJFJ|L7|LJLJL7FJL7|F-7FJL7F--JFJL--7|||F-JJ|.F7F|-F7
LL.|F7JLFF7FJ|||F--JF7F7L--JF-JL-7FJ||FJF---7F-J|||F7FJ|FJ|F7L---7L7|FJF|F---JFJF7F-J|L7L7L7L7|L--7F-JL-7LJ|-||F-JL7FFJF---J|||L7F7-FJL7LFLF
.|-F---FFJ|L7|||L---JLJL---7|F7F7|L-J|L-JF--JL-7|LJ|LJFJL-7|L7F--JFJ|L--J|F-7FJFJ||F7L7L-JFJFJL7F7|L-7FFJF7L7LJL--7L7L7|F7F7||L7LJL7|F-J7L-J
-JF7|-7JL7L-JLJL-----------J|||||L7F-JF-7L7F-7FJL-7|F7L7F-J|FJL--7L7L7F--J|FJL-JFJ||L-JF--J|L7FJ|||F-JFJFJL-JF7.F7|FJF|LJ|||||F|F--J|L-7JJ-.
FLF-J7L7LL---7F---7F7F7F7F-7LJLJL7|L-7|FJLLJFJ|F7FJ||L7||F7||F7F7|FJFJL-7FJ|F7F-JFJL-7FJFF77FJL7|||L7FJFJF--7||FJLJ|F7|F-J|LJ|FJL-7.|F-JJJ.L
F|LJ|FJL-|JF7LJF77LJLJ|||||L-7F-7LJF7|||-F-7L7|||L7|L7||||||LJLJ||L-JF7FJ|FJ|||F7L--7||F7|L7L-7||LJFJL7L-JF-J||L-7FJ||||F7L7FJ|F-7L-JL----7|
LJ|JFJ||FFFJL-7||F7F-7LJLJF--J|FJF7|LJ||FJFJFJ||L-J|7|||LJ||F--7LJF--JLJFJL7||LJL-7FJ|||||FJF7||L-7L7FJF--JF7|L7J|L-JLJ||L-JL-JL7|F7F7F-7FJJ
F----JL|7LL--7LJLJ|L7|F-7LL--7|L7|||7FJ|L7L7L7|L--7|FJLJF-JLJF7|F7|F--7FJF-J||F--7||FJ||||L7||||F7L7||FJF7FJLJFJFJF-7F7LJF-7F7F-J||LJ||FJL7J
F77FJ.LLF7F--JF--7L-JLJFJF7F-J|7LJ|L7L7L7L7L7|L7F7|LJF7FJ|F7J||||LJL-7|L7|F7||L7FJ|||FJ||L7|||||||J|LJ|J|LJF--JFJFJFJ|L7FJ|LJ|L-7|L-7LJL-7||
--L77FJ|||L-7FJF-JF-7F7L7||L--JF7FL7|FJFJFL7LJFJ|||F7|LJF7|L-J||L7F7FJL7||||||FJL7|||L7|L7|||||LJL7|F7L7|F-JF--JFJ-L7L7|L7F7||F7|L-7L7LJ-||7
.L|LF..FJL7FJL7L--J|LJL7LJL----J|F-J|L7|FF7|F-JL||LJ||F7||L-7FJ|FJ||L-7|||||||L7FJ|||FJ|FJ|||||F--JLJ|FJ|L--JF7FJ-F7L-JL-J|L7LJ|L-7L-J.FLLJ.
|L7-J7-L-7LJF-J|F-7F7F-JF--7F7F7LJF7L7|L7||||F7FJL7FJ||LJ|F7||FJL7||F7|||||||L7|L7||||FJ|FJLJ||L-7F7FJL7|F--7|||F7|L--7F77|FJF7L--JJF7-L.|J7
77LJ.-.L-|F7|-F7L7||LJF7L-7LJLJL--JL7|L7LJ|||||L7FJL7|L7J|||||L-7||||||||||||FJ|-|||||L7|L7F-JL-7||LJF7LJL-7LJLJ||L-7FJ|L-JL7||F7F7L||F|7|-|
|F--JJ7|F||LJFJL7||L--JL--JF---7F7F-JL-JF7||LJL7|L7FJL7|FJ|||L7FJ||||||||||||L7L7|||||FJL7|L-7F7|LJF7||F---JF---JL7FJL7|F---J|LJLJL-J|JLL77J
FLJLL7FJL||JFJF7LJL--------JF-7LJ|L---7FJ||L7F7|L7|L7LLJ|FJ||FJ|FJ|LJLJLJLJ|L7L7|||||||F-J|F-J|LJF-JLJ|L---7|F----JL7FJ|L----JF7F----J|F.L77
-J|JJL.LF|L7L-JL7F7F7F--7F-7|FJF7L---7LJFJL7LJ|L7|L7|F--JL7||L7|L7L-------7|FJFJ|||||||L--JL-7L-7L---7L---7LJL---7F-JL-JF----7||L--7.L-L77L7
JF|7..FF7L-J7F-7||||||F-J|FJ|L-J|F--7L7FJ|FJF7|FJL7LJ|F7F-J||FJ|FJF7F7F7F-J|L7|FJLJ|||||F----JF7L7F--JF7F7L--7F7FJL7F7F7L-7F7LJL---JJ77L-7J.
|J|L-7-|L-7F7L7LJ|||||L7FJ|FJF--J|F-JFLJF7|FJ||L7FJF-J|LJF-J|L7|L7||||||L7FJFJ|L-77|||L7|F-7F7||FJ|F-7|LJL--7LJLJF7||LJL-7LJL-7F7F-7.|7JF|JL
L-|..L7L-7LJL-JF7||||L7||FJ|-L---JL-----J||L7LJL|L7L7FJ-FJF7L7LJFLJ||||L-J|FJFJF7L7||L7|||FJ|||LJF|L7||F----JF7|FJLJL7-F7L-7F-J||L7L7.|7FJ.L
|-7-7FJ|LL-7F7FJ|||||FJLJL-JF---7F7F--7F7|L7||F-JFJFJL-7L7||FJ7F---J||L--7|L7|FJL7|||7LJLJL7|||F--JFJLJL-----JL-JF7F7L-JL-7LJF7||FJFJ-JLJ777
JFL-F|.|J.LLJ||FJ|||LJF7F---JF-7LJ|L-7LJ|L7|L7L7FJ-L7F-JFLJ|L7FJF-7FJ|F7FJ|FJ|L-7||LJF7F7F-J||||F-7L7F-7|F7F7F7F7|LJ|F-7F7L--JLJLJFJJ7.7|F77
LJJ7J|F|..L|7LJL-JLJFFJ|L--7FJLL-7L-7L-7L-JL7|LLJFF-JL--7F-JFJ|FJJ|L7||LJFJL7L7FJLJF-JLJLJF-J||LJ.L-JL7L-JLJLJ||||F7LJF|||F-7F7F7FJFL|-L|JJ|
LJ7L.7-FF77F7-F-7F7F7L7|F--J|F-7FL-7|F7|F-7JLJF7F7|F-7F7|L-7|FJL7FJFJ|L-7L7FJFJL--7|F7F--7|F7LJ-F7F7F7L--7F--7LJLJ|L--7||LJFJ||||L77F7.L|7||
|.FL.LF---7||-L7LJLJL7||L---JL7L---JLJLJ|FJF7FJLJ|||FJ||L7FJ|L7FJL7L7|F7L7|L7L7F--J||||F-J||L--7|LJ|||F7|LJF7|F---JF--JLJF7|FJLJL7L-J|7.||L-
..FJ.FL7F7LJL7|L----7LJ|-F7|F7L--------7|L-JLJF--JLJL7|L-JL7|FJL-7|FJ|||FJL7L7|L7F7LJLJL--JL--7|L-7LJLJL7F-JLJ|F---JF----J|LJF7F7L-7FJ7FF77L
F-|-7F|LJL7F-JF-7F--JF-JFJ|FJL--------7LJF--7FJF---7FJ|F---J|L7F7||L7||LJF-JFJL7LJL7F---------J|F7L-7F-7|L----JL----JF7F--JF7|LJL77LJLJ-LJJ|
F-|--LF---J|F7L7|L--7L-7L7|L---------7LS7L-7LJL|F--JL-JL-7F7|FJ||||FJ|L-7L-7L-7|F7FJL--7F7F---7LJ|F-J|FJL-7F--7F-7F-7||L---JLJF-7|7F|.|FLJL7
-7.|FLL7F-7|||FJ|FF7L-7L7|L--77F----7L-7L--JF7FJL-----7F7LJ|||FJ|||L7L-7|F-JF7|||||J|F7LJLJF--JF7LJF7||F-7LJF7|L7|L7|||F7F---7|JLJLFJ|LL77LF
FLL-||LLJFJLJLJFJFJL-7|FJL--7L7L---7L--JF7|FJLJF-7F--7LJ|7FJ|||FJ||FJF-J|L--J||LJ|L-7|L--7FJF7FJ|F7|LJLJFJF7||L-JL7|LJ||LJF-7|L--7---LF-L77|
F|FFLJ-F-JF---7|JL--7LJ|F7F7L7|7F-7L---7|L-JF7FJJLJF7L-7|FJFJ||L7|LJ7L-7L--7FJL-7|F7|L7F7LJFJLJL|||L7F-7L-JLJ|LF-7|L-7|L77|FJL---JJ.||.||7-L
F|777F-L--JF7|||F--7L-7||LJL7||FJFJF---J|F--JLJF7F7|L7LLJL7L7||FJL----7L7F7|L7F-J||LJ-LJL7FJF7F7LJL-JL7|F----JFJFJL7FJL7L-JL----77.F|7-F7|J|
|.|FF77|F--JL-J||F7L--J|L--7LJ|L7|.L----JL-----JLJLJFJF--7L7|||L7F7F-7L7|||L7LJ|.LJF-7F--JL7|LJL7F7F7J||L-7F7L|FJF7LJF7L7F--7F--J7F7JJ||J77|
L--FL-F-JF----7|LJL-7F7L---JF7L7|L7F7F7F7F7F-7F-----JFJF-JFJ|||FJ|||.|FJLJL7L-7777|L7LJF---JL7F7LJLJL-JL--J|L7||7||F-JL7|L-7LJJJFFJ||.||FLFL
F-LL7-L-7|7F--JL7F7JLJ|F7F--JL7||FJ||||||||L7LJF7F7F7L7L-7L7|LJ|FJLJFJL7.F-JF-J7-F7-L--JF--7.LJ|F-7F7F7F-7LL7LJL7|LJF7FJL7FJF-7|L---7FJF-7LL
L7|FLJ..LJ-L---7|||F7FLJ||F---JLJL-JLJLJ||L7L--JLJLJL-JF-J-LJF7|L-7LL-7|FJF7|J-L|||-F7F-JF7L---JL7LJ||||FJF7|F--JL7FJ|L7||L-JFJ7|J-J7LL|JL-7
L7-F.LJ.FFLF---JLJLJL---J|L----7F7F7F--7LJLL-7F-------7L77FLFJLJF-J7-LLJL-JLJF-.F|L-J|L--JL---7F-JF-J|LJL-JLJL----JL7L7L7L--7|F777-L|7J.L|F7
LFJ|L.|-F|FL----7F7F----7|FF7F-J|||||F-JF---7LJJF----7L7L77.L--7L7J|.|.|J7FJJJLFFJF-7L7|F-7F--JL7FJF7|F---7F7F7F7F--JFL-JF-7|LJL7J.L|.77FFF|
||-FJ--.|JF-----J|||F7F7LJFJLJF7|||LJL--JF--J|F7|F--7L7L-JF7|-L|FJ-|-|.L7F|L|L7|L-JLL7L7L7|L--7FJL-JLJL--7LJLJ|||L-------JFJL---J-FFJ.-|-JJ|
7L7L-JFFJ-L---7F7||||LJL7-L7F-JLJLJF7F7F7L7F7FJLJL7-L-JJF7|L7.FLJJFL.F.LLF7-J|F-7F7F7L7L-J||F7LJ7F-7F77F7L--7|LJL---7F----J.F7F--7J.L7JLLFJF
|FLJLF-|JLF7F7||LJ||L7F7L--J|F-----JLJLJL7LJLJF--7L7FF-7||L7|-L-J-|7F77-FJ-F77L7|||||F|F-7L-JL--7L7LJL-J|F-7L7F7F7F7LJF7F7F7||L7FJ7FL77.F|-L
|--|FJ|L|-|LJ|LJF7LJJLJL7F--JL--------7F7|F7F7L-7L7L7L7LJL-JL77FJJ|7-J|.LJLF---JLJLJL-J||L7F---7L7L----7LJ7L7LJ||LJ|F7|||||||L-JL-7F7JL-|JL|
|.|L|LLF|7L-7|F-J|F7-F7FJ|F--7F7F----7LJ|||LJ|F7L7L7L-JF7F7F7|-LJ.|---F-LJFL---7F-7F-7FJF7LJF7FJFJFF--7L---7|F7LJF-J|||LJLJLJF---7LJ|77.||F|
F777L|.|J-F-JLJF7LJ|FJ||FJ|F7LJLJF--7|F-J|L-7||L7|FJF7FJLJLJLJJ|FJ-J7|JFFF7|JLFJL7LJJLJL|L-7||L7|F7L7FJF---JLJ|F7|F7|||F--7F-JF-7L--J-L.--F|
LJ-FFJ-L|LL----JL7FJL7|LJ.LJL--7FJLFJ|L-7L7FJLJL||L7||L-7F7F77-77L|7-7--7F7J-FJF-JJF---7L-7LJL7||||7|L7L-----7|||LJ||||L-7LJF-JFJJF7J||F|-||
L---JLL.-J|F7F7F7||FFJ|F7F7F---J|F-JLL--JLLJF7F7LJ.LJ|F7LJLJL77JF-J|LJ7F7.||F|FJ7|.L--7|F7L--7LJLJL-JFJF-----J|||F-J||L7FJF7L7FJF7|L7F777FF|
-7FJF77-|FFJLJLJLJL7L7||||LJF7F-JL-7JF-7F7F7||||F7F-7LJL---7FJ|.JJ77JLF|77|FLLJLF7-F7FJLJL---JF7F7F-7|FL---7F7LJLJF7|L-JL-JL7||.|||FJ|L77FL7
F--J-F----JF--7F--7L7||||L--JLJF---JFJFJ|||LJLJLJ||FJ7F-7F7LJJ7F|FL-77LL|--L.L|FJL7||L7F-7F7F7|||LJFJ|F7F-7LJL7F7FJLJF7F----J|L-JLJL7L7L7JLJ
J7L--L----7L-7LJF-JFJ||||F7F--7L----JFJJ||L7F----J||F7L7||L7F7J-F7L|.--F|.FJFFFJF7LJL7LJ7LJLJLJ|L7FL7|||L7|F--J|||F--J|L-----JF----7L-JFJJ7J
FL-..F----JF-JF7L-7L-JLJLJ|L-7|LF-7F-JF7||FJL---7L|LJ|-|||FJ|||F77-|L..-JFL7FFL-J|F-7|F7F7F7F--JFJF7||||L||L---JLJL-7|L-7F--7FJF--7L-7FJJ||7
FJ.LFL----7|F-J|F-JF7F-7F7L--JL7L7|L--JLJLJF----JFJF7|FJ|||L|L7|L7-||F-J.J.-FJ.|FJ|FJLJLJLJ|L---JFJLJLJL-J|F---7F7F7L--7|L-7|L-JF7L-7|L-7F7J
..77||F|J7|||F7LJF7||L7LJL----7L-J|F-------JF77F7L7|LJL7LJL-JFJ|FJ-|-JJ|.L7.|FF-JFJL-7F7F-7L----7L---7F7F7LJF7F||LJL---JL--J|F-7|L7FJ|F7LJ||
7.LF|LFJ-FLJLJL--JLJ|FJF7LF7F7L--7LJ7F------JL-JL7|L7F7|F----JFJL77J.|.L--|-JFL7FJF-7LJLJFJF7F-7L----J|LJL-7|L7LJF7F7F7JF--7|L7||.||.|||F-JJ
....|-L7FLF---7F----J|FJL-JLJL---JF7FJF7F7F-7F7F7LJFJ||||7F7F-JF-JF77J|.JF|L7J.LJFL7L---7L-JLJ-L---7F7|F---JL7|LFJ||||L-JF7||FJLJFJL7|||L7JJ
7.FF|7J.F.L-7FJL-7F--JL-7F7F---7F-JLJFJLJ|L7|||||F7|FJLJL7|||F-JF-J|-F77J|LF7.-L|F7L---7L--7F------J|||L-----JL7L7||LJF--JLJLJF7LL7FJ||L7||L
F--7JF7FF---JL--7LJF---7LJ||F--J|F---J7F7|FJ|||||||LJF7F7LJ||L--JF-J7||J7J.|L7..FJL77F7L-7FJ|F-7F-7FJLJF---7F-7L-JLJF7|F7F7F--JL-7||7LJJLJ77
JJF|||F-L7F7F-7FJF7L--7|F7LJL-7FJL-7F--J||L7LJ|||||F7||||F7LJF--7L-7FJ||F-7-F7FFJF7L7||F-JL7LJFJ|FLJF7LL--7|L7|F7F7FJ|LJLJLJF-7F7|LJF|L-7|-7
J7-7.FF|-LJLJFJ|FJ|F7FJLJL7F7FJ|F-7LJF7FJL-JF7LJ||||||LJLJ|F7L-7L7FJ|FJFJFJJ|L7L7|L7LJ|L-7FJF7|FJF--JL----JL-JLJ||||FJF-----JFLJLJ7LF-7J-7.|
LJF|-FJL.|LF7L7|L7|||L--7FJ|LJFJL7L--JLJF---JL-7LJLJ|L--7FJ|L--J7LJ7|L-JFJF-JFJJLJ7L-7L77|L-J|LJ.L-------------7LJ||L7L----7F-7JF-77|FJJLF.F
.LJ|..7--F-JL-JL-J|||F--JL7L--JF7L------JF----7L7F7FL--7|L-JF7-F-7F7L--7|7L-7|F-7F--7L7L-JF--JF7F7F------------JF7LJ.L7F7F7LJFJFJFJFJL77FL-J
LF-|7FF7-L-------7LJ|L---7|.F7FJL--------JF7F7L-J|L-7F7LJF7F|L7L7||L7F-JL7LFJ|L7|L-7L-JF-7||F-JLJLJF-7F-------7FJL7FF7LJ|||F-JFJFJFJF-J-L-J.
L7J||.|.FF7F7FF--JF7L7F--JL-JLJF------77F7|LJL7F-JF-J|L7FJ|FJFJFJ||FJL--7L7L7L7|L77L-7FJFJL7L------JFLJF7F----J|F-JFJL-7LJ||LFJFJFJFJ|J|JL7.
LJF|J.77FJLJL-JF7FJL7LJF7F-----JF7|F-7L-JLJF-7LJF7|F7L7||FJ|FJFJFJ|L7|F7L7L7|FJL7L7F7LJFL7FJF--7F77F7|FJLJ|F7F7|L7FJF--JF7LJFJFJLL7|F777..|.
|7F|J|.-L----7FJ|L-7L--J||F-----JL-JLL-----JFJF-JLJ|L7|LJL7|L7L7L-JFJFJL-JFJ|L-7L7||L--7FJ|-L-7LJL-JL-JF---JLJ||FJL7L---JL7FJFJF7FJLJL-7--77
L7FJF7F-FF---JL7L7FJF---J|L7F7F-7F-7F--7F7F7L-J-F7L|FJL-7FJL7L7|F7FJ-L7F-7L-JF-JFJLJF--JL7L7F7L-----7F7|F--7F7LJL--JF7F---JL7|.|LJF7F--J|-|J
L||-L7-JL|F7F7FJFJ|FJF7F7|FJ|LJ.LJJLJF7LJLJL7-F7|L-JL--7|L-7L7|||LJLF7||FL7F-JF7|F-7L---7L7LJL------J|LJL-7|||F-----JLJF7F7FJL-JF7||L-7J-7F7
||LFLJ.F-LJLJ||FJFJL7|LJLJL-JF7F7F7F7||F-7F7L-JLJF7F---J|F-JFJLJL--7||LJF-JL-7||LJ|L7F--JFJF---7F7F7FJF-7FJLJ|L--7.F--7|LJ||F---J||L--JJJFFL
L|J...FF----7LJL-JF7LJ|F7LF7FJLJLJLJLJ||FJ||F7F7FJLJF7F7||-FJF-----J|L7FJF7F-J|L7JF7||F7F|FJFF-J|||LJJL7LJF-7L--7L-JF-JL-7||L--7LLJF7|F77FJ|
LL7F-7FL-7F7|F7F7FJL--7||FJ|L--------7|||FJLJLJLJF7FJ||||L7|FJ7F--77|FJL-J|L7|L7|FJ||LJL7LJF7L--J||F---JF-JFJ-F7L---JF7F7|LJF--JF7FJL-JL-7JJ
..|7.||FLLJ|LJLJ|L---7LJ|L7|F--7F----JLJLJF---7F-J||FJ||L7|||F7|F-JFJL77F7L7|F7||L7|L--7L--J|F7F7LJL----JF-J-FJL-----JLJLJF7L-7FJ||F-----JJ.
F-7-FJ|F--FL7F-7L---7L-7L-J|L-7|L------7F-JF--JL-7LJL7|L-J||LJ||L-7L7FJFJL-JLJ||L7|L--7L-7F7LJLJL7F7F7JF-J-F7|F-7F-7F7F-7FJL-7LJFJ||FF---7-|
J7|7||L7JFF7|||L7F-7L-7L7F7L--JL-------J|F7L---7FJF--JL-7FJL7FJ|F-JFJ|.L----7FJL7||F-7|F7LJ|F-7F7LJLJL7L---JLJL7LJFJ|||FJL--7L-7L-JL7|F--JL7
.7LFF-L|J-||LJF-JL7|F7L7LJL7F7F7F7F77F7|LJ|F---JL7|F-7F-JL7FJ|FJ|F7L7L7|F7F-JL--JLJL7LJ|L-7|L7LJL---7FJF7F-7F-7L-7L-JLJL7F-7|JFJF7F7LJL--77|
-J-||FFF-7||F7L---JLJL7L7F7||LJLJLJ|FJL7F7|L7F-7FJ||FJL-7FJL7|L7|||FJFJFJ||F----7F--JF7L7FJL-JF77F--JL-JLJFLJJ|F7L-7JF--JL7||FJFJLJL7F--7|FJ
LJF|F--JFJ||||F7F7LF7|L7LJ|LJF7F7F7LJF7LJ|L7LJFJ|FJ||F7J||F7|L-J||LJFJFJFJLJF---JL-7FJ|FJL7F7FJL7L-7F7F7F----7LJ|F7L7L7F-7|LJL7L--7FJL-7||JJ
FF-FL--7L-J||||||L-J|F-JF7L--JLJLJL--JL--J.L-7L-JL7|||L7|LJ|L--7||F-JFJFJ.F7L7F7F7FJ|FJ|F-J|LJF7|F-J|LJLJF7F-JF7|||FJFJL7|L7F7|F-7|L-7FJLJJ7
--7|-F-JF-7|||||L--7|L--JL-----7F---7F7F7F7F-JF-7FJ|||FJL-7|F7FJ|||F7L7|F7||-LJLJ||FJL7|L-7|F-JLJL-7|F---JLJF7||LJLJLL7FJ|FJ|LJ||LJF-J|F77F7
.L77.L--JFJLJLJ|-F7||F7F------7||F--J|||LJ|L-7||LJF||||F77|||||FJ||||FJ|||||F-7F-JLJF-JL-7LJL--7F7.LJL------JLJL-7F7F7LJ-|L7|F7L7.L|F7LJL-J|
7.L-|JJF-JF---7L-JLJLJ|L7F-7F7LJ|L---JLJF7|F-JL7F7FJ|||||FJ|||||FJ|||L7||||||FJL---7|F7.FJF---7||L-7-F------7F---J|LJL7JFJFJLJL7L-7LJL7F7F7|
|-|JJLFJF7|F--JF-7F7F7L-J|LLJL7FJF7F7F--JLJL-7FJ||L7|||||L7LJ||LJFJ||FJ||||||L-7F7J|LJ|FJFJF7JLJL-7L7|F7F--7LJF---JF-7L7|FJF---JF7L--7||||||
FJJ|JF|FJLJL7F7L7LJLJ|F--JF7F7LJFJLJ||F7F7F7FJL7||FJ||||||L-7||F-JFJ||FJ|||LJF7|||FJF-J|FJ.|L-7F7FJFJLJLJF-JF7|F--7L7|FJ||JL--7FJ|F7FJ||LJ||
77FJ-JLJF|F-J|L7|F7F-J|F-7|LJL--JF-7LJ||||||L7FJ|||FJ||||F7|||||F7L7|||7||L7FJLJ||L7|F7||F7L7FJ|||FJF7FF7L--JLJL-7L-JLJFJL-7LFJ||||LJFJ|||||
J-7JJFF---JF7|.LJ||L--JL7|L---7F7|7L7FJ||||L7|L7|||L7|LJ||L7|||||L7|LJL-JL7||F7FJ|FJLJ||||L7||FJ|||FJ|FJL7F-7F7F7L----7L--7|FJFJFJL-7L-J7FLJ
L-77F-|F--7|||F--JL---7FJ|F7F7LJ|L-7|L7||||FJ|FJ||L7|L-7||FJ|LJ|L7|L7F--7-||LJ|L7LJF7FJ||L7||LJFJ||L7||F-JL7||LJL--7F7L7F7LJL7L7L--7|7JL7-JJ
|FL||FLJ|LLJLJ|F-----7|L7LJLJL--JF7||FJ|||||FJL7|L7||F-J||L7L7J|FJL7||F7L-JL-7L7L--J|L7|L7||L-7|FJL7|LJL-7FJ|L--7F7LJL-J|L7JLL-J7J|LJ-7-F77|
FF-JF|F|-.F7F7|L7F---J|||F7F7F-7FJ||||FJ||||L-7|L7|||L-7LJFJFJFJL-7LJLJ|F7F7FJF|F---JFJL7|||F7|||LFJL7F7FJ|F|F-7LJL7F7F7|FJJLFJ-J-|J|FJ.|L-J
-F-F-L-F--|LJLJFJL---7L-J|||||FJL7LJLJ|FJ||L7FJL7|||L7FJF7L7L7L7F7|F---J||||L7FJL--7JL7FJ||||LJLJFJF7LJ|L7|FJL7|F7FJ|LJLJL--77J7.-.|L7LFL-|J
||--77FL-LL-7F-JF----JF7FJ||||L7FJF--7LJ|LJFJ|F-J||L7||FJL-JFJ-||||L-7F7|LJ|FJL7F--JF-J|-LJ|L---7|FJ|F7L7||L7FJLJ||||F----7FJ|FJFLF-7|.LFJJ.
-FJ-F7|.LFLFJ|F7L--7F7||||LJ||FJL-JF7L---7LL7||F7|L7|||L-7F7|F-J|||F-J||L-7|L7||L-7LL--JF--JF---JLJ||||FJLJF|L-7FJL7||F--7||LL7-7L7LF-7LJJ..
FF7.||JF-7JL-J||F7FJ||||L--7LJL--7FJL--7FJF7LJLJ|L7||||F-J|||L7FJ||L-7|L-7||FJFJF7L7JF-7L7F7L-7JF---J|||LLF-JF-JL-7LJLJF-JLJ7|FJ|7LJL-J7JL-7
LLJ7-L-|J.FF--JLJLJFJ|||F--JF7F--JL---7|L7|L----JFJ||LJ|F7|||7|||||F-J|F7|||L7|FJL7|FJFJ7LJ|F7|FJF7F7||L7FJF7L---7|F-7FJF7JJLJJ7L-7FLJ7|7.77
LLLFJ-FJ-FJL---7F-7L7LJ|L7F-JLJF7F7F--JL7||F7F7F7L7|L-7||LJ|L7|L7||L--J|LJ|L7||L-7|LJFJ|F7FJ||||FJ||||L-JL-J|F-7FJLJFJL-JL77FLJJ7.F--7-||FF7
|FJF7.J-FF7FF--JL7L7|F-JFJL--7FJ|||L---7||LJLJ|||FJ|F-JLJF-JFJ|FJ||F---JF7L7|||F7||F7L-7|LJFJ|||L7|||L----7FJL7|L--7L7F7F7L7JJ7LLL-JFLJFF|-J
F|F|J-|--7|-L7F7FJFJ|L7FJ|F--J|7LJ|F-7FJ||F---J|||FJL-7F7L-7L7||FJ|L7F-7|L7|||||LJLJ|F-JL-7L7||L7|LJ|F----J|F-J|F-7L7||LJL-J.L7..L|.LL7-FLJ7
-7-|F7L7J|F7|LJLJ7L7L7LJF7L7F7L7F-J|JLJFJ|L-7F7|||L-7FJ|L--JFJ|||FJ|LJFJL7LJ|||L-7F-JL-7F7L-JLJFJ|F-J|F----JL-7||FJFJ|L-7F7.F.|-7-|-LJJF-7||
||JL||FJFLF--------JFJF-JL-J||FJ|F7L--7L-JF-J|||LJF-JL7L---7|.LJ|L-7F-JF7L-7LJ|F-JL-7F7LJL---7|L7||F-JL7F-7F7FJ||L-JFJF7LJL7JLL-77F-7JF-J---
7.L-J-L-L7L7F7F7F7F-JFJF-7F7||L7LJ|F--JF7LL7FJLJ-FJF-7L-7F-JL-7FJF-JL--JL7FJFFJL-7F-J|L---7F7L7FJ||L-7FJL7||||FJL--7L7||F--J-JF|JJ|LJ7|JLLJJ
L7.FJJJ|L-7LJLJ||||F-JFJFLJ|||FJLFJL---JL7L|L--7FJFJLL7FJ|F7F-JL-JF------JL-7L7F7|L-7L--7JLJL-JL7||F-J|F7|||||L-7F-JFJ||L---7-JL|77FL|JF7-|.
|L7JL|-L---J-|-LJ||L7FJF7F-J|||F-JF------JFJF-7|L7L--7||FJ||L---7FJF-7F7F7F-JFJ|||F-JF-7L---7F-7LJ||F7LJ||LJ||7FJL-7L-J|F---J-JFL|-F-|LJJ--7
J7L7-7..|.L.---J-LJ-||FJLJF7|LJ|F7L---7F7FJFJFJ|FJF-7|||L7|L7F7FJL7|FJ|LJ|L-7|FJLJL7FJFJF---JL7L7FJLJL7FJ|F-JL7L7F7L--7|L-77L7FF7|.J7LFJL7FJ
FF7|7L7-|.|FJL7FFJ|.LJL--7|LJF-J|L7F-7LJ|L-J7L-JL7|FJ|||F|L7|||L7F||L7|F-JF7||L7F--JL7L7L-7.F-JFJL7F7FJL-JL7F7|JLJ|F--JL--JJJ--F7|FL7|LF-FJJ
F|FFJ7LL--F7F--.|F7F-----JL7FJF7|FJL7L-7L---7F---J|L-J||FJFJ||L-JFJ|7LJL7FJLJL-JL7F--J||F-JFJF7L-7LJ|L-7F--J||L--7|L77LL-|J-|F-7LJ7.L7|L-7FJ
LLJL777FJLLJJ7|LFJ|L------7||FJ||L7FJFFJF7F7||F--7|FF-J|L7L7||F7-L7|F---JL--77F--J|F---JL--JFJ|F7L7FJF7||F-7||F7FJ|FJJLJ.L|.L7.|J|L|JFJ7F.77
J.7J777L-J.|FJ-LL7L-------J||L7LJFJL-7L7|LJ||||F-JL7L-7L7|FJ|LJ|F-J|L-7F7F-7|FJF7FJL-7F-7F7FJ.||L7|L7|||LJFJ||||L7LJJJ.|.JJ|7L-F.|.J-7-|JFJ7
FFJ|FJ-|..FJ7|.|L|F-7F---7FJ|FJLFJF7FJFJL7.LJLJ|F-7|F7|FJ|L7|F-JL-7|F-J||L7||L-J||JF-JL7||||F7LJ7LJ-LJ|L-7L-J|||FJJJ|LF77|7F77J|L77L7JFJ-FJ|
L|.F|-LJ.FJF7LJJ|LJFJ|.F-J|||L-7|FJLJFJF7L--7F-JL7|||LJL7L7||L-7JJLJL7FJL7|LJFF-JL7L7F7||||LJL--7-LF--JF-JJ-FJ||L7-LL7|L-|-JJ7F|J.7.-77|F|JJ
FJ-7.-7--|FL--7F|.|L-JFJF7|FJF7||L7-FJFJ|F--JL-7FJLJ|F-7L7||L--JFFFJF||-FJ|FF-JF7FJ|LJ||LJL7F---JJ|L---J7|77L-JL-J77|J|7LL77LJ|.|-|F|.F-JJ|.
|JJFJJ.FLL.|.LL-JFF7|LL7|LJ|FJ||L7|FJFJFJL--7F-J|7.L||F|FJ|L--7JJ-L-LLJJL7|FJF-J||F7JFJL7F-JL7JL|.7LF|-LJ-7-FJJLL|.7JLLJ7.F7-FF77-LF|FFJ-777
||JL7|F-JLF77J|.L-.F-F-J||FJ|7LJ7||L7|FJF-7FJ|F7L-7.LJ-||FJF-7|.|JJ.L|7LL|||FJF-JLJL7|F7|L-7FJJ7F-|--JFL|LL7L|F-FF7L77L7--LF7LLF|JFL|7|--7JJ
JJ--J7-L-7JL|J|-..7|FL--J-L7|7J|FJ|FLJ|FJFJ|7LJ|F-J-7F-J|L7|-LJ-|J|7F|--LLJLJFJF-7F-JLJ||F-JL7-L--L-JL|.7FLJF||.-JJ7.|JL|.LJJ.F|.F7LF-J.FJ..
.|L-J|7|L7.|L-J.LJLJLJL|L||LJ7-LL-J-LLLJ7L7L7L|LJ.|7F|F7|JLJFL|.F.F-LLJ-LLLLJL7|FJL---7LJL-7FJJ.L77.F7|FL-JL|-J7|JF7F|7.F7LJ.--.F||LL.--F-|7
.-7J7LF7-|--JLF-.|7.FFFJF-FJL|F||L77L7|FJ-L-JF|J|-|-FJ|LJ|LL7-FLL.--7F-7.|7|.LLJL7F--7|||LFJ|J.|7FF-J-J7JL.||||-LL|JLJL|.J.LF.F7JL7|L|J.|.|L
|FJ.|.|--.LJJF-LFJJ7FLJ.7LJJF|-|J||7FJJF7F||.||.-7LFL-JJL-F.F.-JL.J-77|77.LL-7|-|||JLLJ-7-|FJJ7.L.|FJ-||LL-F-7F-77FJL.FL7J77F7FJJ.F--JJ-J7FJ
F--J..L-|FF.LFLL.|J-7J7F--|JL7|LL7.F|F-LJF|77||FL--7J|JL.L|7F-.L|7-F.--JL77FLL7|F||J7|LL|.LJ|L.77.-|.|L7F-.|LLF7|-77|.JJ|.F-JL|JFLF|F7|7F7J|
7|FJ.|.F|--J.F7L7JL-J.-FF-77.LF7|JF-J77FL|L-7J.F.L-JL-.|.7-|..7|.|||.|F--FFJJ.F7LLJF-|-.LFJJ||F|FF7|-|-|7F-|JJ.F77FF--7.LL|-JFLJL-L7|J-FF-F7
L7J.F|-7|J|-F|7L-77-L-7LL7FJF.J-|-----LJ-J||J7LF77|.FF-7|J-|F7.J-|7||77--7|||.L|.LL|-J.7-||.L-L7L|-7JL-||J-J.FFFL7LJ-L|-FJ.LF|7FJ--J|77L7.||
FJ-L--7J--J-LL--LL77-LL.L7J.JJJJL-|J..J----7L-JL|-J-|J-LJF-|.L-LJ..|JL-JLLLJJJ--7LJL-J.|L--FFJ.|JL-J.J-L|---F--|L|..7.L|.F|L-J--JJ.-.FJLL7JJ
#+end_src