My attempt at solving Advent of Code 2023.
Go to file
Daniel Ziltener 47ed32253c
Interim commit
2023-12-11 19:19:56 +01:00
.dir-locals.el Day 7 Part 1 2023-12-08 00:43:39 +01:00
.gitignore Cube Conundrum part 1 2023-12-02 12:18:23 +01:00
README.org Add symlink 2023-12-01 23:34:38 +01:00
chicken-src.org Interim commit 2023-12-11 19:19:56 +01:00
chicken.org Day 10 Part 1 2023-12-10 23:58:33 +01:00
day3.scm Day 8: Haunted Wasteland 2023-12-09 10:42:17 +01:00
day4.scm Day 8: Haunted Wasteland 2023-12-09 10:42:17 +01:00
day5.scm Day 8: Haunted Wasteland 2023-12-09 10:42:17 +01:00
day6.scm Day 8: Haunted Wasteland 2023-12-09 10:42:17 +01:00
day7.scm Code sanitising (don't use detangle!) 2023-12-08 10:17:29 +01:00
day8.scm Day 8: Haunted Wasteland 2023-12-09 10:42:17 +01:00
day9.scm Day 10 Part 1 2023-12-10 23:58:33 +01:00
day10.scm Day 10 Part 1 2023-12-10 23:58:33 +01:00

README.org

Advent Of Code with Chicken Scheme

Prelude

I don't know why I am spending my time this way, but I am trying to get through this year's Advent of Code. I decided to use Chicken Scheme, and I am trying to use as few (if any) extensions, for an extra challenge.

This may or may not be the original document (chicken-src.org) or its weave for reading (chicken.org). Choose wisely.

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 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 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:

  1abc2
  pqr3stu8vwx
  a1b2c3d4e5f
  treb7uchet

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

  (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)))

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:

  two1nine
  eightwothree
  abcone2threexyz
  xtwone3four
  4nineeightseven2
  zoneight234
  7pqrstsixteen

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

  (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)))

Puzzle Input

Jump to day 2.

  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

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:

  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

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.

  ;; 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))
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.

  ;; 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))
Draw Processing

And as the last pre-processing step, I take apart the individual draws, and assign each amount to its respective colour keyword.

  ;; 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))
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.

  ;; 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))

Then, I put everything together in a main function, preprocessing the input and summing up all game ids for which game-possible? returns #t.

  ;; 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)))

And now, everything can be put together:

  (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)))

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:

  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
  • 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.

  (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))))

And the main function gets modified to sum everything up.

  (define (game-set-power input)
    (let ((games (record-fold input)))
      (foldl + 0
             (map (lambda (game)
                    (powercalc (cdr game)))
                  games))))

The full thing put together:

  (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))))
78375

Puzzle Input

Jump to day 3.

  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

Day 3: Gear Ratios

Get the puzzle solution as tangled .scm file.

Part One

Quest

You and the Elf eventually reach a 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:

  467..114..
  ...*......
  ..35..633.
  ......#...
  617*......
  .....+.58.
  ..592.....
  ......755.
  ...$.*....
  .664.598..

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
  (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)
Indexing the Input
  (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))))))
Tokenizing the Indexed Input
  (define (number-char? c)
    (case (buffer-char-char c)
      ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) #t)
      (else #f)))
  (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))))
  (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))))))
  (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))))))))
Checking for Part Neighbours
  (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))))
Folding Everything Together
  (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)))))
  (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))
  (let-values (((part-nums part-syms) (tokenize-indexed-input (index-input (string->list input)))))
    (fold-part-numbers part-nums part-syms))
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:

  467..114..
  ...*......
  ..35..633.
  ......#...
  617*......
  .....+.58.
  ..592.....
  ......755.
  ...$.*....
  .664.598..

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
  (define (gather-neighbours part-sym part-nums)
    (foldl (lambda (output input)
             (if (neighbours? input part-sym)
                 (cons input output)
                 output))
           (list) part-nums))
Put Everything Together
  (define (filter-gear-candidates part-syms)
    (foldl (lambda (output input)
             (if (eqv? '* (part-symbol-sym input))
                 (cons input output) output))
           (list) part-syms))
  (define (calc-gear-ratio gears)
    (foldl (lambda (output input)
             (if (= 2 (length input))
                 (+ output (apply * (map part-number-number input)))
                 output))
           0 gears))
  (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)))
75220503

Puzzle Input

Jump to day 4.

  .....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..

Day 4: Scratchcards

Get the puzzle solution as 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 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:

  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

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.

  (define-record scratchcard id winning-numbers card-numbers match-numbers copies)
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.

  (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))

The pattern is then used to extract every scratch card which is then being parsed in a fold statement.

  (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))
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 !.

  (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)))

As a next step, I calculate the points for each card.

  (define (card-points card)
    (let ((match-nums (scratchcard-match-numbers card)))
      (foldl (lambda (points num)
               (if (= 0 points)
                   1
                   (* points 2)))
             0 match-nums)))

And now, we can put everything together and sum up the points:

  (foldl
   (lambda (sum card)
     (calc-card-matches card)
     (+ sum
        (card-points card)))
   0 (input->cards input))
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:

  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
  • 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

  (define (card-alist cards)
    (foldl (lambda (alist card)
             (calc-card-matches card)
             (alist-update (scratchcard-id card)
                           card
                           alist))
           '() (reverse cards)))
  (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)))
  (define (count-scratchcards cardlist)
    (foldl + 0 (map (compose scratchcard-copies cdr) cardlist)))
  (let ((cardlist (card-alist (input->cards input))))
    (generate-copies cardlist)
    (count-scratchcards cardlist))
5923918

Puzzle Input

Jump to day 5.

  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

Day 5: If You Give A Seed A Fertilizer

Get the puzzle solution as 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 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 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:

  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

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:

  50 98 2
  52 50 48

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:

  seed  soil
  0     0
  1     1
  ...   ...
  48    48
  49    49
  50    52
  51    53
  ...   ...
  96    98
  97    99
  98    50
  99    51

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
  (define-record entity type id)
  (define-record mapping-entry from-type to-type from-start from-end to-start to-end)
Data Extraction
Irregexes
  (define seed-irregex
    '(: (* whitespace)
        "seeds: "
        (submatch-named seed-numbers (+ (or numeric whitespace)))))
  (define mapping-irregex
    '(: (submatch-named mapping-from (+ alphabetic))
        "-to-"
        (submatch-named mapping-to (+ alphabetic))
        " map:"
        (submatch-named mapping-vals (+ (or numeric whitespace)))))
  (define mapping-nums-irregex
    '(: (* whitespace)
        (submatch-named to-range (+ numeric))
        (* whitespace)
        (submatch-named from-range (+ numeric))
        (* whitespace)
        (submatch-named range-size (+ numeric))))
Data Reading

A list of seed numbers:

  (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))))

And a mapping from input type (e.g. #:soil) to the mappings to the next type:

  (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))
Processing The Data
  (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)))
  (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)))
Solution
  (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)))
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.

  (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))))

After that, it is almost identical to part 1, but we have to replace the foldl with a recursive function that handles the promises.

  (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)))
  (let ((seeds (expand-seeds (input->seeds-list input)))
        (mapping-alist (input->mapping-alist input)))
    (fold-seeds seeds mapping-alist))
37806486

The Optimized Solution

For the optimized solution using ranges, a new record type is needed: ranged-entity.

  (define-record ranged-entity type from-id to-id)

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.
  (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)))))
  • 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.
  (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))))
  • There is just ranged-entity left, with nothing else: then it gets a new type, and is otherwise passed on 1:1.
  (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))

This behemoth determines which of the functions above to call.

  (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)))))

Here, the mapping is being done.

  (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)))
        '()))

And here, it is all put together.

  (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))))))

Puzzle Input

Jump to day 6.

  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

Day 6: Wait For It

Get the puzzle solution as 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:

  Time:      7  15   30
  Distance:  9  40  200

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.

  (define-record race time-limit record-distance winning-distances losing-distances)

The solution starts with the usual data extraction using irregex.

  (define input-extraction-irregex
    '(: "Time:"
        (submatch-named time-vals (+ (or numeric whitespace)))
        "Distance:"
        (submatch-named distance-vals (+ (or numeric whitespace)))))

Next, the data is converted into race records.

  (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))))))
Race Calculations
  (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)))))))
Getting The Result
  (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)))))
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 kerning. There's really only one race - ignore the spaces between the numbers on each line.

So, the example from before:

  Time:      7  15   30
  Distance:  9  40  200

…now instead means this:

  Time:      71530
  Distance:  940200

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:

  (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)))

And instead of keeping a list of all winning and losing distances, I use a counter.

  (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)))))))
Race Variant Results
  (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))))
41513103

Puzzle Input

Jump to day 7.

  Time:        58     81     96     76
  Distance:   434   1041   2219   1218

Day 7: Camel Cards

Get the puzzle solution as tangled .scm file.

Part One

Quest

Your all-expenses-paid trip turns out to be a one-way, five-minute ride in an 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 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 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:

  32T3K 765
  T55J5 684
  KK677 28
  KTJJT 220
  QQQJA 483

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 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.

  (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))))

The hands are separated into types.

  (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)

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:

  (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)))))

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;

    (get-type-for-cards #:A #:A #:A #:A #:A)
    #:five-of-a-kind

      ((= 5 (car frequencies))
       (hand-type-rec-set! hand (alist-ref #:five-of-a-kind hand-types)))
  • Four of a kind, where four cards have the same label and one card has a different label: AA8AA;

    (get-type-for-cards #:A #:A #:8 #:A #:A)
    #:four-of-a-kind

      ((= 4 (car frequencies))
       (hand-type-rec-set! hand (alist-ref #:four-of-a-kind hand-types)))
  • Full house, where three cards have the same label, and the remaining two cards share a different label: 23332;

    (get-type-for-cards #:2 #:3 #:3 #:3 #:2)
    #:full-house

      ((and (= 3 (car frequencies))
            (= 2 (cadr frequencies)))
       (hand-type-rec-set! hand (alist-ref #:full-house hand-types)))
  • 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;

    (get-type-for-cards #:T #:T #:T #:9 #:8)
    #:three-of-a-kind

      ((= 3 (car frequencies))
       (hand-type-rec-set! hand (alist-ref #:three-of-a-kind hand-types)))
  • Two pair, where two cards share one label, two other cards share a second label, and the remaining card has a third label: 23432;

    (get-type-for-cards #:2 #:3 #:4 #:3 #:2)
    #:two-pair

      ((and (= 2 (car frequencies))
            (= 2 (cadr frequencies)))
       (hand-type-rec-set! hand (alist-ref #:two-pair hand-types)))
  • One pair, where two cards share one label, and the other three cards have a different label from the pair and each other: A23A4;

    (get-type-for-cards #:A #:2 #:3 #:A #:4)
    #:one-pair

      ((= 2 (car frequencies))
       (hand-type-rec-set! hand (alist-ref #:one-pair hand-types)))
  • High card, where all cards' labels are distinct: 23456;

    (get-type-for-cards #:2 #:3 #:4 #:5 #:6)
    #:high-card

      ((= 1 (car frequencies))
       (hand-type-rec-set! hand (alist-ref #:high-card hand-types)))

Hands are primarily ordered based on type; for example, every full house is stronger than any three of a kind.

  (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))))

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.

  (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)))))

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).

  (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))
#t

To play Camel Cards, you are given a list of hands and their corresponding bid (your puzzle input). For example:

  32T3K 765
  T55J5 684
  KK677 28
  KTJJT 220
  QQQJA 483

Better sample input from u/LxsterGames on Reddit:

  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
  (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))

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.

  (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))))

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.
  (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)))))
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.

  (define (total-winnings hands)
    (foldl (lambda (total hand)
             (let ((bid (hand-bid hand))
                   (rank (hand-rank hand)))
               (+ total (* bid rank))))
           0 hands))

Find the rank of every hand in your set. What are the total winnings?

  (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)))
251216224

Part Two

Quest

To make things a little more interesting, the Elf introduces one additional rule. Now, J cards are 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.

  (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))))

In addition, the cardstr->cards and, subsequently, input->hands functions have to be adjusted to use this new list.

  (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))

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.

  (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)

Now, the above example goes very differently:

  32T3K 765
  T55J5 684
  KK677 28
  KTJJT 220
  QQQJA 483
  • 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.

  (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)))))
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?

  (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)))
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:

  (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)))
  (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))

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 day 8.

  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

Day 8: Haunted Wasteland

Get the puzzle solution as tangled .scm file.

Part One

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:

  RL

  AAA = (BBB, CCC)
  BBB = (DDD, EEE)
  CCC = (ZZZ, GGG)
  DDD = (DDD, DDD)
  EEE = (EEE, EEE)
  GGG = (GGG, GGG)
  ZZZ = (ZZZ, ZZZ)

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:

  LLR

  AAA = (BBB, BBB)
  BBB = (AAA, ZZZ)
  ZZZ = (ZZZ, ZZZ)

Starting at AAA, follow the left/right instructions. How many steps are required to reach ZZZ?

Puzzle Solution

Data Definition and Extraction
  (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))
Navigation
  (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)))))
Calculate The Route
  (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)))
19631

Part Two

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:

  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)

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

  (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)))))
  (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) >))))
21003205388413

Puzzle Input

Jump to day 9.

  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)

Day 9: Mirage Maintenance

Get the puzzle solution as 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 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:

  0 3 6 9 12 15
  1 3 6 10 15 21
  10 13 16 21 30 45

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:

  0   3   6   9  12  15
    3   3   3   3   3
      0   0   0   0

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:

  0   3   6   9  12  15   B
    3   3   3   3   3   A
      0   0   0   0   0

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:

  0   3   6   9  12  15   B
    3   3   3   3   3   3
      0   0   0   0   0

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:

  0   3   6   9  12  15  18
    3   3   3   3   3   3
      0   0   0   0   0

So, the next value of the first history is 18.

Finding all-zero differences for the second history requires an additional sequence:

  1   3   6  10  15  21
    2   3   4   5   6
      1   1   1   1
        0   0   0

Then, following the same process as before, work out the next value in each sequence from the bottom up:

  1   3   6  10  15  21  28
    2   3   4   5   6   7
      1   1   1   1   1
        0   0   0   0

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:

  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

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
  (define (input->list input)
    (map
     (lambda (x)
       (map string->number (string-split x)))
     (string-split input "\n")))
Calculation
  (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)))))))))
  (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))))
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:

  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

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?

  (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))))
1208

Puzzle Input

Jump to day 10.

  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

Day 10: Pipe Maze

Get the puzzle solution as 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 "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:

  .....
  .F-7.
  .|.|.
  .L-J.
  .....

If the animal had entered this loop in the northwest corner, the sketch would instead look like this:

  .....
  .S-7.
  .|.|.
  .L-J.
  .....

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:

  -L|F7
  7S-7|
  L|7||
  -L-J|
  L|-JF

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:

  ..F7.
  .FJ|.
  SJ.L7
  |F--J
  LJ...

Here's the same example sketch with the extra, non-main-loop pipe tiles also shown:

  7-F7-
  .FJ|7
  SJLL7
  |F--J
  LJ.LJ

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:

  .....
  .S-7.
  .|.|.
  .L-J.
  .....

You can count the distance each tile in the loop is from the starting point like this:

  .....
  .012.
  .1.3.
  .234.
  .....

In this example, the farthest point from the start is 4 steps away.

Here's the more complex loop again:

  ..F7.
  .FJ|.
  SJ.L7
  |F--J
  LJ...

Here are the distances for each tile on that loop:

  ..45.
  .236.
  01.78
  14567
  23...

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
  (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))))
Load Data
  (define (input->grid input)
    (map (compose (cut map char->tile <>)
                  string->list
                  (cut foldl string-append "" <>)
                  string-split)
         (string-split input "\n")))
Prepare Data
  (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)))))
  (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))))
    (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)))))))
  (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)))))
Calculation
  (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))))
7145

Part Two

Quest

Puzzle Solution

Calculation

Puzzle Input

  .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