Advent-of-Code-2023/day3.scm

268 lines
25 KiB
Scheme

(import (chicken string)
(chicken format))
(define input "
.....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..
")
(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)
(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))))))
(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))))))))
(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))))
(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))
(define (calc-part-1)
(let-values (((part-nums part-syms) (tokenize-indexed-input (index-input (string->list input)))))
(fold-part-numbers part-nums part-syms)))
(define (gather-neighbours part-sym part-nums)
(foldl (lambda (output input)
(if (neighbours? input part-sym)
(cons input output)
output))
(list) part-nums))
(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))
(define (calc-part-2)
(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))))