diff --git a/AOC2021.Test/AOC2021.Test.csproj b/AOC2021.Test/AOC2021.Test.csproj index 077343f..0e8762c 100644 --- a/AOC2021.Test/AOC2021.Test.csproj +++ b/AOC2021.Test/AOC2021.Test.csproj @@ -36,6 +36,12 @@ Always + + Always + + + Always + diff --git a/AOC2021.Test/DayTest.cs b/AOC2021.Test/DayTest.cs index 8b1aef5..a4ab03c 100644 --- a/AOC2021.Test/DayTest.cs +++ b/AOC2021.Test/DayTest.cs @@ -38,5 +38,13 @@ namespace AOC2021.Tests var result = _tester.Test(request); Assert.IsTrue(request.Answer.Equals(result.Answer)); } + + [TestMethod] + public void Day4() + { + var request = new TestRequest() { Day = "day4", Answer = new Answer() { Day_A_Test = "4512", Day_A_Input = "63424", Day_B_Test = "1924", Day_B_Input = "23541" } }; + var result = _tester.Test(request); + Assert.IsTrue(request.Answer.Equals(result.Answer)); + } } } diff --git a/AOC2021.Test/Input/Day4_input.txt b/AOC2021.Test/Input/Day4_input.txt new file mode 100644 index 0000000..9c7ad40 --- /dev/null +++ b/AOC2021.Test/Input/Day4_input.txt @@ -0,0 +1,601 @@ +63,23,2,65,55,94,38,20,22,39,5,98,9,60,80,45,99,68,12,3,6,34,64,10,70,69,95,96,83,81,32,30,42,73,52,48,92,28,37,35,54,7,50,21,74,36,91,97,13,71,86,53,46,58,76,77,14,88,78,1,33,51,89,26,27,31,82,44,61,62,75,66,11,93,49,43,85,0,87,40,24,29,15,59,16,67,19,72,57,41,8,79,56,4,18,17,84,90,47,25 + +25 29 78 57 69 +47 51 7 21 82 +61 81 99 53 30 +50 80 41 94 46 + 9 37 48 71 91 + +26 10 29 27 90 +21 65 44 5 1 +42 51 35 11 98 +72 23 41 95 48 +40 97 99 92 2 + +20 70 21 58 5 +63 29 16 71 45 +43 7 26 0 62 +24 75 9 87 55 +88 10 11 47 4 + + 5 31 99 96 16 +61 37 91 92 23 +46 8 36 9 42 + 3 32 49 64 48 +15 2 47 53 55 + +28 40 96 38 9 +33 11 65 76 13 +24 35 20 3 99 +95 78 51 74 4 +80 14 44 98 58 + +24 55 8 59 65 +96 11 15 12 99 +21 75 35 85 34 +20 53 72 50 70 +61 48 74 41 36 + +61 32 13 42 90 +81 22 66 75 51 +46 1 41 9 34 +86 50 48 64 74 +72 85 97 11 71 + +16 32 41 37 61 +14 31 29 6 79 +28 97 11 15 9 +13 72 3 85 64 +81 95 20 77 69 + +42 76 14 78 35 +49 89 7 81 90 +13 18 32 24 9 +10 98 12 2 65 +82 21 67 70 84 + +89 38 21 83 5 + 7 87 37 14 98 +55 81 13 56 39 +42 19 51 36 30 +76 15 57 94 20 + +29 18 49 10 67 +91 93 37 45 34 +60 8 56 86 32 +95 89 71 51 59 +87 3 27 44 41 + + 9 71 95 12 42 +83 90 98 79 49 +72 1 53 80 33 +29 82 65 4 25 +92 5 76 54 66 + +72 85 4 39 29 +86 0 95 30 21 +11 51 2 99 38 +58 52 25 59 77 +69 74 37 87 32 + +99 16 9 63 55 +79 50 48 96 92 +47 35 15 93 76 +19 70 25 49 38 +80 60 43 69 81 + +50 19 10 7 83 +79 52 14 51 55 +68 65 54 21 62 +71 25 34 70 92 +44 26 61 4 46 + +75 26 15 76 61 +42 0 51 29 81 +82 57 16 91 4 +12 19 30 10 24 +78 58 55 74 53 + +36 80 46 9 85 +34 17 43 96 57 +37 6 33 88 28 +59 48 18 22 79 +55 52 20 2 61 + + 3 99 46 7 31 +61 43 17 78 4 +59 45 47 52 10 +55 95 33 9 35 +13 8 89 73 12 + +19 58 46 56 62 +11 72 82 0 12 +92 9 70 18 65 +35 61 79 87 36 + 1 27 22 8 74 + +60 92 94 2 84 +73 69 72 29 37 +50 74 56 58 6 +51 80 86 33 4 +32 24 20 7 78 + +47 25 76 89 61 +86 77 71 43 22 +42 18 70 24 98 +31 68 62 79 9 +17 10 78 16 84 + +90 41 71 1 58 +88 91 86 4 34 +48 31 3 74 21 +85 5 37 36 28 +18 46 17 49 69 + +41 55 52 58 44 + 4 75 81 12 48 +72 93 8 86 10 +66 29 94 85 69 +74 36 50 9 19 + +80 76 36 21 57 +58 8 27 18 86 +79 5 48 82 64 + 0 93 30 1 4 +78 40 52 50 62 + +58 60 77 25 22 +93 97 49 2 41 +59 38 95 36 44 +30 79 69 54 86 +23 4 80 85 27 + +27 67 68 46 41 +93 4 96 49 23 +11 54 80 88 75 +69 34 44 12 37 +39 78 66 5 43 + +20 32 71 99 19 +42 96 58 47 65 +72 31 70 59 26 +46 17 38 11 23 +18 85 52 77 67 + +38 98 42 31 40 +76 2 77 82 34 +92 73 55 93 19 +25 58 90 10 68 + 6 56 85 43 95 + +16 71 12 76 86 +78 26 15 34 45 +17 22 20 8 1 +51 52 24 90 79 +53 40 14 69 21 + +77 75 68 32 69 +61 9 74 58 44 +21 39 94 84 46 +14 29 93 31 63 +12 72 2 98 40 + +68 32 38 58 24 +61 11 76 55 39 + 6 21 31 93 99 +64 75 15 62 56 +34 12 14 73 77 + +50 24 71 22 67 +18 80 89 51 90 +54 64 31 19 44 +61 88 85 25 98 +73 69 37 72 39 + +79 2 62 91 97 +36 41 72 28 42 +26 89 98 86 10 +35 16 85 63 64 +43 51 39 60 55 + +47 86 44 56 74 + 0 96 39 84 54 +38 45 68 88 21 +11 33 17 52 97 +83 58 42 65 81 + +16 1 22 8 24 + 7 3 12 30 59 +79 91 53 69 68 +20 88 14 81 51 +89 71 54 56 52 + +25 12 32 53 3 +63 29 92 70 97 +54 6 21 4 86 +76 39 84 49 96 +68 0 15 72 28 + +56 20 35 71 23 +51 21 96 42 64 +83 1 8 94 55 +44 73 76 24 67 +81 70 6 61 46 + +85 37 30 39 97 +36 14 71 59 15 +46 26 27 25 9 + 6 56 79 52 67 +72 54 58 74 76 + +90 24 86 43 1 +18 70 89 20 9 +44 4 52 65 66 +56 17 96 78 67 +53 80 32 42 63 + +35 50 95 53 16 +75 1 85 31 81 +99 22 27 84 38 +98 8 19 25 92 +56 59 62 48 54 + + 8 22 67 70 91 +73 51 96 49 37 +31 4 99 52 27 +13 50 39 1 85 +19 9 40 55 47 + +59 35 52 60 91 +75 86 13 39 21 +33 99 11 64 50 +37 58 71 22 54 + 6 72 88 3 85 + +85 63 5 48 20 +96 55 53 35 60 + 0 17 26 22 13 +25 45 62 4 41 +78 40 46 95 33 + +23 53 82 22 74 + 5 45 15 44 65 +62 84 68 83 88 +52 46 61 77 59 +56 60 71 2 43 + +27 77 28 8 84 +33 0 22 62 40 + 3 44 19 53 91 +60 83 75 48 94 +29 93 23 82 65 + +77 34 72 62 4 + 9 8 76 52 60 +37 54 98 20 22 +11 13 86 48 57 +10 63 41 23 61 + +58 57 47 55 3 +38 11 39 15 9 + 5 65 92 98 41 +72 45 6 16 83 +74 40 99 50 30 + +72 46 35 9 53 +70 67 74 93 55 +24 4 30 38 47 +29 96 51 17 71 +90 5 69 54 61 + +90 59 93 99 34 +85 39 52 16 20 +32 66 75 35 17 +38 33 84 40 89 +91 77 26 86 54 + + 2 87 96 34 28 +98 74 56 17 37 +10 62 71 89 95 + 6 90 5 99 92 +39 73 55 18 8 + +87 44 72 2 45 +82 78 32 64 37 +46 75 95 67 80 + 8 60 57 97 56 +22 43 92 26 96 + +98 1 21 17 14 +85 6 33 69 16 +53 82 0 41 73 +46 72 2 35 23 +89 94 80 76 42 + +27 94 98 5 95 +64 19 77 15 92 +11 52 41 50 51 + 4 57 99 21 29 +20 35 78 34 87 + +52 83 84 21 59 +30 64 85 90 91 +24 32 57 0 81 +17 47 1 25 27 +10 51 65 79 34 + +83 9 94 14 85 +65 51 28 32 48 +81 71 8 12 31 +38 50 92 57 47 +34 49 56 73 27 + +54 8 72 38 29 +34 78 69 16 30 +82 24 9 0 13 +90 41 60 28 12 +71 22 70 80 66 + +71 50 24 86 21 +14 92 45 30 95 +57 60 0 88 91 +87 97 6 7 26 +61 98 25 5 84 + + 1 63 45 36 67 +27 16 54 72 41 +32 74 53 9 35 +95 29 90 19 26 +82 97 11 42 28 + + 2 93 86 28 43 +90 12 21 56 76 +98 30 25 9 75 +11 20 45 95 50 +22 31 39 49 6 + + 2 53 74 9 64 +24 8 85 86 59 +41 38 57 63 32 +88 93 14 11 55 +69 31 25 66 52 + +10 60 42 16 95 + 8 14 81 84 5 +98 32 68 12 6 +83 66 90 69 46 +54 40 59 73 91 + +24 66 62 30 83 +72 80 54 25 17 + 3 77 60 68 36 +26 22 8 74 95 +63 39 4 53 87 + +49 96 48 2 78 +14 21 38 98 45 +30 34 54 16 92 + 0 89 70 68 57 + 7 74 10 86 97 + +25 91 46 84 66 +44 50 40 10 67 +62 77 5 6 43 +63 29 79 51 53 +70 69 61 80 54 + +19 11 24 9 93 +21 53 81 2 61 +69 83 33 23 68 +73 22 77 71 52 +92 76 94 86 1 + +51 31 27 28 95 +16 50 36 13 57 + 1 11 79 45 90 +41 77 3 78 42 +56 74 85 44 52 + +58 0 63 88 30 +35 18 48 49 80 +36 11 46 13 76 +37 19 9 93 87 +68 15 17 8 82 + +96 20 7 81 11 +42 17 14 44 36 +99 98 68 58 56 +15 57 80 3 67 +61 66 38 83 59 + + 3 60 25 55 17 +42 45 66 24 14 +13 16 41 11 88 +89 96 97 35 1 +83 5 52 69 28 + +99 11 53 82 3 +88 74 42 38 13 +94 80 27 92 34 +29 56 8 14 76 +85 65 66 79 59 + +80 82 43 87 70 +85 22 53 10 1 +30 78 39 26 77 + 7 92 20 21 93 +75 36 61 13 90 + +53 41 29 77 58 +98 83 86 14 94 +10 99 24 17 32 + 3 87 42 19 61 +57 89 36 13 9 + +30 45 53 99 41 +80 85 25 18 10 +47 98 64 78 11 +58 94 9 91 87 +35 97 43 0 32 + +70 1 80 98 85 +73 69 90 63 20 +53 77 39 49 64 +28 7 78 84 57 +56 86 23 88 97 + +18 53 73 49 40 +36 95 46 42 94 +97 19 23 72 84 +21 47 91 8 17 +99 90 68 30 25 + +26 9 84 35 59 +44 47 66 8 48 + 0 82 68 54 58 +65 7 28 62 61 +55 37 21 72 86 + +47 55 12 75 61 +99 74 9 10 67 + 2 57 25 20 46 +83 97 43 49 59 + 3 79 94 69 70 + +12 2 41 69 24 +93 95 43 52 66 +71 92 57 14 58 +30 25 81 62 79 + 7 96 70 22 42 + +92 83 35 65 8 +63 71 43 33 19 +95 24 51 85 41 +66 13 68 12 20 + 7 1 22 40 75 + +30 56 10 85 72 +83 52 51 80 14 +32 29 67 41 74 +96 62 16 15 98 +73 45 99 48 79 + +24 9 5 38 52 +32 57 87 30 90 + 7 54 39 43 14 +31 76 96 65 0 +51 99 20 61 92 + +19 37 39 15 86 +53 32 42 57 70 + 9 26 84 93 10 +33 25 61 21 0 +34 60 30 99 7 + +62 50 33 29 54 +92 12 81 0 87 +60 2 27 7 9 +28 18 31 35 59 +20 63 38 72 14 + +96 89 34 56 63 +61 8 25 90 78 +94 26 10 47 84 + 1 32 7 83 73 +16 65 69 23 97 + +44 59 87 16 18 +31 50 27 9 38 +49 10 56 69 35 +13 24 91 46 70 +22 37 6 43 25 + +87 79 59 26 35 +81 73 36 66 51 +97 11 43 17 7 +24 94 71 91 48 +12 77 93 55 34 + +91 93 56 55 58 +24 11 82 35 86 +68 81 50 34 23 +59 73 1 8 37 +18 83 80 53 85 + +40 30 7 72 22 +68 94 95 89 42 +91 84 11 49 36 +64 29 26 73 76 +37 1 51 9 25 + +32 48 47 36 88 +54 91 59 72 50 +31 83 19 20 0 +24 67 61 46 99 +52 53 11 16 69 + +86 52 95 73 6 +56 45 8 13 80 +28 77 19 59 48 +99 33 47 10 85 +35 81 27 46 76 + +41 45 1 12 49 +32 16 21 85 27 +50 80 66 64 10 +76 11 9 59 52 +71 37 34 2 43 + +43 19 88 81 12 + 4 48 9 91 31 + 1 46 10 6 56 +72 41 30 36 94 +61 83 86 28 79 + +39 10 40 25 52 +29 60 38 18 31 +65 46 11 0 94 +68 12 42 4 84 +55 20 86 77 26 + +12 65 79 59 43 +93 6 68 1 29 +17 48 45 26 80 +37 22 5 66 47 +71 11 41 18 64 + + 5 45 54 82 64 +90 89 22 17 71 +81 60 65 32 34 +41 86 35 30 48 +67 47 23 51 6 + +19 65 11 58 49 +97 68 56 10 39 +87 29 43 40 83 + 9 41 26 79 77 +63 72 93 4 51 + +82 50 90 45 4 +53 96 93 30 19 + 8 95 73 74 98 +35 20 32 7 36 +56 52 59 26 16 + +94 67 97 34 75 +23 80 68 24 47 +56 8 21 66 36 +69 5 3 95 17 +29 38 44 42 28 + +84 35 72 8 38 +94 30 48 24 27 +81 61 18 87 90 +65 17 85 22 45 +32 15 74 52 68 + + 9 69 63 68 36 +44 31 35 12 39 +57 83 6 49 23 +64 0 10 85 81 +82 40 34 91 24 \ No newline at end of file diff --git a/AOC2021.Test/Input/Day4_test.txt b/AOC2021.Test/Input/Day4_test.txt new file mode 100644 index 0000000..cabc5cc --- /dev/null +++ b/AOC2021.Test/Input/Day4_test.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 \ No newline at end of file diff --git a/AOC2021/Controllers/AdventOfCodeController.cs b/AOC2021/Controllers/AdventOfCodeController.cs index 5e66724..e08ab44 100644 --- a/AOC2021/Controllers/AdventOfCodeController.cs +++ b/AOC2021/Controllers/AdventOfCodeController.cs @@ -22,6 +22,7 @@ namespace AOC2021.Controllers [Route("day1")] [Route("day2")] [Route("day3")] + [Route("day4")] public AOCResponse Day(AOCVersion version, [FromBody] string input, bool IgnoreLogMessages = false) { AOCRequest request = new AOCRequest() { Input = input, Version = version, IgnoreLogMessages = IgnoreLogMessages }; diff --git a/AOC2021/Days/Day4.cs b/AOC2021/Days/Day4.cs new file mode 100644 index 0000000..7757fb7 --- /dev/null +++ b/AOC2021/Days/Day4.cs @@ -0,0 +1,86 @@ +using AOC2021.Helper; +using AOC2021.Models; +using AOC2021.Models.Day4; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AOC2021.Days +{ + public class Day4 : AOCDay + { + private static readonly int BOARD_SIZE = 5; + private List _boards; + public Day4() + { + _boards = new List(); + } + protected override AOCResponse ExecutePartA() + { + var input = GetSplitInput(); + var checkedValues = input.First().Trim().Split(","); //Save selected answers into variable + CreateBoards(input); + + BingoBoard winner = null; + foreach (var ball in checkedValues) + { + Log("Ball picked was " + ball); + foreach (var board in _boards) + { + board.MarkValueAsChecked(ball.ToInt()); + if (board.IsWinner()) + { + winner = board; + Log("We have a winning board, number " + winner.Id); + break; + } + } + if (winner != null) + break; + } + this._response.Answer = winner.CalculateScore().ToString(); + Log("Winning board score is " + this._response.Answer); + + return this._response; + } + + protected override AOCResponse ExecutePartB() + { + var input = GetSplitInput(); + var checkedValues = input.First().Trim().Split(","); //Save selected answers into variable + CreateBoards(input); + + BingoBoard winner = null; + foreach (var ball in checkedValues) + { + Log("Ball picked was " + ball); + foreach (var board in _boards.Reverse()) + { + board.MarkValueAsChecked(ball.ToInt()); + if (board.IsWinner()) + { + winner = board; + _boards.Remove(board); + } + } + } + this._response.Answer = winner.CalculateScore().ToString(); + Log("Winning board score is " + this._response.Answer); + return this._response; + } + + private void CreateBoards(string[] input) + { + //Create all of our game boards + int skipValue = 2; + while (skipValue < input.Length) + { + var group = input.Skip(skipValue).Take(5); + _boards.Add(new BingoBoard(BOARD_SIZE, group)); + skipValue += 6; + } + + } + } +} diff --git a/AOC2021/Models/Day4/BingoBoard.cs b/AOC2021/Models/Day4/BingoBoard.cs new file mode 100644 index 0000000..28710dd --- /dev/null +++ b/AOC2021/Models/Day4/BingoBoard.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AOC2021.Models.Day4 +{ + public class BingoBoard + { + private static int ID_COUNT = 1; + public int Id; + private int _size; + private List _board; + private int _lastAnswer; + public BingoBoard(int size, IEnumerable values) + { + Id = ID_COUNT++; + _size = size; + _board = new List(); + ConstructBoard(values); + } + + private void ConstructBoard(IEnumerable values) + { + for (int x = 0; x < values.Count(); x++) + { + var splitValue = values.ElementAt(x).Trim().Replace(" ", " ").Split(" "); + for (int y = 0; y < splitValue.Length; y++) + { + _board.Add(new BingoSpot() + { + Checked = false, + Value = Convert.ToInt32(splitValue[y]), + X = x, + Y = y + }); + } + } + } + + private BingoSpot SpotAt(int x, int y) + { + foreach (var bs in _board) + if (bs.X == x && bs.Y == y) + return bs; + throw new Exception($"Can't find spot {x},{y} in the bingo board!"); + } + + public void MarkValueAsChecked(int value) + { + + foreach (var bs in _board) + if (bs.Value == value) + { + bs.Checked = true; + } + _lastAnswer = value; + } + + public string PrintBoard() + { + var boardPrintout = string.Empty; + for (int x = 0; x < _size; x++) + { + var line = string.Empty; + for (int y = 0; y < _size; y++) + { + line += $"{SpotAt(x, y).Value} "; + } + boardPrintout += $"{line}{Environment.NewLine}"; + } + return boardPrintout; + } + + public bool IsWinner() + { + for (int x = 0; x < _size; x++) + { + //If its still checked, and the next spot is NOT checked set to false and ends the check + bool horizontalRow = true; + bool verticalRow = true; + for (int y = 0; y < _size; y++) + { + if (horizontalRow && !SpotAt(x, y).Checked) + horizontalRow = false; + if (verticalRow && !SpotAt(y, x).Checked) + verticalRow = false; + } + if (horizontalRow || verticalRow) + return true; + } + return false; + } + + public int CalculateScore() + { + int unMarked = 0; + foreach (var x in _board) + if (!x.Checked) + unMarked += x.Value; + return unMarked * _lastAnswer; + } + } +} diff --git a/AOC2021/Models/Day4/BingoSpot.cs b/AOC2021/Models/Day4/BingoSpot.cs new file mode 100644 index 0000000..e2b03f2 --- /dev/null +++ b/AOC2021/Models/Day4/BingoSpot.cs @@ -0,0 +1,10 @@ +namespace AOC2021.Models.Day4 +{ + public class BingoSpot + { + public int Value { get; set; } + public int X { get; set; } + public int Y { get; set; } + public bool Checked { get; set; } + } +}