Enable running all days at once

I'm kinda bored and wanted to.
This commit is contained in:
2021-12-12 15:28:41 -06:00
parent 5c37fc4129
commit 9e7942a35e
15 changed files with 845 additions and 848 deletions

View File

@ -0,0 +1,11 @@
{
"profiles": {
"All": {
"commandName": "Project",
"commandLineArgs": "all"
},
"Default day": {
"commandName": "Project"
}
}
}

107
src/01.cs
View File

@ -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<string> lines)
{
using var t = new Timer();
int lastDepth = 0;
int numIncreased = -1;
foreach (var line in lines)
{ {
Logger.Log("Day 1"); var depth = Convert.ToInt32(line);
Logger.Log("-----"); if (depth > lastDepth)
var lines = File.ReadAllLines("inputs/01.txt");
Part1(lines);
Part2(lines);
Logger.Log("");
}
private static void Part1(IEnumerable<string> lines)
{
using var t = new Timer();
int lastDepth = 0;
int numIncreased = -1;
foreach (var line in lines)
{ {
var depth = Convert.ToInt32(line); numIncreased++;
if (depth > lastDepth)
{
numIncreased++;
}
lastDepth = depth;
} }
Logger.Log($"part1: {numIncreased}"); lastDepth = depth;
} }
private static void Part2(IEnumerable<string> lines) Logger.Log($"part1: {numIncreased}");
}
private static void Part2(IEnumerable<string> 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; if (num1 < 0 || num2 < 0 || num3 < 0)
int numIncreased = -1;
int num1 = -1;
int num2 = -1;
int num3 = -1;
foreach (var line in lines)
{ {
var depth = Convert.ToInt32(line); continue;
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;
} }
Logger.Log($"part2: {numIncreased}"); var total = num1 + num2 + num3;
if (total > lastTotal)
{
numIncreased++;
}
lastTotal = total;
} }
Logger.Log($"part2: {numIncreased}");
} }
} }

133
src/02.cs
View File

@ -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<Instruction>();
foreach (var instruction in lines)
{ {
Logger.Log("Day 2"); var fmt = instruction.Split(' ');
Logger.Log("-----"); instructions.Add(new Instruction()
var lines = File.ReadAllLines("inputs/02.txt");
var instructions = new List<Instruction>();
foreach (var instruction in lines)
{ {
var fmt = instruction.Split(' '); Direction = fmt[0],
instructions.Add(new Instruction() Amount = Convert.ToInt64(fmt[1]),
{ });
Direction = fmt[0],
Amount = Convert.ToInt64(fmt[1]),
});
}
Part1(instructions);
Part2(instructions);
Logger.Log("");
} }
struct Instruction Part1(instructions);
{ Part2(instructions);
public string Direction; Logger.Log("");
public long Amount; }
}
struct Position struct Instruction
{ {
public long h; public string Direction;
public long d; public long Amount;
} }
private static void Part1(IEnumerable<Instruction> instructions) struct Position
{
public long h;
public long d;
}
private static void Part1(IEnumerable<Instruction> instructions)
{
using var t = new Timer();
Position pos = new();
foreach (var instruction in instructions)
{ {
using var t = new Timer(); switch (instruction.Direction)
Position pos = new();
foreach (var instruction in instructions)
{ {
switch (instruction.Direction) case "forward":
{ pos.h += instruction.Amount;
case "forward": break;
pos.h += instruction.Amount;
break;
case "down": case "down":
pos.d += instruction.Amount; pos.d += instruction.Amount;
break; break;
case "up": case "up":
pos.d -= instruction.Amount; pos.d -= instruction.Amount;
break; break;
}
} }
Logger.Log($"part1: h: {pos.h}, d: {pos.d}, result: {pos.h * pos.d}");
} }
private static void Part2(IEnumerable<Instruction> instructions) Logger.Log($"part1: h: {pos.h}, d: {pos.d}, result: {pos.h * pos.d}");
}
private static void Part2(IEnumerable<Instruction> instructions)
{
using var t = new Timer();
Position pos = new();
long aim = 0;
foreach (var instruction in instructions)
{ {
using var t = new Timer(); switch (instruction.Direction)
Position pos = new();
long aim = 0;
foreach (var instruction in instructions)
{ {
switch (instruction.Direction) case "forward":
{ pos.h += instruction.Amount;
case "forward": pos.d += aim * instruction.Amount;
pos.h += instruction.Amount; break;
pos.d += aim * instruction.Amount;
break;
case "down": case "down":
aim += instruction.Amount; aim += instruction.Amount;
break; break;
case "up": case "up":
aim -= instruction.Amount; aim -= instruction.Amount;
break; 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}");
} }
} }

209
src/03.cs
View File

@ -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("-----");
Logger.Log("Day 3"); var lines = File.ReadAllLines("inputs/03.txt");
Logger.Log("-----"); Part1(lines);
var lines = File.ReadAllLines("inputs/03.txt"); Part2(lines);
Part1(lines); Logger.Log("");
Part2(lines); }
Logger.Log("");
}
private static void Part1(IEnumerable<string> lines) private static void Part1(IEnumerable<string> 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 numZero = 0;
var len = lines.First().Length; var numOne = 0;
int gammaRate = 0; foreach (var line in lines)
int epsilonRate = 0;
for (int i = 0; i < len; i++)
{ {
var numZero = 0; if (line[i] == '0')
var numOne = 0;
foreach (var line in lines)
{ {
if (line[i] == '0') numZero++;
{
numZero++;
}
else if (line[i] == '1')
{
numOne++;
}
} }
else if (line[i] == '1')
if (numOne > numZero)
{ {
gammaRate |= (1 << (len - i - 1)); numOne++;
}
else if (numZero > numOne)
{
epsilonRate |= (1 << (len - i - 1));
} }
} }
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<string> lines) Logger.Log($"part1: gamma rate: {gammaRate}, epsilon rate: {epsilonRate}, mult: {gammaRate * epsilonRate}");
}
private static void Part2(IEnumerable<string> 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(); var numZero = 0;
int o2 = 0; var numOne = 0;
int co2 = 0; foreach (var line in filtered)
var filtered = lines.ToList();
for (int i = 0; i < lines.First().Length; i++)
{ {
var numZero = 0; if (line[i] == '0')
var numOne = 0;
foreach (var line in filtered)
{ {
if (line[i] == '0') numZero++;
{
numZero++;
}
else if (line[i] == '1')
{
numOne++;
}
} }
else if (line[i] == '1')
if (numOne > numZero)
{ {
filtered.RemoveAll(x => x[i] != '1'); numOne++;
}
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;
} }
} }
filtered = lines.ToList(); if (numOne > numZero)
for (int i = 0; i < lines.First().Length; i++)
{ {
var numZero = 0; filtered.RemoveAll(x => x[i] != '1');
var numOne = 0; }
foreach (var line in filtered) else if (numZero > numOne)
{ {
if (line[i] == '0') filtered.RemoveAll(x => x[i] != '0');
{ }
numZero++; else
} {
else if (line[i] == '1') filtered.RemoveAll(x => x[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}"); 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}");
} }
} }

229
src/05.cs
View File

@ -1,130 +1,129 @@
using System.Diagnostics; using System.Diagnostics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace aoc2021 namespace aoc2021;
internal class Day05 : Day
{ {
internal class Day05 private static readonly Regex lineRegex = new(@"(?<x1>\d+),(?<y1>\d+) -> (?<x2>\d+),(?<y2>\d+)", RegexOptions.Compiled);
[DebuggerDisplay("{x},{y}")]
struct Point : IEquatable<Point>
{ {
private static readonly Regex lineRegex = new(@"(?<x1>\d+),(?<y1>\d+) -> (?<x2>\d+),(?<y2>\d+)", RegexOptions.Compiled); public int X { get; init; }
public int Y { get; init; }
[DebuggerDisplay("{x},{y}")] public bool Equals(Point other) => X == other.X && Y == other.Y;
struct Point : IEquatable<Point>
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; } get
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 // this is bad and i feel bad
if (Start.X == End.X || Start.Y == End.Y)
{ {
// this is bad and i feel bad return Math.Abs((End.X - Start.X) + (End.Y - Start.Y));
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<Line> 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<Line> 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<Line> lines)
{
using var t = new Timer();
int numPointsGreater = Solve(lines, (line) => false);
Logger.Log($"part2: {numPointsGreater}");
}
private static int Solve(IEnumerable<Line> lines, Func<Line, bool> filter)
{
Dictionary<Point, int> coveredPoints = new();
int numPointsGreater = 0;
foreach (var line in lines)
{
if (filter(line))
{
continue;
} }
for (int i = 0; i <= line.Length; i++) return Math.Abs(Start.X - End.X);
{
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;
} }
} }
internal override void Go()
{
Logger.Log("Day 5");
Logger.Log("-----");
var lines = File.ReadAllLines("inputs/05.txt");
List<Line> 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<Line> 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<Line> lines)
{
using var t = new Timer();
int numPointsGreater = Solve(lines, (line) => false);
Logger.Log($"part2: {numPointsGreater}");
}
private static int Solve(IEnumerable<Line> lines, Func<Line, bool> filter)
{
Dictionary<Point, int> 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;
}
} }

121
src/06.cs
View File

@ -1,81 +1,80 @@
using System.Diagnostics; using System.Diagnostics;
namespace aoc2021 namespace aoc2021;
internal class Day06 : Day
{ {
internal class Day06 [DebuggerDisplay("{State}")]
struct Fish
{ {
[DebuggerDisplay("{State}")] public int State;
struct Fish }
internal override void Go()
{
Logger.Log("Day 6");
Logger.Log("-----");
var input = File.ReadAllText("inputs/06.txt");
List<Fish> 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> 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"); for (int i = list.Count - 1; i >= 0; i--)
Logger.Log("-----");
var input = File.ReadAllText("inputs/06.txt");
List<Fish> fish = new();
foreach (var state in input.Split(','))
{ {
fish.Add(new Fish() { State = Convert.ToInt32(state) }); Fish f = list[i];
} if (f.State == 0)
Part1(fish);
Part2(fish);
Logger.Log("");
}
private static void Part1(IEnumerable<Fish> 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]; list.Add(new Fish() { State = 8 });
if (f.State == 0) f.State = 7;
{
list.Add(new Fish() { State = 8 });
f.State = 7;
}
f.State--;
list[i] = f;
} }
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 #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 #pragma warning restore CA1829 // Use Length/Count property instead of Count() when available
} }
private static void Part2(IEnumerable<Fish> fish) private static void Part2(IEnumerable<Fish> fish)
{
using var t = new Timer();
// fast method (when brute force threatened to blow RAM and take way too long)
Dictionary<int, long> fishAtState = new();
for (int i = 0; i <= 8; i++)
{ {
using var t = new Timer(); fishAtState[i] = fish.Count(x => x.State == i);
// fast method (when brute force threatened to blow RAM and take way too long)
Dictionary<int, long> 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()}");
} }
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()}");
} }
} }

View File

@ -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("-----");
Logger.Log("Day 7"); var nums = File.ReadAllText("inputs/07.txt").Split(',').Select(int.Parse);
Logger.Log("-----"); Part1(nums);
var nums = File.ReadAllText("inputs/07.txt").Split(',').Select(int.Parse); Part2(nums);
Part1(nums); Logger.Log("");
Part2(nums); }
Logger.Log("");
}
private static (long, int) Solve(IEnumerable<int> nums, Func<long, long> formula) private static (long, int) Solve(IEnumerable<int> nums, Func<long, long> 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(); long dist = 0;
var max = nums.Max(); foreach (var num in nums)
long minDist = long.MaxValue;
int minNum = 0;
for (int i = min; i <= max; i++)
{ {
long dist = 0; dist += formula(Math.Abs(num - i));
foreach (var num in nums)
{
dist += formula(Math.Abs(num - i));
}
if (dist < minDist)
{
minDist = dist;
minNum = i;
}
} }
return (minDist, minNum); if (dist < minDist)
{
minDist = dist;
minNum = i;
}
} }
private static void Part1(IEnumerable<int> nums) return (minDist, minNum);
{ }
using var t = new Timer();
var (minDist, minNum) = Solve(nums, (d) => d); private static void Part1(IEnumerable<int> 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<int> nums) Logger.Log($"part1: position: {minNum}, fuel cost: {minDist}");
{ }
using var t = new Timer();
// summation formula from https://en.wikipedia.org/wiki/Summation private static void Part2(IEnumerable<int> nums)
// found by searching "factorial but with addition" because i'm smart like that. {
var (minDist, minNum) = Solve(nums, (d) => ((d*d)+d)/2); 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}");
} }
} }

283
src/08.cs
View File

@ -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<string>, List<string>)> puzzle = new();
foreach (var line in lines)
{ {
Logger.Log("Day 8"); var portions = line.Split(" | ");
Logger.Log("-----"); puzzle.Add((new List<string>(portions[0].Split(' ')), new List<string>(portions[1].Split(' '))));
var lines = File.ReadAllLines("inputs/08.txt"); }
List<(List<string>, List<string>)> puzzle = new(); Part1(puzzle);
foreach (var line in lines) Part2(puzzle);
Logger.Log("");
}
private static void Part1(List<(List<string>, List<string>)> lines)
{
using var t = new Timer();
int count = 0;
foreach (var line in lines)
{
foreach (var combo in line.Item2)
{ {
var portions = line.Split(" | "); switch (combo.Length)
puzzle.Add((new List<string>(portions[0].Split(' ')), new List<string>(portions[1].Split(' ')))); {
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<string>, List<string>)> lines) Logger.Log($"part1: {count}");
{ }
using var t = new Timer();
int count = 0; private static void Part2(List<(List<string>, List<string>)> lines)
foreach (var line in 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) segments[6] = leftover.First();
{
case 2: // 1
case 4: // 4
case 3: // 7
case 7: // 8
count++;
break;
}
} }
} }
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<string>, List<string>)> lines) // bottom left
{ segments[4] = eight.First(x => x != segments[0] && !four.Contains(x) && x != segments[6]);
using var t = new Timer();
long sum = 0; // top left
foreach (var line in lines) 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<char>() { 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 numInt = FindNum(segments, line.Item2[i]);
var one = line.Item1.First(x => x.Length == 2); num += numInt * (int)Math.Pow(10, (line.Item2.Count - i - 1));
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<char>() { 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;
} }
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<char>() { segments[0], segments[1], segments[2], segments[4], segments[5], segments[6] };
var six = new List<char>() { segments[0], segments[1], segments[3], segments[4], segments[5], segments[6] };
var nine = new List<char>() { segments[0], segments[1], segments[2], segments[3], segments[5], segments[6] };
var two = new List<char>() { segments[0], segments[2], segments[3], segments[4], segments[6] };
var three = new List<char>() { segments[0], segments[2], segments[3], segments[5], segments[6] };
var five = new List<char>() { 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, case 2:
// but this is all left over from my various different attempts to solve this different ways. return 1;
// and it works, so whatever.
var zero = new List<char>() { segments[0], segments[1], segments[2], segments[4], segments[5], segments[6] };
var six = new List<char>() { segments[0], segments[1], segments[3], segments[4], segments[5], segments[6] };
var nine = new List<char>() { segments[0], segments[1], segments[2], segments[3], segments[5], segments[6] };
var two = new List<char>() { segments[0], segments[2], segments[3], segments[4], segments[6] };
var three = new List<char>() { segments[0], segments[2], segments[3], segments[5], segments[6] };
var five = new List<char>() { segments[0], segments[1], segments[3], segments[5], segments[6] };
switch (num.Length) case 3:
{ return 7;
case 2:
return 1;
case 3: case 4:
return 7; return 4;
case 4: case 7:
return 4; return 8;
case 7: case 6:
return 8; 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: throw new Exception();
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(); 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: throw new Exception();
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(); default:
throw new Exception();
default:
throw new Exception();
}
throw new Exception();
} }
throw new Exception();
} }
} }

213
src/09.cs
View File

@ -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"); for (int j = 0; j < lines[i].Length; j++)
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++) 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;
} }
} if (i < grid.GetLength(0) - 1 && grid[i + 1, j] <= val)
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]; continue;
if (i > 0 && grid[i - 1, j] <= val) }
{ if (j > 0 && grid[i, j - 1] <= val)
continue; {
} continue;
if (i < grid.GetLength(0) - 1 && grid[i + 1, j] <= val) }
{ if (j < grid.GetLength(1) - 1 && grid[i, j + 1] <= val)
continue; {
} 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));
} }
}
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<int> basins = new();
foreach (var point in lowPoints)
{ {
using var t = new Timer(); var basinPoints = GetBasinSize(grid, point.Item1, point.Item2);
basins.Add(basinPoints.Distinct().Count() + 1);
var lowPoints = GetLowPoints(grid);
List<int> 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 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(); return 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;
} }
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) basinPoints.Add((i - 1, j));
{ basinPoints.AddRange(GetBasinSize(grid, i - 1, j));
return false;
}
if (grid[i, j] == 9 || val == 9)
{
return false;
}
return grid[i, j] > val;
} }
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;
} }
} }

209
src/10.cs
View File

@ -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<char> Openers = new()
{
'(',
'[',
'{',
'<',
};
private static readonly List<char> Closers = new()
{
')',
']',
'}',
'>',
};
private static bool IsMatching(char open, char close) => Closers.IndexOf(close) == Openers.IndexOf(open);
private static void Part1(IEnumerable<string> lines)
{
List<int> charVals = new()
{ {
Logger.Log("Day 10"); 3,
Logger.Log("-----"); 57,
var lines = File.ReadAllLines("inputs/10.txt"); 1197,
Part1(lines); 25137,
Part2(lines); };
Logger.Log("");
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<char> Openers = new() Logger.Log($"part1: {score}");
{ }
'(',
'[',
'{',
'<',
};
private static readonly List<char> Closers = new() private static (bool, char) IsCorrupted(string line)
{
var s = new Stack<char>();
foreach (var ch in line)
{ {
')', if (Openers.Contains(ch))
']',
'}',
'>',
};
private static bool IsMatching(char open, char close) => Closers.IndexOf(close) == Openers.IndexOf(open);
private static void Part1(IEnumerable<string> lines)
{
List<int> charVals = new()
{ {
3, s.Push(ch);
57, }
1197, else if (Closers.Contains(ch))
25137,
};
using var t = new Timer();
long score = 0;
foreach (var line in lines)
{ {
var (corrupted, ch) = IsCorrupted(line); var popped = s.Pop();
if (corrupted) if (!IsMatching(popped, ch))
{ {
score += charVals[Closers.IndexOf(ch)]; return (true, ch);
} }
} }
else
Logger.Log($"part1: {score}"); {
throw new Exception();
}
} }
private static (bool, char) IsCorrupted(string line) return (false, '\0');
}
private static void Part2(IEnumerable<string> lines)
{
List<int> charVals = new()
{ {
1,
2,
3,
4,
};
using var t = new Timer();
List<long> scores = new();
foreach (var line in lines)
{
var (corrupted, _) = IsCorrupted(line);
if (corrupted)
{
continue;
}
var s = new Stack<char>(); var s = new Stack<char>();
foreach (var ch in line) foreach (var ch in line)
{ {
@ -66,11 +111,7 @@
} }
else if (Closers.Contains(ch)) else if (Closers.Contains(ch))
{ {
var popped = s.Pop(); s.Pop();
if (!IsMatching(popped, ch))
{
return (true, ch);
}
} }
else 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<string> lines) if (scores.Count % 2 == 0)
{ {
List<int> charVals = new() throw new Exception();
{
1,
2,
3,
4,
};
using var t = new Timer();
List<long> scores = new();
foreach (var line in lines)
{
var (corrupted, _) = IsCorrupted(line);
if (corrupted)
{
continue;
}
var s = new Stack<char>();
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}");
} }
var final = scores.OrderBy(x => x).Skip(scores.Count / 2).First();
Logger.Log($"part2: {final}");
} }
} }

View File

@ -1,8 +1,8 @@
namespace aoc2021; namespace aoc2021;
internal class Day11 internal class Day11 : Day
{ {
internal static void Go() internal override void Go()
{ {
Logger.Log("Day 11"); Logger.Log("Day 11");
Logger.Log("-----"); Logger.Log("-----");

View File

@ -1,8 +1,8 @@
namespace aoc2021; namespace aoc2021;
internal class Day12 internal class Day12 : Day
{ {
internal static void Go() internal override void Go()
{ {
Logger.Log("Day 12"); Logger.Log("Day 12");
Logger.Log("-----"); Logger.Log("-----");

6
src/Day.cs Normal file
View File

@ -0,0 +1,6 @@
namespace aoc2021;
internal abstract class Day
{
internal abstract void Go();
}

View File

@ -1,8 +1,8 @@
namespace aoc2021; namespace aoc2021;
internal class DayTemplate internal class DayTemplate : Day
{ {
internal static void Go() internal override void Go()
{ {
Logger.Log("Day #"); Logger.Log("Day #");
Logger.Log("-----"); Logger.Log("-----");

View File

@ -1,47 +1,36 @@
using aoc2021;
var arg = args.FirstOrDefault(); var arg = args.FirstOrDefault();
switch (arg) if (arg == "all")
{ {
case "1": var types = System.Reflection.Assembly
aoc2021.Day01.Go(); .GetExecutingAssembly()
break; .GetTypes()
.Where(t => t.IsSubclassOf(typeof(Day)) && !t.IsAbstract && t.Name != "DayTemplate")
.OrderBy(t => t.Name);
case "2": foreach (var type in types)
aoc2021.Day02.Go(); {
break; var day = (Day)Activator.CreateInstance(type)!;
day.Go();
case "3": }
aoc2021.Day03.Go(); }
break; else
{
case "5": Day day = arg switch
aoc2021.Day05.Go(); {
break; "1" => new Day01(),
"2" => new Day02(),
case "6": "3" => new Day03(),
aoc2021.Day06.Go(); //"4" => new Day04(),
break; "5" => new Day05(),
"6" => new Day06(),
case "7": "7" => new Day07(),
aoc2021.Day07.Go(); "8" => new Day08(),
break; "9" => new Day09(),
"10" => new Day10(),
case "8": "11" => new Day11(),
aoc2021.Day08.Go(); _ => new Day12(),
break; };
day.Go();
case "9":
aoc2021.Day09.Go();
break;
case "10":
aoc2021.Day10.Go();
break;
case "11":
aoc2021.Day11.Go();
break;
default:
aoc2021.Day12.Go();
break;
} }