diff --git a/4/example.txt b/4/example.txt new file mode 100644 index 0000000..669a51d --- /dev/null +++ b/4/example.txt @@ -0,0 +1,19 @@ +7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 + +22 13 17 11 0 + 8 2 23 4 24 +21 9 14 16 7 + 6 10 3 18 5 + 1 12 20 15 19 + + 3 15 0 2 22 + 9 18 13 17 5 +19 8 7 25 23 +20 11 10 24 4 +14 21 16 12 6 + +14 21 17 24 4 +10 16 15 9 19 +18 8 23 26 20 +22 11 13 6 5 + 2 0 12 3 7 diff --git a/4/input.txt b/4/input.txt new file mode 100644 index 0000000..f434a57 --- /dev/null +++ b/4/input.txt @@ -0,0 +1,601 @@ +13,79,74,35,76,12,43,71,87,72,23,91,31,67,58,61,96,16,81,92,41,6,32,86,77,42,0,55,68,14,53,26,25,11,45,94,75,1,93,83,52,7,4,22,34,64,69,88,65,66,39,97,27,29,78,5,49,82,54,46,51,28,98,36,48,15,2,50,38,24,89,59,8,3,18,47,10,90,21,80,73,33,85,62,19,37,57,95,60,20,99,17,63,56,84,44,40,70,9,30 + +14 86 50 89 49 +10 85 33 46 87 +82 91 54 13 90 +63 88 75 99 79 +74 31 4 0 71 + +56 3 70 2 22 +44 63 10 95 8 +92 62 83 4 93 +74 80 5 11 68 +24 50 42 65 72 + +42 21 72 26 7 + 4 78 1 49 50 +93 43 38 71 68 +62 52 40 61 82 +31 28 16 96 18 + +46 77 11 86 64 + 4 14 61 94 30 +76 21 7 2 92 +55 1 66 45 23 +65 51 67 26 29 + + 1 89 70 73 81 +75 40 93 15 60 +11 58 37 42 26 +62 36 20 87 47 +54 35 6 23 10 + + 2 13 21 69 71 +98 59 82 7 32 +67 90 62 51 19 +84 6 23 3 17 +24 10 25 0 47 + +28 10 26 86 65 +33 18 21 6 99 +40 61 30 58 34 +29 37 78 4 83 +87 53 44 22 32 + +19 35 93 78 26 +87 99 15 75 56 +70 22 33 27 24 +58 53 83 48 8 +62 66 18 89 25 + +30 25 67 77 47 +99 0 44 40 23 +31 19 52 55 7 +65 22 12 27 71 +82 62 54 78 18 + +17 19 56 93 15 +62 30 64 68 21 +32 84 43 81 51 +61 83 52 65 58 +90 87 31 67 10 + +95 76 21 10 1 +81 30 64 51 44 +77 31 32 94 90 +58 48 11 43 37 +12 19 82 85 80 + +79 91 84 44 35 +80 6 64 0 20 + 7 36 33 17 51 +71 19 24 26 2 +75 37 25 59 11 + +48 91 17 38 16 +54 46 53 33 28 +20 6 68 96 45 +70 75 35 65 59 + 0 39 13 23 4 + +41 83 90 95 17 +67 4 23 62 93 +31 1 51 21 16 +34 14 92 66 89 + 0 78 58 80 96 + +67 2 42 36 32 + 1 62 37 65 79 +66 80 19 75 0 +17 86 94 49 54 +40 59 16 14 30 + +33 70 65 6 20 +44 22 55 81 15 +54 2 13 5 1 +93 40 97 67 78 +30 75 96 41 7 + +40 96 24 19 32 +88 58 65 34 52 +38 49 50 5 35 + 4 13 2 22 26 +46 55 18 89 33 + +64 17 54 59 16 +22 97 91 83 87 + 0 3 85 92 43 +99 31 19 73 4 + 8 41 68 48 75 + +37 45 16 50 57 +31 14 32 77 60 +90 63 3 40 8 +96 6 56 95 2 +80 69 61 52 24 + +84 50 31 7 40 +32 58 47 51 70 +59 76 44 83 72 +87 52 77 10 81 +57 1 12 37 73 + +14 74 7 98 95 +78 47 1 22 96 +45 80 92 37 21 +15 10 33 73 63 +29 34 51 27 31 + +76 21 26 20 22 +89 58 37 91 38 +59 9 74 24 96 +80 69 30 7 0 +70 87 16 78 49 + +69 79 75 99 65 +20 48 61 29 67 +31 86 90 72 57 +62 83 94 74 1 +34 13 55 56 36 + +54 52 66 15 29 + 7 16 94 62 92 +50 80 6 24 58 +96 13 93 1 0 +65 3 12 44 76 + +45 43 51 92 86 +60 70 3 23 69 +63 78 30 66 48 +17 74 81 75 37 +79 53 25 28 15 + +69 60 98 68 37 +18 39 36 48 75 +50 3 52 11 87 +57 46 63 80 41 +89 12 94 84 25 + +79 11 64 51 67 +17 47 98 57 5 +16 70 49 0 83 +32 56 84 73 86 +74 59 35 15 6 + + 6 94 81 28 82 +53 58 43 46 51 +17 20 18 96 41 +66 22 27 12 44 +93 40 78 26 54 + +28 88 94 9 16 +14 66 2 98 82 +23 69 44 75 10 +38 34 18 51 1 +68 52 29 0 39 + +11 45 80 94 89 +24 44 96 71 58 +97 2 46 92 12 +47 19 99 55 7 +64 62 72 23 61 + +99 92 94 38 98 +10 97 40 57 30 +67 77 7 64 23 +88 80 58 78 59 +42 69 68 16 60 + +68 74 52 73 18 +62 57 49 91 19 +21 48 51 22 70 +45 29 53 75 8 +42 17 20 47 31 + +76 29 88 23 65 +80 2 90 75 48 +93 55 10 50 81 +74 54 6 89 18 +27 26 84 11 78 + +69 39 34 79 12 +72 96 80 68 44 +27 57 99 61 64 +81 63 6 25 95 + 8 32 15 74 35 + +40 38 2 63 21 +28 57 90 19 49 +68 75 11 24 44 +45 50 15 27 9 +31 30 52 33 36 + + 4 55 11 83 95 +35 0 30 25 45 +73 31 94 22 28 +91 19 50 54 47 +14 90 71 98 23 + +31 55 45 78 67 + 1 24 51 25 80 +85 96 46 87 64 +37 93 22 59 90 +69 70 50 17 53 + +20 66 46 83 91 +28 57 99 63 1 +17 59 54 47 55 +50 10 41 53 34 + 3 39 97 9 38 + +58 29 70 23 95 +96 67 84 59 45 +35 64 63 77 52 +31 14 33 12 78 +17 36 98 0 71 + +83 68 7 9 75 +13 39 5 99 73 +82 60 14 8 63 +49 86 67 56 91 +62 52 36 1 29 + +24 65 75 31 63 +48 72 14 70 0 +85 30 42 33 87 +26 8 29 4 96 +93 60 74 9 50 + +16 98 31 91 43 +90 76 97 18 70 +67 2 45 41 58 + 7 8 26 62 61 +72 21 63 69 17 + +15 28 96 16 24 +45 41 62 89 67 +57 4 80 23 3 +29 51 99 94 68 +56 37 81 54 63 + +61 81 6 46 77 +28 43 63 10 41 +76 12 82 23 13 +32 47 94 96 92 + 7 29 69 22 64 + +68 64 51 69 96 +76 18 88 43 55 + 8 91 73 83 54 + 0 35 94 20 97 +50 29 82 71 75 + +28 56 92 79 36 +18 85 35 25 26 +51 54 53 21 59 +64 19 17 14 30 + 9 84 5 93 46 + +58 3 5 76 57 +55 64 79 16 97 +14 59 93 24 60 +84 49 44 69 15 +87 42 43 25 18 + + 5 90 79 46 80 +41 56 93 15 50 +53 25 95 39 0 +77 89 40 17 92 + 9 73 85 28 42 + +20 85 78 73 74 +59 12 82 24 52 +55 33 11 28 60 +15 25 61 16 45 + 3 14 39 95 92 + +82 94 47 30 79 +38 87 15 31 45 +69 63 98 72 1 +77 39 96 81 92 +16 71 80 86 2 + +38 60 28 94 24 +40 46 67 22 34 +39 70 71 3 96 +27 54 41 69 18 +23 62 1 61 84 + +74 85 15 44 11 +39 92 43 79 1 +82 8 26 9 57 +20 93 18 97 31 +67 81 17 21 13 + +54 63 83 89 51 + 0 8 15 25 59 +95 74 18 28 98 +50 3 34 23 77 + 4 24 61 90 88 + +11 64 61 28 27 + 5 35 74 75 47 +69 84 17 62 9 +40 21 32 73 67 +92 36 12 51 26 + +35 50 7 26 36 +43 56 42 41 48 +59 54 91 55 33 +37 13 19 20 88 +22 21 51 4 69 + +93 48 8 94 6 +14 34 13 10 32 +64 90 92 23 15 +63 95 85 28 87 +38 5 91 75 24 + +94 68 32 85 10 +75 33 0 52 37 +82 8 24 58 93 +49 73 63 44 61 +71 50 16 88 72 + +93 71 54 20 51 +39 92 75 79 66 + 6 58 52 22 63 +74 53 99 16 61 +29 96 11 83 24 + +32 26 10 77 16 +31 92 58 44 79 +17 2 72 29 8 +93 38 9 15 3 +50 89 61 88 81 + +95 65 70 27 79 + 4 19 30 86 72 +80 61 68 74 49 + 7 5 77 14 53 +98 44 51 43 93 + +59 70 44 52 14 +31 82 9 55 13 +15 63 99 26 61 +34 48 23 56 41 +97 79 28 29 93 + +26 86 35 66 67 +25 39 48 45 69 +44 93 13 17 81 +70 89 54 62 68 +41 36 90 83 12 + +92 59 53 11 83 +43 70 30 8 66 +46 6 31 56 90 +62 20 65 94 34 +67 96 47 71 17 + +34 85 72 51 46 +21 6 44 64 27 +79 86 29 33 35 + 7 87 47 94 84 +62 90 58 80 73 + + 7 73 50 0 35 +77 6 33 89 94 +71 52 95 53 8 +22 9 46 49 75 +45 56 96 87 67 + +85 64 44 39 57 +90 30 15 35 54 +78 89 55 99 12 +80 96 20 50 45 +56 10 71 59 17 + +66 87 77 71 45 +79 65 80 11 88 +74 99 30 89 73 +58 78 64 85 20 +10 41 1 44 49 + +38 47 3 60 27 + 8 10 14 4 1 +92 24 46 16 95 +55 69 77 7 36 +15 51 13 58 76 + +61 3 71 38 46 +34 93 42 90 32 +99 16 73 55 6 +48 23 56 12 39 +22 87 51 70 89 + + 8 58 99 23 56 +91 62 68 57 32 +46 95 21 3 75 +35 51 33 7 74 +26 2 89 76 48 + +93 89 88 49 55 +11 29 72 27 35 +45 5 46 18 65 +23 32 30 97 42 +76 19 22 77 78 + +17 43 19 2 42 +20 26 36 68 75 +38 94 37 99 93 +62 46 1 45 89 +59 7 92 78 22 + +75 41 53 45 7 +91 55 40 31 36 +29 78 90 17 57 +63 20 77 67 42 +64 62 11 48 84 + +26 89 27 47 91 +15 9 18 62 28 +31 96 42 81 86 +11 52 20 93 38 +83 64 39 1 60 + +99 48 86 72 92 +38 32 62 18 17 +93 71 76 73 64 +26 36 74 52 68 +24 98 34 88 45 + +18 84 79 52 42 +54 10 33 90 64 +35 1 78 62 65 +22 48 87 72 50 +56 3 49 20 63 + +14 50 79 84 49 +17 46 66 80 87 +97 90 24 65 73 +25 30 94 72 99 +78 89 81 96 28 + + 7 24 96 54 86 + 4 56 83 32 27 +29 91 73 34 45 +16 70 1 39 3 +94 47 44 42 87 + +44 74 52 65 22 + 5 46 75 27 12 +25 24 43 21 42 +19 80 60 97 3 + 8 84 9 87 94 + +62 80 7 66 82 +60 79 45 1 75 +55 54 85 64 96 +65 6 16 27 38 +77 26 74 71 91 + +55 23 59 47 62 +53 92 34 96 58 +38 3 88 46 60 +50 56 83 39 80 +37 6 93 7 94 + +56 26 45 73 16 +37 30 74 44 64 +53 70 29 21 49 + 4 5 27 92 22 +36 8 63 50 69 + +70 83 15 22 56 +64 98 32 39 12 +82 21 73 19 14 +44 61 78 26 99 +76 24 81 38 85 + +56 55 64 39 19 +13 70 63 32 54 +85 22 14 27 73 +25 89 15 44 21 +29 77 79 23 10 + +84 27 63 34 5 +57 81 78 90 59 +35 85 51 54 48 +92 4 89 70 30 +97 0 7 86 26 + + 4 44 88 71 6 +80 23 19 55 57 +91 7 18 27 95 +85 13 66 8 34 +63 45 77 17 84 + +58 7 56 38 48 +92 97 50 80 54 + 5 8 17 49 23 +96 82 20 74 4 +90 0 59 93 30 + +44 97 88 33 11 +18 69 4 0 94 +13 57 24 9 53 +49 7 68 15 42 +25 39 52 6 98 + +31 65 59 74 12 +22 39 13 2 16 +44 46 90 60 93 +82 9 71 99 89 +23 80 35 51 41 + +47 30 75 73 22 +62 87 59 42 90 + 9 5 41 54 32 +71 25 46 24 12 +53 28 77 33 76 + +36 25 2 74 29 +58 34 44 94 83 +16 72 69 45 28 +88 0 86 14 49 +10 56 24 82 73 + +27 42 83 51 61 +93 77 33 49 46 +23 5 41 48 90 +81 10 3 16 1 +84 36 40 88 54 + +60 85 7 28 39 +54 11 4 18 84 +63 95 62 13 82 +93 33 40 16 55 +34 78 29 56 66 + +51 99 73 14 69 + 3 65 23 60 96 + 1 49 78 55 25 +15 66 11 42 87 +48 52 56 34 38 + +60 59 65 32 73 +68 76 35 75 42 +72 70 45 34 38 +29 84 28 62 43 +49 85 31 57 23 + +42 57 40 73 32 +70 79 80 11 67 +55 26 87 92 19 +63 58 78 29 77 +17 74 18 20 60 + +84 99 72 74 62 +15 14 50 57 77 +48 91 55 46 82 +85 27 33 21 54 +45 31 43 40 60 + +73 37 66 67 19 +16 79 15 45 89 +84 78 69 28 46 +17 4 12 95 87 +49 99 31 9 36 + +61 34 98 60 74 +30 95 33 46 64 +73 97 12 26 7 + 2 58 49 70 54 +80 55 94 91 11 + +27 5 3 62 49 +38 88 40 9 47 +29 59 94 74 12 +48 73 85 97 35 +28 25 30 14 83 diff --git a/4/solution.hs b/4/solution.hs new file mode 100644 index 0000000..11d0e7b --- /dev/null +++ b/4/solution.hs @@ -0,0 +1,74 @@ +import Data.List +import Debug.Trace + +main :: IO () +main = readFile "4/input.txt" >>= print . solve . parse . lines + +type Input = ([Int], [Board]) + +parse :: [String] -> Input +parse (l : ls) = (n, b) + where + n = map read (words [ if c == ',' then ' ' else c | c <- l ]) + b = parseBoards (filter (/= "") ls) + +solve :: Input -> (Int, Int) +solve input = (f input, g input) + where f = uncurry winBingo + g = uncurry loseBingo + +parseBoards :: [String] -> [Board] +parseBoards [] = [] +parseBoards list = Board (map (map (Unmarked . read) . words) a) : parseBoards b + where + (a, b) = splitAt 5 list + +newtype Board = Board [[Cell]] + deriving + Show + +data Cell = Unmarked Int + | Marked Int + deriving + Show + +hasWon :: Board -> Bool +hasWon (Board b) = completed b || completed (transpose b) + where + completed = any (all isMarked) + +isMarked :: Cell -> Bool +isMarked (Marked _) = True +isMarked _ = False + +winBingo :: [Int] -> [Board] -> Int +winBingo (n : ns) (b : bs) = + if any hasWon r + then score n $ head (filter hasWon r) + else winBingo ns r + where + r = iter n (b : bs) + +loseBingo :: [Int] -> [Board] -> Int +loseBingo (n : ns) [board] + | hasWon b = score n b + | otherwise = loseBingo ns [b] + where + [b] = iter n [board] +loseBingo (n : ns) (b : bs) = + loseBingo ns (filter (not . hasWon) r) + where + r = iter n (b : bs) + +iter :: Int -> [Board] -> [Board] +iter n (b : bs) = callNumber n b : iter n bs +iter _ [] = [] + +callNumber :: Int -> Board -> Board +callNumber n (Board b) = Board (map (map mark) b) + where + mark (Unmarked x) | x == n = Marked x + mark v = v + +score :: Int -> Board -> Int +score n (Board b) = n * sum [ x | c <- b, Unmarked x <- c ]