From 7bc5df124766662f356fc9d988fc7635d6329100 Mon Sep 17 00:00:00 2001 From: MsK` Date: Sat, 4 Dec 2021 23:41:59 +0100 Subject: [PATCH] day 4 --- day-4.input | 601 ++++++++++++++++++++++++++++++++++++++++++++++++++++ day-4.scm | 150 +++++++++++++ 2 files changed, 751 insertions(+) create mode 100644 day-4.input create mode 100644 day-4.scm diff --git a/day-4.input b/day-4.input new file mode 100644 index 0000000..f372bfd --- /dev/null +++ b/day-4.input @@ -0,0 +1,601 @@ +4,77,78,12,91,82,48,59,28,26,34,10,71,89,54,63,66,75,15,22,39,55,83,47,81,74,2,46,25,98,29,21,85,96,3,16,60,31,99,86,52,17,69,27,73,49,95,35,9,53,64,88,37,72,92,70,5,65,79,61,38,14,7,44,43,8,42,45,23,41,57,80,51,90,84,11,93,40,50,33,56,67,68,32,6,94,97,13,87,30,18,76,36,24,19,20,1,0,58,62 + +34 90 18 33 83 +27 7 25 61 15 +43 5 51 32 45 +24 17 72 31 22 +77 46 78 16 9 + +72 95 37 52 68 +80 1 73 96 63 +16 49 9 42 97 +25 81 20 11 46 +31 24 2 34 18 + +88 29 95 98 57 +49 36 6 23 83 +18 5 45 40 44 +62 81 74 99 87 +46 56 35 21 52 + +34 51 57 55 58 + 3 30 35 92 69 +56 53 86 40 4 +46 71 43 29 18 + 6 15 9 60 83 + +49 11 72 87 56 +40 94 71 70 3 +65 2 90 64 63 +32 79 24 44 55 +58 53 35 77 60 + +78 77 89 45 67 +32 35 18 1 60 +61 25 71 56 2 +44 27 73 82 79 +40 53 84 23 16 + + 9 70 11 95 14 +77 54 55 10 97 +88 89 41 8 43 +87 37 20 67 86 +74 24 30 75 25 + +30 36 41 93 66 +27 23 7 40 92 +73 29 1 2 45 +68 95 0 14 59 +78 70 54 64 25 + +35 75 54 52 86 +32 60 72 6 79 +45 26 77 83 41 +74 29 58 19 18 +49 63 31 61 88 + + 0 70 66 5 92 +85 55 65 19 24 +69 73 3 38 79 +58 94 84 22 16 +68 91 59 28 88 + +45 59 73 3 82 + 7 79 55 62 49 +89 32 99 69 19 +10 26 63 36 27 +28 83 43 64 4 + +53 28 61 95 63 +39 78 38 50 26 +46 91 70 6 98 +97 87 27 8 25 + 3 36 48 24 7 + +93 55 34 14 16 +88 92 19 86 53 +37 79 25 21 67 +22 13 10 97 7 +44 8 94 39 64 + +41 8 70 13 23 +16 33 55 89 12 +94 98 28 91 38 + 3 32 82 71 90 +92 15 76 86 80 + +34 99 57 29 48 +89 18 67 90 96 +12 95 93 41 9 +25 78 97 59 65 +87 38 91 61 17 + +31 96 70 24 11 +64 54 52 47 7 +86 27 1 85 44 +77 99 81 97 90 +21 82 6 83 41 + +98 59 95 45 34 +51 66 49 35 47 +83 13 28 94 32 +10 31 96 22 70 +62 48 42 44 16 + +61 44 52 12 7 + 5 24 58 53 51 +95 79 83 11 36 + 1 25 94 55 27 +89 59 88 39 70 + +30 81 65 77 82 +50 53 6 89 85 +12 33 1 72 11 +48 29 23 60 20 +67 27 95 61 28 + +44 6 72 94 32 +61 81 1 23 78 +67 22 15 24 12 +98 9 71 17 8 +25 50 93 92 56 + +89 63 3 53 90 +65 66 52 62 92 +55 59 42 71 49 +67 6 22 25 46 +10 94 84 1 77 + +16 34 96 63 56 +77 32 84 90 49 +52 44 9 95 94 + 3 1 83 39 24 +11 75 17 61 42 + +12 3 9 55 46 +20 68 26 34 4 +42 49 31 28 87 +51 86 0 15 44 +21 97 98 50 95 + +21 92 59 50 46 +93 60 95 75 44 +17 1 15 38 25 +96 49 28 76 83 +18 71 48 63 41 + +57 29 72 50 46 +95 93 92 35 74 +39 73 48 60 89 +80 70 55 76 43 +86 14 75 5 81 + +78 54 48 69 13 +29 88 23 33 67 +28 16 59 40 14 +79 11 94 68 8 +58 50 72 91 92 + +80 63 8 58 71 +45 83 52 98 36 +23 7 56 47 0 +99 1 94 76 54 +24 82 92 97 50 + +95 35 62 5 43 +12 69 85 90 17 +98 20 71 1 34 +13 48 87 78 29 +51 82 28 26 24 + +84 29 33 85 54 + 8 49 10 24 35 +67 15 37 34 32 + 1 48 81 89 94 +88 25 42 50 74 + +83 80 22 64 45 +66 68 23 89 30 +75 61 90 50 55 +99 42 17 54 77 +46 72 13 47 1 + + 7 22 27 6 71 +29 41 9 32 47 +84 67 2 92 53 +36 12 56 68 11 +74 48 38 96 51 + +85 53 8 73 41 +48 70 7 88 89 +87 63 11 32 12 +33 61 96 65 18 +52 97 20 45 67 + +70 0 51 30 37 +23 46 55 98 77 + 9 38 19 63 76 + 4 91 33 8 60 +92 67 39 47 85 + +19 9 17 28 26 +24 99 87 46 93 +16 97 41 96 13 +44 95 56 77 98 +15 61 7 5 58 + +65 11 68 97 95 +36 19 31 40 76 +12 79 27 34 9 + 6 30 78 96 74 +42 93 49 89 20 + +47 93 71 33 80 +62 70 4 32 21 +51 72 38 36 48 +40 7 76 16 60 +94 83 69 15 25 + +85 39 23 25 5 +47 55 75 45 42 +96 18 84 71 92 + 0 19 56 29 14 +58 6 79 21 43 + +26 28 59 55 49 +48 91 50 33 94 +78 97 43 71 17 + 0 95 93 36 80 +68 18 54 75 53 + +99 69 93 81 46 +73 66 4 96 24 +45 82 6 0 19 +83 62 58 18 27 +94 52 22 70 37 + +68 53 35 29 56 +64 8 85 99 41 +86 23 17 83 4 +28 72 50 74 19 +32 11 60 12 39 + +26 5 42 44 70 +46 86 2 28 1 +33 93 67 50 8 +36 7 57 48 71 + 3 80 45 49 15 + +66 47 14 37 52 +71 32 95 28 50 +58 1 0 51 30 +44 11 79 74 75 +46 64 26 29 13 + +25 0 44 52 11 +18 68 9 81 1 +42 41 55 63 91 +10 87 53 7 17 +90 24 49 21 99 + +12 73 26 13 98 +60 5 17 11 52 + 9 65 33 78 51 +91 99 6 8 55 +29 49 87 21 67 + +93 25 7 11 96 +22 48 46 75 90 +19 28 77 81 54 + 2 31 16 14 32 +27 36 52 5 64 + +12 26 90 61 10 +35 75 53 13 51 +50 9 5 71 15 +32 95 55 4 78 +98 48 94 19 27 + +64 75 20 77 82 +46 63 83 69 41 +44 15 73 35 61 +99 71 4 43 72 +76 81 93 23 0 + +46 49 42 7 71 +39 82 2 61 11 +87 81 67 57 85 +52 6 92 19 98 +72 76 99 45 96 + + 4 96 46 42 91 +78 2 52 22 51 +63 65 37 19 45 + 7 77 5 87 36 + 8 55 9 56 97 + +92 81 27 41 10 +93 35 39 84 57 +19 11 28 97 33 + 4 64 95 40 30 + 9 20 29 82 96 + +42 21 70 94 18 +66 15 11 79 89 +41 13 6 27 77 +56 37 3 16 8 + 4 28 24 96 10 + +36 54 66 95 53 +10 92 1 38 44 + 0 26 84 13 48 +99 6 17 34 9 +22 50 33 12 7 + +45 70 25 99 66 +77 19 28 75 93 +58 95 72 38 37 + 7 98 24 68 15 +61 29 1 55 97 + + 8 6 61 67 60 +14 53 78 4 66 +54 77 39 79 73 +88 99 41 70 26 +49 86 40 69 16 + +18 94 52 49 97 +36 38 66 5 34 +48 11 95 92 62 +58 98 33 28 76 +24 25 43 69 10 + +68 17 51 38 80 +66 85 33 7 40 +24 65 73 29 75 +45 42 0 46 5 +84 54 67 86 19 + +18 47 72 17 44 +33 66 19 50 2 +39 28 48 5 4 +97 29 30 80 67 +46 55 84 99 59 + +52 65 63 69 68 +67 25 27 46 4 +42 10 37 99 81 +29 3 93 91 96 +36 19 70 75 88 + +25 15 63 32 17 +82 61 65 34 45 +92 4 33 80 54 +55 70 20 28 8 +44 52 23 26 11 + +30 35 52 81 47 +82 33 62 97 34 +90 1 86 88 68 +36 77 18 12 93 + 9 91 43 87 24 + +93 26 16 30 7 + 9 72 58 74 10 +62 12 80 27 43 +51 40 55 3 83 +28 81 56 52 49 + +64 56 85 9 70 +93 65 50 42 89 +11 81 52 57 99 +44 8 73 45 47 +35 54 86 12 58 + + 4 63 6 17 59 +86 81 65 55 36 +16 30 34 79 20 +80 98 2 88 40 +94 23 69 28 27 + + 0 76 35 44 27 +14 70 87 63 7 +81 80 4 1 69 +33 26 73 25 18 +86 66 3 85 92 + +21 27 16 80 30 +39 79 12 24 47 +15 46 90 13 33 +28 49 36 8 34 +72 6 87 44 59 + +82 99 44 76 59 +42 53 39 47 80 +58 78 68 84 9 +97 65 74 95 14 +55 54 32 50 19 + +50 37 1 67 84 +24 68 34 41 55 +43 66 85 35 88 +58 40 71 10 32 +78 62 94 14 33 + +89 81 79 16 6 +86 91 7 31 1 +47 84 46 23 8 +66 64 48 27 69 +97 73 22 60 80 + +25 76 42 48 67 + 0 99 96 5 82 +86 8 24 28 90 +21 92 56 4 53 +74 61 15 12 50 + +67 16 88 98 0 +10 15 99 96 56 +43 51 13 58 97 +94 57 28 29 23 +40 32 4 9 17 + +86 30 2 35 46 +88 60 57 9 45 +70 3 92 80 18 +11 32 48 1 23 +12 19 74 39 6 + +62 78 16 48 74 +88 49 43 44 35 +87 51 99 17 86 +92 28 70 19 18 +25 80 50 52 24 + +64 9 77 44 31 +11 23 33 62 7 +14 53 84 41 12 +87 48 34 0 63 +71 91 78 27 29 + +49 42 54 43 98 + 7 32 51 62 40 +31 69 17 89 8 +46 5 64 10 1 +41 73 99 94 6 + +22 84 32 80 30 +99 74 60 78 10 +83 4 63 77 67 +17 44 54 6 90 +14 91 55 53 18 + +53 41 12 91 90 +23 66 67 57 11 +55 5 58 16 62 +61 44 21 95 0 +45 59 20 96 29 + +40 46 68 90 56 + 9 17 13 20 59 +76 91 51 39 99 +72 42 16 69 27 +30 52 71 3 66 + + 0 76 19 13 21 +26 72 12 27 11 +65 68 30 39 90 +22 59 49 80 52 +66 23 25 6 24 + +85 64 17 38 66 + 2 99 33 50 52 +58 42 15 86 47 +19 81 16 43 92 +28 30 59 80 36 + +53 46 30 91 5 +17 8 62 31 12 +45 52 56 41 97 +87 65 26 63 36 +58 42 86 68 92 + +72 94 25 75 15 +48 61 68 38 9 + 1 81 77 96 51 +86 82 58 89 70 +90 78 8 63 5 + +45 58 41 27 61 +44 26 18 13 72 +77 39 81 74 5 +59 76 96 42 55 +53 48 79 49 83 + +19 63 3 71 35 +46 13 1 84 30 +25 81 83 27 49 + 2 74 93 48 98 +78 34 68 29 26 + +87 3 46 88 19 +14 8 23 34 60 +90 15 75 51 74 +53 35 94 11 84 +49 12 18 1 64 + + 3 26 34 67 45 +13 85 32 21 51 +73 44 11 15 6 +46 80 35 18 64 +29 38 39 54 94 + +61 25 82 7 22 +39 87 75 81 18 +37 20 17 11 52 +91 70 35 71 30 +86 43 40 58 0 + +10 98 82 53 94 +93 29 81 45 80 +88 15 6 24 14 +25 65 84 54 59 +58 7 16 48 22 + +39 96 24 18 80 +43 29 26 87 41 +35 16 3 28 56 +12 95 42 92 38 +45 0 68 1 10 + +50 72 88 42 69 +53 37 63 43 34 +26 6 7 49 87 +66 38 28 65 18 + 5 35 80 15 59 + +30 65 33 48 97 +43 29 0 73 52 +26 35 36 28 39 +58 51 82 16 75 +12 62 55 83 19 + + 0 88 72 2 19 +91 76 10 16 97 +31 37 39 67 53 +83 54 93 5 18 +63 45 17 78 80 + +68 9 48 64 70 +61 95 81 50 15 +84 38 42 51 96 +65 29 39 41 7 + 5 2 12 23 56 + +82 97 57 86 52 +93 45 89 9 23 +41 32 61 16 2 + 0 26 71 51 28 +14 66 40 75 74 + +53 27 6 92 81 +37 45 91 78 65 +41 4 86 97 69 +40 58 26 14 28 +47 30 46 95 98 + +39 75 72 69 78 +29 31 36 23 19 +79 57 49 34 22 +87 54 77 11 26 +76 3 83 18 15 + +58 84 73 91 83 + 6 52 81 92 76 +23 18 62 66 77 +79 89 4 41 72 +59 36 13 8 31 + +81 32 67 75 44 +96 3 90 11 46 +61 1 14 2 86 +89 24 53 8 7 +26 20 18 59 42 + +71 77 24 72 43 +41 38 62 21 36 +70 10 37 60 83 +79 94 39 0 51 +73 46 98 34 50 + +96 26 95 48 17 +97 40 42 53 35 +74 67 47 22 23 +14 70 54 8 66 +52 31 63 34 1 + +96 55 84 44 10 +57 80 30 52 72 +42 40 36 41 73 +85 38 64 63 13 +47 16 8 76 94 diff --git a/day-4.scm b/day-4.scm new file mode 100644 index 0000000..ef8040c --- /dev/null +++ b/day-4.scm @@ -0,0 +1,150 @@ +(import (srfi :43)) + +; returns a list of numbers parsed from the first line of the file, +; separated by commas +(define (parse-draws file) + (let loop [(draws '()) (n 0)] + (let [(c (get-char file))] + (cond + [(char=? c #\,) (loop (cons n draws) 0)] + [(char-whitespace? c) (reverse (cons n draws))] + [else (loop draws (+ (* n 10) (string->number (string c))))])))) + +; returns numbers 0 to 9 from ascii character +(define (char->number c) + (- (char->integer c) 48)) ; 48 is ASCII's number zero + +; returns a number from two characters +; ex: '0' and '9' => 9 +; ' ' and '6' => 6 +; '1' and '2' => 12 +(define (char-pair->number c1 c2) + (if (char-numeric? c1) + [+ (* 10 (char->number c1)) (char->number c2)] + [char->number c2])) + +; returns a vector of 25 numbers +; parsed from input file where numbers are separated by whitespace +(define (read-board file) + (let parse-loop [(i 0) (numbers '())] + (if (= i 25) + [list->vector (reverse numbers)] + [let [(c2 (get-char file)) + (c1 (get-char file))] + (get-char file) ; consume space or empty line + (parse-loop + (+ i 1) + (cons (char-pair->number c1 c2) numbers))]))) + +; returns a list of vectors of 25 numbers parsed from input file +(define (read-boards file) + (reverse + (let loop [(boards '())] + (get-char file) ; consume empty line + (if (eof-object? (peek-char file)) + boards + [loop (cons (read-board file) boards)])))) + +; returns a number where bit N is set if N'th number +; in board matches given number +; bits that are already set in mark are kept +(define (mark-bingo number board mark) + (let loop [(i 0)] + (if (< i 25) + [if (= (vector-ref board i) number) + [bitwise-ior mark (bitwise-arithmetic-shift-left 1 i)] + [loop (+ i 1)]] + mark))) + +; marks the corresponding n'th bit in each board if +; an n'th element of the corresponding board matches input number +(define (mark-bingos! number boards marks) + (let loop [(board (car boards)) + (boards (cdr boards)) + (index 0)] + (vector-set! marks index + (mark-bingo number board (vector-ref marks index))) + (when (not (null? boards)) + (loop (car boards) (cdr boards) (+ index 1))))) + +; all possible bitfields corresponding to a line or column of bingo +(define bingos + '#(; lines + #b1111100000000000000000000 + #b0000011111000000000000000 + #b0000000000111110000000000 + #b0000000000000001111100000 + #b0000000000000000000011111 + ; columns + #b1000010000100001000010000 + #b0100001000010000100001000 + #b0010000100001000010000100 + #b0001000010000100001000010 + #b0000100001000010000100001)) + +; check if any bitfield represented grid of marked bingo cell is bingo! +(define (check-bingos marks) + (vector-index + (lambda (mark) + (vector-any + (lambda (mask) + (= mask (bitwise-and mask mark))) + bingos)) + marks)) + +; computes the score of the winning board +(define (score boards marks index last-draw) + (let [(board (list-ref boards index)) + (mark (vector-ref marks index))] + (let loop [(score 0) (index 0)] + (if (< index 25) + [if (bitwise-bit-set? mark index) + [loop score (+ index 1)] + [loop (+ score (vector-ref board index)) (+ index 1)]] + [* last-draw score])))) + +; returns list with the index of the board that won and the score +; #f if none won after all draws +(define (bingo draws boards marks) + (let loop [(draw (car draws)) + (draws (cdr draws))] + (mark-bingos! draw boards marks) + (let [(check (check-bingos marks))] + (if check + [list check (score boards marks check draw)] + [if (null? draws) + #f + [loop (car draws) (cdr draws)]])))) + +; returns a list without its n-th element +(define (except list n-th) + (let loop [(list list) (i 0)] + (if (= i n-th) + (cdr list) + (cons (car list) (loop (cdr list) (+ i 1)))))) + +(define (last-winning draws boards) + (let loop [(boards boards) + (prev-score 0) + (marks (make-vector (length boards) 0))] + (if (null? boards) + prev-score + [let [(index+score (bingo draws boards marks))] + (if index+score + [loop + (except boards (car index+score)) + (cadr index+score) + (make-vector (length boards) 0)] + [cadr index+score])]))) + +(call-with-input-file + "day-4.input" + (lambda (file) + (let* [(draws (parse-draws file)) + (boards (read-boards file))] + (printf "part 1: ~% ") + (let* [(marks (make-vector (length boards) 0)) + (index+score (bingo draws boards marks))] + (printf "bingo! ~a~%" (cadr index+score))) + (printf "part 2: ~% bingo! ~a~%" + (last-winning draws boards)))))