refactor to two-digit day names and add puzzlename
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Ben Harris 2020-12-16 17:17:35 -05:00
parent c66d1d6b33
commit 837527d487
28 changed files with 84 additions and 95 deletions

32
Day.cs
View File

@ -2,32 +2,44 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using aoc2019.lib;
namespace aoc2019 namespace aoc2019
{ {
public abstract class Day public abstract class Day
{ {
public abstract int DayNumber { get; } protected Day(int dayNumber, string puzzleName)
{
DayNumber = dayNumber;
PuzzleName = puzzleName;
}
public int DayNumber { get; }
public string PuzzleName { get; }
protected virtual IEnumerable<string> Input => protected virtual IEnumerable<string> Input =>
File.ReadLines($"input/day{DayNumber}.in"); File.ReadLines(FileName);
public virtual void AllParts(bool verbose = false) protected string FileName =>
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"input/day{DayNumber,2:00}.in");
public void AllParts(bool verbose = true)
{ {
Console.WriteLine($"Day {DayNumber}:"); Console.WriteLine($"Day {DayNumber,2}: {PuzzleName}");
var s = new Stopwatch(); var s = Stopwatch.StartNew();
s.Start();
var part1 = Part1(); var part1 = Part1();
s.Stop(); s.Stop();
if (verbose) Console.WriteLine($"part 1 elapsed ticks: {s.ElapsedTicks}"); Console.Write($"Part1: {part1,-15} ");
Console.WriteLine(part1); Console.WriteLine(verbose ? $"{s.ScaleMilliseconds()}ms elapsed" : "");
s.Reset(); s.Reset();
s.Start(); s.Start();
var part2 = Part2(); var part2 = Part2();
s.Stop(); s.Stop();
if (verbose) Console.WriteLine($"part 2 elapsed ticks: {s.ElapsedTicks}"); Console.Write($"Part2: {part2,-15} ");
Console.WriteLine(part2); Console.WriteLine(verbose ? $"{s.ScaleMilliseconds()}ms elapsed" : "");
Console.WriteLine(); Console.WriteLine();
} }

View File

@ -3,17 +3,15 @@ using System.Linq;
namespace aoc2019 namespace aoc2019
{ {
internal sealed class Day1 : Day internal sealed class Day01 : Day
{ {
private readonly IEnumerable<int> masses; private readonly IEnumerable<int> masses;
public Day1() public Day01() : base(1, "The Tyranny of the Rocket Equation")
{ {
masses = Input.Select(int.Parse); masses = Input.Select(int.Parse);
} }
public override int DayNumber => 1;
private static int FuelCost(int weight) private static int FuelCost(int weight)
{ {
return weight / 3 - 2; return weight / 3 - 2;

View File

@ -3,17 +3,15 @@ using System.Linq;
namespace aoc2019 namespace aoc2019
{ {
internal sealed class Day2 : Day internal sealed class Day02 : Day
{ {
private readonly IEnumerable<int> input; private readonly IEnumerable<int> input;
public Day2() public Day02() : base(2, "1202 Program Alarm")
{ {
input = Input.First().Split(',').Select(int.Parse); input = Input.First().Split(',').Select(int.Parse);
} }
public override int DayNumber => 2;
public int RunIntCode(int noun, int verb) public int RunIntCode(int noun, int verb)
{ {
var v = input.ToList(); var v = input.ToList();

View File

@ -4,19 +4,17 @@ using System.Linq;
namespace aoc2019 namespace aoc2019
{ {
internal sealed class Day3 : Day internal sealed class Day03 : Day
{ {
private readonly IEnumerable<(int, int)> intersections; private readonly IEnumerable<(int, int)> intersections;
private readonly List<Dictionary<(int, int), int>> wires; private readonly List<Dictionary<(int, int), int>> wires;
public Day3() public Day03() : base(3, "Crossed Wires")
{ {
wires = Input.Select(ParseWire).ToList(); wires = Input.Select(ParseWire).ToList();
intersections = wires[0].Keys.Intersect(wires[1].Keys); intersections = wires[0].Keys.Intersect(wires[1].Keys);
} }
public override int DayNumber => 3;
protected override string Part1() protected override string Part1()
{ {
return $"{intersections.Min(x => Math.Abs(x.Item1) + Math.Abs(x.Item2))}"; return $"{intersections.Min(x => Math.Abs(x.Item1) + Math.Abs(x.Item2))}";

View File

@ -2,21 +2,19 @@
namespace aoc2019 namespace aoc2019
{ {
internal sealed class Day4 : Day internal sealed class Day04 : Day
{ {
private readonly int end; private readonly int end;
private readonly int start; private readonly int start;
public Day4() public Day04() : base(4, "Secure Container")
{ {
var range = Input.First().Split('-').Select(int.Parse).ToList(); var range = Input.First().Split('-').Select(int.Parse).ToList();
start = range[0]; start = range[0];
end = range[1]; end = range[1];
} }
public override int DayNumber => 4;
private bool IsValid(int i) private bool IsValid(int i)
{ {
var prev = 0; var prev = 0;

View File

@ -3,19 +3,17 @@ using System.Linq;
namespace aoc2019 namespace aoc2019
{ {
internal sealed class Day5 : Day internal sealed class Day05 : Day
{ {
private readonly IEnumerable<int> tape; private readonly IEnumerable<int> tape;
private int output; private int output;
public Day5() public Day05() : base(5, "Sunny with a Chance of Asteroids")
{ {
tape = Input.First().Split(',').Select(int.Parse); tape = Input.First().Split(',').Select(int.Parse);
} }
public override int DayNumber => 5;
public void RunIntCode(List<int> v, int input) public void RunIntCode(List<int> v, int input)
{ {
var i = 0; var i = 0;

View File

@ -3,17 +3,15 @@ using System.Linq;
namespace aoc2019 namespace aoc2019
{ {
internal sealed class Day6 : Day internal sealed class Day06 : Day
{ {
private readonly Dictionary<string, string> input; private readonly Dictionary<string, string> input;
public Day6() public Day06() : base(6, "Universal Orbit Map")
{ {
input = Input.ToDictionary(i => i.Split(')')[1], i => i.Split(')')[0]); input = Input.ToDictionary(i => i.Split(')')[1], i => i.Split(')')[0]);
} }
public override int DayNumber => 6;
private List<string> GetParents(string obj) private List<string> GetParents(string obj)
{ {
var res = new List<string>(); var res = new List<string>();

View File

@ -4,18 +4,15 @@ using aoc2019.lib;
namespace aoc2019 namespace aoc2019
{ {
internal sealed class Day7 : Day internal sealed class Day07 : Day
{ {
private readonly IntCodeVM[] Amplifiers = new IntCodeVM[5]; private readonly IntCodeVM[] Amplifiers = new IntCodeVM[5];
public Day7() public Day07() : base(7, "Amplification Circuit")
{ {
for (var i = 0; i < 5; i++) Amplifiers[i] = new IntCodeVM(Input.First()); for (var i = 0; i < 5; i++) Amplifiers[i] = new IntCodeVM(Input.First());
} }
public override int DayNumber => 7;
protected override string Part1() protected override string Part1()
{ {
long i, largest = 0; long i, largest = 0;

View File

@ -5,17 +5,15 @@ using aoc2019.lib;
namespace aoc2019 namespace aoc2019
{ {
internal sealed class Day8 : Day internal sealed class Day08 : Day
{ {
private readonly List<List<char>> photo; private readonly List<List<char>> photo;
public Day8() public Day08() : base(8, "Space Image Format")
{ {
photo = Input.First().Chunk(25 * 6).Select(s => s.ToList()).ToList(); photo = Input.First().Chunk(25 * 6).Select(s => s.ToList()).ToList();
} }
public override int DayNumber => 8;
protected override string Part1() protected override string Part1()
{ {
var l = photo.OrderBy(layer => layer.Count(pixel => pixel == '0')).First(); var l = photo.OrderBy(layer => layer.Count(pixel => pixel == '0')).First();

View File

@ -3,17 +3,15 @@ using aoc2019.lib;
namespace aoc2019 namespace aoc2019
{ {
internal sealed class Day9 : Day internal sealed class Day09 : Day
{ {
private readonly IntCodeVM vm; private readonly IntCodeVM vm;
public Day9() public Day09() : base(9, "Sensor Boost")
{ {
vm = new IntCodeVM(Input.First()); vm = new IntCodeVM(Input.First());
} }
public override int DayNumber => 9;
protected override string Part1() protected override string Part1()
{ {
vm.Reset(); vm.Reset();

View File

@ -7,11 +7,11 @@ namespace aoc2019
{ {
internal sealed class Day10 : Day internal sealed class Day10 : Day
{ {
private readonly HashSet<(int x, int y)> asteroids = new HashSet<(int x, int y)>(); private readonly HashSet<(int x, int y)> asteroids;
private (int x, int y) best = (x: -1, y: -1); private (int x, int y) best = (x: -1, y: -1);
private int bestcansee; private int bestCanSee;
public Day10() public Day10() : base(10, "Monitoring Station")
{ {
asteroids = Input asteroids = Input
.Select((r, y) => r.Select((c, x) => (x, y, isAsteroid: c == '#')).ToArray()) .Select((r, y) => r.Select((c, x) => (x, y, isAsteroid: c == '#')).ToArray())
@ -21,26 +21,24 @@ namespace aoc2019
.ToHashSet(); .ToHashSet();
} }
public override int DayNumber => 10;
protected override string Part1() protected override string Part1()
{ {
foreach (var asteroid in asteroids) foreach (var asteroid in asteroids)
{ {
var cansee = asteroids var canSee = asteroids
.Except(new[] {asteroid}) .Except(new[] {asteroid})
.Select(a => (x: a.x - asteroid.x, y: a.y - asteroid.y)) .Select(a => (x: a.x - asteroid.x, y: a.y - asteroid.y))
.GroupBy(a => Math.Atan2(a.y, a.x)) .GroupBy(a => Math.Atan2(a.y, a.x))
.Count(); .Count();
if (cansee > bestcansee) if (canSee > bestCanSee)
{ {
best = asteroid; best = asteroid;
bestcansee = cansee; bestCanSee = canSee;
} }
} }
return $"{bestcansee}"; return $"{bestCanSee}";
} }
protected override string Part2() protected override string Part2()
@ -55,10 +53,10 @@ namespace aoc2019
.Where(a => a != best) .Where(a => a != best)
.Select(a => .Select(a =>
{ {
var xdist = a.x - best.x; var xDist = a.x - best.x;
var ydist = a.y - best.y; var yDist = a.y - best.y;
var angle = Math.Atan2(xdist, ydist); var angle = Math.Atan2(xDist, yDist);
return (a.x, a.y, angle, dist: Math.Sqrt(xdist * xdist + ydist * ydist)); return (a.x, a.y, angle, dist: Math.Sqrt(xDist * xDist + yDist * yDist));
}) })
.ToLookup(a => a.angle) .ToLookup(a => a.angle)
.OrderByDescending(a => a.Key) .OrderByDescending(a => a.Key)

View File

@ -11,13 +11,11 @@ namespace aoc2019
private Direction heading; private Direction heading;
private long x, y; private long x, y;
public Day11() public Day11() : base(11, "Space Police")
{ {
vm = new IntCodeVM(Input.First()); vm = new IntCodeVM(Input.First());
} }
public override int DayNumber => 11;
private void Move() private void Move()
{ {
switch (heading) switch (heading)

View File

@ -7,10 +7,9 @@ namespace aoc2019
internal sealed class Day12 : Day internal sealed class Day12 : Day
{ {
private readonly List<Position> moons; private readonly List<Position> moons;
private readonly List<Position> startingPositions;
private int step; private int step;
public Day12() public Day12() : base(12, "The N-Body Problem")
{ {
moons = Input moons = Input
.Select(moon => .Select(moon =>
@ -25,12 +24,8 @@ namespace aoc2019
foreach (var moon in moons) foreach (var moon in moons)
moon.SetSiblings(moons); moon.SetSiblings(moons);
startingPositions = moons;
} }
public override int DayNumber => 12;
public static long LCM(long a, long b) public static long LCM(long a, long b)
{ {
return a * b / GCD(a, b); return a * b / GCD(a, b);

View File

@ -11,14 +11,12 @@ namespace aoc2019
private readonly IntCodeVM vm; private readonly IntCodeVM vm;
public Day13() public Day13() : base(13, "Care Package")
{ {
vm = new IntCodeVM(Input.First()); vm = new IntCodeVM(Input.First());
board = new Dictionary<(int, int), int>(); board = new Dictionary<(int, int), int>();
} }
public override int DayNumber => 13;
private void UpdateTiles(IEnumerable<long> queue) private void UpdateTiles(IEnumerable<long> queue)
{ {
var input = queue.Select(i => (int) i).ToList(); var input = queue.Select(i => (int) i).ToList();
@ -65,9 +63,9 @@ namespace aoc2019
{ {
vm.Reset(); vm.Reset();
vm.memory[0] = 2; vm.memory[0] = 2;
var printboard = false; var printBoard = false;
var gameTicks = 0; var gameTicks = 0;
if (printboard) Console.Clear(); if (printBoard) Console.Clear();
var haltType = IntCodeVM.HaltType.Waiting; var haltType = IntCodeVM.HaltType.Waiting;
while (haltType == IntCodeVM.HaltType.Waiting) while (haltType == IntCodeVM.HaltType.Waiting)
@ -80,7 +78,7 @@ namespace aoc2019
vm.AddInput(ball > paddle ? 1 : ball < paddle ? -1 : 0); vm.AddInput(ball > paddle ? 1 : ball < paddle ? -1 : 0);
gameTicks++; gameTicks++;
if (printboard) PrintBoard(); if (printBoard) PrintBoard();
} }
return $"after {gameTicks} moves, the score is: {board[(-1, 0)]}"; return $"after {gameTicks} moves, the score is: {board[(-1, 0)]}";

View File

@ -10,15 +10,13 @@ namespace aoc2019
private Dictionary<string, long> available; private Dictionary<string, long> available;
public Day14() public Day14() : base(14, "Space Stoichiometry")
{ {
reactions = Input reactions = Input
.Select(Reaction.Parse) .Select(Reaction.Parse)
.ToDictionary(r => r.product.Name); .ToDictionary(r => r.product.Name);
} }
public override int DayNumber => 14;
private bool Consume(string chem, long quantity) private bool Consume(string chem, long quantity)
{ {
if (quantity <= 0) if (quantity <= 0)

View File

@ -10,13 +10,11 @@ namespace aoc2019
private readonly bool verbose = false; private readonly bool verbose = false;
private readonly IntCodeVM vm; private readonly IntCodeVM vm;
public Day15() public Day15() : base(15, "Oxygen System")
{ {
vm = new IntCodeVM(Input.First()); vm = new IntCodeVM(Input.First());
} }
public override int DayNumber => 15;
protected override string Part1() protected override string Part1()
{ {
vm.Reset(); vm.Reset();

View File

@ -10,13 +10,11 @@ namespace aoc2019
private static readonly int[] BasePattern = {0, 1, 0, -1}; private static readonly int[] BasePattern = {0, 1, 0, -1};
private readonly int[] initialList; private readonly int[] initialList;
public Day16() public Day16() : base(16, "Flawed Frequency Transmission")
{ {
initialList = Input.First().Select(c => int.Parse($"{c}")).ToArray(); initialList = Input.First().Select(c => int.Parse($"{c}")).ToArray();
} }
public override int DayNumber => 16;
protected override string Part1() protected override string Part1()
{ {
const int phaseCount = 100; const int phaseCount = 100;

View File

@ -1,5 +1,4 @@
using System; using System;
using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using aoc2019.lib; using aoc2019.lib;
@ -12,13 +11,11 @@ namespace aoc2019
private readonly IntCodeVM vm; private readonly IntCodeVM vm;
public Day17() public Day17() : base(17, "Set and Forget")
{ {
vm = new IntCodeVM(Input.First()); vm = new IntCodeVM(Input.First());
} }
public override int DayNumber => 17;
protected override string Part1() protected override string Part1()
{ {
vm.Reset(); vm.Reset();
@ -44,13 +41,13 @@ namespace aoc2019
protected override string Part2() protected override string Part2()
{ {
vm.Reset(); //vm.Reset();
vm.memory[0] = 2; //vm.memory[0] = 2;
var halt = IntCodeVM.HaltType.Waiting; //var halt = IntCodeVM.HaltType.Waiting;
while (halt == IntCodeVM.HaltType.Waiting) //while (halt == IntCodeVM.HaltType.Waiting)
{ //{
halt = vm.Run(); // halt = vm.Run();
} //}
return ""; return "";
} }
} }

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
namespace aoc2019.lib namespace aoc2019.lib
@ -28,5 +29,20 @@ namespace aoc2019.lib
foreach (var item in sequence) foreach (var item in sequence)
yield return item; 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;
}
} }
} }