ecdb89564123

Merge
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sun, 05 Dec 2021 11:43:10 -0500
parents 17eacdbd1e81 (current diff) a3ef349dfdd0 (diff)
children dd27f6b2d778
branches/tags (none)
files

Changes

--- a/advent.asd	Sun Dec 05 11:43:05 2021 -0500
+++ b/advent.asd	Sun Dec 05 11:43:10 2021 -0500
@@ -33,6 +33,7 @@
                :md5
                :named-readtables
                :pileup
+               :safe-read
                :split-sequence
                :str
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/2021/03.txt	Sun Dec 05 11:43:10 2021 -0500
@@ -0,0 +1,1000 @@
+011110111101
+110010010001
+111011111111
+110011010100
+111100000011
+010101001001
+010101000010
+100111101000
+110110101110
+001001101000
+101100100110
+101001100110
+101110000110
+011111111100
+110010000101
+000011111001
+101000110001
+100111011101
+011011011011
+111100000100
+010100101100
+110010000110
+101000001101
+010100110011
+111101101100
+100101000011
+101000100111
+111010010000
+011111000110
+110100101010
+011010000000
+101110100111
+010000001000
+001111001010
+001011101011
+100001110010
+001100100100
+111110011110
+000011101011
+101100111011
+000000101011
+101000000100
+001000101011
+110101000111
+011010111011
+100011101011
+110101011000
+001110110010
+100011101110
+001101011001
+000101100100
+010000101100
+100010001100
+100101001010
+011010110001
+111001110110
+111101111101
+000010011000
+110100111000
+011010000100
+000000010110
+100000001001
+110101101001
+111010100001
+101011110000
+110100101111
+010000010110
+111010110100
+011110010110
+001100001111
+001110001110
+111001110101
+010111000110
+101111001101
+010011010011
+000001110101
+101100010001
+111101110011
+101000010101
+100110011001
+010101011101
+111111101110
+010011010010
+110000101111
+100101111001
+011110100110
+111100110000
+100000111000
+011010011111
+101001101110
+110001110111
+101011001111
+010101110010
+000110001100
+101110011011
+000111111100
+001001011110
+010000100101
+110110111101
+001000011001
+011011110101
+100000001011
+010110000011
+110011001100
+110000110010
+111000110111
+110000001000
+011110101001
+001111101010
+001111000111
+100010100010
+001001010100
+001101101001
+000011000011
+101010101101
+101101011000
+000010001000
+011101110101
+000001011110
+001000101001
+000110000000
+100010111011
+001111111111
+001101110101
+001101100100
+101000011110
+010001010101
+111011010000
+000011011101
+101101001010
+010000110001
+111110011000
+110011100111
+000110111100
+010110001101
+010100010100
+101010100001
+011010111001
+010001100100
+010100111011
+010010010111
+011100011011
+101110110111
+011111101000
+101110001101
+001001100111
+101100101010
+100001010101
+100101000101
+101000000011
+110000101110
+001000111000
+011100000000
+101100111110
+000100101001
+010100111111
+000101110000
+101111100010
+110011101110
+011001000100
+111001001000
+000001111010
+100100010011
+101010101001
+010110010000
+110011110111
+101000010000
+100000101010
+110010011010
+001001001111
+001011011000
+011101100110
+100101101010
+110010111100
+110000100100
+010010001100
+010011010101
+110011000010
+101111110010
+001011010001
+001011001010
+100000001010
+000110010010
+000111101111
+110011101100
+110100110010
+100100010100
+010001100010
+001101101111
+111110110001
+111101000101
+000101101111
+000100110100
+001000111011
+011000111000
+101000011001
+110110110000
+111111111010
+000000001010
+000010101010
+001000001001
+101001100101
+001001000101
+101111110111
+101101001100
+001110111011
+101000111101
+010100000000
+110011011011
+000110100001
+100110111010
+000011100001
+010000010111
+110111011100
+111100001011
+001111011001
+000011011100
+111110011011
+010110000010
+001000010100
+011110011110
+111100001101
+110011100101
+011111110000
+100111011010
+000000111011
+111111001010
+010100111100
+000101111000
+110010011111
+110111101001
+100011000001
+111001100010
+100101000001
+010111111101
+110010110001
+001101001001
+100101101001
+011000110101
+101110011001
+101111101010
+100111010001
+011100111000
+001100000111
+001110011110
+010010000101
+010010110001
+111010001101
+000010110001
+010110101110
+011111111000
+100000101001
+111101011101
+000001010100
+000011001011
+110000011100
+000011001110
+110101010110
+011000110011
+000111111000
+100000110000
+001010101010
+001001101001
+011101011011
+100011110000
+111011011000
+111101110100
+000001010110
+100011110100
+101101000010
+000011011011
+101011110110
+100001101011
+010111100000
+000011000010
+000111001111
+011001100100
+110110010010
+000011110111
+101001001011
+010110110101
+001100000110
+000111101110
+110011010011
+101001010010
+010011110100
+110101011010
+101100101011
+101110010110
+010000000011
+010001101001
+101010011110
+010101100001
+100100000110
+000010010111
+101100101110
+000111000001
+110100111111
+010011100000
+011101110000
+011111011110
+101011011110
+100011110010
+001100011100
+011010010111
+101010011001
+110100100110
+001011100111
+001001101110
+010001001000
+101111100100
+101011010001
+100101100001
+010000101001
+000100000011
+101011101000
+000001100101
+110001101111
+001110000111
+010010000110
+101001101101
+100110011000
+100110000110
+000000110010
+000111100001
+001000101110
+110000000111
+110011101111
+101110010010
+110010001110
+101111011010
+000001000000
+110010100111
+100111010111
+001100101111
+001110111001
+111100011100
+011000010100
+100101101101
+100001001110
+111110100011
+101111001000
+010111000100
+110001110010
+001110101111
+101000000111
+010001010111
+000000000111
+010001111100
+011100000110
+010100010000
+101000010001
+101110000100
+111111110001
+110000001101
+111001111111
+000100011111
+111001101000
+001011111111
+110100001011
+111011000001
+001111101101
+101011110100
+101010110010
+101111110011
+011100100100
+001101011110
+000100001011
+100001011101
+101000010110
+001011110111
+110101000101
+011011011110
+001010000001
+000111000010
+100101001001
+000001110010
+110100010011
+111100101101
+100111011001
+000110101111
+101010000100
+011101011000
+001110000010
+001000111101
+110000011000
+010010010110
+100101011000
+000010010100
+110001101010
+101010000110
+111111010010
+001111001000
+110100101001
+010001000001
+001111110010
+110001011011
+111100000001
+011011110111
+111001001111
+110010000100
+100101111011
+001000111001
+111010001010
+101100100100
+101000111110
+000100101110
+111000101001
+001001010110
+100100101101
+111111011100
+111001110011
+011111001100
+101010101100
+000011010001
+110111001110
+010100000111
+110011100000
+101001000010
+000111101001
+010100011111
+011101001001
+100110010010
+100110101010
+010001110010
+011101000101
+001111100010
+011010111111
+110110001110
+010010010000
+101100110011
+111111011101
+000011000101
+100000111100
+111101010011
+100111010011
+110010011011
+000011111100
+011110011000
+101100000101
+111110000011
+100100001011
+000010011001
+111000011101
+111000110101
+110010100010
+101001010100
+010001110011
+001101001011
+010000101111
+111011100000
+000110000111
+000011100000
+000101011101
+000101100001
+011100100000
+011100001011
+011110111011
+111110010010
+111000010110
+000110001110
+111100011001
+010110000110
+000001010111
+100001111001
+100111100001
+011000111011
+111111101001
+001000000001
+001101100011
+111101010100
+001101110001
+110100111011
+000111011010
+000111110100
+010100000011
+010001110101
+101100000011
+110011111000
+010010101001
+101111011100
+101101101101
+111110000100
+001011000000
+010100001110
+001001011011
+011000011101
+110111110101
+101010010111
+110101000010
+111111000000
+101010101110
+101100110101
+100110001011
+011010110010
+000010110010
+000101001001
+000011110011
+101010111111
+011000101101
+111001100101
+000110101001
+110100000001
+110010000001
+111011011110
+101110110101
+000001111001
+100100011011
+011111111001
+100111101110
+101010010011
+000010110000
+011110111010
+000011110100
+101010010001
+110000011001
+100100110010
+100110100110
+110000110001
+100111010100
+000111011100
+110001000100
+011000010010
+101111111110
+011100011100
+000001001110
+111101101000
+110011001011
+010001000110
+000111000000
+000001001001
+100100011100
+101111011101
+000111001001
+010001011111
+001100100101
+011101000100
+011001110101
+100111100110
+010110000100
+111011100011
+110000011010
+011000101111
+100010100011
+111101001111
+000111010110
+011001110000
+101101011011
+010011000111
+110001101100
+000100001110
+110101111000
+111100001110
+100101011110
+111011101110
+110010101111
+110111101101
+110100011001
+000111111111
+011001101110
+001100010000
+110011110000
+011010110101
+011110111100
+100001110000
+110101101110
+000010001100
+011001101100
+100000110110
+100111110111
+101110001100
+010101000011
+110001110001
+011001011001
+011001111001
+111010011001
+110011011010
+001011011110
+111000000100
+101110111001
+110000111010
+101010110101
+110001011111
+011001011111
+101110010101
+010110110111
+010101100101
+010111111000
+010000011101
+100111010000
+100001111101
+001101111010
+001000000011
+010110111011
+010001110111
+000011001000
+110001111010
+111101001001
+110000000100
+111100001000
+111010000110
+000100011110
+110101101011
+001011110100
+011101011001
+110101010100
+110010011001
+100101001111
+100110110100
+000101001101
+001011101110
+101000001010
+001100101010
+100010011011
+100011100001
+000101011111
+111001100110
+101110101011
+111101111100
+001000001010
+001100010100
+111010100111
+000101110001
+001010100001
+001111110110
+110110101000
+110110000110
+011110111110
+100111110001
+011000001110
+110101010011
+010110001110
+111110010001
+100101111000
+001111100101
+110011001010
+111101010010
+111111000011
+001100101011
+100001101100
+100001110110
+110000000001
+000101001011
+111111110111
+000100010000
+101010110011
+111001101011
+010111100010
+001000011011
+010010110011
+001010111101
+010011011011
+011110000001
+010101011111
+001011101100
+010000010000
+111001100111
+111001010011
+111000111010
+001100011110
+010111011101
+010110000111
+010101100010
+011110011100
+100101000111
+011010000111
+000101010111
+100101001100
+011010110011
+011000011110
+010011110101
+111000101111
+111010101111
+101111010110
+100100101000
+101011111100
+100001001000
+000100010101
+001001100000
+110100100001
+100011110001
+101110110110
+110011000100
+011001000101
+111001110111
+111011010110
+101110110010
+100110111001
+110101011011
+110110000011
+000111101101
+100011010010
+111000100101
+010001100000
+010011111001
+010101010101
+110011110101
+100000100110
+110010101000
+000100110101
+010010110111
+111000001001
+001011111011
+010000111001
+111011001110
+011101110110
+010001111001
+111001111110
+101010101111
+101111111101
+110011101010
+010011000110
+101001111010
+101110000101
+000010000110
+111110000111
+001010111011
+010110011111
+001011101101
+011101011110
+000010000010
+101011010011
+011100011000
+111000100011
+011111011111
+110000001010
+000100000100
+101010111101
+110000111000
+001100110000
+111111011010
+110100110000
+000000000000
+101001000000
+110010110101
+011011001100
+101101101110
+010110100011
+101111000000
+111011100101
+110100100010
+010111000001
+110110011000
+011101111110
+000010110110
+111000000011
+001101110010
+100000110011
+000110000011
+100111110000
+011110110011
+111010101010
+010010001011
+101111000110
+001010000011
+101111010000
+011000111001
+001001111101
+010100011001
+000000010011
+001111001001
+011000010000
+011001111111
+100010101001
+010000100011
+111111101101
+011011001000
+011001010011
+111011011001
+010001110110
+110010110000
+000000000011
+110110000000
+011101001101
+011010000101
+101011100110
+001101010010
+100000000100
+100100010001
+100110011111
+111100001010
+001100011111
+000100000110
+011011010010
+011010001100
+011111101011
+011010101001
+110111000110
+110000110110
+011110110000
+010011011101
+010011100100
+000110111001
+111011111001
+101111010010
+011000111100
+101111111010
+110011000001
+000100011000
+110101110100
+011001101010
+100011011101
+001011110011
+110010111110
+000110001101
+111011101001
+100110100001
+101011011010
+001000101010
+101011100111
+110110000001
+100100000010
+101100010011
+111001010101
+011100000101
+100010111100
+010110100010
+100100110001
+100111001001
+011101010010
+101101111000
+111100100111
+111011001000
+100111011111
+111001100001
+010001111011
+011110100100
+111111010101
+101011111110
+110101101100
+000100101111
+011110001000
+101101001110
+001111111010
+110011100110
+110110011100
+111111100000
+000000010001
+100100001101
+101000101110
+100001011010
+100011000100
+110011110110
+000000110100
+010110001010
+101000110000
+110110001001
+000001000101
+011111100111
+000011110101
+101111010101
+010101001111
+110111001111
+101001110010
+011001010111
+101000101010
+100100000111
+100011001011
+110010000000
+001000110001
+100010001101
+010001000010
+101101111111
+111001001011
+101001011100
+000100111100
+110000000101
+101010011101
+000101000111
+111000101100
+001100000100
+010010100101
+011010100010
+111000100110
+001001111010
+101001001111
+011000100011
+011000001100
+011110101111
+111011111110
+101001001010
+010000001111
+000000000101
+000111001010
+100001000111
+111101010001
+010011001111
+001110010000
+101101001001
+000110110111
+001101011011
+111100100010
+101010001000
+001001101100
+011110001101
+000101000011
+111101100111
+100110000010
+111010100101
+011010011110
+000000101000
+001011001000
+001001011010
+011100000100
+000011010101
+111110011100
+001101110110
+100011101111
+011001110010
+011100100111
+010101001100
+000101010000
+101001101001
+100101110111
+101101100110
+000101100010
+111011000011
+010010010011
+000111111110
+010101100011
+000001010010
+111100110010
+101011001010
+010110011110
+011001101111
+011100001010
+001111001100
+000110100011
+101011101010
+011111111110
+100011011011
+101010011111
+010001110001
+100010101101
+010101010011
+100001010001
+111010011000
+011110100010
+001111000101
+111101101010
+011110100000
+111110001101
+110010010100
+000001010011
+000100101100
+111000111111
+011111000011
+010000011001
+000110001011
+111100101110
+001000110101
+001011111100
+001111010001
+101000100101
+000101001100
+000110101010
+010010011111
+111101001000
+101110110011
+111100100110
+101010101011
+101010101010
+100000111001
+000101000001
+100010010101
+011000101000
+100100001111
+110111100011
+101100000000
+001011110001
+110011001111
+000001000011
+001100111011
+101100010000
+001111000001
+111100000101
+101010111011
+011111110010
+011111010001
+101011010100
+000111111011
+110000100110
+110111110000
+100101101110
+001011000001
+101100001101
+011100010010
+000110100110
+010101110111
+111100101011
+101101001101
+011011111110
+011100011001
+110010011100
+000001011100
+101110100110
+010001011100
+011111001010
+100111100101
+111111000010
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/2021/04.txt	Sun Dec 05 11:43:10 2021 -0500
@@ -0,0 +1,601 @@
+31,50,68,16,25,15,28,80,41,8,75,45,96,9,3,98,83,27,62,42,59,99,95,13,55,10,23,84,18,76,87,56,88,66,1,58,92,89,19,54,85,74,39,93,77,26,30,52,69,48,91,73,72,38,64,53,32,51,6,29,17,90,34,61,70,4,7,57,44,97,82,37,43,14,81,65,11,22,5,36,71,35,78,12,0,94,47,49,33,79,63,86,40,21,24,46,20,2,67,60
+
+95 91 54 75 45
+46 94 39 44 85
+31 43 24  2 70
+90 58  4 30 77
+13 26 38 52 34
+
+68 14 99 63 46
+67 16 82 10  8
+55 52 41 51  4
+90 17 32 44 74
+89 94 73 56 36
+
+ 6 91  2 28 71
+ 7 88 37 21 36
+95 32 84 57  8
+13 79 89 75 48
+47 81 66 17  5
+
+44 55 48 16 41
+35  5 43 53 11
+ 0 79 19 82 49
+30 85 31 72 39
+27 68 65 66 95
+
+ 6 46 55 24 40
+87 16 62 11 64
+ 8 49 18 59 91
+72 28 48 19 96
+39 73  9 88  0
+
+46  1 18 93  6
+50 96 41 81 58
+62 66 49 32 55
+29 11 65  2 10
+71 30 17 69 43
+
+84 57  6 56 95
+39 15 32  1 10
+55 43 40  3 22
+89 54 13 80 38
+72 12 59 71 77
+
+ 3 51 72 88  6
+56 64 99 82 36
+75 81 42 67 24
+41 79 35 40 73
+ 2 14 61 50 87
+
+72  7  0 99 24
+29 81 92 74 38
+84 53 20 56 91
+93 64 44 48  2
+37 40 88 96 97
+
+39 87 99 75 38
+45 81 46 72 62
+40  8 24 67 79
+96  1 77 73 70
+34 13 55 83 59
+
+18 38 55 84 58
+35 97 31 26 44
+80  1 28 71 85
+45 46 10 32 99
+60 48 72 11 53
+
+53 44  6 30 82
+65 64 10  0 86
+81 50  5 21 60
+16 19 97 66 73
+20 24 96 68 69
+
+33 85 88 58 20
+19  2 99 40 70
+69 10 17 67 23
+48  9 29 34  3
+89 30 43 41 94
+
+30 83 37 14 78
+57 42 98 90 28
+ 5 82 51 15 55
+77 79 96 67 53
+22 76  0 59 47
+
+10 93 84 54 11
+59 30  6 94 75
+ 9 62 68 37 24
+61  3 66 58 74
+64  0 83 32 13
+
+24 77 15  5 49
+23 11 70 17 10
+62 33 38 36 12
+ 3 61  0 26 65
+63 47 54 50  9
+
+34 28 24 55 38
+69 37 36 32 72
+91 85  9 64 68
+94 22 96 90 82
+30 20 97 19 56
+
+35 90 58 93  2
+72  8 27 88 16
+25 54 69 60 61
+ 1 15  9 71 78
+89 42 46 57 91
+
+43 38 47  1 82
+19 32  2 95 51
+78 74 91 10 22
+80 77 33 60 14
+ 0 98 70 54 50
+
+71 94  3 84 31
+10 59 12 28 46
+68 69 13 48 36
+37 49 24 26 61
+72 65 38 16 25
+
+68 78 10 90 29
+40 14 45 43 44
+27 75 72 39 87
+96 93 53 12 11
+37 64 56 59 76
+
+19 78 84 68 41
+36 96 87 15 55
+47 33 10 91 85
+11 94 31 49 35
+83 63 86  4 76
+
+ 5 89 55 46 96
+67 22 95 82 56
+61 94 84 99 28
+71 70 16 57 63
+98 92 86 73 83
+
+56 24 93 88 29
+74 89 50 44 79
+97 49 87 31  8
+70  6 57  3 82
+20 25 99 48 78
+
+80 20 45 22 57
+43 35 48 44 52
+29 98 38 27 11
+64 49 84 60 31
+ 7 97 17 85 74
+
+21  1 18 41 62
+76 38 13 46 27
+ 0 16 43 28 53
+54 42 22 83 20
+ 4 25 50 11 56
+
+21 71 73 30 51
+92 27 14 16 11
+89 43 38 62 31
+65  4 36 84 94
+56 13 59 22  6
+
+46 28 45 57  6
+16 67 33 20 44
+36 86 92  3 11
+98 27 26 84 31
+ 5 76 13 65 25
+
+49 55 99 31 73
+80  0 83 26 65
+ 3 96 60 37 50
+57 34  7 20 23
+70 52 93 13 71
+
+78 41 81 32 76
+37 36 16 99 48
+ 3 93 33 85 35
+60 38 74 80 56
+86 29 87 20  7
+
+98 24  4  9 82
+22 37 52 81 30
+51 70 17 23  8
+60 61 75 35 85
+33 48 88 13 57
+
+49 52 91 21 46
+90 51 70  5 35
+57 68 31 86 87
+42 36 25 95  3
+73 64 17 96 80
+
+ 6 42 13 16 24
+51 72 55 78 47
+67 28  7 97 64
+44 77 98 71 25
+82  8 31 76 73
+
+63 79 18 80 27
+57 66 47 89 14
+15 61 94 38 29
+21 53 73 17 76
+65  7 23 36  3
+
+93 22  8 52  4
+63 31 90 46 68
+51 14 95 50 23
+17 34 60 75 36
+88 55  7  0 73
+
+42 67 91 15 83
+ 1 37 76 12 25
+29 82 50 70 86
+74 66 39 90 16
+31 71 47  5 92
+
+98 48 27 87  2
+60  0 25 30 14
+44 61 94 82 16
+17 19 53 49 59
+15 85 50 63  8
+
+63 12 52 81 97
+87 68 44 31 41
+39 24 99 27  6
+ 1 21 35 59 51
+ 4 92  3 90 62
+
+66 43 98 25 47
+59 16 75 44 82
+40 58 48 60 37
+13 81 61 45 83
+24 89 93 19 67
+
+ 8 86 47 81 83
+ 1 91 57 59 68
+ 0 52 25 93 95
+27 84 63 45 36
+39 62 20 99 88
+
+67 28 65  4 17
+44 33 12 99 84
+27 36 34  5 10
+38 63 97 82 64
+94 19 58 41  6
+
+28 41 96 16 39
+93 78 56 69 75
+74 60  9 30  7
+12 81 35 84 94
+45 20  6 49  2
+
+33  7  5 43  9
+97 65 50  2  1
+26 86 76 47 98
+83 31 30 58 52
+93 51 34 63 12
+
+65 81 10 46 59
+51 89 85  2 52
+13 54 18 70  4
+37 94 75 92 56
+58 99 91 32 41
+
+44 23 18 16 75
+ 5  3 45 76 90
+20 71 69 37 99
+49 91 43 32 82
+ 4 79 51  2 39
+
+54 80 71 61 76
+81 52  6 89 34
+58 14 20 26 40
+25 60 45  0  3
+36 33 65 41 94
+
+53 23 56 55 92
+ 3 81 59  0 35
+32 30 93 70 40
+45 91 24 65  6
+95 88 16 47  8
+
+24 23 10 47 63
+38 79 18 77 62
+13 88 72 68 36
+96 27 12 69 89
+28 94  6 98 20
+
+70  1 61 77 28
+92 22 30 48 96
+66  3 34 29 45
+85  6 17 87  5
+97 89 14 80 20
+
+40 86 97  5 54
+91 57 12 19  7
+62 88 92 20 32
+50 77 11 39 22
+33  2 21 95 35
+
+51 79 64 24 28
+95 19 82 58 76
+69 30  9 14 42
+27 16 56 80 83
+52  5 49 43 45
+
+26 65 68 18 55
+58 83 30 48  4
+69 42 78 96 22
+91 13 82 38 41
+67 33 10 98 53
+
+74 97 43  1 18
+49 30 28 10 15
+42 12 80 20 96
+41 92 67 22 36
+ 5 26 13 47  4
+
+85 60 72 19 48
+61 21 43 34 83
+51 75 94 11 78
+27 89 45 49 79
+97 15  5 28 50
+
+69 99 97 77 98
+37 80 86  7 34
+85 28 31 23 16
+32 47  8 40  4
+46 91 71 54 74
+
+23 43 29  7 21
+58 34 42  4 38
+64 96 16 73 49
+36 92 52 81 31
+85 71 78 13  5
+
+65 71 46  5 11
+24  4  6  0 23
+13 17 76 15 34
+27 79 10 56 85
+90 19 30 94 78
+
+81 40 65 12 35
+23 93 24 96 53
+27 60 87 59 33
+76 56  4 17  6
+78 49 90  3 80
+
+ 7 25 42 85 39
+40  6 26 11 63
+48 20 62 61 89
+78 15 18 21 53
+69  4 87 47  5
+
+38 65 87 72 26
+88 75 10 30  3
+89 58  7 20 32
+85  2 97 63 15
+28 77 82 57 64
+
+16 89  6 31 27
+45 69 61  5 15
+40 75 64 94 98
+36 18 26 58 90
+10 44 59 13 67
+
+80 13 39 49 42
+50 94 12 14 88
+97 48 15 68 69
+21 18 51 99 91
+89 64 35 63 84
+
+81 96 26 43 30
+ 5 74  9 93 60
+63 41  1 14 22
+ 4 77 33 53  3
+38 90 50 25 10
+
+58 66 17  0 16
+ 5 67 41 48 40
+43 93 76 95 68
+ 4 13 14 51  8
+56 74 23 57 94
+
+18 15 92  4 20
+69 26 84 23  2
+72 35 56 96  9
+61 41 85 91 25
+13 70  1 14 77
+
+15 20 77 80 47
+45 34 63 55 75
+65 12 66 44 22
+74  3 25 38 93
+ 9 31 68 87 67
+
+54 95 79 50 75
+18 36 20 34 43
+17 65 55 98 61
+27 46 56  6 52
+91 31 30 40  0
+
+25 30 24 64 98
+ 8 72 53 45  3
+27 77  0 33 44
+89 39 34 71 38
+54 21 20 80 23
+
+69 38 63 60  4
+55 37 83 68 61
+67 25 86 24 18
+22 59 65 28 70
+84 46 44 91 96
+
+35 27 65 31  0
+46 97 44 74  4
+56 61  7 49 88
+ 5 38 50 20 26
+62  9 45 64 51
+
+ 3 28 43 97  7
+88 57 17 82 73
+16 94 74 22 39
+84 99 31  1 47
+92 91 55 38 78
+
+60 31 29 49 72
+89 41  5 79 22
+58 28 90 76 95
+93 45 14 47 37
+65 25  7 59 62
+
+58  1 73 30 55
+95 46  5 80 63
+52 16 70 20 71
+84 60 15  0 77
+99 89 17 72 31
+
+83 21 68 18 42
+ 1 28 97 31 35
+ 2 38 67 63 74
+77 27 48 90 86
+12 52 26 29 60
+
+81 53 80 85 96
+19 32 31 15 88
+91 92 66 37 34
+74 75 33 39 78
+42 40 30 83 58
+
+40 41 80 69 67
+24 63 97 33  5
+28 84 34 72 11
+36 79 91 14 92
+55 89 59 10 44
+
+ 0 51 49 24 60
+48 65 28 70 66
+86 58 78 77 18
+ 6 44 50 37 36
+ 4 73 91 97 43
+
+66 42 76 12 48
+77 83 35 18 50
+30 87 95 99 11
+ 0 52 92 16 51
+26 56 39 64 62
+
+83 89 52 61 45
+74 77 66 59 30
+85 17 38 10  8
+97 67 54 21 26
+34 63 11 94 40
+
+93 91 14 49 38
+77 53 29 36 39
+12 52  0 48 92
+95 82 71 76 37
+19 70 75  9 74
+
+80 49 59 67 27
+43 66 97 81 12
+10 77 24 75 68
+16 57 14 28 85
+41 52 23 15  2
+
+39 89 66 27 11
+63 84 21 44 69
+56 51 58 70 83
+14  0  8 41 31
+98 18 61 97 74
+
+97 18 63 29 24
+75 73 80  8  7
+81 37 46 93 68
+57 32  2 41  5
+ 4 65 88 45 54
+
+87 26 81 12 50
+19  9 68 23 71
+74 38  4 34 16
+18 99 86 45  7
+35  8 11 98 57
+
+13 31 78 59 58
+51 61 96 68 44
+41 85 26 55 92
+11 62 30  7 64
+18 19 73 27 17
+
+48 85 71 39 29
+33 79 24  0 72
+95 52 12 77 40
+70 31 46 44 43
+61 88 73 49 65
+
+60 81 51 24 27
+23 28 47 85 67
+35 57 45 76 84
+19 48 30 37 74
+15 78 56 87 16
+
+12  5 45 26 21
+ 1 71 51 10 25
+37 68 73 46 56
+55 20 63 87 91
+22 32 66 90 19
+
+20 59 12 29 97
+92 30 77 27 49
+14 98 23 50  6
+11 47 61 34 36
+55 82 13 22 21
+
+29 37  0 40 71
+ 2 43 97 18 59
+32 72 89 99 24
+58 90 73 60 85
+69 53 95 78 27
+
+58 28 32 52 55
+86 33  1 41 60
+ 8 53 42 92  5
+43 69 96 54 24
+74 10 17 89 85
+
+51 74 99 21 64
+54 27 60 32 37
+14 45 50 81 94
+28 11 77 17 23
+93 95 53 57 79
+
+16  5 80 45 71
+22 57  9 90 43
+ 3 52 47 59 84
+28 53 14 15  7
+50 76 46 56 34
+
+83 62 77 56 26
+82 35 11  6 51
+96 97 15  1 78
+92 45 55 84 94
+20  8 70 21 31
+
+ 4 47 68 81 12
+66 23 35  8 39
+73 94 27 69 22
+59 11 53 26 99
+ 7 20 87 60 88
+
+90  0 88 81 43
+47 54 42 29 97
+60 13 85 51 71
+56 14 94 80 41
+75  8 35 69 61
+
+51 38 40 17 42
+19 26 92 64 67
+33 66 82 27 55
+62  2 68 59 31
+ 7 24 20 91 79
+
+21 83 45 35 88
+85 11  5 86 72
+78  3 58  0 89
+67  1 39 59 63
+79 87 19  4 57
+
+25 16 40 17 27
+96 72 29 32 87
+50 63 35 81 66
+ 7 11 92 68 69
+54 83 12 51 95
+
+64 98 67 54 75
+ 8 10 31  5 57
+89 23 25 34 47
+72 74 37 48 94
+39 59 15 55 87
--- a/package.lisp	Sun Dec 05 11:43:05 2021 -0500
+++ b/package.lisp	Sun Dec 05 11:43:10 2021 -0500
@@ -3,18 +3,21 @@
   (:export
     :define-problem
 
+    :read-2d-array
     :read-all
+    :read-and-collect
+    :read-before
+    :read-chunks
+    :read-comma-separated-values
+    :read-digits
     :read-lines
+    :read-lines-of-numbers-and-garbage
     :read-lines-of-words
-    :read-lines-of-numbers-and-garbage
     :read-numbers
     :read-numbers-from-string
-    :read-comma-separated-values
-    :read-2d-array
-    :read-before
     :read-to
-    :read-digits
-    :read-chunks
+    :read-word
+    :with-eof-handled
 
     :ensure-string
     :ensure-stream
@@ -39,7 +42,7 @@
     :positions
     :positions-if
     :digits
-    :digits-to-number
+    :digits->number
     :fresh-vector
     :first-character
     :let-result
@@ -87,9 +90,11 @@
     :print-hash-table-map
     :print-2d-array
 
+    :bold
     :clear
     :green
     :reset
+    :underline
 
     :mkinput
 
--- a/src/2019/days/day-16.lisp	Sun Dec 05 11:43:05 2021 -0500
+++ b/src/2019/days/day-16.lisp	Sun Dec 05 11:43:10 2021 -0500
@@ -60,7 +60,7 @@
   (let* ((digits (coerce (iterate (repeat 10000)
                                   (appending digits))
                          'vector))
-         (offset (digits-to-number (subseq digits 0 7)))
+         (offset (digits->number (subseq digits 0 7)))
          (data (subseq digits offset)))
     (do-repeat 100
       (iterate
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/2021/days/day-03.lisp	Sun Dec 05 11:43:10 2021 -0500
@@ -0,0 +1,46 @@
+(advent:defpackage* :advent/2021/03)
+(in-package :advent/2021/03)
+
+(defun-inline bool->bit (b) (if b 1 0))
+
+(defun-inline char->δ (ch) (ecase ch (#\0 -1) (#\1 1)))
+
+(defun count-bits (data)
+  (iterate
+    (with counts = (make-array (length (first data)) :initial-element 0))
+    (for line :in data)
+    (iterate (for ch :in-string line :with-index i)
+             (incf (aref counts i) (char->δ ch)))
+    (returning counts)))
+
+(defun rates (data)
+  (let ((counts (count-bits data)))
+    (values
+      (digits->number counts :radix 2 :key (compose #'bool->bit #'plusp)) ; γ
+      (digits->number counts :radix 2 :key (compose #'bool->bit #'minusp))))) ; ε
+
+(defun find-rating (sorted-data count->target)
+  (iterate
+    (with lo = 0)
+    (with hi = (1- (length sorted-data)))
+    (when (= lo hi)
+      (return (parse-integer (aref sorted-data lo) :radix 2)))
+    (for i :from 0)
+    (for count = (iterate (for candidate :in-vector sorted-data :from lo :to hi)
+                          (summing (char->δ (aref candidate i)))))
+    (for target = (funcall count->target count))
+    ;; Could potentially bisect these instead of linearly scanning, but it's fine.
+    (loop :while (char/= target (char (aref sorted-data lo) i)) :do (incf lo))
+    (loop :while (char/= target (char (aref sorted-data hi) i)) :do (decf hi))))
+
+(defun ratings (data)
+  (let ((data (sort (fresh-vector data) #'string<)))
+    (values
+      (find-rating data (lambda (c) (if (minusp c) #\0 #\1))) ; O₂
+      (find-rating data (lambda (c) (if (not (minusp c)) #\0 #\1)))))) ; CO₂
+
+(define-problem (2021 3) (data read-lines) (3847100 4105235)
+  (values (multiple-value-call #'* (rates data))
+          (multiple-value-call #'* (ratings data))))
+
+#; Scratch --------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/2021/days/day-04.lisp	Sun Dec 05 11:43:10 2021 -0500
@@ -0,0 +1,100 @@
+(advent:defpackage* :advent/2021/04)
+(in-package :advent/2021/04)
+
+;; Cells ----------------------------------------------------------------------
+(defun cell (num) (cons num nil))
+(defun num (cell) (car cell))
+(defun markedp (cell) (cdr cell))
+(defun unmarkedp (cell) (not (markedp cell)))
+(defun mark (cell) (setf (cdr cell) t))
+
+
+;; Input ----------------------------------------------------------------------
+(defun read-bingo-numbers (stream)
+  (read-numbers-from-string (read-line stream)))
+
+(defun read-board (&optional (stream *standard-input*) (eof-error-p t) eof-value)
+  (peek-char t stream nil)
+  (with-eof-handled (stream eof-error-p eof-value)
+    (do-array (v (make-array '(5 5)))
+      (setf v (cell (parse-integer (read-word stream)))))))
+
+(defun parse (stream)
+  (values (read-bingo-numbers stream)
+          (read-and-collect stream #'read-board)))
+
+
+;; Boards ---------------------------------------------------------------------
+(defun copy-board (board)
+  (do-array (cell (alexandria:copy-array board))
+    (setf cell (cons (car cell) (cdr cell)))))
+
+(defun print-board (board)
+  (print-2d-array board :printer (lambda (cell)
+                                   (when (markedp cell) (green) (bold))
+                                   (format t "~3D" (num cell))
+                                   (when (markedp cell) (reset)))))
+
+(defun print-boards (boards &optional heading)
+  (when heading (write-line heading))
+  (dolist (board boards)
+    (print-board board)
+    (terpri)))
+
+
+;; Playing --------------------------------------------------------------------
+(defun mark-number-on-board (n board)
+  (do-array (cell board)
+    (when (= n (num cell))
+      (return (mark cell)))))
+
+(defun mark-number-on-boards (n boards)
+  (dolist (board boards)
+    (mark-number-on-board n board)))
+
+(defun winning-row-p (board row)
+  (iterate (for col :below 5) (always (markedp (aref board row col)))))
+
+(defun winning-col-p (board col)
+  (iterate (for row :below 5) (always (markedp (aref board row col)))))
+
+(defun winning-board-p (board)
+  (or (iterate (for row :below 5) (thereis (winning-row-p board row)))
+      (iterate (for col :below 5) (thereis (winning-col-p board col)))))
+
+(defun play-first (numbers boards)
+  (iterate
+    (with boards = (mapcar #'copy-board boards))
+    (for n :in numbers)
+    (mark-number-on-boards n boards)
+    (dolist (board boards)
+      (when (winning-board-p board)
+        (return-from play-first (values n board))))))
+
+(defun play-last (numbers boards)
+  (iterate
+    (with boards = (mapcar #'copy-board boards))
+    (for n :in numbers)
+    (mark-number-on-boards n boards)
+    (if (null (rest boards))
+      (when (winning-board-p (first boards)) ;; Run last board to completion.
+        (return-from play-last (values n (first boards))))
+      (setf boards (delete-if #'winning-board-p boards))))) ;; Still pruning boards.
+
+(defun unmarked-sum (board)
+  (iterate (for cell :across-flat-array board)
+           (when (unmarkedp cell)
+             (summing (num cell)))))
+
+(defun score (last-number board)
+  (* last-number (unmarked-sum board)))
+
+;; Main -----------------------------------------------------------------------
+(define-problem (2021 4) (data) (49860 24628)
+  (multiple-value-bind (numbers boards) (parse data)
+    (values
+      (multiple-value-call #'score (play-first numbers boards))
+      (multiple-value-call #'score (play-last numbers boards)))))
+
+
+#; Scratch --------------------------------------------------------------------
--- a/src/utils.lisp	Sun Dec 05 11:43:05 2021 -0500
+++ b/src/utils.lisp	Sun Dec 05 11:43:10 2021 -0500
@@ -73,6 +73,10 @@
 
 
 ;;;; Readers ------------------------------------------------------------------
+(alexandria:define-constant +whitespace-chars+
+  '(#\Space #\Newline #\Backspace #\Tab #\Linefeed #\Page #\Return #\Rubout)
+  :test #'equal)
+
 (defun read-numbers-from-string (line)
   (mapcar #'parse-integer (ppcre:all-matches-as-strings "-?\\d+" line)))
 
@@ -81,6 +85,14 @@
            (collect value)))
 
 
+(defmacro with-eof-handled ((stream eof-error-p eof-value) &body body)
+  (once-only (stream eof-error-p eof-value)
+    `(if (null (peek-char nil ,stream nil))
+       (if ,eof-error-p
+         (error 'end-of-file)
+         ,eof-value)
+       (progn ,@body))))
+
 (defun read-before (char &optional (discard-delimiter t) (stream *standard-input*) (eof-error-p t) eof-value)
   "Read characters from `stream` up to, but *not* including, `char`.
 
@@ -94,10 +106,7 @@
   invocation).
 
   "
-  (if (null (peek-char nil stream nil))
-    (if eof-error-p
-      (error 'end-of-file)
-      eof-value)
+  (with-eof-handled (stream eof-error-p eof-value) 
     (iterate
       (for c = (peek-char nil stream nil))
       (until (null c))
@@ -117,16 +126,27 @@
   invocation).
 
   "
-  (if (null (peek-char nil stream nil))
-    (if eof-error-p
-      (error 'end-of-file)
-      eof-value)
+  (with-eof-handled (stream eof-error-p eof-value)
     (iterate
       (for c = (peek-char nil stream nil))
       (until (null c))
       (collect (read-char stream) :result-type 'string)
       (until (char= char c)))))
 
+(defun read-word (&optional (stream *standard-input*) (eof-error-p t) eof-value)
+  "Read the next word from `stream` and return it as a string.
+
+  A word is a sequence of non-whitespace characters.  Leading whitespace will be
+  skipped.
+
+  "
+  (peek-char t stream nil)
+  (with-eof-handled (stream eof-error-p eof-value)
+    (iterate
+      (for c = (read-char stream nil #\space))
+      (until (member c +whitespace-chars+))
+      (collect c :result-type 'string))))
+
 
 (defun read-all (stream)
   "Read all forms from `stream` and return them as a fresh list."
@@ -139,6 +159,7 @@
   "Read all lines from `stream` and return them as a fresh list of strings."
   (read-and-collect stream #'read-line))
 
+
 (defun read-lines-of-numbers-and-garbage (stream)
   "Read the lines of numbers in `stream` into a list of lists of numbers.
 
@@ -542,20 +563,22 @@
               (nreverse result))
             result-type)))
 
-(defun digits-to-number (digits &key from-end (radix 10))
+(defun digits->number (digits &key from-end (radix 10) key)
   "Concatenate `digits` to return an integer in base `radix`.
 
   If `from-end` is `t`, start at the end of the list.
 
+  If `key` is given, call it on the digits first.
+
   "
-  (if digits
+  (if (not (emptyp digits))
     (if from-end
-      (iterate (for d :in digits)
+      (iterate (for digit :in digits)
                (for multiplier :first 1 :then (* radix multiplier))
-               (summing (* multiplier d)))
+               (summing (* multiplier (if key (funcall key digit) digit))))
       (reduce (lambda (total digit)
-                (+ (* total radix) digit))
-              digits))
+                (+ (* total radix) (if key (funcall key digit) digit)))
+              digits :initial-value 0))
     0))
 
 
@@ -837,18 +860,17 @@
   (esc "[2J")
   (esc "[;H"))
 
-(defun green ()
-  (esc "[32m"))
-
-(defun reset ()
-  (esc "[0m"))
+(defun green () (esc "[32m"))
+(defun bold () (esc "[1m"))
+(defun underline () (esc "[4m"))
+(defun reset () (esc "[0m"))
 
 
-(defun print-2d-array (array)
+(defun print-2d-array (array &key (printer #'princ) (key #'identity))
   (destructuring-bind (rows cols) (array-dimensions array)
     (dotimes (r rows)
       (dotimes (c cols)
-        (princ (aref array r c)))
+        (funcall printer (funcall key (aref array r c))))
       (terpri))))