Enable running all days at once
I'm kinda bored and wanted to.
This commit is contained in:
11
Properties/launchSettings.json
Normal file
11
Properties/launchSettings.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"profiles": {
|
||||
"All": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "all"
|
||||
},
|
||||
"Default day": {
|
||||
"commandName": "Project"
|
||||
}
|
||||
}
|
||||
}
|
107
src/01.cs
107
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<string> 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<string> 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<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;
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
133
src/02.cs
133
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<Instruction>();
|
||||
foreach (var instruction in lines)
|
||||
{
|
||||
Logger.Log("Day 2");
|
||||
Logger.Log("-----");
|
||||
var lines = File.ReadAllLines("inputs/02.txt");
|
||||
var instructions = new List<Instruction>();
|
||||
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<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();
|
||||
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<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();
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
209
src/03.cs
209
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<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 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<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();
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
229
src/05.cs
229
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(@"(?<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}")]
|
||||
struct Point : IEquatable<Point>
|
||||
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<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;
|
||||
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<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
121
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> 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");
|
||||
Logger.Log("-----");
|
||||
var input = File.ReadAllText("inputs/06.txt");
|
||||
List<Fish> 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> 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> 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();
|
||||
|
||||
// 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()}");
|
||||
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()}");
|
||||
}
|
||||
}
|
||||
|
85
src/07.cs
85
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<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();
|
||||
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<int> nums)
|
||||
{
|
||||
using var t = new Timer();
|
||||
return (minDist, minNum);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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<int> 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}");
|
||||
}
|
||||
}
|
||||
|
283
src/08.cs
283
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<string>, List<string>)> puzzle = new();
|
||||
foreach (var line in lines)
|
||||
{
|
||||
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)
|
||||
var portions = line.Split(" | ");
|
||||
puzzle.Add((new List<string>(portions[0].Split(' ')), new List<string>(portions[1].Split(' '))));
|
||||
}
|
||||
Part1(puzzle);
|
||||
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(" | ");
|
||||
puzzle.Add((new List<string>(portions[0].Split(' ')), new List<string>(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<string>, List<string>)> lines)
|
||||
{
|
||||
using var t = new Timer();
|
||||
Logger.Log($"part1: {count}");
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
foreach (var line in lines)
|
||||
private static void Part2(List<(List<string>, List<string>)> 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<string>, List<string>)> 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<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 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<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;
|
||||
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<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,
|
||||
// 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] };
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
213
src/09.cs
213
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<int> basins = new();
|
||||
foreach (var point in lowPoints)
|
||||
{
|
||||
using var t = new Timer();
|
||||
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
|
209
src/10.cs
209
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<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");
|
||||
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<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)
|
||||
{
|
||||
')',
|
||||
']',
|
||||
'}',
|
||||
'>',
|
||||
};
|
||||
|
||||
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()
|
||||
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<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>();
|
||||
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<string> lines)
|
||||
if (scores.Count % 2 == 0)
|
||||
{
|
||||
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>();
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
@ -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("-----");
|
||||
|
@ -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("-----");
|
||||
|
6
src/Day.cs
Normal file
6
src/Day.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace aoc2021;
|
||||
|
||||
internal abstract class Day
|
||||
{
|
||||
internal abstract void Go();
|
||||
}
|
@ -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("-----");
|
||||
|
75
src/main.cs
75
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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user