update to .net 6
continuous-integration/drone/push Build was killed
Details
continuous-integration/drone/push Build was killed
Details
This commit is contained in:
parent
bbd0d2b4db
commit
2c9737d6d2
|
@ -4,7 +4,7 @@ name: run
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: run
|
- name: run
|
||||||
image: mcr.microsoft.com/dotnet/sdk:latest
|
image: mcr.microsoft.com/dotnet/sdk:6.0
|
||||||
commands:
|
commands:
|
||||||
- dotnet test
|
- dotnet test
|
||||||
- dotnet run --project aoc2019/aoc2019.csproj
|
- dotnet run --project aoc2019/aoc2019.csproj
|
||||||
|
|
|
@ -1,60 +1,58 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using aoc2019.lib;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
namespace aoc2019.test
|
namespace aoc2019.test;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class Tests
|
||||||
{
|
{
|
||||||
[TestClass]
|
[DataTestMethod]
|
||||||
public class Tests
|
[DataRow(typeof(Day01), "3394106", "5088280")]
|
||||||
|
[DataRow(typeof(Day02), "3085697", "9425")]
|
||||||
|
[DataRow(typeof(Day03), "1195", "91518")]
|
||||||
|
[DataRow(typeof(Day04), "1079", "699")]
|
||||||
|
[DataRow(typeof(Day05), "7692125", "14340395")]
|
||||||
|
[DataRow(typeof(Day06), "145250", "274")]
|
||||||
|
[DataRow(typeof(Day07), "19650", "35961106")]
|
||||||
|
[DataRow(typeof(Day08), "2413",
|
||||||
|
"\nxxx xx xxx xxxx xxx \nx x x x x x x x x \nxxx x x x x xxx \nx x x xxx x x x \nx x x x x x x x \nxxx xx x xxxx xxx ")]
|
||||||
|
[DataRow(typeof(Day09), "3409270027", "82760")]
|
||||||
|
[DataRow(typeof(Day10), "260", "608")]
|
||||||
|
[DataRow(typeof(Day11), "2054",
|
||||||
|
"\n # # ### #### #### ## ## # # ### \n # # # # # # # # # # # # # \n ## # # # ### # # # #### ### \n # # ### # # #### # # # # # \n # # # # # # # # # # # # # # \n # # # # #### #### # # ## # # ### ")]
|
||||||
|
[DataRow(typeof(Day12), "10635", "583523031727256")]
|
||||||
|
//[DataRow(typeof(Day13), "361", "after 7133 moves, the score is: 17590")]
|
||||||
|
[DataRow(typeof(Day14), "397771", "3126714")]
|
||||||
|
[DataRow(typeof(Day15), "280", "400")]
|
||||||
|
[DataRow(typeof(Day16), "90744714", "82994322")]
|
||||||
|
[DataRow(typeof(Day17), "2804", "")]
|
||||||
|
[DataRow(typeof(Day19), "114", "10671712")]
|
||||||
|
[DataRow(typeof(Day21), "", "")]
|
||||||
|
[DataRow(typeof(Day23), "23626", "19019")]
|
||||||
|
public void TestAllDays(Type dayType, string part1, string part2)
|
||||||
{
|
{
|
||||||
[DataTestMethod]
|
// create day instance
|
||||||
[DataRow(typeof(Day01), "3394106", "5088280")]
|
var s = Stopwatch.StartNew();
|
||||||
[DataRow(typeof(Day02), "3085697", "9425")]
|
var day = (Day)Activator.CreateInstance(dayType);
|
||||||
[DataRow(typeof(Day03), "1195", "91518")]
|
s.Stop();
|
||||||
[DataRow(typeof(Day04), "1079", "699")]
|
Assert.IsNotNull(day, "failed to create day object");
|
||||||
[DataRow(typeof(Day05), "7692125", "14340395")]
|
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in constructor");
|
||||||
[DataRow(typeof(Day06), "145250", "274")]
|
|
||||||
[DataRow(typeof(Day07), "19650", "35961106")]
|
|
||||||
[DataRow(typeof(Day08), "2413",
|
|
||||||
"\nxxx xx xxx xxxx xxx \nx x x x x x x x x \nxxx x x x x xxx \nx x x xxx x x x \nx x x x x x x x \nxxx xx x xxxx xxx ")]
|
|
||||||
[DataRow(typeof(Day09), "3409270027", "82760")]
|
|
||||||
[DataRow(typeof(Day10), "260", "608")]
|
|
||||||
[DataRow(typeof(Day11), "2054",
|
|
||||||
"\n # # ### #### #### ## ## # # ### \n # # # # # # # # # # # # # \n ## # # # ### # # # #### ### \n # # ### # # #### # # # # # \n # # # # # # # # # # # # # # \n # # # # #### #### # # ## # # ### ")]
|
|
||||||
[DataRow(typeof(Day12), "10635", "583523031727256")]
|
|
||||||
//[DataRow(typeof(Day13), "361", "after 7133 moves, the score is: 17590")]
|
|
||||||
[DataRow(typeof(Day14), "397771", "3126714")]
|
|
||||||
[DataRow(typeof(Day15), "280", "400")]
|
|
||||||
[DataRow(typeof(Day16), "90744714", "82994322")]
|
|
||||||
[DataRow(typeof(Day17), "2804", "")]
|
|
||||||
[DataRow(typeof(Day19), "114", "10671712")]
|
|
||||||
[DataRow(typeof(Day21), "", "")]
|
|
||||||
[DataRow(typeof(Day23), "23626", "19019")]
|
|
||||||
public void TestAllDays(Type dayType, string part1, string part2)
|
|
||||||
{
|
|
||||||
// create day instance
|
|
||||||
var s = Stopwatch.StartNew();
|
|
||||||
var day = (Day) Activator.CreateInstance(dayType);
|
|
||||||
s.Stop();
|
|
||||||
Assert.IsNotNull(day, "failed to create day object");
|
|
||||||
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in constructor");
|
|
||||||
|
|
||||||
// part 1
|
// part 1
|
||||||
s.Reset();
|
s.Reset();
|
||||||
s.Start();
|
s.Start();
|
||||||
var part1Actual = day.Part1();
|
var part1Actual = day.Part1();
|
||||||
s.Stop();
|
s.Stop();
|
||||||
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in part1");
|
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in part1");
|
||||||
Assert.AreEqual(part1, part1Actual, $"Incorrect answer for Day {day.DayNumber} Part1");
|
Assert.AreEqual(part1, part1Actual, $"Incorrect answer for Day {day.DayNumber} Part1");
|
||||||
|
|
||||||
// part 2
|
// part 2
|
||||||
s.Reset();
|
s.Reset();
|
||||||
s.Start();
|
s.Start();
|
||||||
var part2Actual = day.Part2();
|
var part2Actual = day.Part2();
|
||||||
s.Stop();
|
s.Stop();
|
||||||
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in part2");
|
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in part2");
|
||||||
Assert.AreEqual(part2, part2Actual, $"Incorrect answer for Day {day.DayNumber} Part2");
|
Assert.AreEqual(part2, part2Actual, $"Incorrect answer for Day {day.DayNumber} Part2");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -1,49 +1,44 @@
|
||||||
using System;
|
using System.Diagnostics;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
namespace aoc2019;
|
||||||
|
|
||||||
|
public abstract class Day
|
||||||
{
|
{
|
||||||
public abstract class Day
|
protected Day(int dayNumber, string puzzleName)
|
||||||
{
|
{
|
||||||
protected Day(int dayNumber, string puzzleName)
|
DayNumber = dayNumber;
|
||||||
{
|
PuzzleName = puzzleName;
|
||||||
DayNumber = dayNumber;
|
|
||||||
PuzzleName = puzzleName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int DayNumber { get; }
|
|
||||||
public string PuzzleName { get; }
|
|
||||||
|
|
||||||
protected virtual IEnumerable<string> Input =>
|
|
||||||
File.ReadLines(FileName);
|
|
||||||
|
|
||||||
protected string FileName =>
|
|
||||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"input/day{DayNumber,2:00}.in");
|
|
||||||
|
|
||||||
public void AllParts(bool verbose = true)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Day {DayNumber,2}: {PuzzleName}");
|
|
||||||
var s = Stopwatch.StartNew();
|
|
||||||
var part1 = Part1();
|
|
||||||
s.Stop();
|
|
||||||
Console.Write($"Part1: {part1,-15} ");
|
|
||||||
Console.WriteLine(verbose ? $"{s.ScaleMilliseconds()}ms elapsed" : "");
|
|
||||||
|
|
||||||
s.Reset();
|
|
||||||
|
|
||||||
s.Start();
|
|
||||||
var part2 = Part2();
|
|
||||||
s.Stop();
|
|
||||||
Console.Write($"Part2: {part2,-15} ");
|
|
||||||
Console.WriteLine(verbose ? $"{s.ScaleMilliseconds()}ms elapsed" : "");
|
|
||||||
|
|
||||||
Console.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract string Part1();
|
|
||||||
public abstract string Part2();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public int DayNumber { get; }
|
||||||
|
public string PuzzleName { get; }
|
||||||
|
|
||||||
|
protected virtual IEnumerable<string> Input =>
|
||||||
|
File.ReadLines(FileName);
|
||||||
|
|
||||||
|
protected string FileName =>
|
||||||
|
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"input/day{DayNumber,2:00}.in");
|
||||||
|
|
||||||
|
public void AllParts(bool verbose = true)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Day {DayNumber,2}: {PuzzleName}");
|
||||||
|
var s = Stopwatch.StartNew();
|
||||||
|
var part1 = Part1();
|
||||||
|
s.Stop();
|
||||||
|
Console.Write($"Part1: {part1,-15} ");
|
||||||
|
Console.WriteLine(verbose ? $"{s.ScaleMilliseconds()}ms elapsed" : "");
|
||||||
|
|
||||||
|
s.Reset();
|
||||||
|
|
||||||
|
s.Start();
|
||||||
|
var part2 = Part2();
|
||||||
|
s.Stop();
|
||||||
|
Console.Write($"Part2: {part2,-15} ");
|
||||||
|
Console.WriteLine(verbose ? $"{s.ScaleMilliseconds()}ms elapsed" : "");
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract string Part1();
|
||||||
|
public abstract string Part2();
|
||||||
|
}
|
||||||
|
|
|
@ -1,43 +1,39 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2019;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day01 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day01 : Day
|
private readonly IEnumerable<int> masses;
|
||||||
|
|
||||||
|
public Day01() : base(1, "The Tyranny of the Rocket Equation")
|
||||||
{
|
{
|
||||||
private readonly IEnumerable<int> masses;
|
masses = Input.Select(int.Parse);
|
||||||
|
|
||||||
public Day01() : base(1, "The Tyranny of the Rocket Equation")
|
|
||||||
{
|
|
||||||
masses = Input.Select(int.Parse);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int FuelCost(int weight)
|
|
||||||
{
|
|
||||||
return weight / 3 - 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int FullCost(int cost)
|
|
||||||
{
|
|
||||||
int total = 0, newcost, tmp = cost;
|
|
||||||
|
|
||||||
while ((newcost = FuelCost(tmp)) >= 0)
|
|
||||||
{
|
|
||||||
total += newcost;
|
|
||||||
tmp = newcost;
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return $"{masses.Sum(FuelCost)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return $"{masses.Sum(FullCost)}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static int FuelCost(int weight)
|
||||||
|
{
|
||||||
|
return weight / 3 - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int FullCost(int cost)
|
||||||
|
{
|
||||||
|
int total = 0, newcost, tmp = cost;
|
||||||
|
|
||||||
|
while ((newcost = FuelCost(tmp)) >= 0)
|
||||||
|
{
|
||||||
|
total += newcost;
|
||||||
|
tmp = newcost;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{masses.Sum(FuelCost)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return $"{masses.Sum(FullCost)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,46 +1,42 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2019;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day02 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day02 : Day
|
private readonly IEnumerable<int> input;
|
||||||
|
|
||||||
|
public Day02() : base(2, "1202 Program Alarm")
|
||||||
{
|
{
|
||||||
private readonly IEnumerable<int> input;
|
input = Input.First().Split(',').Select(int.Parse);
|
||||||
|
}
|
||||||
|
|
||||||
public Day02() : base(2, "1202 Program Alarm")
|
public int RunIntCode(int noun, int verb)
|
||||||
{
|
{
|
||||||
input = Input.First().Split(',').Select(int.Parse);
|
var v = input.ToList();
|
||||||
}
|
v[1] = noun;
|
||||||
|
v[2] = verb;
|
||||||
|
|
||||||
public int RunIntCode(int noun, int verb)
|
for (var i = 0; v[i] != 99; i += 4)
|
||||||
{
|
v[v[i + 3]] = v[i] switch
|
||||||
var v = input.ToList();
|
{
|
||||||
v[1] = noun;
|
1 => v[v[i + 1]] + v[v[i + 2]],
|
||||||
v[2] = verb;
|
2 => v[v[i + 1]] * v[v[i + 2]]
|
||||||
|
};
|
||||||
|
|
||||||
for (var i = 0; v[i] != 99; i += 4)
|
return v[0];
|
||||||
v[v[i + 3]] = v[i] switch
|
}
|
||||||
{
|
|
||||||
1 => v[v[i + 1]] + v[v[i + 2]],
|
|
||||||
2 => v[v[i + 1]] * v[v[i + 2]]
|
|
||||||
};
|
|
||||||
|
|
||||||
return v[0];
|
public override string Part1()
|
||||||
}
|
{
|
||||||
|
return $"{RunIntCode(12, 2)}";
|
||||||
|
}
|
||||||
|
|
||||||
public override string Part1()
|
public override string Part2()
|
||||||
{
|
{
|
||||||
return $"{RunIntCode(12, 2)}";
|
for (var i = 0; i < 100; i++)
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < 100; i++)
|
|
||||||
for (var j = 0; j < 100; j++)
|
for (var j = 0; j < 100; j++)
|
||||||
if (RunIntCode(i, j) == 19690720)
|
if (RunIntCode(i, j) == 19690720)
|
||||||
return $"{100 * i + j}";
|
return $"{100 * i + j}";
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
101
aoc2019/Day03.cs
101
aoc2019/Day03.cs
|
@ -1,57 +1,52 @@
|
||||||
using System;
|
namespace aoc2019;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day03 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day03 : Day
|
private readonly IEnumerable<(int, int)> intersections;
|
||||||
|
private readonly List<Dictionary<(int, int), int>> wires;
|
||||||
|
|
||||||
|
public Day03() : base(3, "Crossed Wires")
|
||||||
{
|
{
|
||||||
private readonly IEnumerable<(int, int)> intersections;
|
wires = Input.Select(ParseWire).ToList();
|
||||||
private readonly List<Dictionary<(int, int), int>> wires;
|
intersections = wires[0].Keys.Intersect(wires[1].Keys);
|
||||||
|
|
||||||
public Day03() : base(3, "Crossed Wires")
|
|
||||||
{
|
|
||||||
wires = Input.Select(ParseWire).ToList();
|
|
||||||
intersections = wires[0].Keys.Intersect(wires[1].Keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return $"{intersections.Min(x => Math.Abs(x.Item1) + Math.Abs(x.Item2))}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
// add 2 to count (0, 0) on both lines
|
|
||||||
return $"{intersections.Min(x => wires[0][x] + wires[1][x]) + 2}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<(int, int), int> ParseWire(string line)
|
|
||||||
{
|
|
||||||
var r = new Dictionary<(int, int), int>();
|
|
||||||
int x = 0, y = 0, c = 0, i;
|
|
||||||
|
|
||||||
foreach (var step in line.Split(','))
|
|
||||||
{
|
|
||||||
var d = int.Parse(step.Substring(1));
|
|
||||||
switch (step[0])
|
|
||||||
{
|
|
||||||
case 'U':
|
|
||||||
for (i = 0; i < d; i++) r.TryAdd((x, ++y), c++);
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
for (i = 0; i < d; i++) r.TryAdd((x, --y), c++);
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
for (i = 0; i < d; i++) r.TryAdd((++x, y), c++);
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
for (i = 0; i < d; i++) r.TryAdd((--x, y), c++);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{intersections.Min(x => Math.Abs(x.Item1) + Math.Abs(x.Item2))}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
// add 2 to count (0, 0) on both lines
|
||||||
|
return $"{intersections.Min(x => wires[0][x] + wires[1][x]) + 2}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<(int, int), int> ParseWire(string line)
|
||||||
|
{
|
||||||
|
var r = new Dictionary<(int, int), int>();
|
||||||
|
int x = 0, y = 0, c = 0, i;
|
||||||
|
|
||||||
|
foreach (var step in line.Split(','))
|
||||||
|
{
|
||||||
|
var d = int.Parse(step.Substring(1));
|
||||||
|
switch (step[0])
|
||||||
|
{
|
||||||
|
case 'U':
|
||||||
|
for (i = 0; i < d; i++) r.TryAdd((x, ++y), c++);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
for (i = 0; i < d; i++) r.TryAdd((x, --y), c++);
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
for (i = 0; i < d; i++) r.TryAdd((++x, y), c++);
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
for (i = 0; i < d; i++) r.TryAdd((--x, y), c++);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,49 +1,46 @@
|
||||||
using System.Linq;
|
namespace aoc2019;
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day04 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day04 : Day
|
private readonly int end;
|
||||||
|
|
||||||
|
private readonly int start;
|
||||||
|
|
||||||
|
public Day04() : base(4, "Secure Container")
|
||||||
{
|
{
|
||||||
private readonly int end;
|
var range = Input.First().Split('-').Select(int.Parse).ToList();
|
||||||
|
start = range[0];
|
||||||
private readonly int start;
|
end = range[1];
|
||||||
|
|
||||||
public Day04() : base(4, "Secure Container")
|
|
||||||
{
|
|
||||||
var range = Input.First().Split('-').Select(int.Parse).ToList();
|
|
||||||
start = range[0];
|
|
||||||
end = range[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsValid(int i)
|
|
||||||
{
|
|
||||||
var prev = 0;
|
|
||||||
var hasDup = false;
|
|
||||||
foreach (var c in i.ToString())
|
|
||||||
{
|
|
||||||
var curr = c - '0';
|
|
||||||
if (curr < prev) return false;
|
|
||||||
if (curr == prev) hasDup = true;
|
|
||||||
prev = curr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i >= start && i <= end && hasDup;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool HasOnePair(int i)
|
|
||||||
{
|
|
||||||
var s = i.ToString();
|
|
||||||
return IsValid(i) && s.Select(c => s.Count(j => j == c)).Any(c => c == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return $"{Enumerable.Range(start, end).Count(IsValid)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return $"{Enumerable.Range(start, end).Count(HasOnePair)}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private bool IsValid(int i)
|
||||||
|
{
|
||||||
|
var prev = 0;
|
||||||
|
var hasDup = false;
|
||||||
|
foreach (var c in i.ToString())
|
||||||
|
{
|
||||||
|
var curr = c - '0';
|
||||||
|
if (curr < prev) return false;
|
||||||
|
if (curr == prev) hasDup = true;
|
||||||
|
prev = curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i >= start && i <= end && hasDup;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HasOnePair(int i)
|
||||||
|
{
|
||||||
|
var s = i.ToString();
|
||||||
|
return IsValid(i) && s.Select(c => s.Count(j => j == c)).Any(c => c == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{Enumerable.Range(start, end).Count(IsValid)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return $"{Enumerable.Range(start, end).Count(HasOnePair)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
130
aoc2019/Day05.cs
130
aoc2019/Day05.cs
|
@ -1,78 +1,74 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2019;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day05 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day05 : Day
|
private readonly IEnumerable<int> tape;
|
||||||
|
|
||||||
|
private int output;
|
||||||
|
|
||||||
|
public Day05() : base(5, "Sunny with a Chance of Asteroids")
|
||||||
{
|
{
|
||||||
private readonly IEnumerable<int> tape;
|
tape = Input.First().Split(',').Select(int.Parse);
|
||||||
|
}
|
||||||
|
|
||||||
private int output;
|
public void RunIntCode(List<int> v, int input)
|
||||||
|
{
|
||||||
public Day05() : base(5, "Sunny with a Chance of Asteroids")
|
var i = 0;
|
||||||
|
while (i < v.Count && v[i] != 99)
|
||||||
{
|
{
|
||||||
tape = Input.First().Split(',').Select(int.Parse);
|
int Val(int mode, int val)
|
||||||
}
|
|
||||||
|
|
||||||
public void RunIntCode(List<int> v, int input)
|
|
||||||
{
|
|
||||||
var i = 0;
|
|
||||||
while (i < v.Count && v[i] != 99)
|
|
||||||
{
|
{
|
||||||
int Val(int mode, int val)
|
return mode != 0 ? val : v[val];
|
||||||
{
|
}
|
||||||
return mode != 0 ? val : v[val];
|
|
||||||
}
|
|
||||||
|
|
||||||
var mode1 = v[i] / 100 % 10;
|
var mode1 = v[i] / 100 % 10;
|
||||||
var mode2 = v[i] / 1000;
|
var mode2 = v[i] / 1000;
|
||||||
|
|
||||||
switch (v[i] % 100)
|
switch (v[i] % 100)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
v[v[i + 3]] = Val(mode1, v[i + 1]) + Val(mode2, v[i + 2]);
|
v[v[i + 3]] = Val(mode1, v[i + 1]) + Val(mode2, v[i + 2]);
|
||||||
i += 4;
|
i += 4;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
v[v[i + 3]] = Val(mode1, v[i + 1]) * Val(mode2, v[i + 2]);
|
v[v[i + 3]] = Val(mode1, v[i + 1]) * Val(mode2, v[i + 2]);
|
||||||
i += 4;
|
i += 4;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
v[v[i + 1]] = input;
|
v[v[i + 1]] = input;
|
||||||
i += 2;
|
i += 2;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
output = Val(mode1, v[i + 1]);
|
output = Val(mode1, v[i + 1]);
|
||||||
i += 2;
|
i += 2;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
i = Val(mode1, v[i + 1]) == 0 ? i + 3 : Val(mode2, v[i + 2]);
|
i = Val(mode1, v[i + 1]) == 0 ? i + 3 : Val(mode2, v[i + 2]);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
i = Val(mode1, v[i + 1]) != 0 ? i + 3 : Val(mode2, v[i + 2]);
|
i = Val(mode1, v[i + 1]) != 0 ? i + 3 : Val(mode2, v[i + 2]);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
v[v[i + 3]] = Val(mode1, v[i + 1]) < Val(mode2, v[i + 2]) ? 1 : 0;
|
v[v[i + 3]] = Val(mode1, v[i + 1]) < Val(mode2, v[i + 2]) ? 1 : 0;
|
||||||
i += 4;
|
i += 4;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
v[v[i + 3]] = Val(mode1, v[i + 1]) == Val(mode2, v[i + 2]) ? 1 : 0;
|
v[v[i + 3]] = Val(mode1, v[i + 1]) == Val(mode2, v[i + 2]) ? 1 : 0;
|
||||||
i += 4;
|
i += 4;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
RunIntCode(tape.ToList(), 1);
|
|
||||||
return $"{output}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
RunIntCode(tape.ToList(), 5);
|
|
||||||
return $"{output}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
RunIntCode(tape.ToList(), 1);
|
||||||
|
return $"{output}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
RunIntCode(tape.ToList(), 5);
|
||||||
|
return $"{output}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,38 +1,34 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2019;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day06 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day06 : Day
|
private readonly Dictionary<string, string> input;
|
||||||
|
|
||||||
|
public Day06() : base(6, "Universal Orbit Map")
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, string> input;
|
input = Input.ToDictionary(i => i.Split(')')[1], i => i.Split(')')[0]);
|
||||||
|
|
||||||
public Day06() : base(6, "Universal Orbit Map")
|
|
||||||
{
|
|
||||||
input = Input.ToDictionary(i => i.Split(')')[1], i => i.Split(')')[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> GetParents(string obj)
|
|
||||||
{
|
|
||||||
var res = new List<string>();
|
|
||||||
for (var curr = obj; curr != "COM"; curr = input[curr])
|
|
||||||
res.Add(curr);
|
|
||||||
res.Add("COM");
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return $"{input.Keys.Sum(o => GetParents(o).Count - 1)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
var you = GetParents("YOU");
|
|
||||||
var san = GetParents("SAN");
|
|
||||||
var common = 1;
|
|
||||||
for (; you[^common] == san[^common]; common++) ;
|
|
||||||
return $"{you.Count + san.Count - common * 2}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private List<string> GetParents(string obj)
|
||||||
|
{
|
||||||
|
var res = new List<string>();
|
||||||
|
for (var curr = obj; curr != "COM"; curr = input[curr])
|
||||||
|
res.Add(curr);
|
||||||
|
res.Add("COM");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{input.Keys.Sum(o => GetParents(o).Count - 1)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var you = GetParents("YOU");
|
||||||
|
var san = GetParents("SAN");
|
||||||
|
var common = 1;
|
||||||
|
for (; you[^common] == san[^common]; common++) ;
|
||||||
|
return $"{you.Count + san.Count - common * 2}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
121
aoc2019/Day07.cs
121
aoc2019/Day07.cs
|
@ -1,67 +1,62 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2019;
|
||||||
using System.Linq;
|
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day07 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day07 : Day
|
private readonly IntCodeVM[] Amplifiers = new IntCodeVM[5];
|
||||||
|
|
||||||
|
public Day07() : base(7, "Amplification Circuit")
|
||||||
{
|
{
|
||||||
private readonly IntCodeVM[] Amplifiers = new IntCodeVM[5];
|
for (var i = 0; i < 5; i++) Amplifiers[i] = new IntCodeVM(Input.First());
|
||||||
|
|
||||||
public Day07() : base(7, "Amplification Circuit")
|
|
||||||
{
|
|
||||||
for (var i = 0; i < 5; i++) Amplifiers[i] = new IntCodeVM(Input.First());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
long i, largest = 0;
|
|
||||||
|
|
||||||
foreach (var phaseSeq in Enumerable.Range(0, 5).Permute())
|
|
||||||
{
|
|
||||||
i = 0;
|
|
||||||
foreach (var (vm, phase) in Amplifiers.Zip(phaseSeq))
|
|
||||||
{
|
|
||||||
vm.Reset();
|
|
||||||
vm.Run(phase, i);
|
|
||||||
i = vm.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > largest)
|
|
||||||
largest = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{largest}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
long i, largest = 0;
|
|
||||||
|
|
||||||
foreach (var phaseSeq in Enumerable.Range(5, 5).Permute())
|
|
||||||
{
|
|
||||||
i = 0;
|
|
||||||
foreach (var (vm, phase) in Amplifiers.Zip(phaseSeq))
|
|
||||||
{
|
|
||||||
vm.Reset();
|
|
||||||
vm.AddInput(phase);
|
|
||||||
}
|
|
||||||
|
|
||||||
var vms = new Queue<IntCodeVM>(Amplifiers);
|
|
||||||
while (vms.Count > 0)
|
|
||||||
{
|
|
||||||
var vm = vms.Dequeue();
|
|
||||||
var haltType = vm.Run(i);
|
|
||||||
if (haltType == IntCodeVM.HaltType.Waiting)
|
|
||||||
vms.Enqueue(vm);
|
|
||||||
i = vm.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > largest)
|
|
||||||
largest = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{largest}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
long i, largest = 0;
|
||||||
|
|
||||||
|
foreach (var phaseSeq in Enumerable.Range(0, 5).Permute())
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
foreach (var (vm, phase) in Amplifiers.Zip(phaseSeq))
|
||||||
|
{
|
||||||
|
vm.Reset();
|
||||||
|
vm.Run(phase, i);
|
||||||
|
i = vm.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > largest)
|
||||||
|
largest = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{largest}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
long i, largest = 0;
|
||||||
|
|
||||||
|
foreach (var phaseSeq in Enumerable.Range(5, 5).Permute())
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
foreach (var (vm, phase) in Amplifiers.Zip(phaseSeq))
|
||||||
|
{
|
||||||
|
vm.Reset();
|
||||||
|
vm.AddInput(phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
var vms = new Queue<IntCodeVM>(Amplifiers);
|
||||||
|
while (vms.Count > 0)
|
||||||
|
{
|
||||||
|
var vm = vms.Dequeue();
|
||||||
|
var haltType = vm.Run(i);
|
||||||
|
if (haltType == IntCodeVM.HaltType.Waiting)
|
||||||
|
vms.Enqueue(vm);
|
||||||
|
i = vm.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > largest)
|
||||||
|
largest = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{largest}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,37 +1,32 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2019;
|
||||||
using System.Linq;
|
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day08 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day08 : Day
|
private readonly List<List<char>> photo;
|
||||||
|
|
||||||
|
public Day08() : base(8, "Space Image Format")
|
||||||
{
|
{
|
||||||
private readonly List<List<char>> photo;
|
photo = Input.First().Chunk(25 * 6).Select(s => s.ToList()).ToList();
|
||||||
|
|
||||||
public Day08() : base(8, "Space Image Format")
|
|
||||||
{
|
|
||||||
photo = Input.First().Chunk(25 * 6).Select(s => s.ToList()).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
var l = photo.OrderBy(layer => layer.Count(pixel => pixel == '0')).First();
|
|
||||||
return $"{l.Count(p => p == '1') * l.Count(p => p == '2')}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return "\n" + Enumerable.Range(0, 25 * 6)
|
|
||||||
.Select(p => Enumerable.Range(0, photo.Count)
|
|
||||||
.Select(l => photo[l][p])
|
|
||||||
.Aggregate('2', (acc, next) =>
|
|
||||||
acc != '2' ? acc : next == '0' ? ' ' : next
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.ToDelimitedString()
|
|
||||||
.Chunk(25)
|
|
||||||
.ToDelimitedString("\n")
|
|
||||||
.Replace('1', 'x');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
var l = photo.OrderBy(layer => layer.Count(pixel => pixel == '0')).First();
|
||||||
|
return $"{l.Count(p => p == '1') * l.Count(p => p == '2')}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "\n" + Enumerable.Range(0, 25 * 6)
|
||||||
|
.Select(p => Enumerable.Range(0, photo.Count)
|
||||||
|
.Select(l => photo[l][p])
|
||||||
|
.Aggregate('2', (acc, next) =>
|
||||||
|
acc != '2' ? acc : next == '0' ? ' ' : next
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.ToDelimitedString()
|
||||||
|
.Chunk(25)
|
||||||
|
.ToDelimitedString("\n")
|
||||||
|
.Replace('1', 'x');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,29 +1,25 @@
|
||||||
using System.Linq;
|
namespace aoc2019;
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day09 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day09 : Day
|
private readonly IntCodeVM vm;
|
||||||
|
|
||||||
|
public Day09() : base(9, "Sensor Boost")
|
||||||
{
|
{
|
||||||
private readonly IntCodeVM vm;
|
vm = new IntCodeVM(Input.First());
|
||||||
|
|
||||||
public Day09() : base(9, "Sensor Boost")
|
|
||||||
{
|
|
||||||
vm = new IntCodeVM(Input.First());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
vm.Reset();
|
|
||||||
vm.Run(1);
|
|
||||||
return $"{vm.output.ToDelimitedString(",")}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
vm.Reset();
|
|
||||||
vm.Run(2);
|
|
||||||
return $"{vm.output.ToDelimitedString(",")}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
vm.Reset();
|
||||||
|
vm.Run(1);
|
||||||
|
return $"{vm.output.ToDelimitedString(",")}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
vm.Reset();
|
||||||
|
vm.Run(2);
|
||||||
|
return $"{vm.output.ToDelimitedString(",")}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
132
aoc2019/Day10.cs
132
aoc2019/Day10.cs
|
@ -1,73 +1,67 @@
|
||||||
using System;
|
namespace aoc2019;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day10 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day10 : Day
|
private readonly HashSet<(int x, int y)> asteroids;
|
||||||
|
private (int x, int y) best = (x: -1, y: -1);
|
||||||
|
private int bestCanSee;
|
||||||
|
|
||||||
|
public Day10() : base(10, "Monitoring Station")
|
||||||
{
|
{
|
||||||
private readonly HashSet<(int x, int y)> asteroids;
|
asteroids = Input
|
||||||
private (int x, int y) best = (x: -1, y: -1);
|
.Select((r, y) => r.Select((c, x) => (x, y, isAsteroid: c == '#')).ToArray())
|
||||||
private int bestCanSee;
|
.SelectMany(r => r)
|
||||||
|
.Where(a => a.isAsteroid)
|
||||||
public Day10() : base(10, "Monitoring Station")
|
.Select(a => (a.x, a.y))
|
||||||
{
|
.ToHashSet();
|
||||||
asteroids = Input
|
|
||||||
.Select((r, y) => r.Select((c, x) => (x, y, isAsteroid: c == '#')).ToArray())
|
|
||||||
.SelectMany(r => r)
|
|
||||||
.Where(a => a.isAsteroid)
|
|
||||||
.Select(a => (a.x, a.y))
|
|
||||||
.ToHashSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
foreach (var asteroid in asteroids)
|
|
||||||
{
|
|
||||||
var canSee = asteroids
|
|
||||||
.Except(new[] {asteroid})
|
|
||||||
.Select(a => (x: a.x - asteroid.x, y: a.y - asteroid.y))
|
|
||||||
.GroupBy(a => Math.Atan2(a.y, a.x))
|
|
||||||
.Count();
|
|
||||||
|
|
||||||
if (canSee > bestCanSee)
|
|
||||||
{
|
|
||||||
best = asteroid;
|
|
||||||
bestCanSee = canSee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{bestCanSee}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
static IEnumerable<(int x, int y, double angle, double dist)> GetValue(
|
|
||||||
Queue<(int x, int y, double angle, double dist)> q)
|
|
||||||
{
|
|
||||||
if (q.Count > 0) yield return q.Dequeue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return asteroids
|
|
||||||
.Where(a => a != best)
|
|
||||||
.Select(a =>
|
|
||||||
{
|
|
||||||
var xDist = a.x - best.x;
|
|
||||||
var yDist = a.y - best.y;
|
|
||||||
var angle = Math.Atan2(xDist, yDist);
|
|
||||||
return (a.x, a.y, angle, dist: Math.Sqrt(xDist * xDist + yDist * yDist));
|
|
||||||
})
|
|
||||||
.ToLookup(a => a.angle)
|
|
||||||
.OrderByDescending(a => a.Key)
|
|
||||||
.Select(a => new Queue<(int x, int y, double angle, double dist)>(a.OrderBy(b => b.dist)))
|
|
||||||
.Repeat()
|
|
||||||
.SelectMany(GetValue)
|
|
||||||
.Skip(199)
|
|
||||||
.Take(1)
|
|
||||||
.Select(a => a.x * 100 + a.y)
|
|
||||||
.Single()
|
|
||||||
.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
foreach (var asteroid in asteroids)
|
||||||
|
{
|
||||||
|
var canSee = asteroids
|
||||||
|
.Except(new[] { asteroid })
|
||||||
|
.Select(a => (x: a.x - asteroid.x, y: a.y - asteroid.y))
|
||||||
|
.GroupBy(a => Math.Atan2(a.y, a.x))
|
||||||
|
.Count();
|
||||||
|
|
||||||
|
if (canSee > bestCanSee)
|
||||||
|
{
|
||||||
|
best = asteroid;
|
||||||
|
bestCanSee = canSee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{bestCanSee}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
static IEnumerable<(int x, int y, double angle, double dist)> GetValue(
|
||||||
|
Queue<(int x, int y, double angle, double dist)> q)
|
||||||
|
{
|
||||||
|
if (q.Count > 0) yield return q.Dequeue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return asteroids
|
||||||
|
.Where(a => a != best)
|
||||||
|
.Select(a =>
|
||||||
|
{
|
||||||
|
var xDist = a.x - best.x;
|
||||||
|
var yDist = a.y - best.y;
|
||||||
|
var angle = Math.Atan2(xDist, yDist);
|
||||||
|
return (a.x, a.y, angle, dist: Math.Sqrt(xDist * xDist + yDist * yDist));
|
||||||
|
})
|
||||||
|
.ToLookup(a => a.angle)
|
||||||
|
.OrderByDescending(a => a.Key)
|
||||||
|
.Select(a => new Queue<(int x, int y, double angle, double dist)>(a.OrderBy(b => b.dist)))
|
||||||
|
.Repeat()
|
||||||
|
.SelectMany(GetValue)
|
||||||
|
.Skip(199)
|
||||||
|
.Take(1)
|
||||||
|
.Select(a => a.x * 100 + a.y)
|
||||||
|
.Single()
|
||||||
|
.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
209
aoc2019/Day11.cs
209
aoc2019/Day11.cs
|
@ -1,111 +1,106 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2019;
|
||||||
using System.Linq;
|
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day11 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day11 : Day
|
private readonly IntCodeVM vm;
|
||||||
|
private Direction heading;
|
||||||
|
private long x, y;
|
||||||
|
|
||||||
|
public Day11() : base(11, "Space Police")
|
||||||
{
|
{
|
||||||
private readonly IntCodeVM vm;
|
vm = new IntCodeVM(Input.First());
|
||||||
private Direction heading;
|
|
||||||
private long x, y;
|
|
||||||
|
|
||||||
public Day11() : base(11, "Space Police")
|
|
||||||
{
|
|
||||||
vm = new IntCodeVM(Input.First());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Move()
|
|
||||||
{
|
|
||||||
switch (heading)
|
|
||||||
{
|
|
||||||
case Direction.Up:
|
|
||||||
y++;
|
|
||||||
break;
|
|
||||||
case Direction.Down:
|
|
||||||
y--;
|
|
||||||
break;
|
|
||||||
case Direction.Left:
|
|
||||||
x--;
|
|
||||||
break;
|
|
||||||
case Direction.Right:
|
|
||||||
x++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Turn(long direction)
|
|
||||||
{
|
|
||||||
switch (heading)
|
|
||||||
{
|
|
||||||
case Direction.Up:
|
|
||||||
heading = direction == 0 ? Direction.Left : Direction.Right;
|
|
||||||
break;
|
|
||||||
case Direction.Down:
|
|
||||||
heading = direction == 0 ? Direction.Right : Direction.Left;
|
|
||||||
break;
|
|
||||||
case Direction.Left:
|
|
||||||
heading = direction == 0 ? Direction.Down : Direction.Up;
|
|
||||||
break;
|
|
||||||
case Direction.Right:
|
|
||||||
heading = direction == 0 ? Direction.Up : Direction.Down;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Move();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<(long x, long y), long> PaintShip(int initialVal)
|
|
||||||
{
|
|
||||||
var map = new Dictionary<(long, long), long>();
|
|
||||||
vm.Reset();
|
|
||||||
heading = Direction.Up;
|
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
map[(x, y)] = initialVal;
|
|
||||||
|
|
||||||
var haltType = IntCodeVM.HaltType.Waiting;
|
|
||||||
while (haltType == IntCodeVM.HaltType.Waiting)
|
|
||||||
{
|
|
||||||
haltType = vm.Run(map.GetValueOrDefault((x, y)));
|
|
||||||
map[(x, y)] = vm.Result;
|
|
||||||
Turn(vm.Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return $"{PaintShip(0).Count}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
var map = PaintShip(1);
|
|
||||||
var minX = (int) map.Keys.Select(i => i.x).Min();
|
|
||||||
var maxX = (int) map.Keys.Select(i => i.x).Max();
|
|
||||||
var minY = (int) map.Keys.Select(i => i.y).Min();
|
|
||||||
var maxY = (int) map.Keys.Select(i => i.y).Max();
|
|
||||||
|
|
||||||
return "\n" + Enumerable.Range(minY, maxY - minY + 1)
|
|
||||||
.Select(j =>
|
|
||||||
Enumerable.Range(minX, maxX - minX + 1)
|
|
||||||
.Select(i => map.GetValueOrDefault((x: i, y: j)) == 0 ? ' ' : '#')
|
|
||||||
.ToDelimitedString()
|
|
||||||
)
|
|
||||||
.Reverse()
|
|
||||||
.ToDelimitedString("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Direction
|
|
||||||
{
|
|
||||||
Up,
|
|
||||||
Down,
|
|
||||||
Left,
|
|
||||||
Right
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private void Move()
|
||||||
|
{
|
||||||
|
switch (heading)
|
||||||
|
{
|
||||||
|
case Direction.Up:
|
||||||
|
y++;
|
||||||
|
break;
|
||||||
|
case Direction.Down:
|
||||||
|
y--;
|
||||||
|
break;
|
||||||
|
case Direction.Left:
|
||||||
|
x--;
|
||||||
|
break;
|
||||||
|
case Direction.Right:
|
||||||
|
x++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Turn(long direction)
|
||||||
|
{
|
||||||
|
switch (heading)
|
||||||
|
{
|
||||||
|
case Direction.Up:
|
||||||
|
heading = direction == 0 ? Direction.Left : Direction.Right;
|
||||||
|
break;
|
||||||
|
case Direction.Down:
|
||||||
|
heading = direction == 0 ? Direction.Right : Direction.Left;
|
||||||
|
break;
|
||||||
|
case Direction.Left:
|
||||||
|
heading = direction == 0 ? Direction.Down : Direction.Up;
|
||||||
|
break;
|
||||||
|
case Direction.Right:
|
||||||
|
heading = direction == 0 ? Direction.Up : Direction.Down;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Move();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<(long x, long y), long> PaintShip(int initialVal)
|
||||||
|
{
|
||||||
|
var map = new Dictionary<(long, long), long>();
|
||||||
|
vm.Reset();
|
||||||
|
heading = Direction.Up;
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
map[(x, y)] = initialVal;
|
||||||
|
|
||||||
|
var haltType = IntCodeVM.HaltType.Waiting;
|
||||||
|
while (haltType == IntCodeVM.HaltType.Waiting)
|
||||||
|
{
|
||||||
|
haltType = vm.Run(map.GetValueOrDefault((x, y)));
|
||||||
|
map[(x, y)] = vm.Result;
|
||||||
|
Turn(vm.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{PaintShip(0).Count}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var map = PaintShip(1);
|
||||||
|
var minX = (int)map.Keys.Select(i => i.x).Min();
|
||||||
|
var maxX = (int)map.Keys.Select(i => i.x).Max();
|
||||||
|
var minY = (int)map.Keys.Select(i => i.y).Min();
|
||||||
|
var maxY = (int)map.Keys.Select(i => i.y).Max();
|
||||||
|
|
||||||
|
return "\n" + Enumerable.Range(minY, maxY - minY + 1)
|
||||||
|
.Select(j =>
|
||||||
|
Enumerable.Range(minX, maxX - minX + 1)
|
||||||
|
.Select(i => map.GetValueOrDefault((x: i, y: j)) == 0 ? ' ' : '#')
|
||||||
|
.ToDelimitedString()
|
||||||
|
)
|
||||||
|
.Reverse()
|
||||||
|
.ToDelimitedString("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Direction
|
||||||
|
{
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
Right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
206
aoc2019/Day12.cs
206
aoc2019/Day12.cs
|
@ -1,127 +1,123 @@
|
||||||
using System;
|
namespace aoc2019;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day12 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day12 : Day
|
private readonly List<Position> moons;
|
||||||
|
private int step;
|
||||||
|
|
||||||
|
public Day12() : base(12, "The N-Body Problem")
|
||||||
{
|
{
|
||||||
private readonly List<Position> moons;
|
moons = Input
|
||||||
private int step;
|
.Select(moon =>
|
||||||
|
moon
|
||||||
|
.TrimStart('<')
|
||||||
|
.TrimEnd('>')
|
||||||
|
.Split(",")
|
||||||
|
.Select(val => int.Parse(val.Split("=").Last()))
|
||||||
|
)
|
||||||
|
.Select(moon => new Position(moon.ToList()))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
public Day12() : base(12, "The N-Body Problem")
|
foreach (var moon in moons)
|
||||||
|
moon.SetSiblings(moons);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long LCM(long a, long b)
|
||||||
|
{
|
||||||
|
return a * b / GCD(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long GCD(long a, long b)
|
||||||
|
{
|
||||||
|
if (b == 0) return a;
|
||||||
|
return GCD(b, a % b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Step()
|
||||||
|
{
|
||||||
|
foreach (var moon in moons)
|
||||||
|
moon.Gravitate();
|
||||||
|
|
||||||
|
foreach (var moon in moons)
|
||||||
|
moon.Move();
|
||||||
|
|
||||||
|
step++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
while (step < 1000)
|
||||||
|
Step();
|
||||||
|
|
||||||
|
return $"{moons.Sum(p => p.TotalEnergy)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
int cycleX = 0, cycleY = 0, cycleZ = 0;
|
||||||
|
|
||||||
|
while (cycleX == 0 || cycleY == 0 || cycleZ == 0)
|
||||||
{
|
{
|
||||||
moons = Input
|
Step();
|
||||||
.Select(moon =>
|
if (cycleX == 0 && moons.All(m => m.dx == 0)) cycleX = step * 2;
|
||||||
moon
|
if (cycleY == 0 && moons.All(m => m.dy == 0)) cycleY = step * 2;
|
||||||
.TrimStart('<')
|
if (cycleZ == 0 && moons.All(m => m.dz == 0)) cycleZ = step * 2;
|
||||||
.TrimEnd('>')
|
|
||||||
.Split(",")
|
|
||||||
.Select(val => int.Parse(val.Split("=").Last()))
|
|
||||||
)
|
|
||||||
.Select(moon => new Position(moon.ToList()))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (var moon in moons)
|
|
||||||
moon.SetSiblings(moons);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long LCM(long a, long b)
|
return $"{LCM(cycleX, LCM(cycleY, cycleZ))}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Position
|
||||||
|
{
|
||||||
|
public int dx, dy, dz;
|
||||||
|
private List<Position> siblings;
|
||||||
|
public int x, y, z;
|
||||||
|
|
||||||
|
public Position(IList<int> moon)
|
||||||
{
|
{
|
||||||
return a * b / GCD(a, b);
|
x = moon[0];
|
||||||
|
y = moon[1];
|
||||||
|
z = moon[2];
|
||||||
|
dx = 0;
|
||||||
|
dy = 0;
|
||||||
|
dz = 0;
|
||||||
|
siblings = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long GCD(long a, long b)
|
internal int KineticEnergy =>
|
||||||
|
Math.Abs(x) + Math.Abs(y) + Math.Abs(z);
|
||||||
|
|
||||||
|
internal int PotentialEnergy =>
|
||||||
|
Math.Abs(dx) + Math.Abs(dy) + Math.Abs(dz);
|
||||||
|
|
||||||
|
internal int TotalEnergy =>
|
||||||
|
KineticEnergy * PotentialEnergy;
|
||||||
|
|
||||||
|
public void SetSiblings(List<Position> positions)
|
||||||
{
|
{
|
||||||
if (b == 0) return a;
|
siblings = positions.Where(p => p != this).ToList();
|
||||||
return GCD(b, a % b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Step()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
foreach (var moon in moons)
|
return $"pos=<x={x}, y={y}, z={z}> vel=<x={dx}, y={dy}, z={dz}>";
|
||||||
moon.Gravitate();
|
|
||||||
|
|
||||||
foreach (var moon in moons)
|
|
||||||
moon.Move();
|
|
||||||
|
|
||||||
step++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part1()
|
internal void Gravitate()
|
||||||
{
|
{
|
||||||
while (step < 1000)
|
foreach (var m in siblings)
|
||||||
Step();
|
{
|
||||||
|
if (x != m.x) dx += x > m.x ? -1 : 1;
|
||||||
return $"{moons.Sum(p => p.TotalEnergy)}";
|
if (y != m.y) dy += y > m.y ? -1 : 1;
|
||||||
|
if (z != m.z) dz += z > m.z ? -1 : 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part2()
|
internal void Move()
|
||||||
{
|
{
|
||||||
int cycleX = 0, cycleY = 0, cycleZ = 0;
|
x += dx;
|
||||||
|
y += dy;
|
||||||
while (cycleX == 0 || cycleY == 0 || cycleZ == 0)
|
z += dz;
|
||||||
{
|
|
||||||
Step();
|
|
||||||
if (cycleX == 0 && moons.All(m => m.dx == 0)) cycleX = step * 2;
|
|
||||||
if (cycleY == 0 && moons.All(m => m.dy == 0)) cycleY = step * 2;
|
|
||||||
if (cycleZ == 0 && moons.All(m => m.dz == 0)) cycleZ = step * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{LCM(cycleX, LCM(cycleY, cycleZ))}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Position
|
|
||||||
{
|
|
||||||
public int dx, dy, dz;
|
|
||||||
private List<Position> siblings;
|
|
||||||
public int x, y, z;
|
|
||||||
|
|
||||||
public Position(IList<int> moon)
|
|
||||||
{
|
|
||||||
x = moon[0];
|
|
||||||
y = moon[1];
|
|
||||||
z = moon[2];
|
|
||||||
dx = 0;
|
|
||||||
dy = 0;
|
|
||||||
dz = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal int KineticEnergy =>
|
|
||||||
Math.Abs(x) + Math.Abs(y) + Math.Abs(z);
|
|
||||||
|
|
||||||
internal int PotentialEnergy =>
|
|
||||||
Math.Abs(dx) + Math.Abs(dy) + Math.Abs(dz);
|
|
||||||
|
|
||||||
internal int TotalEnergy =>
|
|
||||||
KineticEnergy * PotentialEnergy;
|
|
||||||
|
|
||||||
public void SetSiblings(List<Position> positions)
|
|
||||||
{
|
|
||||||
siblings = positions.Where(p => p != this).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"pos=<x={x}, y={y}, z={z}> vel=<x={dx}, y={dy}, z={dz}>";
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Gravitate()
|
|
||||||
{
|
|
||||||
foreach (var m in siblings)
|
|
||||||
{
|
|
||||||
if (x != m.x) dx += x > m.x ? -1 : 1;
|
|
||||||
if (y != m.y) dy += y > m.y ? -1 : 1;
|
|
||||||
if (z != m.z) dz += z > m.z ? -1 : 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Move()
|
|
||||||
{
|
|
||||||
x += dx;
|
|
||||||
y += dy;
|
|
||||||
z += dz;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
150
aoc2019/Day13.cs
150
aoc2019/Day13.cs
|
@ -1,87 +1,81 @@
|
||||||
using System;
|
namespace aoc2019;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day13 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day13 : Day
|
private readonly Dictionary<(int x, int y), int> board;
|
||||||
|
|
||||||
|
private readonly IntCodeVM vm;
|
||||||
|
|
||||||
|
public Day13() : base(13, "Care Package")
|
||||||
{
|
{
|
||||||
private readonly Dictionary<(int x, int y), int> board;
|
vm = new IntCodeVM(Input.First());
|
||||||
|
board = new Dictionary<(int, int), int>();
|
||||||
|
}
|
||||||
|
|
||||||
private readonly IntCodeVM vm;
|
private void UpdateTiles(IEnumerable<long> queue)
|
||||||
|
{
|
||||||
|
var input = queue.Select(i => (int)i).ToList();
|
||||||
|
|
||||||
public Day13() : base(13, "Care Package")
|
for (var i = 0; i < input.Count - 2; i += 3)
|
||||||
{
|
{
|
||||||
vm = new IntCodeVM(Input.First());
|
var x = input[i];
|
||||||
board = new Dictionary<(int, int), int>();
|
var y = input[i + 1];
|
||||||
}
|
var val = input[i + 2];
|
||||||
|
|
||||||
private void UpdateTiles(IEnumerable<long> queue)
|
if (board.ContainsKey((x, y)))
|
||||||
{
|
board[(x, y)] = val;
|
||||||
var input = queue.Select(i => (int) i).ToList();
|
else
|
||||||
|
board.Add((x, y), val);
|
||||||
for (var i = 0; i < input.Count - 2; i += 3)
|
|
||||||
{
|
|
||||||
var x = input[i];
|
|
||||||
var y = input[i + 1];
|
|
||||||
var val = input[i + 2];
|
|
||||||
|
|
||||||
if (board.ContainsKey((x, y)))
|
|
||||||
board[(x, y)] = val;
|
|
||||||
else
|
|
||||||
board.Add((x, y), val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PrintBoard()
|
|
||||||
{
|
|
||||||
foreach (var ((x, y), value) in board)
|
|
||||||
{
|
|
||||||
if (x < 0 || y < 0) continue;
|
|
||||||
Console.SetCursorPosition(x, y);
|
|
||||||
Console.Write(value switch
|
|
||||||
{
|
|
||||||
0 => " ",
|
|
||||||
1 => "|",
|
|
||||||
2 => "B",
|
|
||||||
3 => "_",
|
|
||||||
4 => ".",
|
|
||||||
_ => value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
vm.Reset();
|
|
||||||
vm.Run();
|
|
||||||
return $"{vm.output.Where((v, i) => (i + 1) % 3 == 0 && v == 2).Count()}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
vm.Reset();
|
|
||||||
vm.memory[0] = 2;
|
|
||||||
var printBoard = false;
|
|
||||||
var gameTicks = 0;
|
|
||||||
if (printBoard) Console.Clear();
|
|
||||||
|
|
||||||
var haltType = IntCodeVM.HaltType.Waiting;
|
|
||||||
while (haltType == IntCodeVM.HaltType.Waiting)
|
|
||||||
{
|
|
||||||
haltType = vm.Run();
|
|
||||||
UpdateTiles(vm.output);
|
|
||||||
|
|
||||||
var (ball, _) = board.First(t => t.Value == 4).Key;
|
|
||||||
var (paddle, _) = board.First(t => t.Value == 3).Key;
|
|
||||||
vm.AddInput(ball > paddle ? 1 : ball < paddle ? -1 : 0);
|
|
||||||
|
|
||||||
gameTicks++;
|
|
||||||
if (printBoard) PrintBoard();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"after {gameTicks} moves, the score is: {board[(-1, 0)]}";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private void PrintBoard()
|
||||||
|
{
|
||||||
|
foreach (var ((x, y), value) in board)
|
||||||
|
{
|
||||||
|
if (x < 0 || y < 0) continue;
|
||||||
|
Console.SetCursorPosition(x, y);
|
||||||
|
Console.Write(value switch
|
||||||
|
{
|
||||||
|
0 => " ",
|
||||||
|
1 => "|",
|
||||||
|
2 => "B",
|
||||||
|
3 => "_",
|
||||||
|
4 => ".",
|
||||||
|
_ => value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
vm.Reset();
|
||||||
|
vm.Run();
|
||||||
|
return $"{vm.output.Where((v, i) => (i + 1) % 3 == 0 && v == 2).Count()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
vm.Reset();
|
||||||
|
vm.memory[0] = 2;
|
||||||
|
var printBoard = false;
|
||||||
|
var gameTicks = 0;
|
||||||
|
if (printBoard) Console.Clear();
|
||||||
|
|
||||||
|
var haltType = IntCodeVM.HaltType.Waiting;
|
||||||
|
while (haltType == IntCodeVM.HaltType.Waiting)
|
||||||
|
{
|
||||||
|
haltType = vm.Run();
|
||||||
|
UpdateTiles(vm.output);
|
||||||
|
|
||||||
|
var (ball, _) = board.First(t => t.Value == 4).Key;
|
||||||
|
var (paddle, _) = board.First(t => t.Value == 3).Key;
|
||||||
|
vm.AddInput(ball > paddle ? 1 : ball < paddle ? -1 : 0);
|
||||||
|
|
||||||
|
gameTicks++;
|
||||||
|
if (printBoard) PrintBoard();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"after {gameTicks} moves, the score is: {board[(-1, 0)]}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
171
aoc2019/Day14.cs
171
aoc2019/Day14.cs
|
@ -1,110 +1,107 @@
|
||||||
using System;
|
namespace aoc2019;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day14 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day14 : Day
|
private readonly Dictionary<string, Reaction> reactions;
|
||||||
|
|
||||||
|
private Dictionary<string, long> available;
|
||||||
|
|
||||||
|
public Day14() : base(14, "Space Stoichiometry")
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, Reaction> reactions;
|
reactions = Input
|
||||||
|
.Select(Reaction.Parse)
|
||||||
|
.ToDictionary(r => r.product.Name);
|
||||||
|
|
||||||
|
available = new();
|
||||||
|
}
|
||||||
|
|
||||||
private Dictionary<string, long> available;
|
private bool Consume(string chem, long quantity)
|
||||||
|
{
|
||||||
|
if (quantity <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(quantity));
|
||||||
|
|
||||||
public Day14() : base(14, "Space Stoichiometry")
|
if (!available.ContainsKey(chem))
|
||||||
{
|
available[chem] = 0;
|
||||||
reactions = Input
|
|
||||||
.Select(Reaction.Parse)
|
|
||||||
.ToDictionary(r => r.product.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Consume(string chem, long quantity)
|
if (available[chem] < quantity && !Produce(chem, quantity - available[chem]))
|
||||||
{
|
return false;
|
||||||
if (quantity <= 0)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(quantity));
|
|
||||||
|
|
||||||
if (!available.ContainsKey(chem))
|
available[chem] -= quantity;
|
||||||
available[chem] = 0;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (available[chem] < quantity && !Produce(chem, quantity - available[chem]))
|
private bool Produce(string chem, long quantity)
|
||||||
|
{
|
||||||
|
if (chem == "ORE")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var reaction = reactions[chem];
|
||||||
|
var reactionCount = (long)Math.Ceiling((double)quantity / reaction.product.Quantity);
|
||||||
|
|
||||||
|
foreach (var reactant in reaction.reactants)
|
||||||
|
if (!Consume(reactant.Name, reactionCount * reactant.Quantity))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
available[chem] -= quantity;
|
available[chem] = available.GetValueOrDefault(chem) + reactionCount * reaction.product.Quantity;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
available = new Dictionary<string, long> { { "ORE", long.MaxValue } };
|
||||||
|
Consume("FUEL", 1);
|
||||||
|
return $"{long.MaxValue - available["ORE"]}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
const long capacity = 1_000_000_000_000;
|
||||||
|
available = new Dictionary<string, long> { { "ORE", capacity } };
|
||||||
|
Consume("FUEL", 1);
|
||||||
|
|
||||||
|
var oreConsumed = capacity - available["ORE"];
|
||||||
|
while (Produce("FUEL", Math.Max(1, available["ORE"] / oreConsumed)))
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Produce(string chem, long quantity)
|
return $"{available["FUEL"] + 1}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct Component
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Quantity { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Reaction
|
||||||
|
{
|
||||||
|
public readonly Component product;
|
||||||
|
public readonly Component[] reactants;
|
||||||
|
|
||||||
|
private Reaction(Component[] reactants, Component product)
|
||||||
{
|
{
|
||||||
if (chem == "ORE")
|
this.reactants = reactants;
|
||||||
return false;
|
this.product = product;
|
||||||
|
|
||||||
var reaction = reactions[chem];
|
|
||||||
var reactionCount = (long) Math.Ceiling((double) quantity / reaction.product.Quantity);
|
|
||||||
|
|
||||||
foreach (var reactant in reaction.reactants)
|
|
||||||
if (!Consume(reactant.Name, reactionCount * reactant.Quantity))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
available[chem] = available.GetValueOrDefault(chem) + reactionCount * reaction.product.Quantity;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part1()
|
public static Reaction Parse(string s)
|
||||||
{
|
{
|
||||||
available = new Dictionary<string, long> {{"ORE", long.MaxValue}};
|
var ss = s.Split(new[] { ", ", " => " }, StringSplitOptions.None);
|
||||||
Consume("FUEL", 1);
|
|
||||||
return $"{long.MaxValue - available["ORE"]}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
return new Reaction(
|
||||||
{
|
ss.Take(ss.Length - 1).Select(ParseComponent).ToArray(),
|
||||||
const long capacity = 1_000_000_000_000;
|
ParseComponent(ss[^1])
|
||||||
available = new Dictionary<string, long> {{"ORE", capacity}};
|
);
|
||||||
Consume("FUEL", 1);
|
|
||||||
|
|
||||||
var oreConsumed = capacity - available["ORE"];
|
static Component ParseComponent(string s)
|
||||||
while (Produce("FUEL", Math.Max(1, available["ORE"] / oreConsumed)))
|
|
||||||
{
|
{
|
||||||
}
|
var spl = s.Split(' ', 2);
|
||||||
|
return new Component
|
||||||
return $"{available["FUEL"] + 1}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct Component
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public int Quantity { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Reaction
|
|
||||||
{
|
|
||||||
public readonly Component product;
|
|
||||||
public readonly Component[] reactants;
|
|
||||||
|
|
||||||
private Reaction(Component[] reactants, Component product)
|
|
||||||
{
|
|
||||||
this.reactants = reactants;
|
|
||||||
this.product = product;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Reaction Parse(string s)
|
|
||||||
{
|
|
||||||
var ss = s.Split(new[] {", ", " => "}, StringSplitOptions.None);
|
|
||||||
|
|
||||||
return new Reaction(
|
|
||||||
ss.Take(ss.Length - 1).Select(ParseComponent).ToArray(),
|
|
||||||
ParseComponent(ss[^1])
|
|
||||||
);
|
|
||||||
|
|
||||||
static Component ParseComponent(string s)
|
|
||||||
{
|
{
|
||||||
var spl = s.Split(' ', 2);
|
Quantity = int.Parse(spl[0]),
|
||||||
return new Component
|
Name = spl[1]
|
||||||
{
|
};
|
||||||
Quantity = int.Parse(spl[0]),
|
|
||||||
Name = spl[1]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
352
aoc2019/Day15.cs
352
aoc2019/Day15.cs
|
@ -1,224 +1,206 @@
|
||||||
using System;
|
namespace aoc2019;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day15 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day15 : Day
|
private readonly bool verbose = false;
|
||||||
|
private readonly IntCodeVM vm;
|
||||||
|
|
||||||
|
public Day15() : base(15, "Oxygen System")
|
||||||
{
|
{
|
||||||
private readonly bool verbose = false;
|
vm = new IntCodeVM(Input.First());
|
||||||
private readonly IntCodeVM vm;
|
}
|
||||||
|
|
||||||
public Day15() : base(15, "Oxygen System")
|
public override string Part1()
|
||||||
|
{
|
||||||
|
vm.Reset();
|
||||||
|
var currentLocation = new Location(0, 0);
|
||||||
|
var halt = IntCodeVM.HaltType.Waiting;
|
||||||
|
while (halt == IntCodeVM.HaltType.Waiting)
|
||||||
{
|
{
|
||||||
vm = new IntCodeVM(Input.First());
|
var direction = currentLocation!.NextDirection();
|
||||||
}
|
if (direction <= 4)
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
vm.Reset();
|
|
||||||
var currentLocation = new Location(0, 0);
|
|
||||||
var halt = IntCodeVM.HaltType.Waiting;
|
|
||||||
while (halt == IntCodeVM.HaltType.Waiting)
|
|
||||||
{
|
{
|
||||||
var direction = currentLocation.NextDirection();
|
var (x, y) = currentLocation.Neighbor(direction);
|
||||||
if (direction <= 4)
|
if (Location.GetLocation(x, y) == null)
|
||||||
{
|
{
|
||||||
var (x, y) = currentLocation.Neighbor(direction);
|
halt = vm.Run(direction);
|
||||||
if (Location.GetLocation(x, y) == null)
|
currentLocation = vm.Result switch
|
||||||
{
|
{
|
||||||
halt = vm.Run(direction);
|
Location.Wall => new Location(x, y, Location.Opposites[direction], Location.Wall),
|
||||||
switch (vm.Result)
|
Location.Empty => new Location(x, y, Location.Opposites[direction]),
|
||||||
{
|
Location.System => new Location(x, y, Location.Opposites[direction], Location.System),
|
||||||
case Location.Wall:
|
_ => throw new Exception($"Unknown IntCodeVM response: {vm.Result}"),
|
||||||
new Location(x, y, Location.Opposites[direction], Location.Wall);
|
};
|
||||||
break;
|
}
|
||||||
case Location.Empty:
|
}
|
||||||
currentLocation = new Location(x, y, Location.Opposites[direction]);
|
else
|
||||||
break;
|
{
|
||||||
case Location.System:
|
direction = currentLocation.PreviousDirection;
|
||||||
currentLocation = new Location(x, y, Location.Opposites[direction], Location.System);
|
if (direction > 0)
|
||||||
break;
|
{
|
||||||
default:
|
halt = vm.Run(direction);
|
||||||
throw new Exception($"Unknown IntCodeVM response: {vm.Result}");
|
currentLocation = vm.Result switch
|
||||||
}
|
{
|
||||||
}
|
Location.Empty or Location.System => Location.GetLocation(currentLocation.Neighbor(direction)),
|
||||||
|
_ => throw new Exception($"Unknown or unexpected response for previous room: {vm.Result}"),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
direction = currentLocation.PreviousDirection;
|
if (verbose)
|
||||||
if (direction > 0)
|
|
||||||
{
|
{
|
||||||
halt = vm.Run(direction);
|
// find extents of canvas
|
||||||
switch (vm.Result)
|
int xMin, xMax, yMin, yMax;
|
||||||
|
xMin = yMin = int.MaxValue;
|
||||||
|
xMax = yMax = int.MinValue;
|
||||||
|
foreach (var (x, y) in Location.AllLocations.Keys)
|
||||||
{
|
{
|
||||||
case Location.Empty:
|
if (x < xMin) xMin = x;
|
||||||
case Location.System:
|
if (x > xMax) xMax = x;
|
||||||
currentLocation = Location.GetLocation(currentLocation.Neighbor(direction));
|
if (y < yMin) yMin = y;
|
||||||
break;
|
if (y > yMax) yMax = y;
|
||||||
default:
|
}
|
||||||
throw new Exception($"Unknown or unexpected response for previous room: {vm.Result}");
|
|
||||||
|
Console.WriteLine($"Canvas extends from ({xMin}, {yMin}) to ({xMax}, {yMax})");
|
||||||
|
|
||||||
|
// print board
|
||||||
|
for (var y = yMin; y <= yMax; y++)
|
||||||
|
{
|
||||||
|
var line = "";
|
||||||
|
for (var x = xMin; x <= xMax; x++)
|
||||||
|
if (Location.AllLocations.ContainsKey((x, y)))
|
||||||
|
line += Location.AllLocations[(x, y)].Image();
|
||||||
|
else
|
||||||
|
line += "@";
|
||||||
|
|
||||||
|
Console.WriteLine(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
currentLocation = Location.OxygenLocation;
|
||||||
|
var distance = 0;
|
||||||
|
while (currentLocation?.PreviousDirection != 0)
|
||||||
{
|
{
|
||||||
if (verbose)
|
distance++;
|
||||||
{
|
currentLocation = Location.GetLocation(currentLocation!.PreviousLocation());
|
||||||
// find extents of canvas
|
|
||||||
int xMin, xMax, yMin, yMax;
|
|
||||||
xMin = yMin = int.MaxValue;
|
|
||||||
xMax = yMax = int.MinValue;
|
|
||||||
foreach (var (x, y) in Location.AllLocations.Keys)
|
|
||||||
{
|
|
||||||
if (x < xMin) xMin = x;
|
|
||||||
if (x > xMax) xMax = x;
|
|
||||||
if (y < yMin) yMin = y;
|
|
||||||
if (y > yMax) yMax = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine($"Canvas extends from ({xMin}, {yMin}) to ({xMax}, {yMax})");
|
|
||||||
|
|
||||||
// print board
|
|
||||||
for (var y = yMin; y <= yMax; y++)
|
|
||||||
{
|
|
||||||
var line = "";
|
|
||||||
for (var x = xMin; x <= xMax; x++)
|
|
||||||
if (Location.AllLocations.ContainsKey((x, y)))
|
|
||||||
line += Location.AllLocations[(x, y)].Image();
|
|
||||||
else
|
|
||||||
line += "@";
|
|
||||||
|
|
||||||
Console.WriteLine(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentLocation = Location.OxygenLocation;
|
|
||||||
var distance = 0;
|
|
||||||
while (currentLocation.PreviousDirection != 0)
|
|
||||||
{
|
|
||||||
distance++;
|
|
||||||
currentLocation = Location.GetLocation(currentLocation.PreviousLocation());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{distance}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $"{distance}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part2()
|
return "";
|
||||||
{
|
}
|
||||||
var changed = true;
|
|
||||||
while (changed)
|
|
||||||
{
|
|
||||||
changed = false;
|
|
||||||
foreach (var location in Location.AllLocations.Values)
|
|
||||||
changed = location.UpdateDistanceToOxygenSystem() || changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Location.AllLocations.Values
|
public override string Part2()
|
||||||
.Where(l => !l.IsWall)
|
{
|
||||||
.Max(l => l.DistanceToOxygenSystem)
|
var changed = true;
|
||||||
.ToString();
|
while (changed)
|
||||||
|
{
|
||||||
|
changed = false;
|
||||||
|
foreach (var location in Location.AllLocations.Values)
|
||||||
|
changed = location.UpdateDistanceToOxygenSystem() || changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Location
|
return Location.AllLocations.Values
|
||||||
|
.Where(l => !l.IsWall)
|
||||||
|
.Max(l => l.DistanceToOxygenSystem)
|
||||||
|
.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Location
|
||||||
|
{
|
||||||
|
public const int Wall = 0;
|
||||||
|
public const int Empty = 1;
|
||||||
|
public const int System = 2;
|
||||||
|
|
||||||
|
private static readonly int[] Dx = { 0, 0, 0, 1, -1 };
|
||||||
|
private static readonly int[] Dy = { 0, 1, -1, 0, 0 };
|
||||||
|
public static readonly int[] Opposites = { 0, 2, 1, 4, 3 };
|
||||||
|
|
||||||
|
public static readonly Dictionary<(int x, int y), Location> AllLocations = new();
|
||||||
|
|
||||||
|
private readonly int currentType;
|
||||||
|
public int DistanceToOxygenSystem = int.MaxValue - 1;
|
||||||
|
|
||||||
|
private int searchDirection = 1;
|
||||||
|
|
||||||
|
public Location(int x, int y, int prev = 0, int type = Empty)
|
||||||
{
|
{
|
||||||
public const int Wall = 0;
|
PreviousDirection = prev;
|
||||||
public const int Empty = 1;
|
currentType = type;
|
||||||
public const int System = 2;
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
|
||||||
private static readonly int[] Dx = {0, 0, 0, 1, -1};
|
if (type == System)
|
||||||
private static readonly int[] Dy = {0, 1, -1, 0, 0};
|
|
||||||
public static readonly int[] Opposites = {0, 2, 1, 4, 3};
|
|
||||||
|
|
||||||
public static readonly Dictionary<(int x, int y), Location>
|
|
||||||
AllLocations = new Dictionary<(int x, int y), Location>();
|
|
||||||
|
|
||||||
private readonly int currentType;
|
|
||||||
public int DistanceToOxygenSystem = int.MaxValue - 1;
|
|
||||||
|
|
||||||
private int searchDirection = 1;
|
|
||||||
|
|
||||||
public Location(int x, int y, int prev = 0, int type = Empty)
|
|
||||||
{
|
{
|
||||||
PreviousDirection = prev;
|
OxygenLocation = this;
|
||||||
currentType = type;
|
DistanceToOxygenSystem = 0;
|
||||||
X = x;
|
// Console.WriteLine($"Found Oxygen System at ({x}, {y})");
|
||||||
Y = y;
|
}
|
||||||
|
|
||||||
if (type == System)
|
AllLocations.Add((x, y), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Location? OxygenLocation { get; private set; }
|
||||||
|
public int PreviousDirection { get; }
|
||||||
|
private int X { get; }
|
||||||
|
private int Y { get; }
|
||||||
|
|
||||||
|
public bool IsWall => currentType == Wall;
|
||||||
|
|
||||||
|
public string Image()
|
||||||
|
{
|
||||||
|
return currentType switch
|
||||||
|
{
|
||||||
|
Wall => "\u2587",
|
||||||
|
Empty => X == 0 && Y == 0 ? "S" : " ",
|
||||||
|
System => "O",
|
||||||
|
_ => "?"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateDistanceToOxygenSystem()
|
||||||
|
{
|
||||||
|
if (currentType != Empty) return false;
|
||||||
|
|
||||||
|
foreach (var direction in Enumerable.Range(1, 4))
|
||||||
|
{
|
||||||
|
var distance = GetLocation(Neighbor(direction))?.DistanceToOxygenSystem ?? int.MaxValue;
|
||||||
|
if (distance + 1 < DistanceToOxygenSystem)
|
||||||
{
|
{
|
||||||
OxygenLocation = this;
|
DistanceToOxygenSystem = distance + 1;
|
||||||
DistanceToOxygenSystem = 0;
|
return true;
|
||||||
// Console.WriteLine($"Found Oxygen System at ({x}, {y})");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AllLocations.Add((x, y), this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Location OxygenLocation { get; private set; }
|
return false;
|
||||||
public int PreviousDirection { get; }
|
}
|
||||||
private int X { get; }
|
|
||||||
private int Y { get; }
|
|
||||||
|
|
||||||
public bool IsWall => currentType == Wall;
|
public (int, int) Neighbor(int direction)
|
||||||
|
{
|
||||||
|
return (X + Dx[direction], Y + Dy[direction]);
|
||||||
|
}
|
||||||
|
|
||||||
public string Image()
|
public (int, int) PreviousLocation()
|
||||||
{
|
{
|
||||||
return currentType switch
|
return Neighbor(PreviousDirection);
|
||||||
{
|
}
|
||||||
Wall => "\u2587",
|
|
||||||
Empty => X == 0 && Y == 0 ? "S" : " ",
|
|
||||||
System => "O",
|
|
||||||
_ => "?"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool UpdateDistanceToOxygenSystem()
|
public int NextDirection()
|
||||||
{
|
{
|
||||||
if (currentType != Empty) return false;
|
return searchDirection++;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var direction in Enumerable.Range(1, 4))
|
public static Location? GetLocation(int x, int y)
|
||||||
{
|
{
|
||||||
var distance = GetLocation(Neighbor(direction))?.DistanceToOxygenSystem ?? int.MaxValue;
|
return AllLocations.ContainsKey((x, y)) ? AllLocations[(x, y)] : null;
|
||||||
if (distance + 1 < DistanceToOxygenSystem)
|
}
|
||||||
{
|
|
||||||
DistanceToOxygenSystem = distance + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
public static Location? GetLocation((int x, int y) coords)
|
||||||
}
|
{
|
||||||
|
return GetLocation(coords.x, coords.y);
|
||||||
public (int, int) Neighbor(int direction)
|
|
||||||
{
|
|
||||||
return (X + Dx[direction], Y + Dy[direction]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public (int, int) PreviousLocation()
|
|
||||||
{
|
|
||||||
return Neighbor(PreviousDirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int NextDirection()
|
|
||||||
{
|
|
||||||
return searchDirection++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Location GetLocation(int x, int y)
|
|
||||||
{
|
|
||||||
return AllLocations.ContainsKey((x, y)) ? AllLocations[(x, y)] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Location GetLocation((int x, int y) coords)
|
|
||||||
{
|
|
||||||
return GetLocation(coords.x, coords.y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
114
aoc2019/Day16.cs
114
aoc2019/Day16.cs
|
@ -1,64 +1,58 @@
|
||||||
using System;
|
namespace aoc2019;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day16 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day16 : Day
|
private static readonly int[] BasePattern = { 0, 1, 0, -1 };
|
||||||
|
private readonly int[] initialList;
|
||||||
|
|
||||||
|
public Day16() : base(16, "Flawed Frequency Transmission")
|
||||||
{
|
{
|
||||||
private static readonly int[] BasePattern = {0, 1, 0, -1};
|
initialList = Input.First().Select(c => int.Parse($"{c}")).ToArray();
|
||||||
private readonly int[] initialList;
|
|
||||||
|
|
||||||
public Day16() : base(16, "Flawed Frequency Transmission")
|
|
||||||
{
|
|
||||||
initialList = Input.First().Select(c => int.Parse($"{c}")).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
const int phaseCount = 100;
|
|
||||||
var signal0 = initialList.ToArray();
|
|
||||||
var signal1 = new int[signal0.Length];
|
|
||||||
|
|
||||||
for (var i = 0; i < phaseCount; i++)
|
|
||||||
CalculateSignal(i % 2 == 0 ? signal0 : signal1, i % 2 == 0 ? signal1 : signal0);
|
|
||||||
|
|
||||||
return new string(
|
|
||||||
signal0.Take(8).Select(c => (char) (c + '0'))
|
|
||||||
.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
const int phaseCount = 100;
|
|
||||||
var messageOffset = initialList.Take(7).Aggregate((n, i) => n * 10 + i);
|
|
||||||
var signal = initialList.Repeat(10_000).Skip(messageOffset).ToArray();
|
|
||||||
|
|
||||||
for (var p = 0; p < phaseCount; p++)
|
|
||||||
{
|
|
||||||
signal[^1] %= 10;
|
|
||||||
for (var i = signal.Length - 2; i >= 0; i--)
|
|
||||||
signal[i] = (signal[i + 1] + signal[i]) % 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new string(signal.Take(8).Select(c => (char) (c + '0')).ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CalculateSignal(IReadOnlyList<int> input, IList<int> output)
|
|
||||||
{
|
|
||||||
for (var outputIndex = 0; outputIndex < output.Count; outputIndex++)
|
|
||||||
output[outputIndex] =
|
|
||||||
Math.Abs(PatternValues(outputIndex, input.Count).Select((pv, i) => pv * input[i] % 10).Sum()) % 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<int> PatternValues(int index, int count)
|
|
||||||
{
|
|
||||||
return BasePattern
|
|
||||||
.SelectMany(v => Enumerable.Repeat(v, index + 1))
|
|
||||||
.Repeat(int.MaxValue)
|
|
||||||
.Skip(1)
|
|
||||||
.Take(count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
const int phaseCount = 100;
|
||||||
|
var signal0 = initialList.ToArray();
|
||||||
|
var signal1 = new int[signal0.Length];
|
||||||
|
|
||||||
|
for (var i = 0; i < phaseCount; i++)
|
||||||
|
CalculateSignal(i % 2 == 0 ? signal0 : signal1, i % 2 == 0 ? signal1 : signal0);
|
||||||
|
|
||||||
|
return new string(
|
||||||
|
signal0.Take(8).Select(c => (char)(c + '0'))
|
||||||
|
.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
const int phaseCount = 100;
|
||||||
|
var messageOffset = initialList.Take(7).Aggregate((n, i) => n * 10 + i);
|
||||||
|
var signal = initialList.Repeat(10_000).Skip(messageOffset).ToArray();
|
||||||
|
|
||||||
|
for (var p = 0; p < phaseCount; p++)
|
||||||
|
{
|
||||||
|
signal[^1] %= 10;
|
||||||
|
for (var i = signal.Length - 2; i >= 0; i--)
|
||||||
|
signal[i] = (signal[i + 1] + signal[i]) % 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(signal.Take(8).Select(c => (char)(c + '0')).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CalculateSignal(IReadOnlyList<int> input, IList<int> output)
|
||||||
|
{
|
||||||
|
for (var outputIndex = 0; outputIndex < output.Count; outputIndex++)
|
||||||
|
output[outputIndex] =
|
||||||
|
Math.Abs(PatternValues(outputIndex, input.Count).Select((pv, i) => pv * input[i] % 10).Sum()) % 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<int> PatternValues(int index, int count)
|
||||||
|
{
|
||||||
|
return BasePattern
|
||||||
|
.SelectMany(v => Enumerable.Repeat(v, index + 1))
|
||||||
|
.Repeat(int.MaxValue)
|
||||||
|
.Skip(1)
|
||||||
|
.Take(count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,32 +1,27 @@
|
||||||
using System;
|
namespace aoc2019;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day17 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day17 : Day
|
private readonly bool Verbose = false;
|
||||||
|
private readonly IntCodeVM vm;
|
||||||
|
|
||||||
|
public Day17() : base(17, "Set and Forget")
|
||||||
{
|
{
|
||||||
private readonly bool Verbose = false;
|
vm = new IntCodeVM(Input.First());
|
||||||
private readonly IntCodeVM vm;
|
}
|
||||||
|
|
||||||
public Day17() : base(17, "Set and Forget")
|
public override string Part1()
|
||||||
{
|
{
|
||||||
vm = new IntCodeVM(Input.First());
|
vm.Reset();
|
||||||
}
|
vm.Run();
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
while (vm.output.Any())
|
||||||
|
sb.Append((char)vm.Result);
|
||||||
|
if (Verbose) Console.Write(sb);
|
||||||
|
var grid = sb.ToString().Trim().Split().Select(s => s.ToCharArray()).ToArray();
|
||||||
|
|
||||||
public override string Part1()
|
var sum = 0;
|
||||||
{
|
for (var y = 1; y < grid.Length - 1; y++)
|
||||||
vm.Reset();
|
|
||||||
vm.Run();
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
while (vm.output.Any())
|
|
||||||
sb.Append((char) vm.Result);
|
|
||||||
if (Verbose) Console.Write(sb);
|
|
||||||
var grid = sb.ToString().Trim().Split().Select(s => s.ToCharArray()).ToArray();
|
|
||||||
|
|
||||||
var sum = 0;
|
|
||||||
for (var y = 1; y < grid.Length - 1; y++)
|
|
||||||
for (var x = 1; x < grid[y].Length - 1; x++)
|
for (var x = 1; x < grid[y].Length - 1; x++)
|
||||||
if (grid[y][x] == '#' &&
|
if (grid[y][x] == '#' &&
|
||||||
grid[y - 1][x] == '#' &&
|
grid[y - 1][x] == '#' &&
|
||||||
|
@ -35,19 +30,18 @@ namespace aoc2019
|
||||||
grid[y][x + 1] == '#')
|
grid[y][x + 1] == '#')
|
||||||
sum += x * y;
|
sum += x * y;
|
||||||
|
|
||||||
return $"{sum}";
|
return $"{sum}";
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
//vm.Reset();
|
|
||||||
//vm.memory[0] = 2;
|
|
||||||
//var halt = IntCodeVM.HaltType.Waiting;
|
|
||||||
//while (halt == IntCodeVM.HaltType.Waiting)
|
|
||||||
//{
|
|
||||||
// halt = vm.Run();
|
|
||||||
//}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
//vm.Reset();
|
||||||
|
//vm.memory[0] = 2;
|
||||||
|
//var halt = IntCodeVM.HaltType.Waiting;
|
||||||
|
//while (halt == IntCodeVM.HaltType.Waiting)
|
||||||
|
//{
|
||||||
|
// halt = vm.Run();
|
||||||
|
//}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace aoc2019;
|
||||||
|
|
||||||
|
public sealed class Day18 : Day
|
||||||
|
{
|
||||||
|
public Day18() : base(18, "Many-Worlds Interpretation")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +1,19 @@
|
||||||
using System.Linq;
|
namespace aoc2019;
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day19 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day19 : Day
|
private readonly long[,] grid;
|
||||||
|
private readonly IntCodeVM vm;
|
||||||
|
|
||||||
|
public Day19() : base(19, "Tractor Beam")
|
||||||
{
|
{
|
||||||
private readonly long[,] grid;
|
vm = new IntCodeVM(Input.First());
|
||||||
private readonly IntCodeVM vm;
|
grid = new long[50, 50];
|
||||||
|
}
|
||||||
|
|
||||||
public Day19() : base(19, "Tractor Beam")
|
public override string Part1()
|
||||||
{
|
{
|
||||||
vm = new IntCodeVM(Input.First());
|
for (var x = 0; x < 50; x++)
|
||||||
grid = new long[50, 50];
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
for (var x = 0; x < 50; x++)
|
|
||||||
for (var y = 0; y < 50; y++)
|
for (var y = 0; y < 50; y++)
|
||||||
{
|
{
|
||||||
vm.Reset();
|
vm.Reset();
|
||||||
|
@ -24,26 +21,25 @@ namespace aoc2019
|
||||||
grid[x, y] = vm.Result;
|
grid[x, y] = vm.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $"{grid.Cast<long>().Sum()}";
|
return $"{grid.Cast<long>().Sum()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part2()
|
public override string Part2()
|
||||||
|
{
|
||||||
|
for (int x = 101, y = 0; ; x++)
|
||||||
{
|
{
|
||||||
for (int x = 101, y = 0;; x++)
|
while (true)
|
||||||
{
|
{
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
vm.Reset();
|
|
||||||
vm.Run(x, y);
|
|
||||||
if (vm.Result == 1) break;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.Reset();
|
vm.Reset();
|
||||||
vm.Run(x - 99, y + 99);
|
vm.Run(x, y);
|
||||||
if (vm.Result == 1)
|
if (vm.Result == 1) break;
|
||||||
return $"{(x - 99) * 1e4 + y}";
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vm.Reset();
|
||||||
|
vm.Run(x - 99, y + 99);
|
||||||
|
if (vm.Result == 1)
|
||||||
|
return $"{(x - 99) * 1e4 + y}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace aoc2019;
|
||||||
|
|
||||||
|
public sealed class Day20 : Day
|
||||||
|
{
|
||||||
|
public Day20() : base(20, "Donut Maze")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,27 +1,23 @@
|
||||||
using System.Linq;
|
namespace aoc2019;
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day21 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day21 : Day
|
private readonly IntCodeVM vm;
|
||||||
|
|
||||||
|
public Day21() : base(21, "Springdroid Adventure")
|
||||||
{
|
{
|
||||||
private readonly IntCodeVM vm;
|
vm = new IntCodeVM(Input.First());
|
||||||
|
|
||||||
public Day21() : base(21, "Springdroid Adventure")
|
|
||||||
{
|
|
||||||
vm = new IntCodeVM(Input.First());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
vm.Reset();
|
|
||||||
var halt = vm.Run();
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
vm.Reset();
|
||||||
|
var halt = vm.Run();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace aoc2019;
|
||||||
|
|
||||||
|
public sealed class Day22 : Day
|
||||||
|
{
|
||||||
|
public Day22() : base(22, "Slam Shuffle")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
142
aoc2019/Day23.cs
142
aoc2019/Day23.cs
|
@ -1,90 +1,86 @@
|
||||||
using System.Linq;
|
namespace aoc2019;
|
||||||
using aoc2019.lib;
|
|
||||||
|
|
||||||
namespace aoc2019
|
public sealed class Day23 : Day
|
||||||
{
|
{
|
||||||
public sealed class Day23 : Day
|
public Day23() : base(23, "Category Six")
|
||||||
{
|
{
|
||||||
public Day23() : base(23, "Category Six")
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
public override string Part1()
|
||||||
{
|
{
|
||||||
var vms = Enumerable.Range(0, 50)
|
var vms = Enumerable.Range(0, 50)
|
||||||
.Select((s, i) =>
|
.Select((s, i) =>
|
||||||
{
|
{
|
||||||
var vm = new IntCodeVM(Input.First());
|
var vm = new IntCodeVM(Input.First());
|
||||||
vm.Run(i);
|
vm.Run(i);
|
||||||
return vm;
|
return vm;
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
foreach (var vm in vms)
|
foreach (var vm in vms)
|
||||||
|
{
|
||||||
|
while (vm.output.Count > 0)
|
||||||
{
|
{
|
||||||
while (vm.output.Count > 0)
|
var destination = (int)vm.Result;
|
||||||
|
var x = vm.Result;
|
||||||
|
var y = vm.Result;
|
||||||
|
|
||||||
|
if (destination == 255) return $"{y}";
|
||||||
|
|
||||||
|
vms[destination].Run(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.Run(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var vms = Enumerable.Range(0, 50)
|
||||||
|
.Select((s, i) =>
|
||||||
|
{
|
||||||
|
var vm = new IntCodeVM(Input.First());
|
||||||
|
vm.Run(i);
|
||||||
|
return vm;
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
long natX = 0, natY = 0, lastYSent = -1;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var numIdle = 0;
|
||||||
|
foreach (var vm in vms)
|
||||||
|
{
|
||||||
|
var isIdle = true;
|
||||||
|
while (vm.output.Count > 0)
|
||||||
|
{
|
||||||
|
var destination = (int)vm.Result;
|
||||||
|
var x = vm.Result;
|
||||||
|
var y = vm.Result;
|
||||||
|
|
||||||
|
if (destination == 255)
|
||||||
|
{
|
||||||
|
natX = x;
|
||||||
|
natY = y;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
var destination = (int) vm.Result;
|
|
||||||
var x = vm.Result;
|
|
||||||
var y = vm.Result;
|
|
||||||
|
|
||||||
if (destination == 255) return $"{y}";
|
|
||||||
|
|
||||||
vms[destination].Run(x, y);
|
vms[destination].Run(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.Run(-1);
|
isIdle = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
vm.Run(-1);
|
||||||
{
|
if (isIdle) numIdle++;
|
||||||
var vms = Enumerable.Range(0, 50)
|
}
|
||||||
.Select((s, i) =>
|
|
||||||
{
|
|
||||||
var vm = new IntCodeVM(Input.First());
|
|
||||||
vm.Run(i);
|
|
||||||
return vm;
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
long natX = 0, natY = 0, lastYSent = -1;
|
if (numIdle == 50)
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
var numIdle = 0;
|
if (natY == lastYSent) return $"{natY}";
|
||||||
foreach (var vm in vms)
|
vms[0].Run(natX, natY);
|
||||||
{
|
lastYSent = natY;
|
||||||
var isIdle = true;
|
|
||||||
while (vm.output.Count > 0)
|
|
||||||
{
|
|
||||||
var destination = (int) vm.Result;
|
|
||||||
var x = vm.Result;
|
|
||||||
var y = vm.Result;
|
|
||||||
|
|
||||||
if (destination == 255)
|
|
||||||
{
|
|
||||||
natX = x;
|
|
||||||
natY = y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vms[destination].Run(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
isIdle = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.Run(-1);
|
|
||||||
if (isIdle) numIdle++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numIdle == 50)
|
|
||||||
{
|
|
||||||
if (natY == lastYSent) return $"{natY}";
|
|
||||||
vms[0].Run(natX, natY);
|
|
||||||
lastYSent = natY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace aoc2019;
|
||||||
|
|
||||||
|
public sealed class Day24 : Day
|
||||||
|
{
|
||||||
|
public Day24() : base(24, "Planet of Discord")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace aoc2019;
|
||||||
|
|
||||||
|
public sealed class Day25 : Day
|
||||||
|
{
|
||||||
|
public Day25() : base(25, "Cryostasis")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace aoc2019;
|
||||||
|
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static IEnumerable<IEnumerable<T>> Permute<T>(this IEnumerable<T> list)
|
||||||
|
{
|
||||||
|
if (list.Count() == 1) return new[] { list };
|
||||||
|
return list.SelectMany(t => Permute(list.Where(x => !x!.Equals(t))), (v, p) => p.Prepend(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> Chunk(this string str, int chunkSize)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < str.Length; i += chunkSize)
|
||||||
|
yield return str.Substring(i, chunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToDelimitedString<T>(this IEnumerable<T> enumerable, string delimiter = "")
|
||||||
|
{
|
||||||
|
return string.Join(delimiter, enumerable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> Repeat<T>(this IEnumerable<T> sequence, int? count = null)
|
||||||
|
{
|
||||||
|
while (count == null || count-- > 0)
|
||||||
|
foreach (var item in sequence)
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// increased accuracy for stopwatch based on frequency.
|
||||||
|
/// <see
|
||||||
|
/// href="http://geekswithblogs.net/BlackRabbitCoder/archive/2012/01/12/c.net-little-pitfalls-stopwatch-ticks-are-not-timespan-ticks.aspx">
|
||||||
|
/// blog
|
||||||
|
/// details here
|
||||||
|
/// </see>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stopwatch"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double ScaleMilliseconds(this Stopwatch stopwatch)
|
||||||
|
{
|
||||||
|
return 1_000 * stopwatch.ElapsedTicks / (double)Stopwatch.Frequency;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
namespace aoc2019;
|
||||||
|
|
||||||
|
public class IntCodeVM
|
||||||
|
{
|
||||||
|
public enum HaltType
|
||||||
|
{
|
||||||
|
Terminate,
|
||||||
|
Waiting
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly long[] program;
|
||||||
|
private long i;
|
||||||
|
public Queue<long> input, output;
|
||||||
|
public long[] memory;
|
||||||
|
private long relativeBase;
|
||||||
|
|
||||||
|
public IntCodeVM(string tape)
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
relativeBase = 0;
|
||||||
|
program = tape.Split(',').Select(long.Parse).ToArray();
|
||||||
|
memory = program;
|
||||||
|
input = new Queue<long>();
|
||||||
|
output = new Queue<long>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Result => output.Dequeue();
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
relativeBase = 0;
|
||||||
|
memory = program;
|
||||||
|
input.Clear();
|
||||||
|
output.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddInput(params long[] values)
|
||||||
|
{
|
||||||
|
foreach (var v in values) AddInput(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddInput(long value)
|
||||||
|
{
|
||||||
|
input.Enqueue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long MemGet(long addr)
|
||||||
|
{
|
||||||
|
return addr < memory.Length ? memory[addr] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MemSet(long addr, long value)
|
||||||
|
{
|
||||||
|
if (addr < 0) addr = 0;
|
||||||
|
if (addr >= memory.Length)
|
||||||
|
Array.Resize(ref memory, (int)addr + 1);
|
||||||
|
memory[addr] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long Mode(long idx)
|
||||||
|
{
|
||||||
|
var mode = MemGet(i) / 100;
|
||||||
|
for (var s = 1; s < idx; s++)
|
||||||
|
mode /= 10;
|
||||||
|
return mode % 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long Get(long idx)
|
||||||
|
{
|
||||||
|
var param = MemGet(i + idx);
|
||||||
|
return Mode(idx) switch
|
||||||
|
{
|
||||||
|
0 => MemGet(param),
|
||||||
|
1 => param,
|
||||||
|
2 => MemGet(relativeBase + param),
|
||||||
|
_ => throw new Exception("invalid parameter mode"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Set(long idx, long val)
|
||||||
|
{
|
||||||
|
var param = MemGet(i + idx);
|
||||||
|
switch (Mode(idx))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
MemSet(param, val);
|
||||||
|
break;
|
||||||
|
case 1: throw new Exception("cannot set in immediate mode");
|
||||||
|
case 2:
|
||||||
|
MemSet(relativeBase + param, val);
|
||||||
|
break;
|
||||||
|
default: throw new Exception("invalid parameter mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HaltType Run(params long[] additionalInput)
|
||||||
|
{
|
||||||
|
foreach (var s in additionalInput) AddInput(s);
|
||||||
|
return Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HaltType Run()
|
||||||
|
{
|
||||||
|
while (i < memory.Length)
|
||||||
|
{
|
||||||
|
var op = MemGet(i) % 100;
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
Set(3, Get(1) + Get(2));
|
||||||
|
i += 4;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Set(3, Get(1) * Get(2));
|
||||||
|
i += 4;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (!input.Any())
|
||||||
|
return HaltType.Waiting;
|
||||||
|
Set(1, input.Dequeue());
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
output.Enqueue(Get(1));
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
i = Get(1) == 0 ? i + 3 : Get(2);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
i = Get(1) != 0 ? i + 3 : Get(2);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
Set(3, Get(1) < Get(2) ? 1 : 0);
|
||||||
|
i += 4;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
Set(3, Get(1) == Get(2) ? 1 : 0);
|
||||||
|
i += 4;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
relativeBase += Get(1);
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
case 99:
|
||||||
|
return HaltType.Terminate;
|
||||||
|
default:
|
||||||
|
throw new Exception($"unknown op {op} at {i}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return HaltType.Terminate;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +1,29 @@
|
||||||
using System;
|
using System.Reflection;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace aoc2019
|
namespace aoc2019;
|
||||||
|
|
||||||
|
internal static class Program
|
||||||
{
|
{
|
||||||
internal static class Program
|
private static void Main(string[] args)
|
||||||
{
|
{
|
||||||
private static void Main(string[] args)
|
var days =
|
||||||
|
Assembly.GetExecutingAssembly().GetTypes()
|
||||||
|
.Where(t => t.BaseType == typeof(Day))
|
||||||
|
.Select(t => Activator.CreateInstance(t) as Day)
|
||||||
|
.OrderBy(d => d?.DayNumber);
|
||||||
|
|
||||||
|
if (args.Length == 1 && int.TryParse(args[0], out var dayNum))
|
||||||
{
|
{
|
||||||
var days =
|
var day = days.FirstOrDefault(d => d?.DayNumber == dayNum);
|
||||||
Assembly.GetExecutingAssembly().GetTypes()
|
|
||||||
.Where(t => t.BaseType == typeof(Day))
|
|
||||||
.Select(t => (Day) Activator.CreateInstance(t))
|
|
||||||
.OrderBy(d => d.DayNumber);
|
|
||||||
|
|
||||||
if (args.Length == 1 && int.TryParse(args[0], out var dayNum))
|
if (day != null)
|
||||||
{
|
day.AllParts();
|
||||||
var day = days.FirstOrDefault(d => d.DayNumber == dayNum);
|
|
||||||
|
|
||||||
if (day != null)
|
|
||||||
day.AllParts();
|
|
||||||
else
|
|
||||||
Console.WriteLine($"{dayNum} invalid or not yet implemented");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
Console.WriteLine($"{dayNum} invalid or not yet implemented");
|
||||||
foreach (var d in days) d.AllParts();
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
foreach (var d in days) d?.AllParts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -11,4 +13,11 @@
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="System.Collections.Generic" />
|
||||||
|
<Using Include="System.Collections.Immutable" />
|
||||||
|
<Using Include="System.Text" />
|
||||||
|
<Using Include="System.Text.RegularExpressions" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2019.lib
|
|
||||||
{
|
|
||||||
public static class Extensions
|
|
||||||
{
|
|
||||||
public static IEnumerable<IEnumerable<T>> Permute<T>(this IEnumerable<T> list)
|
|
||||||
{
|
|
||||||
if (list.Count() == 1) return new[] {list};
|
|
||||||
return list.SelectMany(t => Permute(list.Where(x => !x.Equals(t))), (v, p) => p.Prepend(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<string> Chunk(this string str, int chunkSize)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < str.Length; i += chunkSize)
|
|
||||||
yield return str.Substring(i, chunkSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ToDelimitedString<T>(this IEnumerable<T> enumerable, string delimiter = "")
|
|
||||||
{
|
|
||||||
return string.Join(delimiter, enumerable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<T> Repeat<T>(this IEnumerable<T> sequence, int? count = null)
|
|
||||||
{
|
|
||||||
while (count == null || count-- > 0)
|
|
||||||
foreach (var item in sequence)
|
|
||||||
yield return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// increased accuracy for stopwatch based on frequency.
|
|
||||||
/// <see
|
|
||||||
/// href="http://geekswithblogs.net/BlackRabbitCoder/archive/2012/01/12/c.net-little-pitfalls-stopwatch-ticks-are-not-timespan-ticks.aspx">
|
|
||||||
/// blog
|
|
||||||
/// details here
|
|
||||||
/// </see>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stopwatch"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static double ScaleMilliseconds(this Stopwatch stopwatch)
|
|
||||||
{
|
|
||||||
return 1_000 * stopwatch.ElapsedTicks / (double) Stopwatch.Frequency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,160 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2019.lib
|
|
||||||
{
|
|
||||||
public class IntCodeVM
|
|
||||||
{
|
|
||||||
public enum HaltType
|
|
||||||
{
|
|
||||||
Terminate,
|
|
||||||
Waiting
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly long[] program;
|
|
||||||
private long i;
|
|
||||||
public Queue<long> input, output;
|
|
||||||
public long[] memory;
|
|
||||||
private long relativeBase;
|
|
||||||
|
|
||||||
public IntCodeVM(string tape)
|
|
||||||
{
|
|
||||||
i = 0;
|
|
||||||
relativeBase = 0;
|
|
||||||
program = tape.Split(',').Select(long.Parse).ToArray();
|
|
||||||
memory = program;
|
|
||||||
input = new Queue<long>();
|
|
||||||
output = new Queue<long>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long Result => output.Dequeue();
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
i = 0;
|
|
||||||
relativeBase = 0;
|
|
||||||
memory = program;
|
|
||||||
input.Clear();
|
|
||||||
output.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddInput(params long[] values)
|
|
||||||
{
|
|
||||||
foreach (var v in values) AddInput(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddInput(long value)
|
|
||||||
{
|
|
||||||
input.Enqueue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private long MemGet(long addr)
|
|
||||||
{
|
|
||||||
return addr < memory.Length ? memory[addr] : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MemSet(long addr, long value)
|
|
||||||
{
|
|
||||||
if (addr < 0) addr = 0;
|
|
||||||
if (addr >= memory.Length)
|
|
||||||
Array.Resize(ref memory, (int) addr + 1);
|
|
||||||
memory[addr] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long Mode(long idx)
|
|
||||||
{
|
|
||||||
var mode = MemGet(i) / 100;
|
|
||||||
for (var s = 1; s < idx; s++)
|
|
||||||
mode /= 10;
|
|
||||||
return mode % 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long Get(long idx)
|
|
||||||
{
|
|
||||||
var param = MemGet(i + idx);
|
|
||||||
switch (Mode(idx))
|
|
||||||
{
|
|
||||||
case 0: return MemGet(param);
|
|
||||||
case 1: return param;
|
|
||||||
case 2: return MemGet(relativeBase + param);
|
|
||||||
default: throw new Exception("invalid parameter mode");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Set(long idx, long val)
|
|
||||||
{
|
|
||||||
var param = MemGet(i + idx);
|
|
||||||
switch (Mode(idx))
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
MemSet(param, val);
|
|
||||||
break;
|
|
||||||
case 1: throw new Exception("cannot set in immediate mode");
|
|
||||||
case 2:
|
|
||||||
MemSet(relativeBase + param, val);
|
|
||||||
break;
|
|
||||||
default: throw new Exception("invalid parameter mode");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public HaltType Run(params long[] additionalInput)
|
|
||||||
{
|
|
||||||
foreach (var s in additionalInput) AddInput(s);
|
|
||||||
return Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public HaltType Run()
|
|
||||||
{
|
|
||||||
while (i < memory.Length)
|
|
||||||
{
|
|
||||||
var op = MemGet(i) % 100;
|
|
||||||
switch (op)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
Set(3, Get(1) + Get(2));
|
|
||||||
i += 4;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
Set(3, Get(1) * Get(2));
|
|
||||||
i += 4;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (!input.Any())
|
|
||||||
return HaltType.Waiting;
|
|
||||||
Set(1, input.Dequeue());
|
|
||||||
i += 2;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
output.Enqueue(Get(1));
|
|
||||||
i += 2;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
i = Get(1) == 0 ? i + 3 : Get(2);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
i = Get(1) != 0 ? i + 3 : Get(2);
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
Set(3, Get(1) < Get(2) ? 1 : 0);
|
|
||||||
i += 4;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
Set(3, Get(1) == Get(2) ? 1 : 0);
|
|
||||||
i += 4;
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
relativeBase += Get(1);
|
|
||||||
i += 2;
|
|
||||||
break;
|
|
||||||
case 99:
|
|
||||||
return HaltType.Terminate;
|
|
||||||
default:
|
|
||||||
throw new Exception($"unknown op {op} at {i}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return HaltType.Terminate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue