|
| 1 | +namespace Basje.AdventOfCode.Y2024.D14; |
| 2 | + |
| 3 | +public class Day14 : Solution<((int X, int Y) Position, (int X, int Y) Velocity)[]> |
| 4 | +{ |
| 5 | + protected override ((int X, int Y) Position, (int X, int Y) Velocity)[] ParseInput(string input) |
| 6 | + { |
| 7 | + return input |
| 8 | + .PerLine() |
| 9 | + .IgnoreEmptyLines() |
| 10 | + .Select(line => |
| 11 | + line.Replace("p=", "") |
| 12 | + .Split(" v=") |
| 13 | + .IgnoreEmptyLines() |
| 14 | + .ToArray() |
| 15 | + ) |
| 16 | + .Select(line => ( |
| 17 | + Position: line[0].Split(",").Select(int.Parse).ToArray(), |
| 18 | + Velocity: line[1].Split(",").Select(int.Parse).ToArray()) |
| 19 | + ) |
| 20 | + .Select(line => ( |
| 21 | + Position: (X: line.Position[0], Y: line.Position[1]), |
| 22 | + Velocity: (X: line.Velocity[0], Y: line.Velocity[1])) |
| 23 | + ) |
| 24 | + .ToArray(); |
| 25 | + } |
| 26 | + |
| 27 | + protected override object SolvePart1(((int X, int Y) Position, (int X, int Y) Velocity)[] list) |
| 28 | + { |
| 29 | + var height = list.Select(robot => robot.Position.Y).Max() + 1; |
| 30 | + var width = list.Select(robot => robot.Position.X).Max() + 1; |
| 31 | + |
| 32 | + List<(int X, int Y)> robots = []; |
| 33 | + |
| 34 | + foreach (var robot in list) |
| 35 | + { |
| 36 | + var newPosition = ( |
| 37 | + X: robot.Position.X + 100 * robot.Velocity.X, |
| 38 | + Y: robot.Position.Y + 100 * robot.Velocity.Y); |
| 39 | + |
| 40 | + newPosition = (X: newPosition.X.Modulo(width), Y: newPosition.Y.Modulo(height)); |
| 41 | + |
| 42 | + robots.Add(newPosition); |
| 43 | + } |
| 44 | + |
| 45 | + robots.RemoveAll(robot => robot.X == width / 2 || robot.Y == height / 2); |
| 46 | + |
| 47 | + var nw = robots.Count(robot => robot.X <= width / 2 && robot.Y <= height / 2); |
| 48 | + var ne = robots.Count(robot => robot.X > width / 2 && robot.Y <= height / 2); |
| 49 | + var sw = robots.Count(robot => robot.X <= width / 2 && robot.Y > height / 2); |
| 50 | + var se = robots.Count(robot => robot.X > width / 2 && robot.Y > height / 2); |
| 51 | + |
| 52 | + return nw * ne * sw * se; |
| 53 | + } |
| 54 | + |
| 55 | + protected override object SolvePart2(((int X, int Y) Position, (int X, int Y) Velocity)[] list) |
| 56 | + { |
| 57 | + var height = list.Select(robot => robot.Position.Y).Max() + 1; |
| 58 | + var width = list.Select(robot => robot.Position.X).Max() + 1; |
| 59 | + |
| 60 | + var treeFound = false; |
| 61 | + var i = 1; |
| 62 | + // var key = '.'; |
| 63 | + |
| 64 | + while (!treeFound) |
| 65 | + { |
| 66 | + |
| 67 | + List<(int X, int Y)> robots = []; |
| 68 | + |
| 69 | + foreach (var robot in list) |
| 70 | + { |
| 71 | + var newPosition = ( |
| 72 | + X: robot.Position.X + i * robot.Velocity.X, |
| 73 | + Y: robot.Position.Y + i * robot.Velocity.Y); |
| 74 | + |
| 75 | + newPosition = (X: newPosition.X.Modulo(width), Y: newPosition.Y.Modulo(height)); |
| 76 | + |
| 77 | + robots.Add(newPosition); |
| 78 | + } |
| 79 | + |
| 80 | + // First wrote a visualiser. Then looked through the output and |
| 81 | + // noticed that sometimes the robots seemed to cluster. Based on |
| 82 | + // clustering I played with values of number of robots on the same |
| 83 | + // line. I visually found tree, after which I updated the search |
| 84 | + // criteria. |
| 85 | + treeFound = robots |
| 86 | + .GroupBy(robot => robot.Y) |
| 87 | + .Count(line => line.Count() >= 31) == 2 |
| 88 | + && robots |
| 89 | + .GroupBy(robot => robot.X) |
| 90 | + .Count(column => column.Count() >= 33) == 2; |
| 91 | + |
| 92 | + // if (treeFound) |
| 93 | + // { |
| 94 | + // Console.WriteLine($"i: {i}"); |
| 95 | + // robots.Print(width, height); |
| 96 | + // key = Console.ReadKey().KeyChar; |
| 97 | + // } |
| 98 | + |
| 99 | + i++; |
| 100 | + } |
| 101 | + return i; |
| 102 | + } |
| 103 | +} |
| 104 | + |
| 105 | +internal static class Day14Extensions |
| 106 | +{ |
| 107 | + // Apparently the % operator in C# is not an actual modulo, but the remainder. |
| 108 | + // So we need to make a correct modulo that works with negative numbers too. |
| 109 | + // Source: https://stackoverflow.com/a/6400477 |
| 110 | + internal static int Modulo(this int a, double b) |
| 111 | + { |
| 112 | + return (int)Math.Round(a - b * Math.Floor(a / b)); |
| 113 | + } |
| 114 | + |
| 115 | + internal static void Print(this List<(int X, int Y)> robots, int width, int height) |
| 116 | + { |
| 117 | + for (var y = 0; y < height; y++) |
| 118 | + { |
| 119 | + for (var x = 0; x < width; x++) |
| 120 | + { |
| 121 | + var character = '.'; |
| 122 | + if (robots.Contains((X: x, Y: y))) |
| 123 | + { |
| 124 | + character = 'X'; |
| 125 | + } |
| 126 | + Console.Write(character); |
| 127 | + if (x == width - 1) |
| 128 | + { |
| 129 | + Console.WriteLine(); |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + if (y == height - 1) |
| 134 | + { |
| 135 | + Console.WriteLine(); |
| 136 | + } |
| 137 | + } |
| 138 | + } |
| 139 | +} |
0 commit comments