update to .net 6
continuous-integration/drone/push Build was killed Details

This commit is contained in:
Ben Harris 2021-11-09 16:52:21 -05:00
parent bbd0d2b4db
commit 2c9737d6d2
35 changed files with 1557 additions and 1580 deletions

View File

@ -4,7 +4,7 @@ name: run
steps:
- name: run
image: mcr.microsoft.com/dotnet/sdk:latest
image: mcr.microsoft.com/dotnet/sdk:6.0
commands:
- dotnet test
- dotnet run --project aoc2019/aoc2019.csproj

View File

@ -1,13 +1,12 @@
using System;
using System.Diagnostics;
using aoc2019.lib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace aoc2019.test
namespace aoc2019.test;
[TestClass]
public class Tests
{
[TestClass]
public class Tests
{
[DataTestMethod]
[DataRow(typeof(Day01), "3394106", "5088280")]
[DataRow(typeof(Day02), "3085697", "9425")]
@ -35,7 +34,7 @@ namespace aoc2019.test
{
// create day instance
var s = Stopwatch.StartNew();
var day = (Day) Activator.CreateInstance(dayType);
var day = (Day)Activator.CreateInstance(dayType);
s.Stop();
Assert.IsNotNull(day, "failed to create day object");
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in constructor");
@ -56,5 +55,4 @@ namespace aoc2019.test
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in part2");
Assert.AreEqual(part2, part2Actual, $"Incorrect answer for Day {day.DayNumber} Part2");
}
}
}

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

View File

@ -1,13 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using aoc2019.lib;
using System.Diagnostics;
namespace aoc2019
namespace aoc2019;
public abstract class Day
{
public abstract class Day
{
protected Day(int dayNumber, string puzzleName)
{
DayNumber = dayNumber;
@ -45,5 +41,4 @@ namespace aoc2019
public abstract string Part1();
public abstract string Part2();
}
}

View File

@ -1,10 +1,7 @@
using System.Collections.Generic;
using System.Linq;
namespace aoc2019;
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")
@ -39,5 +36,4 @@ namespace aoc2019
{
return $"{masses.Sum(FullCost)}";
}
}
}

View File

@ -1,10 +1,7 @@
using System.Collections.Generic;
using System.Linq;
namespace aoc2019;
namespace aoc2019
public sealed class Day02 : Day
{
public sealed class Day02 : Day
{
private readonly IEnumerable<int> input;
public Day02() : base(2, "1202 Program Alarm")
@ -42,5 +39,4 @@ namespace aoc2019
return string.Empty;
}
}
}

View File

@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace aoc2019;
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;
@ -53,5 +49,4 @@ namespace aoc2019
return r;
}
}
}

View File

@ -1,9 +1,7 @@
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;
@ -45,5 +43,4 @@ namespace aoc2019
{
return $"{Enumerable.Range(start, end).Count(HasOnePair)}";
}
}
}

View File

@ -1,10 +1,7 @@
using System.Collections.Generic;
using System.Linq;
namespace aoc2019;
namespace aoc2019
public sealed class Day05 : Day
{
public sealed class Day05 : Day
{
private readonly IEnumerable<int> tape;
private int output;
@ -74,5 +71,4 @@ namespace aoc2019
RunIntCode(tape.ToList(), 5);
return $"{output}";
}
}
}

View File

@ -1,10 +1,7 @@
using System.Collections.Generic;
using System.Linq;
namespace aoc2019;
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")
@ -34,5 +31,4 @@ namespace aoc2019
for (; you[^common] == san[^common]; common++) ;
return $"{you.Count + san.Count - common * 2}";
}
}
}

View File

@ -1,11 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
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")
@ -63,5 +59,4 @@ namespace aoc2019
return $"{largest}";
}
}
}

View File

@ -1,11 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
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")
@ -33,5 +29,4 @@ namespace aoc2019
.ToDelimitedString("\n")
.Replace('1', 'x');
}
}
}

View File

@ -1,10 +1,7 @@
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
namespace aoc2019
public sealed class Day09 : Day
{
public sealed class Day09 : Day
{
private readonly IntCodeVM vm;
public Day09() : base(9, "Sensor Boost")
@ -25,5 +22,4 @@ namespace aoc2019
vm.Run(2);
return $"{vm.output.ToDelimitedString(",")}";
}
}
}

View File

@ -1,12 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
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;
@ -26,7 +21,7 @@ namespace aoc2019
foreach (var asteroid in asteroids)
{
var canSee = asteroids
.Except(new[] {asteroid})
.Except(new[] { asteroid })
.Select(a => (x: a.x - asteroid.x, y: a.y - asteroid.y))
.GroupBy(a => Math.Atan2(a.y, a.x))
.Count();
@ -69,5 +64,4 @@ namespace aoc2019
.Single()
.ToString();
}
}
}

View File

@ -1,11 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
namespace aoc2019
public sealed class Day11 : Day
{
public sealed class Day11 : Day
{
private readonly IntCodeVM vm;
private Direction heading;
private long x, y;
@ -85,10 +81,10 @@ namespace aoc2019
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();
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 =>
@ -107,5 +103,4 @@ namespace aoc2019
Left,
Right
}
}
}

View File

@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace aoc2019;
namespace aoc2019
public sealed class Day12 : Day
{
public sealed class Day12 : Day
{
private readonly List<Position> moons;
private int step;
@ -85,6 +81,7 @@ namespace aoc2019
dx = 0;
dy = 0;
dz = 0;
siblings = new();
}
internal int KineticEnergy =>
@ -123,5 +120,4 @@ namespace aoc2019
z += dz;
}
}
}
}

View File

@ -1,12 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
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;
@ -19,7 +14,7 @@ namespace aoc2019
private void UpdateTiles(IEnumerable<long> queue)
{
var input = queue.Select(i => (int) i).ToList();
var input = queue.Select(i => (int)i).ToList();
for (var i = 0; i < input.Count - 2; i += 3)
{
@ -83,5 +78,4 @@ namespace aoc2019
return $"after {gameTicks} moves, the score is: {board[(-1, 0)]}";
}
}
}

View File

@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace aoc2019;
namespace aoc2019
public sealed class Day14 : Day
{
public sealed class Day14 : Day
{
private readonly Dictionary<string, Reaction> reactions;
private Dictionary<string, long> available;
@ -15,6 +11,8 @@ namespace aoc2019
reactions = Input
.Select(Reaction.Parse)
.ToDictionary(r => r.product.Name);
available = new();
}
private bool Consume(string chem, long quantity)
@ -38,7 +36,7 @@ namespace aoc2019
return false;
var reaction = reactions[chem];
var reactionCount = (long) Math.Ceiling((double) quantity / reaction.product.Quantity);
var reactionCount = (long)Math.Ceiling((double)quantity / reaction.product.Quantity);
foreach (var reactant in reaction.reactants)
if (!Consume(reactant.Name, reactionCount * reactant.Quantity))
@ -50,7 +48,7 @@ namespace aoc2019
public override string Part1()
{
available = new Dictionary<string, long> {{"ORE", long.MaxValue}};
available = new Dictionary<string, long> { { "ORE", long.MaxValue } };
Consume("FUEL", 1);
return $"{long.MaxValue - available["ORE"]}";
}
@ -58,7 +56,7 @@ namespace aoc2019
public override string Part2()
{
const long capacity = 1_000_000_000_000;
available = new Dictionary<string, long> {{"ORE", capacity}};
available = new Dictionary<string, long> { { "ORE", capacity } };
Consume("FUEL", 1);
var oreConsumed = capacity - available["ORE"];
@ -88,7 +86,7 @@ namespace aoc2019
public static Reaction Parse(string s)
{
var ss = s.Split(new[] {", ", " => "}, StringSplitOptions.None);
var ss = s.Split(new[] { ", ", " => " }, StringSplitOptions.None);
return new Reaction(
ss.Take(ss.Length - 1).Select(ParseComponent).ToArray(),
@ -106,5 +104,4 @@ namespace aoc2019
}
}
}
}
}

View File

@ -1,12 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
namespace aoc2019
public sealed class Day15 : Day
{
public sealed class Day15 : Day
{
private readonly bool verbose = false;
private readonly IntCodeVM vm;
@ -22,27 +17,20 @@ namespace aoc2019
var halt = IntCodeVM.HaltType.Waiting;
while (halt == IntCodeVM.HaltType.Waiting)
{
var direction = currentLocation.NextDirection();
var direction = currentLocation!.NextDirection();
if (direction <= 4)
{
var (x, y) = currentLocation.Neighbor(direction);
if (Location.GetLocation(x, y) == null)
{
halt = vm.Run(direction);
switch (vm.Result)
currentLocation = vm.Result switch
{
case Location.Wall:
new Location(x, y, Location.Opposites[direction], Location.Wall);
break;
case Location.Empty:
currentLocation = new Location(x, y, Location.Opposites[direction]);
break;
case Location.System:
currentLocation = new Location(x, y, Location.Opposites[direction], Location.System);
break;
default:
throw new Exception($"Unknown IntCodeVM response: {vm.Result}");
}
Location.Wall => new Location(x, y, Location.Opposites[direction], Location.Wall),
Location.Empty => new Location(x, y, Location.Opposites[direction]),
Location.System => new Location(x, y, Location.Opposites[direction], Location.System),
_ => throw new Exception($"Unknown IntCodeVM response: {vm.Result}"),
};
}
}
else
@ -51,15 +39,11 @@ namespace aoc2019
if (direction > 0)
{
halt = vm.Run(direction);
switch (vm.Result)
currentLocation = vm.Result switch
{
case Location.Empty:
case Location.System:
currentLocation = Location.GetLocation(currentLocation.Neighbor(direction));
break;
default:
throw new Exception($"Unknown or unexpected response for previous room: {vm.Result}");
}
Location.Empty or Location.System => Location.GetLocation(currentLocation.Neighbor(direction)),
_ => throw new Exception($"Unknown or unexpected response for previous room: {vm.Result}"),
};
}
else
{
@ -95,10 +79,10 @@ namespace aoc2019
currentLocation = Location.OxygenLocation;
var distance = 0;
while (currentLocation.PreviousDirection != 0)
while (currentLocation?.PreviousDirection != 0)
{
distance++;
currentLocation = Location.GetLocation(currentLocation.PreviousLocation());
currentLocation = Location.GetLocation(currentLocation!.PreviousLocation());
}
return $"{distance}";
@ -131,12 +115,11 @@ namespace aoc2019
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};
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 Dictionary<(int x, int y), Location>();
public static readonly Dictionary<(int x, int y), Location> AllLocations = new();
private readonly int currentType;
public int DistanceToOxygenSystem = int.MaxValue - 1;
@ -160,7 +143,7 @@ namespace aoc2019
AllLocations.Add((x, y), this);
}
public static Location OxygenLocation { get; private set; }
public static Location? OxygenLocation { get; private set; }
public int PreviousDirection { get; }
private int X { get; }
private int Y { get; }
@ -210,15 +193,14 @@ namespace aoc2019
return searchDirection++;
}
public static Location GetLocation(int x, int y)
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)
public static Location? GetLocation((int x, int y) coords)
{
return GetLocation(coords.x, coords.y);
}
}
}
}

View File

@ -1,13 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
namespace aoc2019
public sealed class Day16 : Day
{
public sealed class Day16 : Day
{
private static readonly int[] BasePattern = {0, 1, 0, -1};
private static readonly int[] BasePattern = { 0, 1, 0, -1 };
private readonly int[] initialList;
public Day16() : base(16, "Flawed Frequency Transmission")
@ -25,7 +20,7 @@ namespace aoc2019
CalculateSignal(i % 2 == 0 ? signal0 : signal1, i % 2 == 0 ? signal1 : signal0);
return new string(
signal0.Take(8).Select(c => (char) (c + '0'))
signal0.Take(8).Select(c => (char)(c + '0'))
.ToArray());
}
@ -42,7 +37,7 @@ namespace aoc2019
signal[i] = (signal[i + 1] + signal[i]) % 10;
}
return new string(signal.Take(8).Select(c => (char) (c + '0')).ToArray());
return new string(signal.Take(8).Select(c => (char)(c + '0')).ToArray());
}
private static void CalculateSignal(IReadOnlyList<int> input, IList<int> output)
@ -60,5 +55,4 @@ namespace aoc2019
.Skip(1)
.Take(count);
}
}
}

View File

@ -1,12 +1,7 @@
using System;
using System.Linq;
using System.Text;
using aoc2019.lib;
namespace aoc2019;
namespace aoc2019
public sealed class Day17 : Day
{
public sealed class Day17 : Day
{
private readonly bool Verbose = false;
private readonly IntCodeVM vm;
@ -21,7 +16,7 @@ namespace aoc2019
vm.Run();
var sb = new StringBuilder();
while (vm.output.Any())
sb.Append((char) vm.Result);
sb.Append((char)vm.Result);
if (Verbose) Console.Write(sb);
var grid = sb.ToString().Trim().Split().Select(s => s.ToCharArray()).ToArray();
@ -49,5 +44,4 @@ namespace aoc2019
//}
return "";
}
}
}

18
aoc2019/Day18.cs Normal file
View File

@ -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 "";
}
}

View File

@ -1,10 +1,7 @@
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
namespace aoc2019
public sealed class Day19 : Day
{
public sealed class Day19 : Day
{
private readonly long[,] grid;
private readonly IntCodeVM vm;
@ -29,7 +26,7 @@ namespace aoc2019
public override string Part2()
{
for (int x = 101, y = 0;; x++)
for (int x = 101, y = 0; ; x++)
{
while (true)
{
@ -45,5 +42,4 @@ namespace aoc2019
return $"{(x - 99) * 1e4 + y}";
}
}
}
}

18
aoc2019/Day20.cs Normal file
View File

@ -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 "";
}
}

View File

@ -1,10 +1,7 @@
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
namespace aoc2019
public sealed class Day21 : Day
{
public sealed class Day21 : Day
{
private readonly IntCodeVM vm;
public Day21() : base(21, "Springdroid Adventure")
@ -23,5 +20,4 @@ namespace aoc2019
{
return "";
}
}
}

18
aoc2019/Day22.cs Normal file
View File

@ -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 "";
}
}

View File

@ -1,10 +1,7 @@
using System.Linq;
using aoc2019.lib;
namespace aoc2019;
namespace aoc2019
public sealed class Day23 : Day
{
public sealed class Day23 : Day
{
public Day23() : base(23, "Category Six")
{
}
@ -24,7 +21,7 @@ namespace aoc2019
{
while (vm.output.Count > 0)
{
var destination = (int) vm.Result;
var destination = (int)vm.Result;
var x = vm.Result;
var y = vm.Result;
@ -57,7 +54,7 @@ namespace aoc2019
var isIdle = true;
while (vm.output.Count > 0)
{
var destination = (int) vm.Result;
var destination = (int)vm.Result;
var x = vm.Result;
var y = vm.Result;
@ -86,5 +83,4 @@ namespace aoc2019
}
}
}
}
}

18
aoc2019/Day24.cs Normal file
View File

@ -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 "";
}
}

18
aoc2019/Day25.cs Normal file
View File

@ -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 "";
}
}

45
aoc2019/Extensions.cs Normal file
View File

@ -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;
}
}

155
aoc2019/IntCodeVM.cs Normal file
View File

@ -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;
}
}

View File

@ -1,22 +1,20 @@
using System;
using System.Linq;
using System.Reflection;
using System.Reflection;
namespace aoc2019
namespace aoc2019;
internal static class Program
{
internal static class Program
{
private static void Main(string[] args)
{
var days =
Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.BaseType == typeof(Day))
.Select(t => (Day) Activator.CreateInstance(t))
.OrderBy(d => d.DayNumber);
.Select(t => Activator.CreateInstance(t) as Day)
.OrderBy(d => d?.DayNumber);
if (args.Length == 1 && int.TryParse(args[0], out var dayNum))
{
var day = days.FirstOrDefault(d => d.DayNumber == dayNum);
var day = days.FirstOrDefault(d => d?.DayNumber == dayNum);
if (day != null)
day.AllParts();
@ -25,8 +23,7 @@ namespace aoc2019
}
else
{
foreach (var d in days) d.AllParts();
}
foreach (var d in days) d?.AllParts();
}
}
}

View File

@ -2,7 +2,9 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
@ -11,4 +13,11 @@
</None>
</ItemGroup>
<ItemGroup>
<Using Include="System.Collections.Generic" />
<Using Include="System.Collections.Immutable" />
<Using Include="System.Text" />
<Using Include="System.Text.RegularExpressions" />
</ItemGroup>
</Project>

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}