268 lines
25 KiB
Scheme
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))))
|