diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..c388e17 --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "All": { + "commandName": "Project", + "commandLineArgs": "all" + }, + "Default day": { + "commandName": "Project" + } + } +} \ No newline at end of file diff --git a/src/01.cs b/src/01.cs index b25ac64..69af1e7 100644 --- a/src/01.cs +++ b/src/01.cs @@ -1,70 +1,69 @@ -namespace aoc2021 +namespace aoc2021; + +internal class Day01 : Day { - internal class Day01 + internal override void Go() { - internal static void Go() + Logger.Log("Day 1"); + Logger.Log("-----"); + var lines = File.ReadAllLines("inputs/01.txt"); + Part1(lines); + Part2(lines); + Logger.Log(""); + } + + private static void Part1(IEnumerable lines) + { + using var t = new Timer(); + + int lastDepth = 0; + int numIncreased = -1; + + foreach (var line in lines) { - Logger.Log("Day 1"); - Logger.Log("-----"); - var lines = File.ReadAllLines("inputs/01.txt"); - Part1(lines); - Part2(lines); - Logger.Log(""); - } - - private static void Part1(IEnumerable lines) - { - using var t = new Timer(); - - int lastDepth = 0; - int numIncreased = -1; - - foreach (var line in lines) + var depth = Convert.ToInt32(line); + if (depth > lastDepth) { - var depth = Convert.ToInt32(line); - if (depth > lastDepth) - { - numIncreased++; - } - - lastDepth = depth; + numIncreased++; } - Logger.Log($"part1: {numIncreased}"); + lastDepth = depth; } - private static void Part2(IEnumerable lines) + Logger.Log($"part1: {numIncreased}"); + } + + private static void Part2(IEnumerable lines) + { + using var t = new Timer(); + + int lastTotal = 0; + int numIncreased = -1; + int num1 = -1; + int num2 = -1; + int num3 = -1; + + foreach (var line in lines) { - using var t = new Timer(); + var depth = Convert.ToInt32(line); + num1 = num2; + num2 = num3; + num3 = depth; - int lastTotal = 0; - int numIncreased = -1; - int num1 = -1; - int num2 = -1; - int num3 = -1; - - foreach (var line in lines) + if (num1 < 0 || num2 < 0 || num3 < 0) { - var depth = Convert.ToInt32(line); - num1 = num2; - num2 = num3; - num3 = depth; - - if (num1 < 0 || num2 < 0 || num3 < 0) - { - continue; - } - - var total = num1 + num2 + num3; - if (total > lastTotal) - { - numIncreased++; - } - - lastTotal = total; + continue; } - Logger.Log($"part2: {numIncreased}"); + var total = num1 + num2 + num3; + if (total > lastTotal) + { + numIncreased++; + } + + lastTotal = total; } + + Logger.Log($"part2: {numIncreased}"); } } diff --git a/src/02.cs b/src/02.cs index 52b9464..bf206a9 100644 --- a/src/02.cs +++ b/src/02.cs @@ -1,90 +1,89 @@ -namespace aoc2021 +namespace aoc2021; + +internal class Day02 : Day { - internal class Day02 + internal override void Go() { - internal static void Go() + Logger.Log("Day 2"); + Logger.Log("-----"); + var lines = File.ReadAllLines("inputs/02.txt"); + var instructions = new List(); + foreach (var instruction in lines) { - Logger.Log("Day 2"); - Logger.Log("-----"); - var lines = File.ReadAllLines("inputs/02.txt"); - var instructions = new List(); - foreach (var instruction in lines) + var fmt = instruction.Split(' '); + instructions.Add(new Instruction() { - var fmt = instruction.Split(' '); - instructions.Add(new Instruction() - { - Direction = fmt[0], - Amount = Convert.ToInt64(fmt[1]), - }); - } - - Part1(instructions); - Part2(instructions); - Logger.Log(""); + Direction = fmt[0], + Amount = Convert.ToInt64(fmt[1]), + }); } - struct Instruction - { - public string Direction; - public long Amount; - } + Part1(instructions); + Part2(instructions); + Logger.Log(""); + } - struct Position - { - public long h; - public long d; - } + struct Instruction + { + public string Direction; + public long Amount; + } - private static void Part1(IEnumerable instructions) + struct Position + { + public long h; + public long d; + } + + private static void Part1(IEnumerable instructions) + { + using var t = new Timer(); + Position pos = new(); + foreach (var instruction in instructions) { - using var t = new Timer(); - Position pos = new(); - foreach (var instruction in instructions) + switch (instruction.Direction) { - switch (instruction.Direction) - { - case "forward": - pos.h += instruction.Amount; - break; + case "forward": + pos.h += instruction.Amount; + break; - case "down": - pos.d += instruction.Amount; - break; + case "down": + pos.d += instruction.Amount; + break; - case "up": - pos.d -= instruction.Amount; - break; - } + case "up": + pos.d -= instruction.Amount; + break; } - - Logger.Log($"part1: h: {pos.h}, d: {pos.d}, result: {pos.h * pos.d}"); } - private static void Part2(IEnumerable instructions) + Logger.Log($"part1: h: {pos.h}, d: {pos.d}, result: {pos.h * pos.d}"); + } + + private static void Part2(IEnumerable instructions) + { + using var t = new Timer(); + Position pos = new(); + long aim = 0; + foreach (var instruction in instructions) { - using var t = new Timer(); - Position pos = new(); - long aim = 0; - foreach (var instruction in instructions) + switch (instruction.Direction) { - switch (instruction.Direction) - { - case "forward": - pos.h += instruction.Amount; - pos.d += aim * instruction.Amount; - break; + case "forward": + pos.h += instruction.Amount; + pos.d += aim * instruction.Amount; + break; - case "down": - aim += instruction.Amount; - break; + case "down": + aim += instruction.Amount; + break; - case "up": - aim -= instruction.Amount; - break; - } + case "up": + aim -= instruction.Amount; + break; } - - Logger.Log($"part2: h: {pos.h}, d: {pos.d}, result: {pos.h * pos.d}"); } + + Logger.Log($"part2: h: {pos.h}, d: {pos.d}, result: {pos.h * pos.d}"); } } diff --git a/src/03.cs b/src/03.cs index 0477d8e..7a5c63e 100644 --- a/src/03.cs +++ b/src/03.cs @@ -1,132 +1,131 @@ -namespace aoc2021 +namespace aoc2021; + +internal class Day03 : Day { - internal class Day03 + internal override void Go() { - internal static void Go() - { - Logger.Log("Day 3"); - Logger.Log("-----"); - var lines = File.ReadAllLines("inputs/03.txt"); - Part1(lines); - Part2(lines); - Logger.Log(""); - } + Logger.Log("Day 3"); + Logger.Log("-----"); + var lines = File.ReadAllLines("inputs/03.txt"); + Part1(lines); + Part2(lines); + Logger.Log(""); + } - private static void Part1(IEnumerable lines) + private static void Part1(IEnumerable lines) + { + using var t = new Timer(); + var len = lines.First().Length; + int gammaRate = 0; + int epsilonRate = 0; + for (int i = 0; i < len; i++) { - using var t = new Timer(); - var len = lines.First().Length; - int gammaRate = 0; - int epsilonRate = 0; - for (int i = 0; i < len; i++) + var numZero = 0; + var numOne = 0; + foreach (var line in lines) { - var numZero = 0; - var numOne = 0; - foreach (var line in lines) + if (line[i] == '0') { - if (line[i] == '0') - { - numZero++; - } - else if (line[i] == '1') - { - numOne++; - } + numZero++; } - - if (numOne > numZero) + else if (line[i] == '1') { - gammaRate |= (1 << (len - i - 1)); - } - else if (numZero > numOne) - { - epsilonRate |= (1 << (len - i - 1)); + numOne++; } } - Logger.Log($"part1: gamma rate: {gammaRate}, epsilon rate: {epsilonRate}, mult: {gammaRate * epsilonRate}"); + if (numOne > numZero) + { + gammaRate |= (1 << (len - i - 1)); + } + else if (numZero > numOne) + { + epsilonRate |= (1 << (len - i - 1)); + } } - private static void Part2(IEnumerable lines) + Logger.Log($"part1: gamma rate: {gammaRate}, epsilon rate: {epsilonRate}, mult: {gammaRate * epsilonRate}"); + } + + private static void Part2(IEnumerable lines) + { + using var t = new Timer(); + int o2 = 0; + int co2 = 0; + var filtered = lines.ToList(); + for (int i = 0; i < lines.First().Length; i++) { - using var t = new Timer(); - int o2 = 0; - int co2 = 0; - var filtered = lines.ToList(); - for (int i = 0; i < lines.First().Length; i++) + var numZero = 0; + var numOne = 0; + foreach (var line in filtered) { - var numZero = 0; - var numOne = 0; - foreach (var line in filtered) + if (line[i] == '0') { - if (line[i] == '0') - { - numZero++; - } - else if (line[i] == '1') - { - numOne++; - } + numZero++; } - - if (numOne > numZero) + else if (line[i] == '1') { - filtered.RemoveAll(x => x[i] != '1'); - } - else if (numZero > numOne) - { - filtered.RemoveAll(x => x[i] != '0'); - } - else - { - filtered.RemoveAll(x => x[i] != '1'); - } - - if (filtered.Count == 1) - { - o2 = Convert.ToInt32(filtered[0], 2); - break; + numOne++; } } - filtered = lines.ToList(); - for (int i = 0; i < lines.First().Length; i++) + if (numOne > numZero) { - var numZero = 0; - var numOne = 0; - foreach (var line in filtered) - { - if (line[i] == '0') - { - numZero++; - } - else if (line[i] == '1') - { - numOne++; - } - } - - if (numOne < numZero) - { - filtered.RemoveAll(x => x[i] != '1'); - } - else if (numZero < numOne) - { - filtered.RemoveAll(x => x[i] != '0'); - } - else - { - filtered.RemoveAll(x => x[i] != '0'); - } - - if (filtered.Count == 1) - { - co2 = Convert.ToInt32(filtered[0], 2); - break; - } + filtered.RemoveAll(x => x[i] != '1'); + } + else if (numZero > numOne) + { + filtered.RemoveAll(x => x[i] != '0'); + } + else + { + filtered.RemoveAll(x => x[i] != '1'); } - Logger.Log($"part2: o2*co2 = {o2} * {co2} = {o2 * co2}"); + if (filtered.Count == 1) + { + o2 = Convert.ToInt32(filtered[0], 2); + break; + } } + + filtered = lines.ToList(); + for (int i = 0; i < lines.First().Length; i++) + { + var numZero = 0; + var numOne = 0; + foreach (var line in filtered) + { + if (line[i] == '0') + { + numZero++; + } + else if (line[i] == '1') + { + numOne++; + } + } + + if (numOne < numZero) + { + filtered.RemoveAll(x => x[i] != '1'); + } + else if (numZero < numOne) + { + filtered.RemoveAll(x => x[i] != '0'); + } + else + { + filtered.RemoveAll(x => x[i] != '0'); + } + + if (filtered.Count == 1) + { + co2 = Convert.ToInt32(filtered[0], 2); + break; + } + } + + Logger.Log($"part2: o2*co2 = {o2} * {co2} = {o2 * co2}"); } } diff --git a/src/05.cs b/src/05.cs index 9419957..da4ca18 100644 --- a/src/05.cs +++ b/src/05.cs @@ -1,130 +1,129 @@ using System.Diagnostics; using System.Text.RegularExpressions; -namespace aoc2021 +namespace aoc2021; + +internal class Day05 : Day { - internal class Day05 + private static readonly Regex lineRegex = new(@"(?\d+),(?\d+) -> (?\d+),(?\d+)", RegexOptions.Compiled); + + [DebuggerDisplay("{x},{y}")] + struct Point : IEquatable { - private static readonly Regex lineRegex = new(@"(?\d+),(?\d+) -> (?\d+),(?\d+)", RegexOptions.Compiled); + public int X { get; init; } + public int Y { get; init; } - [DebuggerDisplay("{x},{y}")] - struct Point : IEquatable + public bool Equals(Point other) => X == other.X && Y == other.Y; + + public override bool Equals(object? obj) => obj is Point point && Equals(point); + + public override int GetHashCode() => HashCode.Combine(X, Y); + } + + [DebuggerDisplay("{start} -> {end}")] + struct Line + { + public Point Start { get; init; } + public Point End { get; init; } + + public int Length { - public int X { get; init; } - public int Y { get; init; } - - public bool Equals(Point other) => X == other.X && Y == other.Y; - - public override bool Equals(object? obj) => obj is Point point && Equals(point); - - public override int GetHashCode() => HashCode.Combine(X, Y); - } - - [DebuggerDisplay("{start} -> {end}")] - struct Line - { - public Point Start { get; init; } - public Point End { get; init; } - - public int Length + get { - get + // this is bad and i feel bad + if (Start.X == End.X || Start.Y == End.Y) { - // this is bad and i feel bad - if (Start.X == End.X || Start.Y == End.Y) - { - return Math.Abs((End.X - Start.X) + (End.Y - Start.Y)); - } - - return Math.Abs(Start.X - End.X); - } - } - } - - internal static void Go() - { - Logger.Log("Day 5"); - Logger.Log("-----"); - var lines = File.ReadAllLines("inputs/05.txt"); - List segments = new(); - foreach (var line in lines) - { - var match = lineRegex.Match(line); - Line segment = new() - { - Start = new Point() - { - X = Convert.ToInt32(match.Groups["x1"].Value), - Y = Convert.ToInt32(match.Groups["y1"].Value), - }, - End = new Point() - { - X = Convert.ToInt32(match.Groups["x2"].Value), - Y = Convert.ToInt32(match.Groups["y2"].Value) - }, - }; - segments.Add(segment); - } - - Part1(segments); - Part2(segments); - Logger.Log(""); - } - - private static void Part1(IEnumerable lines) - { - using var t = new Timer(); - int numPointsGreater = Solve(lines, (line) => !(line.Start.X == line.End.X || line.Start.Y == line.End.Y)); - Logger.Log($"part1: {numPointsGreater}"); - } - - private static void Part2(IEnumerable lines) - { - using var t = new Timer(); - int numPointsGreater = Solve(lines, (line) => false); - Logger.Log($"part2: {numPointsGreater}"); - } - - private static int Solve(IEnumerable lines, Func filter) - { - Dictionary coveredPoints = new(); - int numPointsGreater = 0; - foreach (var line in lines) - { - if (filter(line)) - { - continue; + return Math.Abs((End.X - Start.X) + (End.Y - Start.Y)); } - for (int i = 0; i <= line.Length; i++) - { - int x = line.Start.X; - int y = line.Start.Y; - if (line.Start.X != line.End.X) - { - x += (line.Start.X > line.End.X ? -1 : 1) * i; - } - if (line.Start.Y != line.End.Y) - { - y += (line.Start.Y > line.End.Y ? -1 : 1) * i; - } - - Point point = new() { X = x, Y = y }; - if (!coveredPoints.TryGetValue(point, out int curr)) - { - coveredPoints.Add(point, curr); - } - - if (curr == 1) - { - numPointsGreater++; - } - - coveredPoints[point] = curr + 1; - } + return Math.Abs(Start.X - End.X); } - - return numPointsGreater; } } + + internal override void Go() + { + Logger.Log("Day 5"); + Logger.Log("-----"); + var lines = File.ReadAllLines("inputs/05.txt"); + List segments = new(); + foreach (var line in lines) + { + var match = lineRegex.Match(line); + Line segment = new() + { + Start = new Point() + { + X = Convert.ToInt32(match.Groups["x1"].Value), + Y = Convert.ToInt32(match.Groups["y1"].Value), + }, + End = new Point() + { + X = Convert.ToInt32(match.Groups["x2"].Value), + Y = Convert.ToInt32(match.Groups["y2"].Value) + }, + }; + segments.Add(segment); + } + + Part1(segments); + Part2(segments); + Logger.Log(""); + } + + private static void Part1(IEnumerable lines) + { + using var t = new Timer(); + int numPointsGreater = Solve(lines, (line) => !(line.Start.X == line.End.X || line.Start.Y == line.End.Y)); + Logger.Log($"part1: {numPointsGreater}"); + } + + private static void Part2(IEnumerable lines) + { + using var t = new Timer(); + int numPointsGreater = Solve(lines, (line) => false); + Logger.Log($"part2: {numPointsGreater}"); + } + + private static int Solve(IEnumerable lines, Func filter) + { + Dictionary coveredPoints = new(); + int numPointsGreater = 0; + foreach (var line in lines) + { + if (filter(line)) + { + continue; + } + + for (int i = 0; i <= line.Length; i++) + { + int x = line.Start.X; + int y = line.Start.Y; + if (line.Start.X != line.End.X) + { + x += (line.Start.X > line.End.X ? -1 : 1) * i; + } + if (line.Start.Y != line.End.Y) + { + y += (line.Start.Y > line.End.Y ? -1 : 1) * i; + } + + Point point = new() { X = x, Y = y }; + if (!coveredPoints.TryGetValue(point, out int curr)) + { + coveredPoints.Add(point, curr); + } + + if (curr == 1) + { + numPointsGreater++; + } + + coveredPoints[point] = curr + 1; + } + } + + return numPointsGreater; + } } diff --git a/src/06.cs b/src/06.cs index 946286a..c00f03a 100644 --- a/src/06.cs +++ b/src/06.cs @@ -1,81 +1,80 @@ using System.Diagnostics; -namespace aoc2021 +namespace aoc2021; + +internal class Day06 : Day { - internal class Day06 + [DebuggerDisplay("{State}")] + struct Fish { - [DebuggerDisplay("{State}")] - struct Fish + public int State; + } + + internal override void Go() + { + Logger.Log("Day 6"); + Logger.Log("-----"); + var input = File.ReadAllText("inputs/06.txt"); + List fish = new(); + foreach (var state in input.Split(',')) { - public int State; + fish.Add(new Fish() { State = Convert.ToInt32(state) }); } + Part1(fish); + Part2(fish); + Logger.Log(""); + } - internal static void Go() + private static void Part1(IEnumerable fish) + { + using var t = new Timer(); + + var list = fish.ToList(); + // brute force method (my initial solution) + for (int day = 0; day < 80; day++) { - Logger.Log("Day 6"); - Logger.Log("-----"); - var input = File.ReadAllText("inputs/06.txt"); - List fish = new(); - foreach (var state in input.Split(',')) + for (int i = list.Count - 1; i >= 0; i--) { - fish.Add(new Fish() { State = Convert.ToInt32(state) }); - } - Part1(fish); - Part2(fish); - Logger.Log(""); - } - - private static void Part1(IEnumerable fish) - { - using var t = new Timer(); - - var list = fish.ToList(); - // brute force method (my initial solution) - for (int day = 0; day < 80; day++) - { - for (int i = list.Count - 1; i >= 0; i--) + Fish f = list[i]; + if (f.State == 0) { - Fish f = list[i]; - if (f.State == 0) - { - list.Add(new Fish() { State = 8 }); - f.State = 7; - } - - f.State--; - list[i] = f; + list.Add(new Fish() { State = 8 }); + f.State = 7; } + + f.State--; + list[i] = f; } + } #pragma warning disable CA1829 // Use Length/Count property instead of Count() when available - Count is of type int, list might be longer than that - Logger.Log($"part1: #fish={list.LongCount()}"); + Logger.Log($"part1: #fish={list.LongCount()}"); #pragma warning restore CA1829 // Use Length/Count property instead of Count() when available - } + } - private static void Part2(IEnumerable fish) + private static void Part2(IEnumerable fish) + { + using var t = new Timer(); + + // fast method (when brute force threatened to blow RAM and take way too long) + Dictionary fishAtState = new(); + for (int i = 0; i <= 8; i++) { - using var t = new Timer(); - - // fast method (when brute force threatened to blow RAM and take way too long) - Dictionary fishAtState = new(); - for (int i = 0; i <= 8; i++) - { - fishAtState[i] = fish.Count(x => x.State == i); - } - - for (int day = 0; day < 256; day++) - { - var adders = fishAtState[0]; - for (int i = 0; i < 8; i++) - { - fishAtState[i] = fishAtState[i + 1]; - } - - fishAtState[6] += adders; - fishAtState[8] = adders; - } - - Logger.Log($"part2: #fish={fishAtState.Values.Sum()}"); + fishAtState[i] = fish.Count(x => x.State == i); } + + for (int day = 0; day < 256; day++) + { + var adders = fishAtState[0]; + for (int i = 0; i < 8; i++) + { + fishAtState[i] = fishAtState[i + 1]; + } + + fishAtState[6] += adders; + fishAtState[8] = adders; + } + + Logger.Log($"part2: #fish={fishAtState.Values.Sum()}"); } } diff --git a/src/07.cs b/src/07.cs index 9a6c66a..cc30e5c 100644 --- a/src/07.cs +++ b/src/07.cs @@ -1,59 +1,58 @@ -namespace aoc2021 +namespace aoc2021; + +internal class Day07 : Day { - internal class Day07 + internal override void Go() { - internal static void Go() - { - Logger.Log("Day 7"); - Logger.Log("-----"); - var nums = File.ReadAllText("inputs/07.txt").Split(',').Select(int.Parse); - Part1(nums); - Part2(nums); - Logger.Log(""); - } + Logger.Log("Day 7"); + Logger.Log("-----"); + var nums = File.ReadAllText("inputs/07.txt").Split(',').Select(int.Parse); + Part1(nums); + Part2(nums); + Logger.Log(""); + } - private static (long, int) Solve(IEnumerable nums, Func formula) + private static (long, int) Solve(IEnumerable nums, Func formula) + { + var min = nums.Min(); + var max = nums.Max(); + long minDist = long.MaxValue; + int minNum = 0; + for (int i = min; i <= max; i++) { - var min = nums.Min(); - var max = nums.Max(); - long minDist = long.MaxValue; - int minNum = 0; - for (int i = min; i <= max; i++) + long dist = 0; + foreach (var num in nums) { - long dist = 0; - foreach (var num in nums) - { - dist += formula(Math.Abs(num - i)); - } - - if (dist < minDist) - { - minDist = dist; - minNum = i; - } + dist += formula(Math.Abs(num - i)); } - return (minDist, minNum); + if (dist < minDist) + { + minDist = dist; + minNum = i; + } } - private static void Part1(IEnumerable nums) - { - using var t = new Timer(); + return (minDist, minNum); + } - var (minDist, minNum) = Solve(nums, (d) => d); + private static void Part1(IEnumerable nums) + { + using var t = new Timer(); - Logger.Log($"part1: position: {minNum}, fuel cost: {minDist}"); - } + var (minDist, minNum) = Solve(nums, (d) => d); - private static void Part2(IEnumerable nums) - { - using var t = new Timer(); + Logger.Log($"part1: position: {minNum}, fuel cost: {minDist}"); + } - // summation formula from https://en.wikipedia.org/wiki/Summation - // found by searching "factorial but with addition" because i'm smart like that. - var (minDist, minNum) = Solve(nums, (d) => ((d*d)+d)/2); + private static void Part2(IEnumerable nums) + { + using var t = new Timer(); - Logger.Log($"part2: position: {minNum}, fuel cost: {minDist}"); - } + // summation formula from https://en.wikipedia.org/wiki/Summation + // found by searching "factorial but with addition" because i'm smart like that. + var (minDist, minNum) = Solve(nums, (d) => ((d * d) + d) / 2); + + Logger.Log($"part2: position: {minNum}, fuel cost: {minDist}"); } } diff --git a/src/08.cs b/src/08.cs index 63926b7..a8867e8 100644 --- a/src/08.cs +++ b/src/08.cs @@ -1,174 +1,173 @@ -namespace aoc2021 +namespace aoc2021; + +internal class Day08 : Day { - internal class Day08 + internal override void Go() { - internal static void Go() + Logger.Log("Day 8"); + Logger.Log("-----"); + var lines = File.ReadAllLines("inputs/08.txt"); + List<(List, List)> puzzle = new(); + foreach (var line in lines) { - Logger.Log("Day 8"); - Logger.Log("-----"); - var lines = File.ReadAllLines("inputs/08.txt"); - List<(List, List)> puzzle = new(); - foreach (var line in lines) + var portions = line.Split(" | "); + puzzle.Add((new List(portions[0].Split(' ')), new List(portions[1].Split(' ')))); + } + Part1(puzzle); + Part2(puzzle); + Logger.Log(""); + } + + private static void Part1(List<(List, List)> lines) + { + using var t = new Timer(); + + int count = 0; + foreach (var line in lines) + { + foreach (var combo in line.Item2) { - var portions = line.Split(" | "); - puzzle.Add((new List(portions[0].Split(' ')), new List(portions[1].Split(' ')))); + switch (combo.Length) + { + case 2: // 1 + case 4: // 4 + case 3: // 7 + case 7: // 8 + count++; + break; + } } - Part1(puzzle); - Part2(puzzle); - Logger.Log(""); } - private static void Part1(List<(List, List)> lines) - { - using var t = new Timer(); + Logger.Log($"part1: {count}"); + } - int count = 0; - foreach (var line in lines) + private static void Part2(List<(List, List)> lines) + { + using var t = new Timer(); + + long sum = 0; + foreach (var line in lines) + { + var segments = new char[7]; + var one = line.Item1.First(x => x.Length == 2); + var four = line.Item1.First(x => x.Length == 4); + var seven = line.Item1.First(x => x.Length == 3); + var eight = line.Item1.First(x => x.Length == 7); + + var len5 = line.Item1.Where(x => x.Length == 5); // 2, 3, 5 + var len6 = line.Item1.Where(x => x.Length == 6); // 0, 6, 9 + + // top + segments[0] = seven.First(x => !one.Contains(x)); + + // bottom + foreach (var pattern in len6) { - foreach (var combo in line.Item2) + var leftover = pattern.Where(x => !seven.Contains(x) && !four.Contains(x)); + if (leftover.Count() == 1) { - switch (combo.Length) - { - case 2: // 1 - case 4: // 4 - case 3: // 7 - case 7: // 8 - count++; - break; - } + segments[6] = leftover.First(); } } - Logger.Log($"part1: {count}"); - } + var three = len5.First(seg => seg.Contains(segments[0]) && seg.Contains(segments[6]) && seg.Contains(one[0]) && seg.Contains(one[1])); + // center + segments[3] = three.First(x => x != segments[0] && x != segments[6] && !one.Contains(x)); - private static void Part2(List<(List, List)> lines) - { - using var t = new Timer(); + // bottom left + segments[4] = eight.First(x => x != segments[0] && !four.Contains(x) && x != segments[6]); - long sum = 0; - foreach (var line in lines) + // top left + segments[1] = eight.First(x => !three.Contains(x) && x != segments[4]); + + var two = len5.First(x => x.Where(y => y != segments[0] && y != segments[6]).Except(four).Count() == 1); + //var five = len5.First(x => x != two && x != three); + var nine = len6.First(x => !x.Except(four).Except(new List() { segments[0], segments[6] }).Any()); + var zero = len6.First(x => !x.Contains(segments[3])); + var six = len6.First(x => x != zero && x != nine); + + // bottom right + segments[5] = six.Except(two).First(x => x != segments[1]); + + // top right + segments[2] = one.First(x => x != segments[5]); + + int num = 0; + for (int i = 0; i < line.Item2.Count; i++) { - var segments = new char[7]; - var one = line.Item1.First(x => x.Length == 2); - var four = line.Item1.First(x => x.Length == 4); - var seven = line.Item1.First(x => x.Length == 3); - var eight = line.Item1.First(x => x.Length == 7); - - var len5 = line.Item1.Where(x => x.Length == 5); // 2, 3, 5 - var len6 = line.Item1.Where(x => x.Length == 6); // 0, 6, 9 - - // top - segments[0] = seven.First(x => !one.Contains(x)); - - // bottom - foreach (var pattern in len6) - { - var leftover = pattern.Where(x => !seven.Contains(x) && !four.Contains(x)); - if (leftover.Count() == 1) - { - segments[6] = leftover.First(); - } - } - - var three = len5.First(seg => seg.Contains(segments[0]) && seg.Contains(segments[6]) && seg.Contains(one[0]) && seg.Contains(one[1])); - // center - segments[3] = three.First(x => x != segments[0] && x != segments[6] && !one.Contains(x)); - - // bottom left - segments[4] = eight.First(x => x != segments[0] && !four.Contains(x) && x != segments[6]); - - // top left - segments[1] = eight.First(x => !three.Contains(x) && x != segments[4]); - - var two = len5.First(x => x.Where(y => y != segments[0] && y != segments[6]).Except(four).Count() == 1); - //var five = len5.First(x => x != two && x != three); - var nine = len6.First(x => !x.Except(four).Except(new List() { segments[0], segments[6] }).Any()); - var zero = len6.First(x => !x.Contains(segments[3])); - var six = len6.First(x => x != zero && x != nine); - - // bottom right - segments[5] = six.Except(two).First(x => x != segments[1]); - - // top right - segments[2] = one.First(x => x != segments[5]); - - int num = 0; - for (int i = 0; i < line.Item2.Count; i++) - { - var numInt = FindNum(segments, line.Item2[i]); - num += numInt * (int)Math.Pow(10, (line.Item2.Count - i - 1)); - } - - sum += num; + var numInt = FindNum(segments, line.Item2[i]); + num += numInt * (int)Math.Pow(10, (line.Item2.Count - i - 1)); } - Logger.Log($"part2: {sum}"); + sum += num; } - private static int FindNum(char[] segments, string num) + Logger.Log($"part2: {sum}"); + } + + private static int FindNum(char[] segments, string num) + { + // i already solved for each number in part2, so it's kind of dumb to rebuild my own set of numbers here, + // but this is all left over from my various different attempts to solve this different ways. + // and it works, so whatever. + var zero = new List() { segments[0], segments[1], segments[2], segments[4], segments[5], segments[6] }; + var six = new List() { segments[0], segments[1], segments[3], segments[4], segments[5], segments[6] }; + var nine = new List() { segments[0], segments[1], segments[2], segments[3], segments[5], segments[6] }; + var two = new List() { segments[0], segments[2], segments[3], segments[4], segments[6] }; + var three = new List() { segments[0], segments[2], segments[3], segments[5], segments[6] }; + var five = new List() { segments[0], segments[1], segments[3], segments[5], segments[6] }; + + switch (num.Length) { - // i already solved for each number in part2, so it's kind of dumb to rebuild my own set of numbers here, - // but this is all left over from my various different attempts to solve this different ways. - // and it works, so whatever. - var zero = new List() { segments[0], segments[1], segments[2], segments[4], segments[5], segments[6] }; - var six = new List() { segments[0], segments[1], segments[3], segments[4], segments[5], segments[6] }; - var nine = new List() { segments[0], segments[1], segments[2], segments[3], segments[5], segments[6] }; - var two = new List() { segments[0], segments[2], segments[3], segments[4], segments[6] }; - var three = new List() { segments[0], segments[2], segments[3], segments[5], segments[6] }; - var five = new List() { segments[0], segments[1], segments[3], segments[5], segments[6] }; + case 2: + return 1; - switch (num.Length) - { - case 2: - return 1; + case 3: + return 7; - case 3: - return 7; + case 4: + return 4; - case 4: - return 4; + case 7: + return 8; - case 7: - return 8; + case 6: + if (num.All(x => zero.Contains(x))) + { + return 0; + } + else if (num.All(x => six.Contains(x))) + { + return 6; + } + else if (num.All(x => nine.Contains(x))) + { + return 9; + } - case 6: - if (num.All(x => zero.Contains(x))) - { - return 0; - } - else if (num.All(x => six.Contains(x))) - { - return 6; - } - else if (num.All(x => nine.Contains(x))) - { - return 9; - } + throw new Exception(); - throw new Exception(); + case 5: + if (num.All(x => two.Contains(x))) + { + return 2; + } + else if (num.All(x => three.Contains(x))) + { + return 3; + } + else if (num.All(x => five.Contains(x))) + { + return 5; + } - case 5: - if (num.All(x => two.Contains(x))) - { - return 2; - } - else if (num.All(x => three.Contains(x))) - { - return 3; - } - else if (num.All(x => five.Contains(x))) - { - return 5; - } + throw new Exception(); - throw new Exception(); - - default: - throw new Exception(); - } - - throw new Exception(); + default: + throw new Exception(); } + + throw new Exception(); } } diff --git a/src/09.cs b/src/09.cs index eae3b84..1fc7beb 100644 --- a/src/09.cs +++ b/src/09.cs @@ -1,128 +1,127 @@ -namespace aoc2021 +namespace aoc2021; + +internal class Day09 : Day { - internal class Day09 + internal override void Go() { - internal static void Go() + Logger.Log("Day 9"); + Logger.Log("-----"); + var lines = File.ReadAllLines("inputs/09.txt"); + byte[,] grid = new byte[lines.Length, lines[0].Length]; + for (int i = 0; i < lines.Length; i++) { - Logger.Log("Day 9"); - Logger.Log("-----"); - var lines = File.ReadAllLines("inputs/09.txt"); - byte[,] grid = new byte[lines.Length, lines[0].Length]; - for (int i = 0; i < lines.Length; i++) + for (int j = 0; j < lines[i].Length; j++) { - for (int j = 0; j < lines[i].Length; j++) + grid[i, j] = (byte)char.GetNumericValue(lines[i][j]); + } + } + Part1(grid); + Part2(grid); + Logger.Log(""); + } + + private static void Part1(byte[,] grid) + { + using var t = new Timer(); + + var lowPoints = GetLowPoints(grid); + var totalRisk = lowPoints.Sum(x => grid[x.Item1, x.Item2] + 1); + + Logger.Log($"part1: {totalRisk}"); + } + + private static List<(int, int)> GetLowPoints(byte[,] grid) + { + List<(int, int)> lowPoints = new(); + for (int i = 0; i < grid.GetLength(0); i++) + { + for (int j = 0; j < grid.GetLength(1); j++) + { + byte val = grid[i, j]; + if (i > 0 && grid[i - 1, j] <= val) { - grid[i, j] = (byte)char.GetNumericValue(lines[i][j]); + continue; } - } - Part1(grid); - Part2(grid); - Logger.Log(""); - } - - private static void Part1(byte[,] grid) - { - using var t = new Timer(); - - var lowPoints = GetLowPoints(grid); - var totalRisk = lowPoints.Sum(x => grid[x.Item1, x.Item2] + 1); - - Logger.Log($"part1: {totalRisk}"); - } - - private static List<(int, int)> GetLowPoints(byte[,] grid) - { - List<(int, int)> lowPoints = new(); - for (int i = 0; i < grid.GetLength(0); i++) - { - for (int j = 0; j < grid.GetLength(1); j++) + if (i < grid.GetLength(0) - 1 && grid[i + 1, j] <= val) { - byte val = grid[i, j]; - if (i > 0 && grid[i - 1, j] <= val) - { - continue; - } - if (i < grid.GetLength(0) - 1 && grid[i + 1, j] <= val) - { - continue; - } - if (j > 0 && grid[i, j - 1] <= val) - { - continue; - } - if (j < grid.GetLength(1) - 1 && grid[i, j + 1] <= val) - { - continue; - } - - lowPoints.Add((i, j)); + continue; + } + if (j > 0 && grid[i, j - 1] <= val) + { + continue; + } + if (j < grid.GetLength(1) - 1 && grid[i, j + 1] <= val) + { + continue; } - } - return lowPoints; + lowPoints.Add((i, j)); + } } - private static void Part2(byte[,] grid) + return lowPoints; + } + + private static void Part2(byte[,] grid) + { + using var t = new Timer(); + + var lowPoints = GetLowPoints(grid); + List basins = new(); + foreach (var point in lowPoints) { - using var t = new Timer(); - - var lowPoints = GetLowPoints(grid); - List basins = new(); - foreach (var point in lowPoints) - { - var basinPoints = GetBasinSize(grid, point.Item1, point.Item2); - basins.Add(basinPoints.Distinct().Count() + 1); - } - var top3Mult = basins.OrderByDescending(x => x).Take(3).Aggregate(1, (x,y) => x * y); - - Logger.Log($"part2: {top3Mult}"); + var basinPoints = GetBasinSize(grid, point.Item1, point.Item2); + basins.Add(basinPoints.Distinct().Count() + 1); } + var top3Mult = basins.OrderByDescending(x => x).Take(3).Aggregate(1, (x, y) => x * y); - private static List<(int, int)> GetBasinSize(byte[,] grid, int i, int j) + Logger.Log($"part2: {top3Mult}"); + } + + private static List<(int, int)> GetBasinSize(byte[,] grid, int i, int j) + { + List<(int, int)> basinPoints = new(); + + if (i >= grid.GetLength(0) || j >= grid.GetLength(1) || i < 0 || j < 0) { - List<(int, int)> basinPoints = new(); - - if (i >= grid.GetLength(0) || j >= grid.GetLength(1) || i < 0 || j < 0) - { - return new(); - } - - if (!basinPoints.Contains((i - 1, j)) && IsBasinPoint(grid, grid[i, j], i - 1, j)) - { - basinPoints.Add((i - 1, j)); - basinPoints.AddRange(GetBasinSize(grid, i - 1, j)); - } - if (!basinPoints.Contains((i + 1, j)) && IsBasinPoint(grid, grid[i, j], i + 1, j)) - { - basinPoints.Add((i + 1, j)); - basinPoints.AddRange(GetBasinSize(grid, i + 1, j)); - } - if (!basinPoints.Contains((i, j - 1)) && IsBasinPoint(grid, grid[i, j], i, j - 1)) - { - basinPoints.Add((i, j - 1)); - basinPoints.AddRange(GetBasinSize(grid, i, j - 1)); - } - if (!basinPoints.Contains((i, j + 1)) && IsBasinPoint(grid, grid[i, j], i, j + 1)) - { - basinPoints.Add((i, j + 1)); - basinPoints.AddRange(GetBasinSize(grid, i, j + 1)); - } - - return basinPoints; + return new(); } - private static bool IsBasinPoint(byte[,] grid, byte val, int i, int j) + if (!basinPoints.Contains((i - 1, j)) && IsBasinPoint(grid, grid[i, j], i - 1, j)) { - if (i >= grid.GetLength(0) || j >= grid.GetLength(1) || i < 0 || j < 0) - { - return false; - } - if (grid[i, j] == 9 || val == 9) - { - return false; - } - - return grid[i, j] > val; + basinPoints.Add((i - 1, j)); + basinPoints.AddRange(GetBasinSize(grid, i - 1, j)); } + if (!basinPoints.Contains((i + 1, j)) && IsBasinPoint(grid, grid[i, j], i + 1, j)) + { + basinPoints.Add((i + 1, j)); + basinPoints.AddRange(GetBasinSize(grid, i + 1, j)); + } + if (!basinPoints.Contains((i, j - 1)) && IsBasinPoint(grid, grid[i, j], i, j - 1)) + { + basinPoints.Add((i, j - 1)); + basinPoints.AddRange(GetBasinSize(grid, i, j - 1)); + } + if (!basinPoints.Contains((i, j + 1)) && IsBasinPoint(grid, grid[i, j], i, j + 1)) + { + basinPoints.Add((i, j + 1)); + basinPoints.AddRange(GetBasinSize(grid, i, j + 1)); + } + + return basinPoints; + } + + private static bool IsBasinPoint(byte[,] grid, byte val, int i, int j) + { + if (i >= grid.GetLength(0) || j >= grid.GetLength(1) || i < 0 || j < 0) + { + return false; + } + if (grid[i, j] == 9 || val == 9) + { + return false; + } + + return grid[i, j] > val; } } diff --git a/src/10.cs b/src/10.cs index e0401f8..4dca8d3 100644 --- a/src/10.cs +++ b/src/10.cs @@ -1,62 +1,107 @@ -namespace aoc2021 +namespace aoc2021; + +internal class Day10 : Day { - internal class Day10 + internal override void Go() { - internal static void Go() + Logger.Log("Day 10"); + Logger.Log("-----"); + var lines = File.ReadAllLines("inputs/10.txt"); + Part1(lines); + Part2(lines); + Logger.Log(""); + } + + private static readonly List Openers = new() + { + '(', + '[', + '{', + '<', + }; + + private static readonly List Closers = new() + { + ')', + ']', + '}', + '>', + }; + + private static bool IsMatching(char open, char close) => Closers.IndexOf(close) == Openers.IndexOf(open); + + private static void Part1(IEnumerable lines) + { + List charVals = new() { - Logger.Log("Day 10"); - Logger.Log("-----"); - var lines = File.ReadAllLines("inputs/10.txt"); - Part1(lines); - Part2(lines); - Logger.Log(""); + 3, + 57, + 1197, + 25137, + }; + + using var t = new Timer(); + + long score = 0; + foreach (var line in lines) + { + var (corrupted, ch) = IsCorrupted(line); + if (corrupted) + { + score += charVals[Closers.IndexOf(ch)]; + } } - private static readonly List Openers = new() - { - '(', - '[', - '{', - '<', - }; + Logger.Log($"part1: {score}"); + } - private static readonly List Closers = new() + private static (bool, char) IsCorrupted(string line) + { + var s = new Stack(); + foreach (var ch in line) { - ')', - ']', - '}', - '>', - }; - - private static bool IsMatching(char open, char close) => Closers.IndexOf(close) == Openers.IndexOf(open); - - private static void Part1(IEnumerable lines) - { - List charVals = new() + if (Openers.Contains(ch)) { - 3, - 57, - 1197, - 25137, - }; - - using var t = new Timer(); - - long score = 0; - foreach (var line in lines) + s.Push(ch); + } + else if (Closers.Contains(ch)) { - var (corrupted, ch) = IsCorrupted(line); - if (corrupted) + var popped = s.Pop(); + if (!IsMatching(popped, ch)) { - score += charVals[Closers.IndexOf(ch)]; + return (true, ch); } } - - Logger.Log($"part1: {score}"); + else + { + throw new Exception(); + } } - private static (bool, char) IsCorrupted(string line) + return (false, '\0'); + } + + private static void Part2(IEnumerable lines) + { + List charVals = new() { + 1, + 2, + 3, + 4, + }; + + using var t = new Timer(); + + List scores = new(); + foreach (var line in lines) + { + var (corrupted, _) = IsCorrupted(line); + if (corrupted) + { + continue; + } + var s = new Stack(); foreach (var ch in line) { @@ -66,11 +111,7 @@ } else if (Closers.Contains(ch)) { - var popped = s.Pop(); - if (!IsMatching(popped, ch)) - { - return (true, ch); - } + s.Pop(); } else { @@ -78,65 +119,23 @@ } } - return (false, '\0'); + long score = 0; + while (s.Count > 0) + { + var ch = s.Pop(); + score = (score * 5) + charVals[Openers.IndexOf(ch)]; + } + + scores.Add(score); } - private static void Part2(IEnumerable lines) + if (scores.Count % 2 == 0) { - List charVals = new() - { - 1, - 2, - 3, - 4, - }; - - using var t = new Timer(); - - List scores = new(); - foreach (var line in lines) - { - var (corrupted, _) = IsCorrupted(line); - if (corrupted) - { - continue; - } - - var s = new Stack(); - foreach (var ch in line) - { - if (Openers.Contains(ch)) - { - s.Push(ch); - } - else if (Closers.Contains(ch)) - { - s.Pop(); - } - else - { - throw new Exception(); - } - } - - long score = 0; - while (s.Count > 0) - { - var ch = s.Pop(); - score = (score * 5) + charVals[Openers.IndexOf(ch)]; - } - - scores.Add(score); - } - - if (scores.Count % 2 == 0) - { - throw new Exception(); - } - - var final = scores.OrderBy(x => x).Skip(scores.Count / 2).First(); - - Logger.Log($"part2: {final}"); + throw new Exception(); } + + var final = scores.OrderBy(x => x).Skip(scores.Count / 2).First(); + + Logger.Log($"part2: {final}"); } } diff --git a/src/11.cs b/src/11.cs index c7cf47c..6ed03fc 100644 --- a/src/11.cs +++ b/src/11.cs @@ -1,8 +1,8 @@ namespace aoc2021; -internal class Day11 +internal class Day11 : Day { - internal static void Go() + internal override void Go() { Logger.Log("Day 11"); Logger.Log("-----"); diff --git a/src/12.cs b/src/12.cs index e1c9e38..6a7a3c6 100644 --- a/src/12.cs +++ b/src/12.cs @@ -1,8 +1,8 @@ namespace aoc2021; -internal class Day12 +internal class Day12 : Day { - internal static void Go() + internal override void Go() { Logger.Log("Day 12"); Logger.Log("-----"); diff --git a/src/Day.cs b/src/Day.cs new file mode 100644 index 0000000..751fd61 --- /dev/null +++ b/src/Day.cs @@ -0,0 +1,6 @@ +namespace aoc2021; + +internal abstract class Day +{ + internal abstract void Go(); +} diff --git a/src/Template.cs b/src/Template.cs index c6d9115..a0d6858 100644 --- a/src/Template.cs +++ b/src/Template.cs @@ -1,8 +1,8 @@ namespace aoc2021; -internal class DayTemplate +internal class DayTemplate : Day { - internal static void Go() + internal override void Go() { Logger.Log("Day #"); Logger.Log("-----"); diff --git a/src/main.cs b/src/main.cs index 0e612e9..405ad9a 100644 --- a/src/main.cs +++ b/src/main.cs @@ -1,47 +1,36 @@ +using aoc2021; + var arg = args.FirstOrDefault(); -switch (arg) +if (arg == "all") { - case "1": - aoc2021.Day01.Go(); - break; + var types = System.Reflection.Assembly + .GetExecutingAssembly() + .GetTypes() + .Where(t => t.IsSubclassOf(typeof(Day)) && !t.IsAbstract && t.Name != "DayTemplate") + .OrderBy(t => t.Name); - case "2": - aoc2021.Day02.Go(); - break; - - case "3": - aoc2021.Day03.Go(); - break; - - case "5": - aoc2021.Day05.Go(); - break; - - case "6": - aoc2021.Day06.Go(); - break; - - case "7": - aoc2021.Day07.Go(); - break; - - case "8": - aoc2021.Day08.Go(); - break; - - case "9": - aoc2021.Day09.Go(); - break; - - case "10": - aoc2021.Day10.Go(); - break; - - case "11": - aoc2021.Day11.Go(); - break; - - default: - aoc2021.Day12.Go(); - break; + foreach (var type in types) + { + var day = (Day)Activator.CreateInstance(type)!; + day.Go(); + } +} +else +{ + Day day = arg switch + { + "1" => new Day01(), + "2" => new Day02(), + "3" => new Day03(), + //"4" => new Day04(), + "5" => new Day05(), + "6" => new Day06(), + "7" => new Day07(), + "8" => new Day08(), + "9" => new Day09(), + "10" => new Day10(), + "11" => new Day11(), + _ => new Day12(), + }; + day.Go(); }