|
1 |
| -type alias Bag = (Int32, Int32, Int32) |
2 |
| -type alias Game = (Int32, List[Bag]) |
| 1 | +@Test |
| 2 | +def test_part1(): Bool = |
| 3 | + let lines = |
| 4 | + "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green" :: |
| 5 | + "Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue" :: |
| 6 | + "Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red" :: |
| 7 | + "Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red" :: |
| 8 | + "Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green" :: Nil; |
| 9 | + let ans = List.filterMap(parseGame, lines) |> solvePart1; |
| 10 | + Assert.eq("8", ans) |
| 11 | + |
| 12 | +@Test |
| 13 | +def test_part2(): Bool = |
| 14 | + let lines = |
| 15 | + "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green" :: |
| 16 | + "Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue" :: |
| 17 | + "Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red" :: |
| 18 | + "Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red" :: |
| 19 | + "Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green" :: Nil; |
| 20 | + let ans = List.filterMap(parseGame, lines) |> solvePart2; |
| 21 | + Assert.eq("2286", ans) |
| 22 | + |
| 23 | +type alias Bag = { red = Int32, green = Int32, blue = Int32 } |
| 24 | +type alias Game = { gameId = Int32, bags = List[Bag] } |
3 | 25 |
|
4 | 26 | def parseBag(s: String): Bag =
|
5 |
| - let colors = s |
6 |
| - |> String.splitOn({substr = ", "}) |
7 |
| - |> List.map(String.breakOnLeft({substr = " "})) |
8 |
| - |> List.map(x -> (String.sliceRight({start=1}, snd(x)), Result.getWithDefault(0, Int32.parse(10, fst(x))))) |
9 |
| - |> List.toMap; |
10 |
| - ( |
11 |
| - Map.getWithDefault("red", 0, colors), |
12 |
| - Map.getWithDefault("green", 0, colors), |
13 |
| - Map.getWithDefault("blue", 0, colors) |
14 |
| - ) |
| 27 | + let cubeCounts = s |
| 28 | + |> String.splitOn({substr = ", "}) |
| 29 | + |> List.map(String.breakOnLeft({substr = " "})) |
| 30 | + |> List.map(x -> { |
| 31 | + let cubeColor = String.trimLeft(snd(x)); |
| 32 | + let count = Result.getWithDefault(0, Int32.parse(10, fst(x))); |
| 33 | + (cubeColor, count) |
| 34 | + }) |
| 35 | + |> List.toMap; |
| 36 | + { |
| 37 | + red = Map.getWithDefault("red", 0, cubeCounts), |
| 38 | + green = Map.getWithDefault("green", 0, cubeCounts), |
| 39 | + blue = Map.getWithDefault("blue", 0, cubeCounts) |
| 40 | + } |
15 | 41 |
|
16 | 42 | def parseGame(s: String): Option[Game] =
|
17 | 43 | match String.splitOn({substr = ": "}, s) {
|
18 |
| - case gameTitle :: rest :: Nil => { |
| 44 | + case gameTitle :: bagsStr :: Nil => { |
19 | 45 | let gameNum = gameTitle
|
20 | 46 | |> String.sliceRight({start = 5})
|
21 | 47 | |> Int32.parse(10)
|
22 | 48 | |> Result.getWithDefault(0);
|
23 |
| - let bags = rest |
| 49 | + let bags = bagsStr |
24 | 50 | |> String.splitOn({substr = "; "})
|
25 | 51 | |> List.map(parseBag);
|
26 |
| - Some((gameNum, bags)) |
| 52 | + Some({ gameId = gameNum, bags = bags }) |
27 | 53 | }
|
28 | 54 | case _ => None
|
29 | 55 | }
|
30 | 56 |
|
31 | 57 | def possibleBag(bag: Bag): Bool =
|
32 |
| - let (r, g, b) = bag; |
| 58 | + let {red = r, green = g, blue = b} = bag; |
33 | 59 | (r <= 12) `Bool.and` lazy (g <= 13) `Bool.and` lazy (b <= 14)
|
34 | 60 |
|
35 |
| -def possibleGame(g: Game): Bool = |
36 |
| - let bags = snd(g); |
37 |
| - List.forAll(possibleBag, bags) |
38 |
| - |
39 | 61 | def solvePart1(games: List[Game]): String =
|
40 | 62 | games
|
41 |
| - |> List.filter(possibleGame) |
42 |
| - |> List.map(fst) |
| 63 | + |> List.filter(game -> { |
| 64 | + let {gameId = _, bags = bags} = game; |
| 65 | + List.forAll(possibleBag, bags) |
| 66 | + }) |
| 67 | + |> List.map(game -> { |
| 68 | + let { gameId = gameId, bags = _ } = game; |
| 69 | + gameId |
| 70 | + }) |
43 | 71 | |> List.sum
|
44 | 72 | |> ToString.toString
|
45 | 73 |
|
46 | 74 | def minimumBagPower(game: Game): Int32 =
|
47 |
| - let bags = snd(game); |
48 |
| - let (r, g, b) = |
49 |
| - bags |
50 |
| - |> List.foldLeft((acc, bag) -> { |
| 75 | + let { gameId = _, bags = bags } = game; |
| 76 | + let (r, g, b) = List.foldLeft( |
| 77 | + (acc, bag) -> { |
51 | 78 | let (maxR, maxG, maxB) = acc;
|
52 |
| - let (r, g, b) = bag; |
| 79 | + let {red = r, green = g, blue = b} = bag; |
53 | 80 | (Int32.max(maxR, r), Int32.max(maxG, g), Int32.max(maxB, b))
|
54 |
| - }, (0, 0, 0)); |
| 81 | + }, |
| 82 | + (0, 0, 0), |
| 83 | + bags |
| 84 | + ); |
55 | 85 | r * g * b
|
56 | 86 |
|
57 | 87 |
|
|
0 commit comments