update to .net 6
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
- global usings - file-scope namespaces - update drone image tag
This commit is contained in:
parent
f1c329ddaa
commit
811c0f5d74
|
@ -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 aoc2020/aoc2020.csproj
|
- dotnet run --project aoc2020/aoc2020.csproj
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
MIT License Copyright (c) <year> <copyright holders>
|
MIT License Copyright (c) 2020 Ben Harris
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,62 +1,60 @@
|
||||||
using System;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
namespace aoc2020.test
|
namespace aoc2020.test;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class DayTests
|
||||||
{
|
{
|
||||||
[TestClass]
|
[DataTestMethod]
|
||||||
public class DayTests
|
[DataRow(typeof(Day01), "751776", "42275090")]
|
||||||
|
[DataRow(typeof(Day02), "556", "605")]
|
||||||
|
[DataRow(typeof(Day03), "189", "1718180100")]
|
||||||
|
[DataRow(typeof(Day04), "247", "145")]
|
||||||
|
[DataRow(typeof(Day05), "878", "504")]
|
||||||
|
[DataRow(typeof(Day06), "6273", "3254")]
|
||||||
|
[DataRow(typeof(Day07), "169", "82372")]
|
||||||
|
[DataRow(typeof(Day08), "1654", "833")]
|
||||||
|
[DataRow(typeof(Day09), "138879426", "23761694")]
|
||||||
|
[DataRow(typeof(Day10), "1980", "4628074479616")]
|
||||||
|
[DataRow(typeof(Day11), "2303", "2057")]
|
||||||
|
[DataRow(typeof(Day12), "1710", "62045")]
|
||||||
|
[DataRow(typeof(Day13), "171", "539746751134958")]
|
||||||
|
[DataRow(typeof(Day14), "17481577045893", "4160009892257")]
|
||||||
|
[DataRow(typeof(Day15), "257", "8546398")]
|
||||||
|
[DataRow(typeof(Day16), "19093", "5311123569883")]
|
||||||
|
// [DataRow(typeof(Day17), "293", "1816")]
|
||||||
|
[DataRow(typeof(Day18), "12918250417632", "171259538712010")]
|
||||||
|
[DataRow(typeof(Day19), "160", "357")]
|
||||||
|
[DataRow(typeof(Day20), "21599955909991", "")]
|
||||||
|
[DataRow(typeof(Day21), "", "")]
|
||||||
|
[DataRow(typeof(Day22), "", "")]
|
||||||
|
[DataRow(typeof(Day23), "", "")]
|
||||||
|
[DataRow(typeof(Day24), "", "")]
|
||||||
|
[DataRow(typeof(Day25), "", "")]
|
||||||
|
public void CheckAllDays(Type dayType, string part1, string part2)
|
||||||
{
|
{
|
||||||
[DataTestMethod]
|
// create day instance
|
||||||
[DataRow(typeof(Day01), "751776", "42275090")]
|
var s = Stopwatch.StartNew();
|
||||||
[DataRow(typeof(Day02), "556", "605")]
|
var day = Activator.CreateInstance(dayType) as Day;
|
||||||
[DataRow(typeof(Day03), "189", "1718180100")]
|
s.Stop();
|
||||||
[DataRow(typeof(Day04), "247", "145")]
|
Assert.IsNotNull(day, "failed to create day object");
|
||||||
[DataRow(typeof(Day05), "878", "504")]
|
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in constructor");
|
||||||
[DataRow(typeof(Day06), "6273", "3254")]
|
|
||||||
[DataRow(typeof(Day07), "169", "82372")]
|
|
||||||
[DataRow(typeof(Day08), "1654", "833")]
|
|
||||||
[DataRow(typeof(Day09), "138879426", "23761694")]
|
|
||||||
[DataRow(typeof(Day10), "1980", "4628074479616")]
|
|
||||||
[DataRow(typeof(Day11), "2303", "2057")]
|
|
||||||
[DataRow(typeof(Day12), "1710", "62045")]
|
|
||||||
[DataRow(typeof(Day13), "171", "539746751134958")]
|
|
||||||
[DataRow(typeof(Day14), "17481577045893", "4160009892257")]
|
|
||||||
[DataRow(typeof(Day15), "257", "8546398")]
|
|
||||||
[DataRow(typeof(Day16), "19093", "5311123569883")]
|
|
||||||
// [DataRow(typeof(Day17), "293", "1816")]
|
|
||||||
[DataRow(typeof(Day18), "12918250417632", "171259538712010")]
|
|
||||||
[DataRow(typeof(Day19), "160", "357")]
|
|
||||||
[DataRow(typeof(Day20), "21599955909991", "")]
|
|
||||||
[DataRow(typeof(Day21), "", "")]
|
|
||||||
[DataRow(typeof(Day22), "", "")]
|
|
||||||
[DataRow(typeof(Day23), "", "")]
|
|
||||||
[DataRow(typeof(Day24), "", "")]
|
|
||||||
[DataRow(typeof(Day25), "", "")]
|
|
||||||
public void CheckAllDays(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,9 +1,10 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<IsPackable>false</IsPackable>
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,48 +1,44 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace aoc2020
|
namespace aoc2020;
|
||||||
|
|
||||||
|
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 IEnumerable<string> Input =>
|
|
||||||
File.ReadLines(FileName);
|
|
||||||
|
|
||||||
protected string FileName =>
|
|
||||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"input/day{DayNumber,2:00}.in");
|
|
||||||
|
|
||||||
public abstract string Part1();
|
|
||||||
public abstract string Part2();
|
|
||||||
|
|
||||||
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 int DayNumber { get; }
|
||||||
|
public string PuzzleName { get; }
|
||||||
|
|
||||||
|
protected IEnumerable<string> Input =>
|
||||||
|
File.ReadLines(FileName);
|
||||||
|
|
||||||
|
protected string FileName =>
|
||||||
|
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"input/day{DayNumber,2:00}.in");
|
||||||
|
|
||||||
|
public abstract string Part1();
|
||||||
|
public abstract string Part2();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,35 +1,31 @@
|
||||||
using System.Collections.Immutable;
|
namespace aoc2020;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 1: <see href="https://adventofcode.com/2020/day/1" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day01 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly ImmutableHashSet<int> _entries;
|
||||||
/// Day 1: <see href="https://adventofcode.com/2020/day/1" />
|
|
||||||
/// </summary>
|
public Day01() : base(1, "Report Repair")
|
||||||
public sealed class Day01 : Day
|
|
||||||
{
|
{
|
||||||
private readonly ImmutableHashSet<int> _entries;
|
_entries = Input.Select(int.Parse).ToImmutableHashSet();
|
||||||
|
|
||||||
public Day01() : base(1, "Report Repair")
|
|
||||||
{
|
|
||||||
_entries = Input.Select(int.Parse).ToImmutableHashSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
var entry = _entries.First(e => _entries.Contains(2020 - e));
|
|
||||||
return $"{entry * (2020 - entry)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
foreach (var i in _entries)
|
|
||||||
foreach (var j in _entries)
|
|
||||||
foreach (var k in _entries)
|
|
||||||
if (i + j + k == 2020)
|
|
||||||
return $"{i * j * k}";
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
var entry = _entries.First(e => _entries.Contains(2020 - e));
|
||||||
|
return $"{entry * (2020 - entry)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
foreach (var i in _entries)
|
||||||
|
foreach (var j in _entries)
|
||||||
|
foreach (var k in _entries)
|
||||||
|
if (i + j + k == 2020)
|
||||||
|
return $"{i * j * k}";
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
100
aoc2020/Day02.cs
100
aoc2020/Day02.cs
|
@ -1,56 +1,52 @@
|
||||||
using System.Collections.Immutable;
|
namespace aoc2020;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 2: <see href="https://adventofcode.com/2020/day/1" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day02 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly ImmutableList<Password> _passwords;
|
||||||
/// Day 2: <see href="https://adventofcode.com/2020/day/1" />
|
|
||||||
/// </summary>
|
public Day02() : base(2, "Password Philosophy")
|
||||||
public sealed class Day02 : Day
|
|
||||||
{
|
{
|
||||||
private readonly ImmutableList<Password> _passwords;
|
_passwords = Input.Select(p => new Password(p)).ToImmutableList();
|
||||||
|
|
||||||
public Day02() : base(2, "Password Philosophy")
|
|
||||||
{
|
|
||||||
_passwords = Input.Select(p => new Password(p)).ToImmutableList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return $"{_passwords.Count(p => p.IsValid)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return $"{_passwords.Count(p => p.IsValidByIndex)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Password
|
|
||||||
{
|
|
||||||
public Password(string line)
|
|
||||||
{
|
|
||||||
var split = line.Split(": ", 2);
|
|
||||||
var split2 = split[0].Split(' ', 2);
|
|
||||||
var indices = split2[0].Split('-', 2);
|
|
||||||
I = int.Parse(indices[0]);
|
|
||||||
J = int.Parse(indices[1]);
|
|
||||||
C = char.Parse(split2[1]);
|
|
||||||
Value = split[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsValid =>
|
|
||||||
Count >= I && Count <= J;
|
|
||||||
|
|
||||||
public bool IsValidByIndex =>
|
|
||||||
(Value[I - 1] == C) ^ (Value[J - 1] == C);
|
|
||||||
|
|
||||||
private int Count =>
|
|
||||||
Value.Count(p => p == C);
|
|
||||||
|
|
||||||
private int I { get; }
|
|
||||||
private int J { get; }
|
|
||||||
private char C { get; }
|
|
||||||
private string Value { get; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{_passwords.Count(p => p.IsValid)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return $"{_passwords.Count(p => p.IsValidByIndex)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Password
|
||||||
|
{
|
||||||
|
public Password(string line)
|
||||||
|
{
|
||||||
|
var split = line.Split(": ", 2);
|
||||||
|
var split2 = split[0].Split(' ', 2);
|
||||||
|
var indices = split2[0].Split('-', 2);
|
||||||
|
I = int.Parse(indices[0]);
|
||||||
|
J = int.Parse(indices[1]);
|
||||||
|
C = char.Parse(split2[1]);
|
||||||
|
Value = split[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsValid =>
|
||||||
|
Count >= I && Count <= J;
|
||||||
|
|
||||||
|
public bool IsValidByIndex =>
|
||||||
|
(Value[I - 1] == C) ^ (Value[J - 1] == C);
|
||||||
|
|
||||||
|
private int Count =>
|
||||||
|
Value.Count(p => p == C);
|
||||||
|
|
||||||
|
private int I { get; }
|
||||||
|
private int J { get; }
|
||||||
|
private char C { get; }
|
||||||
|
private string Value { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,45 +1,42 @@
|
||||||
using System.Linq;
|
namespace aoc2020;
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 3: <see href="https://adventofcode.com/2020/day/3" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day03 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly string[] _grid;
|
||||||
/// Day 3: <see href="https://adventofcode.com/2020/day/3" />
|
private readonly int _width;
|
||||||
/// </summary>
|
|
||||||
public sealed class Day03 : Day
|
public Day03() : base(3, "Toboggan Trajectory")
|
||||||
{
|
{
|
||||||
private readonly string[] _grid;
|
_grid = Input.ToArray();
|
||||||
private readonly int _width;
|
_width = _grid[0].Length;
|
||||||
|
|
||||||
public Day03() : base(3, "Toboggan Trajectory")
|
|
||||||
{
|
|
||||||
_grid = Input.ToArray();
|
|
||||||
_width = _grid[0].Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long CountSlope(int dx, int dy)
|
|
||||||
{
|
|
||||||
long hits = 0;
|
|
||||||
for (int x = 0, y = 0; y < _grid.Length; y += dy, x = (x + dx) % _width)
|
|
||||||
if (_grid[y][x] == '#')
|
|
||||||
hits++;
|
|
||||||
|
|
||||||
return hits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return $"{CountSlope(3, 1)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
var xSlopes = new[] {1, 3, 5, 7, 1};
|
|
||||||
var ySlopes = new[] {1, 1, 1, 1, 2};
|
|
||||||
|
|
||||||
return xSlopes.Zip(ySlopes)
|
|
||||||
.Select(s => CountSlope(s.Item1, s.Item2))
|
|
||||||
.Aggregate((acc, i) => acc * i)
|
|
||||||
.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private long CountSlope(int dx, int dy)
|
||||||
|
{
|
||||||
|
long hits = 0;
|
||||||
|
for (int x = 0, y = 0; y < _grid.Length; y += dy, x = (x + dx) % _width)
|
||||||
|
if (_grid[y][x] == '#')
|
||||||
|
hits++;
|
||||||
|
|
||||||
|
return hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{CountSlope(3, 1)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var xSlopes = new[] { 1, 3, 5, 7, 1 };
|
||||||
|
var ySlopes = new[] { 1, 1, 1, 1, 2 };
|
||||||
|
|
||||||
|
return xSlopes.Zip(ySlopes)
|
||||||
|
.Select(s => CountSlope(s.First, s.Second))
|
||||||
|
.Aggregate((acc, i) => acc * i)
|
||||||
|
.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
330
aoc2020/Day04.cs
330
aoc2020/Day04.cs
|
@ -1,188 +1,182 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 4: <see href="https://adventofcode.com/2020/day/4" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day04 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly List<Passport> _passports;
|
||||||
/// Day 4: <see href="https://adventofcode.com/2020/day/4" />
|
|
||||||
/// </summary>
|
public Day04() : base(4, "Passport Processing")
|
||||||
public sealed class Day04 : Day
|
|
||||||
{
|
{
|
||||||
private readonly List<Passport> _passports;
|
_passports = new List<Passport>();
|
||||||
|
|
||||||
public Day04() : base(4, "Passport Processing")
|
var a = new List<string>();
|
||||||
|
foreach (var line in Input)
|
||||||
{
|
{
|
||||||
_passports = new List<Passport>();
|
if (line == "")
|
||||||
|
|
||||||
var a = new List<string>();
|
|
||||||
foreach (var line in Input)
|
|
||||||
{
|
{
|
||||||
if (line == "")
|
_passports.Add(Passport.Parse(a));
|
||||||
{
|
a.Clear();
|
||||||
_passports.Add(Passport.Parse(a));
|
continue;
|
||||||
a.Clear();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Add(line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.Any()) _passports.Add(Passport.Parse(a));
|
a.Add(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part1()
|
if (a.Any()) _passports.Add(Passport.Parse(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{_passports.Count(p => p.IsValid)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return $"{_passports.Count(p => p.ExtendedValidation())}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Passport
|
||||||
|
{
|
||||||
|
private string _byr;
|
||||||
|
private string _cid;
|
||||||
|
private string _ecl;
|
||||||
|
private string _eyr;
|
||||||
|
private string _hcl;
|
||||||
|
private string _hgt;
|
||||||
|
private string _iyr;
|
||||||
|
private string _pid;
|
||||||
|
|
||||||
|
public bool IsValid =>
|
||||||
|
_byr != null &&
|
||||||
|
_iyr != null &&
|
||||||
|
_eyr != null &&
|
||||||
|
_hgt != null &&
|
||||||
|
_hcl != null &&
|
||||||
|
_ecl != null &&
|
||||||
|
_pid != null;
|
||||||
|
|
||||||
|
public bool ExtendedValidation()
|
||||||
{
|
{
|
||||||
return $"{_passports.Count(p => p.IsValid)}";
|
if (!IsValid) return false;
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
// birth year
|
||||||
{
|
if (int.TryParse(_byr, out var byr))
|
||||||
return $"{_passports.Count(p => p.ExtendedValidation())}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Passport
|
|
||||||
{
|
|
||||||
private string _byr;
|
|
||||||
private string _cid;
|
|
||||||
private string _ecl;
|
|
||||||
private string _eyr;
|
|
||||||
private string _hcl;
|
|
||||||
private string _hgt;
|
|
||||||
private string _iyr;
|
|
||||||
private string _pid;
|
|
||||||
|
|
||||||
public bool IsValid =>
|
|
||||||
_byr != null &&
|
|
||||||
_iyr != null &&
|
|
||||||
_eyr != null &&
|
|
||||||
_hgt != null &&
|
|
||||||
_hcl != null &&
|
|
||||||
_ecl != null &&
|
|
||||||
_pid != null;
|
|
||||||
|
|
||||||
public bool ExtendedValidation()
|
|
||||||
{
|
{
|
||||||
if (!IsValid) return false;
|
if (byr < 1920 || byr > 2002)
|
||||||
|
|
||||||
// birth year
|
|
||||||
if (int.TryParse(_byr, out var byr))
|
|
||||||
{
|
|
||||||
if (byr < 1920 || byr > 2002)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// issuance year
|
{
|
||||||
if (int.TryParse(_iyr, out var iyr))
|
return false;
|
||||||
{
|
|
||||||
if (iyr < 2010 || iyr > 2020)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// expiration year
|
|
||||||
if (int.TryParse(_eyr, out var eyr))
|
|
||||||
{
|
|
||||||
if (eyr < 2020 || eyr > 2030)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// height
|
|
||||||
if (_hgt.EndsWith("cm"))
|
|
||||||
{
|
|
||||||
var h = _hgt.Substring(0, 3);
|
|
||||||
if (int.TryParse(h, out var hgt))
|
|
||||||
{
|
|
||||||
if (hgt < 150 || hgt > 193)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (_hgt.EndsWith("in"))
|
|
||||||
{
|
|
||||||
var h = _hgt.Substring(0, 2);
|
|
||||||
if (int.TryParse(h, out var hgt))
|
|
||||||
{
|
|
||||||
if (hgt < 59 || hgt > 76)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// hair color
|
|
||||||
if (!Regex.IsMatch(_hcl, "#[0-9a-f]{6}"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// eye color
|
|
||||||
if (!new[] {"amb", "blu", "brn", "gry", "grn", "hzl", "oth"}.Contains(_ecl))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// passport id
|
|
||||||
if (_pid.Length != 9)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Passport Parse(IEnumerable<string> list)
|
// issuance year
|
||||||
|
if (int.TryParse(_iyr, out var iyr))
|
||||||
{
|
{
|
||||||
var passport = new Passport();
|
if (iyr < 2010 || iyr > 2020)
|
||||||
foreach (var entry in string.Join(' ', list).Split(' ', StringSplitOptions.TrimEntries))
|
return false;
|
||||||
{
|
|
||||||
var spl = entry.Split(':', 2);
|
|
||||||
switch (spl[0])
|
|
||||||
{
|
|
||||||
case "byr":
|
|
||||||
passport._byr = spl[1];
|
|
||||||
break;
|
|
||||||
case "iyr":
|
|
||||||
passport._iyr = spl[1];
|
|
||||||
break;
|
|
||||||
case "eyr":
|
|
||||||
passport._eyr = spl[1];
|
|
||||||
break;
|
|
||||||
case "hgt":
|
|
||||||
passport._hgt = spl[1];
|
|
||||||
break;
|
|
||||||
case "hcl":
|
|
||||||
passport._hcl = spl[1];
|
|
||||||
break;
|
|
||||||
case "ecl":
|
|
||||||
passport._ecl = spl[1];
|
|
||||||
break;
|
|
||||||
case "pid":
|
|
||||||
passport._pid = spl[1];
|
|
||||||
break;
|
|
||||||
case "cid":
|
|
||||||
passport._cid = spl[1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return passport;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expiration year
|
||||||
|
if (int.TryParse(_eyr, out var eyr))
|
||||||
|
{
|
||||||
|
if (eyr < 2020 || eyr > 2030)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// height
|
||||||
|
if (_hgt.EndsWith("cm"))
|
||||||
|
{
|
||||||
|
var h = _hgt[..3];
|
||||||
|
if (int.TryParse(h, out var hgt))
|
||||||
|
{
|
||||||
|
if (hgt < 150 || hgt > 193)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_hgt.EndsWith("in"))
|
||||||
|
{
|
||||||
|
var h = _hgt.Substring(0, 2);
|
||||||
|
if (int.TryParse(h, out var hgt))
|
||||||
|
{
|
||||||
|
if (hgt < 59 || hgt > 76)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// hair color
|
||||||
|
if (!Regex.IsMatch(_hcl, "#[0-9a-f]{6}"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// eye color
|
||||||
|
if (!new[] { "amb", "blu", "brn", "gry", "grn", "hzl", "oth" }.Contains(_ecl))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// passport id
|
||||||
|
if (_pid.Length != 9)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Passport Parse(IEnumerable<string> list)
|
||||||
|
{
|
||||||
|
var passport = new Passport();
|
||||||
|
foreach (var entry in string.Join(' ', list).Split(' ', StringSplitOptions.TrimEntries))
|
||||||
|
{
|
||||||
|
var spl = entry.Split(':', 2);
|
||||||
|
switch (spl[0])
|
||||||
|
{
|
||||||
|
case "byr":
|
||||||
|
passport._byr = spl[1];
|
||||||
|
break;
|
||||||
|
case "iyr":
|
||||||
|
passport._iyr = spl[1];
|
||||||
|
break;
|
||||||
|
case "eyr":
|
||||||
|
passport._eyr = spl[1];
|
||||||
|
break;
|
||||||
|
case "hgt":
|
||||||
|
passport._hgt = spl[1];
|
||||||
|
break;
|
||||||
|
case "hcl":
|
||||||
|
passport._hcl = spl[1];
|
||||||
|
break;
|
||||||
|
case "ecl":
|
||||||
|
passport._ecl = spl[1];
|
||||||
|
break;
|
||||||
|
case "pid":
|
||||||
|
passport._pid = spl[1];
|
||||||
|
break;
|
||||||
|
case "cid":
|
||||||
|
passport._cid = spl[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return passport;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,29 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 5: <see href="https://adventofcode.com/2020/day/5" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day05 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly ImmutableHashSet<int> _ids;
|
||||||
/// Day 5: <see href="https://adventofcode.com/2020/day/5" />
|
|
||||||
/// </summary>
|
public Day05() : base(5, "Binary Boarding")
|
||||||
public sealed class Day05 : Day
|
|
||||||
{
|
{
|
||||||
private readonly ImmutableHashSet<int> _ids;
|
_ids = Input
|
||||||
|
.Select(s =>
|
||||||
public Day05() : base(5, "Binary Boarding")
|
Convert.ToInt32(s.Replace('F', '0').Replace('B', '1').Replace('L', '0').Replace('R', '1'), 2))
|
||||||
{
|
.OrderBy(i => i)
|
||||||
_ids = Input
|
.ToImmutableHashSet();
|
||||||
.Select(s =>
|
|
||||||
Convert.ToInt32(s.Replace('F', '0').Replace('B', '1').Replace('L', '0').Replace('R', '1'), 2))
|
|
||||||
.OrderBy(i => i)
|
|
||||||
.ToImmutableHashSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return $"{_ids.Last()}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
// arithmetic sum of full series
|
|
||||||
return $"{(_ids.Count + 1) * (_ids.First() + _ids.Last()) / 2 - _ids.Sum()}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{_ids.Last()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
// arithmetic sum of full series
|
||||||
|
return $"{(_ids.Count + 1) * (_ids.First() + _ids.Last()) / 2 - _ids.Sum()}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,54 +1,50 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2020;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 6: <see href="https://adventofcode.com/2020/day/6" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day06 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly int _countPart1;
|
||||||
/// Day 6: <see href="https://adventofcode.com/2020/day/6" />
|
private readonly int _countPart2;
|
||||||
/// </summary>
|
|
||||||
public sealed class Day06 : Day
|
public Day06() : base(6, "Custom Customs")
|
||||||
{
|
{
|
||||||
private readonly int _countPart1;
|
var alphabet = "abcedfghijklmnopqrstuvwxyz".ToCharArray();
|
||||||
private readonly int _countPart2;
|
_countPart1 = 0;
|
||||||
|
_countPart2 = 0;
|
||||||
public Day06() : base(6, "Custom Customs")
|
var s = new HashSet<char>();
|
||||||
|
var lines = new HashSet<string>();
|
||||||
|
foreach (var line in Input)
|
||||||
{
|
{
|
||||||
var alphabet = "abcedfghijklmnopqrstuvwxyz".ToCharArray();
|
if (line == "")
|
||||||
_countPart1 = 0;
|
|
||||||
_countPart2 = 0;
|
|
||||||
var s = new HashSet<char>();
|
|
||||||
var lines = new HashSet<string>();
|
|
||||||
foreach (var line in Input)
|
|
||||||
{
|
|
||||||
if (line == "")
|
|
||||||
{
|
|
||||||
_countPart1 += s.Count;
|
|
||||||
_countPart2 += alphabet.Count(a => lines.All(l => l.Contains(a)));
|
|
||||||
s.Clear();
|
|
||||||
lines.Clear();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var c in line)
|
|
||||||
s.Add(c);
|
|
||||||
lines.Add(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s.Any())
|
|
||||||
{
|
{
|
||||||
_countPart1 += s.Count;
|
_countPart1 += s.Count;
|
||||||
_countPart2 += alphabet.Count(a => lines.All(l => l.Contains(a)));
|
_countPart2 += alphabet.Count(a => lines.All(l => l.Contains(a)));
|
||||||
|
s.Clear();
|
||||||
|
lines.Clear();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var c in line)
|
||||||
|
s.Add(c);
|
||||||
|
lines.Add(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part1()
|
if (s.Any())
|
||||||
{
|
{
|
||||||
return $"{_countPart1}";
|
_countPart1 += s.Count;
|
||||||
}
|
_countPart2 += alphabet.Count(a => lines.All(l => l.Contains(a)));
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return $"{_countPart2}";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{_countPart1}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return $"{_countPart2}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
108
aoc2020/Day07.cs
108
aoc2020/Day07.cs
|
@ -1,61 +1,57 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2020;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 7: <see href="https://adventofcode.com/2020/day/7" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day07 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly Dictionary<string, IEnumerable<(int, string)?>> _rules;
|
||||||
/// Day 7: <see href="https://adventofcode.com/2020/day/7" />
|
|
||||||
/// </summary>
|
public Day07() : base(7, "Handy Haversacks")
|
||||||
public sealed class Day07 : Day
|
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, IEnumerable<(int, string)?>> _rules;
|
_rules = Input.Select(rule =>
|
||||||
|
|
||||||
public Day07() : base(7, "Handy Haversacks")
|
|
||||||
{
|
|
||||||
_rules = Input.Select(rule =>
|
|
||||||
{
|
|
||||||
var spl = rule.Split(" bags contain ", 2);
|
|
||||||
var outer = string.Join(' ', spl[0].Split(' ').Take(2));
|
|
||||||
var inner = spl[1].Split(", ").Select(ParseQuantity).Where(i => i != null);
|
|
||||||
return (outer, inner);
|
|
||||||
})
|
|
||||||
.ToDictionary(t => t.outer, t => t.inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static (int, string)? ParseQuantity(string arg)
|
|
||||||
{
|
|
||||||
if (arg == "no other bags.") return null;
|
|
||||||
var words = arg.Split(' ');
|
|
||||||
return (int.Parse(words[0]), string.Join(' ', words[1..3]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private int Weight(string node)
|
|
||||||
{
|
|
||||||
return 1 + _rules[node].Sum(i => i.Value.Item1 * Weight(i.Value.Item2));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
// breadth-first search with Queue
|
|
||||||
var start = new Queue<string>(new[] {"shiny gold"});
|
|
||||||
var p = new HashSet<string>();
|
|
||||||
string node;
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
node = start.Dequeue();
|
var spl = rule.Split(" bags contain ", 2);
|
||||||
foreach (var (container, contained) in _rules)
|
var outer = string.Join(' ', spl[0].Split(' ').Take(2));
|
||||||
if (contained.Any(i => i.HasValue && i.Value.Item2 == node) && p.Add(container))
|
var inner = spl[1].Split(", ").Select(ParseQuantity).Where(i => i != null);
|
||||||
start.Enqueue(container);
|
return (outer, inner);
|
||||||
|
})
|
||||||
if (!start.Any()) break;
|
.ToDictionary(t => t.outer, t => t.inner);
|
||||||
}
|
|
||||||
|
|
||||||
return $"{p.Count}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return $"{Weight("shiny gold") - 1}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static (int, string)? ParseQuantity(string arg)
|
||||||
|
{
|
||||||
|
if (arg == "no other bags.") return null;
|
||||||
|
var words = arg.Split(' ');
|
||||||
|
return (int.Parse(words[0]), string.Join(' ', words[1..3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int Weight(string node)
|
||||||
|
{
|
||||||
|
return 1 + _rules[node].Sum(i => i.Value.Item1 * Weight(i.Value.Item2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
// breadth-first search with Queue
|
||||||
|
var start = new Queue<string>(new[] { "shiny gold" });
|
||||||
|
var p = new HashSet<string>();
|
||||||
|
string node;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
node = start.Dequeue();
|
||||||
|
foreach (var (container, contained) in _rules)
|
||||||
|
if (contained.Any(i => i.HasValue && i.Value.Item2 == node) && p.Add(container))
|
||||||
|
start.Enqueue(container);
|
||||||
|
|
||||||
|
if (!start.Any()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{p.Count}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return $"{Weight("shiny gold") - 1}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
127
aoc2020/Day08.cs
127
aoc2020/Day08.cs
|
@ -1,77 +1,74 @@
|
||||||
using System.Linq;
|
namespace aoc2020;
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 8: <see href="https://adventofcode.com/2020/day/8" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day08 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly (string instruction, int value)[] _instructions;
|
||||||
/// Day 8: <see href="https://adventofcode.com/2020/day/8" />
|
private int _accumulator;
|
||||||
/// </summary>
|
private int _currentInstruction;
|
||||||
public sealed class Day08 : Day
|
|
||||||
|
public Day08() : base(8, "Handheld Halting")
|
||||||
{
|
{
|
||||||
private readonly (string instruction, int value)[] _instructions;
|
_instructions = Input.Select(ParseLine).ToArray();
|
||||||
private int _accumulator;
|
}
|
||||||
private int _currentInstruction;
|
|
||||||
|
|
||||||
public Day08() : base(8, "Handheld Halting")
|
private static (string, int) ParseLine(string line)
|
||||||
|
{
|
||||||
|
var spl = line.Split(' ', 2);
|
||||||
|
return (spl[0], int.Parse(spl[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Halts()
|
||||||
|
{
|
||||||
|
_accumulator = 0;
|
||||||
|
_currentInstruction = 0;
|
||||||
|
var visited = new bool[_instructions.Length + 1];
|
||||||
|
|
||||||
|
while (!visited[_currentInstruction] && _currentInstruction < _instructions.Length)
|
||||||
{
|
{
|
||||||
_instructions = Input.Select(ParseLine).ToArray();
|
visited[_currentInstruction] = true;
|
||||||
}
|
|
||||||
|
|
||||||
private static (string, int) ParseLine(string line)
|
switch (_instructions[_currentInstruction].instruction)
|
||||||
{
|
|
||||||
var spl = line.Split(' ', 2);
|
|
||||||
return (spl[0], int.Parse(spl[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Halts()
|
|
||||||
{
|
|
||||||
_accumulator = 0;
|
|
||||||
_currentInstruction = 0;
|
|
||||||
var visited = new bool[_instructions.Length + 1];
|
|
||||||
|
|
||||||
while (!visited[_currentInstruction] && _currentInstruction < _instructions.Length)
|
|
||||||
{
|
{
|
||||||
visited[_currentInstruction] = true;
|
case "acc":
|
||||||
|
_accumulator += _instructions[_currentInstruction].value;
|
||||||
switch (_instructions[_currentInstruction].instruction)
|
break;
|
||||||
{
|
case "jmp":
|
||||||
case "acc":
|
_currentInstruction += _instructions[_currentInstruction].value;
|
||||||
_accumulator += _instructions[_currentInstruction].value;
|
continue;
|
||||||
break;
|
|
||||||
case "jmp":
|
|
||||||
_currentInstruction += _instructions[_currentInstruction].value;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentInstruction++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _currentInstruction == _instructions.Length;
|
_currentInstruction++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part1()
|
return _currentInstruction == _instructions.Length;
|
||||||
{
|
|
||||||
Halts();
|
|
||||||
return $"{_accumulator}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < _instructions.Length; i++)
|
|
||||||
// swap each nop and jmp and check if the program halts
|
|
||||||
if (_instructions[i].instruction == "nop")
|
|
||||||
{
|
|
||||||
_instructions[i].instruction = "jmp";
|
|
||||||
if (Halts()) break;
|
|
||||||
_instructions[i].instruction = "nop";
|
|
||||||
}
|
|
||||||
else if (_instructions[i].instruction == "jmp")
|
|
||||||
{
|
|
||||||
_instructions[i].instruction = "nop";
|
|
||||||
if (Halts()) break;
|
|
||||||
_instructions[i].instruction = "jmp";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{_accumulator}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
Halts();
|
||||||
|
return $"{_accumulator}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < _instructions.Length; i++)
|
||||||
|
// swap each nop and jmp and check if the program halts
|
||||||
|
if (_instructions[i].instruction == "nop")
|
||||||
|
{
|
||||||
|
_instructions[i].instruction = "jmp";
|
||||||
|
if (Halts()) break;
|
||||||
|
_instructions[i].instruction = "nop";
|
||||||
|
}
|
||||||
|
else if (_instructions[i].instruction == "jmp")
|
||||||
|
{
|
||||||
|
_instructions[i].instruction = "nop";
|
||||||
|
if (Halts()) break;
|
||||||
|
_instructions[i].instruction = "jmp";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{_accumulator}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,52 +1,49 @@
|
||||||
using System.Linq;
|
namespace aoc2020;
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 9: <see href="https://adventofcode.com/2020/day/9" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day09 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly long[] _list;
|
||||||
/// Day 9: <see href="https://adventofcode.com/2020/day/9" />
|
private long _part1;
|
||||||
/// </summary>
|
|
||||||
public sealed class Day09 : Day
|
public Day09() : base(9, "Encoding Error")
|
||||||
{
|
{
|
||||||
private readonly long[] _list;
|
_list = Input.Select(long.Parse).ToArray();
|
||||||
private long _part1;
|
|
||||||
|
|
||||||
public Day09() : base(9, "Encoding Error")
|
|
||||||
{
|
|
||||||
_list = Input.Select(long.Parse).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
for (var i = 25; i < _list.Length - 25; i++)
|
|
||||||
{
|
|
||||||
var preamble = _list[(i - 25)..i];
|
|
||||||
if (!preamble.Any(num1 => preamble.Any(num2 => num1 + num2 == _list[i])))
|
|
||||||
{
|
|
||||||
_part1 = _list[i];
|
|
||||||
return $"{_part1}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < _list.Length; i++)
|
|
||||||
{
|
|
||||||
long sum = 0;
|
|
||||||
for (var j = i; j < _list.Length; j++)
|
|
||||||
{
|
|
||||||
sum += _list[j];
|
|
||||||
if (sum > _part1) break;
|
|
||||||
if (sum != _part1) continue;
|
|
||||||
|
|
||||||
var subset = _list[i..(j + 1)].ToArray();
|
|
||||||
return $"{subset.Min() + subset.Max()}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
for (var i = 25; i < _list.Length - 25; i++)
|
||||||
|
{
|
||||||
|
var preamble = _list[(i - 25)..i];
|
||||||
|
if (!preamble.Any(num1 => preamble.Any(num2 => num1 + num2 == _list[i])))
|
||||||
|
{
|
||||||
|
_part1 = _list[i];
|
||||||
|
return $"{_part1}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < _list.Length; i++)
|
||||||
|
{
|
||||||
|
long sum = 0;
|
||||||
|
for (var j = i; j < _list.Length; j++)
|
||||||
|
{
|
||||||
|
sum += _list[j];
|
||||||
|
if (sum > _part1) break;
|
||||||
|
if (sum != _part1) continue;
|
||||||
|
|
||||||
|
var subset = _list[i..(j + 1)].ToArray();
|
||||||
|
return $"{subset.Min() + subset.Max()}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
106
aoc2020/Day10.cs
106
aoc2020/Day10.cs
|
@ -1,59 +1,55 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 10: <see href="https://adventofcode.com/2020/day/10" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day10 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly int[] _adapters;
|
||||||
/// Day 10: <see href="https://adventofcode.com/2020/day/10" />
|
private readonly long[] _memo;
|
||||||
/// </summary>
|
|
||||||
public sealed class Day10 : Day
|
public Day10() : base(10, "Adapter Array")
|
||||||
{
|
{
|
||||||
private readonly int[] _adapters;
|
var parsed = Input.Select(int.Parse).ToArray();
|
||||||
private readonly long[] _memo;
|
// add socket and device to the list
|
||||||
|
_adapters = parsed.Concat(new[] { 0, parsed.Max() + 3 }).OrderBy(i => i).ToArray();
|
||||||
public Day10() : base(10, "Adapter Array")
|
_memo = new long[_adapters.Length];
|
||||||
{
|
|
||||||
var parsed = Input.Select(int.Parse).ToArray();
|
|
||||||
// add socket and device to the list
|
|
||||||
_adapters = parsed.Concat(new[] {0, parsed.Max() + 3}).OrderBy(i => i).ToArray();
|
|
||||||
_memo = new long[_adapters.Length];
|
|
||||||
}
|
|
||||||
|
|
||||||
private long Connections(int i)
|
|
||||||
{
|
|
||||||
if (i == _adapters.Length - 1) _memo[i] = 1;
|
|
||||||
if (_memo[i] > 0) return _memo[i];
|
|
||||||
|
|
||||||
for (var j = i + 1; j <= i + 3 && j < _adapters.Length; j++)
|
|
||||||
if (_adapters[j] - _adapters[i] <= 3)
|
|
||||||
_memo[i] += Connections(j);
|
|
||||||
|
|
||||||
return _memo[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
var ones = 0;
|
|
||||||
var threes = 0;
|
|
||||||
|
|
||||||
for (var i = 0; i < _adapters.Length - 1; i++)
|
|
||||||
switch (_adapters[i + 1] - _adapters[i])
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
ones++;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
threes++;
|
|
||||||
break;
|
|
||||||
default: throw new Exception("something went wrong");
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{ones * threes}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return $"{Connections(0)}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private long Connections(int i)
|
||||||
|
{
|
||||||
|
if (i == _adapters.Length - 1) _memo[i] = 1;
|
||||||
|
if (_memo[i] > 0) return _memo[i];
|
||||||
|
|
||||||
|
for (var j = i + 1; j <= i + 3 && j < _adapters.Length; j++)
|
||||||
|
if (_adapters[j] - _adapters[i] <= 3)
|
||||||
|
_memo[i] += Connections(j);
|
||||||
|
|
||||||
|
return _memo[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
var ones = 0;
|
||||||
|
var threes = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < _adapters.Length - 1; i++)
|
||||||
|
switch (_adapters[i + 1] - _adapters[i])
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
ones++;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
threes++;
|
||||||
|
break;
|
||||||
|
default: throw new Exception("something went wrong");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{ones * threes}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return $"{Connections(0)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
215
aoc2020/Day11.cs
215
aoc2020/Day11.cs
|
@ -1,91 +1,87 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 11: <see href="https://adventofcode.com/2020/day/11" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day11 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
public Day11() : base(11, "Seating System")
|
||||||
/// Day 11: <see href="https://adventofcode.com/2020/day/11" />
|
|
||||||
/// </summary>
|
|
||||||
public sealed class Day11 : Day
|
|
||||||
{
|
{
|
||||||
public Day11() : base(11, "Seating System")
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
var prev = new LifeGame(Input);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var next = prev.StepPart1();
|
||||||
|
var same = true;
|
||||||
|
for (var i = 0; i < next.Grid.Length; i++)
|
||||||
|
if (!next.Grid[i].SequenceEqual(prev.Grid[i]))
|
||||||
|
{
|
||||||
|
same = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (same) break;
|
||||||
|
prev = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{prev.TotalSeated}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var prev = new LifeGame(Input);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var next = prev.StepPart2();
|
||||||
|
var same = true;
|
||||||
|
for (var i = 0; i < next.Grid.Length; i++)
|
||||||
|
if (!next.Grid[i].SequenceEqual(prev.Grid[i]))
|
||||||
|
{
|
||||||
|
same = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (same) break;
|
||||||
|
prev = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{prev.TotalSeated}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LifeGame
|
||||||
|
{
|
||||||
|
private int _h, _w;
|
||||||
|
public char[][] Grid;
|
||||||
|
|
||||||
|
public LifeGame(IEnumerable<string> input)
|
||||||
|
{
|
||||||
|
Grid = input.Select(line => line.ToCharArray()).ToArray();
|
||||||
|
_h = Grid.Length;
|
||||||
|
_w = Grid[0].Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LifeGame()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part1()
|
public int TotalSeated =>
|
||||||
|
Grid.Sum(l => l.Count(c => c == '#'));
|
||||||
|
|
||||||
|
private void PrintBoard()
|
||||||
{
|
{
|
||||||
var prev = new LifeGame(Input);
|
Console.Clear();
|
||||||
|
foreach (var line in Grid)
|
||||||
while (true)
|
Console.WriteLine(line);
|
||||||
{
|
|
||||||
var next = prev.StepPart1();
|
|
||||||
var same = true;
|
|
||||||
for (var i = 0; i < next.Grid.Length; i++)
|
|
||||||
if (!next.Grid[i].SequenceEqual(prev.Grid[i]))
|
|
||||||
{
|
|
||||||
same = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (same) break;
|
|
||||||
prev = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{prev.TotalSeated}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part2()
|
public LifeGame StepPart1()
|
||||||
{
|
{
|
||||||
var prev = new LifeGame(Input);
|
var next = new LifeGame { _h = _h, _w = _w, Grid = Grid.Select(s => s.ToArray()).ToArray() };
|
||||||
while (true)
|
for (var y = 0; y < _h; y++)
|
||||||
{
|
|
||||||
var next = prev.StepPart2();
|
|
||||||
var same = true;
|
|
||||||
for (var i = 0; i < next.Grid.Length; i++)
|
|
||||||
if (!next.Grid[i].SequenceEqual(prev.Grid[i]))
|
|
||||||
{
|
|
||||||
same = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (same) break;
|
|
||||||
prev = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{prev.TotalSeated}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LifeGame
|
|
||||||
{
|
|
||||||
private int _h, _w;
|
|
||||||
public char[][] Grid;
|
|
||||||
|
|
||||||
public LifeGame(IEnumerable<string> input)
|
|
||||||
{
|
|
||||||
Grid = input.Select(line => line.ToCharArray()).ToArray();
|
|
||||||
_h = Grid.Length;
|
|
||||||
_w = Grid[0].Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
private LifeGame()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public int TotalSeated =>
|
|
||||||
Grid.Sum(l => l.Count(c => c == '#'));
|
|
||||||
|
|
||||||
private void PrintBoard()
|
|
||||||
{
|
|
||||||
Console.Clear();
|
|
||||||
foreach (var line in Grid)
|
|
||||||
Console.WriteLine(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LifeGame StepPart1()
|
|
||||||
{
|
|
||||||
var next = new LifeGame {_h = _h, _w = _w, Grid = Grid.Select(s => s.ToArray()).ToArray()};
|
|
||||||
for (var y = 0; y < _h; y++)
|
|
||||||
for (var x = 0; x < _w; x++)
|
for (var x = 0; x < _w; x++)
|
||||||
next.Grid[y][x] = Grid[y][x] switch
|
next.Grid[y][x] = Grid[y][x] switch
|
||||||
{
|
{
|
||||||
|
@ -94,29 +90,29 @@ namespace aoc2020
|
||||||
_ => Grid[y][x]
|
_ => Grid[y][x]
|
||||||
};
|
};
|
||||||
|
|
||||||
// next.PrintBoard();
|
// next.PrintBoard();
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
private char At(int y, int x)
|
private char At(int y, int x)
|
||||||
{
|
{
|
||||||
return x < 0 || y < 0 || x >= _w || y >= _h ? '.' : Grid[y][x];
|
return x < 0 || y < 0 || x >= _w || y >= _h ? '.' : Grid[y][x];
|
||||||
}
|
}
|
||||||
|
|
||||||
private int CountAdjacent(int y, int x)
|
private int CountAdjacent(int y, int x)
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
{
|
{
|
||||||
return new[]
|
|
||||||
{
|
|
||||||
At(y - 1, x - 1), At(y - 1, x + 0), At(y - 1, x + 1),
|
At(y - 1, x - 1), At(y - 1, x + 0), At(y - 1, x + 1),
|
||||||
At(y + 0, x - 1), At(y + 0, x + 1),
|
At(y + 0, x - 1), At(y + 0, x + 1),
|
||||||
At(y + 1, x - 1), At(y + 1, x + 0), At(y + 1, x + 1)
|
At(y + 1, x - 1), At(y + 1, x + 0), At(y + 1, x + 1)
|
||||||
}.Count(c => c == '#');
|
}.Count(c => c == '#');
|
||||||
}
|
}
|
||||||
|
|
||||||
public LifeGame StepPart2()
|
public LifeGame StepPart2()
|
||||||
{
|
{
|
||||||
var next = new LifeGame {_h = _h, _w = _w, Grid = Grid.Select(s => s.ToArray()).ToArray()};
|
var next = new LifeGame { _h = _h, _w = _w, Grid = Grid.Select(s => s.ToArray()).ToArray() };
|
||||||
for (var y = 0; y < _h; y++)
|
for (var y = 0; y < _h; y++)
|
||||||
for (var x = 0; x < _w; x++)
|
for (var x = 0; x < _w; x++)
|
||||||
next.Grid[y][x] = Grid[y][x] switch
|
next.Grid[y][x] = Grid[y][x] switch
|
||||||
{
|
{
|
||||||
|
@ -125,33 +121,32 @@ namespace aoc2020
|
||||||
_ => Grid[y][x]
|
_ => Grid[y][x]
|
||||||
};
|
};
|
||||||
|
|
||||||
// next.PrintBoard();
|
// next.PrintBoard();
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int CanSee(int y, int x)
|
private int CanSee(int y, int x)
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
{
|
{
|
||||||
return new[]
|
|
||||||
{
|
|
||||||
TraceRay(y, x, -1, -1), TraceRay(y, x, -1, +0), TraceRay(y, x, -1, +1),
|
TraceRay(y, x, -1, -1), TraceRay(y, x, -1, +0), TraceRay(y, x, -1, +1),
|
||||||
TraceRay(y, x, +0, -1), TraceRay(y, x, +0, +1),
|
TraceRay(y, x, +0, -1), TraceRay(y, x, +0, +1),
|
||||||
TraceRay(y, x, +1, -1), TraceRay(y, x, +1, +0), TraceRay(y, x, +1, +1)
|
TraceRay(y, x, +1, -1), TraceRay(y, x, +1, +0), TraceRay(y, x, +1, +1)
|
||||||
}.Count(c => c == '#');
|
}.Count(c => c == '#');
|
||||||
}
|
}
|
||||||
|
|
||||||
private char TraceRay(int y, int x, int dy, int dx)
|
private char TraceRay(int y, int x, int dy, int dx)
|
||||||
|
{
|
||||||
|
y += dy;
|
||||||
|
x += dx;
|
||||||
|
while (y >= 0 && y < _h && x >= 0 && x < _w)
|
||||||
{
|
{
|
||||||
|
if (Grid[y][x] != '.') return Grid[y][x];
|
||||||
y += dy;
|
y += dy;
|
||||||
x += dx;
|
x += dx;
|
||||||
while (y >= 0 && y < _h && x >= 0 && x < _w)
|
|
||||||
{
|
|
||||||
if (Grid[y][x] != '.') return Grid[y][x];
|
|
||||||
y += dy;
|
|
||||||
x += dx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return '.';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
175
aoc2020/Day12.cs
175
aoc2020/Day12.cs
|
@ -1,94 +1,89 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 12: <see href="https://adventofcode.com/2020/day/12" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day12 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
public Day12() : base(12, "Rain Risk")
|
||||||
/// Day 12: <see href="https://adventofcode.com/2020/day/12" />
|
|
||||||
/// </summary>
|
|
||||||
public sealed class Day12 : Day
|
|
||||||
{
|
{
|
||||||
public Day12() : base(12, "Rain Risk")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Swap(ref int x, ref int y)
|
|
||||||
{
|
|
||||||
var tmp = x;
|
|
||||||
x = y;
|
|
||||||
y = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private (int x, int y, int sx, int sy) ProcessInstructions()
|
|
||||||
{
|
|
||||||
// start facing east
|
|
||||||
int x = 0, y = 0, dx = 1, dy = 0;
|
|
||||||
int sx = 0, sy = 0, waypointX = 10, waypointY = -1;
|
|
||||||
|
|
||||||
foreach (var instruction in Input)
|
|
||||||
{
|
|
||||||
var value = int.Parse(instruction[1..]);
|
|
||||||
|
|
||||||
switch (instruction[0])
|
|
||||||
{
|
|
||||||
case 'N':
|
|
||||||
y -= value;
|
|
||||||
waypointY -= value;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
y += value;
|
|
||||||
waypointY += value;
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
x += value;
|
|
||||||
waypointX += value;
|
|
||||||
break;
|
|
||||||
case 'W':
|
|
||||||
x -= value;
|
|
||||||
waypointX -= value;
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
for (var i = 0; i < value / 90; ++i)
|
|
||||||
{
|
|
||||||
Swap(ref dx, ref dy);
|
|
||||||
Swap(ref waypointX, ref waypointY);
|
|
||||||
dy *= -1;
|
|
||||||
waypointY *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
for (var i = 0; i < value / 90; ++i)
|
|
||||||
{
|
|
||||||
Swap(ref dx, ref dy);
|
|
||||||
Swap(ref waypointX, ref waypointY);
|
|
||||||
dx *= -1;
|
|
||||||
waypointX *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
x += dx * value;
|
|
||||||
y += dy * value;
|
|
||||||
sx += waypointX * value;
|
|
||||||
sy += waypointY * value;
|
|
||||||
break;
|
|
||||||
default: throw new InvalidOperationException(nameof(instruction));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (x, y, sx, sy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
var (x, y, _, _) = ProcessInstructions();
|
|
||||||
return $"{Math.Abs(x) + Math.Abs(y)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
var (_, _, sx, sy) = ProcessInstructions();
|
|
||||||
return $"{Math.Abs(sx) + Math.Abs(sy)}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static void Swap(ref int x, ref int y)
|
||||||
|
{
|
||||||
|
(y, x) = (x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private (int x, int y, int sx, int sy) ProcessInstructions()
|
||||||
|
{
|
||||||
|
// start facing east
|
||||||
|
int x = 0, y = 0, dx = 1, dy = 0;
|
||||||
|
int sx = 0, sy = 0, waypointX = 10, waypointY = -1;
|
||||||
|
|
||||||
|
foreach (var instruction in Input)
|
||||||
|
{
|
||||||
|
var value = int.Parse(instruction[1..]);
|
||||||
|
|
||||||
|
switch (instruction[0])
|
||||||
|
{
|
||||||
|
case 'N':
|
||||||
|
y -= value;
|
||||||
|
waypointY -= value;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
y += value;
|
||||||
|
waypointY += value;
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
x += value;
|
||||||
|
waypointX += value;
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
x -= value;
|
||||||
|
waypointX -= value;
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
for (var i = 0; i < value / 90; ++i)
|
||||||
|
{
|
||||||
|
Swap(ref dx, ref dy);
|
||||||
|
Swap(ref waypointX, ref waypointY);
|
||||||
|
dy *= -1;
|
||||||
|
waypointY *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
for (var i = 0; i < value / 90; ++i)
|
||||||
|
{
|
||||||
|
Swap(ref dx, ref dy);
|
||||||
|
Swap(ref waypointX, ref waypointY);
|
||||||
|
dx *= -1;
|
||||||
|
waypointX *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
x += dx * value;
|
||||||
|
y += dy * value;
|
||||||
|
sx += waypointX * value;
|
||||||
|
sy += waypointY * value;
|
||||||
|
break;
|
||||||
|
default: throw new InvalidOperationException(nameof(instruction));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (x, y, sx, sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
var (x, y, _, _) = ProcessInstructions();
|
||||||
|
return $"{Math.Abs(x) + Math.Abs(y)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var (_, _, sx, sy) = ProcessInstructions();
|
||||||
|
return $"{Math.Abs(sx) + Math.Abs(sy)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,54 +1,51 @@
|
||||||
using System.Linq;
|
namespace aoc2020;
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 13: <see href="https://adventofcode.com/2020/day/13" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day13 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly long[] _buses;
|
||||||
/// Day 13: <see href="https://adventofcode.com/2020/day/13" />
|
private readonly long _earliest;
|
||||||
/// </summary>
|
private readonly string[] _fullSchedule;
|
||||||
public sealed class Day13 : Day
|
|
||||||
|
public Day13() : base(13, "Shuttle Search")
|
||||||
{
|
{
|
||||||
private readonly long[] _buses;
|
_earliest = long.Parse(Input.First());
|
||||||
private readonly long _earliest;
|
_fullSchedule = Input.Last().Split(',');
|
||||||
private readonly string[] _fullSchedule;
|
_buses = _fullSchedule.Where(c => c != "x").Select(long.Parse).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
public Day13() : base(13, "Shuttle Search")
|
public override string Part1()
|
||||||
{
|
{
|
||||||
_earliest = long.Parse(Input.First());
|
for (var i = _earliest; ; i++)
|
||||||
_fullSchedule = Input.Last().Split(',');
|
if (_buses.Any(b => i % b == 0))
|
||||||
_buses = _fullSchedule.Where(c => c != "x").Select(long.Parse).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
for (var i = _earliest;; i++)
|
|
||||||
if (_buses.Any(b => i % b == 0))
|
|
||||||
{
|
|
||||||
var bus = _buses.First(b => i % b == 0);
|
|
||||||
return $"{bus * (i - _earliest)}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
var i = 0;
|
|
||||||
long result = 1, multiplier = 1;
|
|
||||||
|
|
||||||
foreach (var id in _fullSchedule)
|
|
||||||
{
|
{
|
||||||
if (id != "x")
|
var bus = _buses.First(b => i % b == 0);
|
||||||
{
|
return $"{bus * (i - _earliest)}";
|
||||||
var increment = long.Parse(id);
|
}
|
||||||
while (((result += multiplier) + i) % increment != 0)
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
multiplier *= increment;
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var i = 0;
|
||||||
|
long result = 1, multiplier = 1;
|
||||||
|
|
||||||
|
foreach (var id in _fullSchedule)
|
||||||
|
{
|
||||||
|
if (id != "x")
|
||||||
|
{
|
||||||
|
var increment = long.Parse(id);
|
||||||
|
while (((result += multiplier) + i) % increment != 0)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
multiplier *= increment;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $"{result}";
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $"{result}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
195
aoc2020/Day14.cs
195
aoc2020/Day14.cs
|
@ -1,111 +1,106 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 14: <see href="https://adventofcode.com/2020/day/14" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day14 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
public Day14() : base(14, "Docking Data")
|
||||||
/// Day 14: <see href="https://adventofcode.com/2020/day/14" />
|
|
||||||
/// </summary>
|
|
||||||
public sealed class Day14 : Day
|
|
||||||
{
|
{
|
||||||
public Day14() : base(14, "Docking Data")
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
public override string Part1()
|
||||||
{
|
{
|
||||||
var writes = new Dictionary<ulong, ulong>();
|
var writes = new Dictionary<ulong, ulong>();
|
||||||
ulong mask = 0, bits = 0;
|
ulong mask = 0, bits = 0;
|
||||||
|
|
||||||
foreach (var line in Input)
|
foreach (var line in Input)
|
||||||
if (line.StartsWith("mask = "))
|
if (line.StartsWith("mask = "))
|
||||||
{
|
|
||||||
var str = line.Split("mask = ", 2)[1];
|
|
||||||
mask = bits = 0;
|
|
||||||
for (var i = 35; i >= 0; --i)
|
|
||||||
switch (str[35 - i])
|
|
||||||
{
|
|
||||||
case 'X':
|
|
||||||
mask |= 1UL << i;
|
|
||||||
break;
|
|
||||||
case '1':
|
|
||||||
bits |= 1UL << i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var spl = line.Split(new[] {'[', ']', '='},
|
|
||||||
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
|
||||||
.Skip(1)
|
|
||||||
.Select(ulong.Parse)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
writes[spl[0]] = (spl[1] & mask) | bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{writes.Aggregate<KeyValuePair<ulong, ulong>, ulong>(0, (current, w) => current + w.Value)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
var memory = new Dictionary<ulong, ulong>();
|
|
||||||
var mask = "";
|
|
||||||
|
|
||||||
foreach (var line in Input)
|
|
||||||
{
|
{
|
||||||
var spl = line.Split(' ', 3, StringSplitOptions.TrimEntries);
|
var str = line.Split("mask = ", 2)[1];
|
||||||
|
mask = bits = 0;
|
||||||
if (spl[0] == "mask")
|
for (var i = 35; i >= 0; --i)
|
||||||
{
|
switch (str[35 - i])
|
||||||
mask = spl[2];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var value = ulong.Parse(spl[2]);
|
|
||||||
var addr = ulong.Parse(spl[0].Split(new[] {'[', ']'},
|
|
||||||
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)[1]);
|
|
||||||
|
|
||||||
var floats = new List<int>();
|
|
||||||
for (var i = 0; i < mask.Length; i++)
|
|
||||||
switch (mask[i])
|
|
||||||
{
|
|
||||||
case 'X':
|
|
||||||
floats.Add(i);
|
|
||||||
break;
|
|
||||||
case '1':
|
|
||||||
addr |= 1UL << (35 - i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (floats.Any())
|
|
||||||
{
|
{
|
||||||
var combos = new List<ulong> {addr};
|
case 'X':
|
||||||
|
mask |= 1UL << i;
|
||||||
foreach (var i in floats)
|
break;
|
||||||
{
|
case '1':
|
||||||
var newCombos = new List<ulong>();
|
bits |= 1UL << i;
|
||||||
foreach (var c in combos)
|
break;
|
||||||
{
|
|
||||||
newCombos.Add(c | (1UL << (35 - i)));
|
|
||||||
newCombos.Add(c & ~(1UL << (35 - i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
combos = newCombos;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var c in combos)
|
|
||||||
memory[c] = value;
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
memory[addr] = value;
|
{
|
||||||
}
|
var spl = line.Split(new[] { '[', ']', '=' },
|
||||||
}
|
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||||
|
.Skip(1)
|
||||||
|
.Select(ulong.Parse)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
writes[spl[0]] = (spl[1] & mask) | bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $"{memory.Aggregate<KeyValuePair<ulong, ulong>, ulong>(0, (current, w) => current + w.Value)}";
|
return $"{writes.Aggregate<KeyValuePair<ulong, ulong>, ulong>(0, (current, w) => current + w.Value)}";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var memory = new Dictionary<ulong, ulong>();
|
||||||
|
var mask = "";
|
||||||
|
|
||||||
|
foreach (var line in Input)
|
||||||
|
{
|
||||||
|
var spl = line.Split(' ', 3, StringSplitOptions.TrimEntries);
|
||||||
|
|
||||||
|
if (spl[0] == "mask")
|
||||||
|
{
|
||||||
|
mask = spl[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var value = ulong.Parse(spl[2]);
|
||||||
|
var addr = ulong.Parse(spl[0].Split(new[] { '[', ']' },
|
||||||
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)[1]);
|
||||||
|
|
||||||
|
var floats = new List<int>();
|
||||||
|
for (var i = 0; i < mask.Length; i++)
|
||||||
|
switch (mask[i])
|
||||||
|
{
|
||||||
|
case 'X':
|
||||||
|
floats.Add(i);
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
addr |= 1UL << (35 - i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (floats.Any())
|
||||||
|
{
|
||||||
|
var combos = new List<ulong> { addr };
|
||||||
|
|
||||||
|
foreach (var i in floats)
|
||||||
|
{
|
||||||
|
var newCombos = new List<ulong>();
|
||||||
|
foreach (var c in combos)
|
||||||
|
{
|
||||||
|
newCombos.Add(c | (1UL << (35 - i)));
|
||||||
|
newCombos.Add(c & ~(1UL << (35 - i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
combos = newCombos;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var c in combos)
|
||||||
|
memory[c] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memory[addr] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{memory.Aggregate<KeyValuePair<ulong, ulong>, ulong>(0, (current, w) => current + w.Value)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,48 +1,45 @@
|
||||||
using System.Linq;
|
namespace aoc2020;
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 15: <see href="https://adventofcode.com/2020/day/15" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day15 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly int[] _turns;
|
||||||
/// Day 15: <see href="https://adventofcode.com/2020/day/15" />
|
private int _current;
|
||||||
/// </summary>
|
private int _i;
|
||||||
public sealed class Day15 : Day
|
|
||||||
|
public Day15() : base(15, "Rambunctious Recitation")
|
||||||
{
|
{
|
||||||
private readonly int[] _turns;
|
var initial = Input.First().Split(',').Select(int.Parse).ToArray();
|
||||||
private int _current;
|
_turns = new int[30_000_000];
|
||||||
private int _i;
|
|
||||||
|
|
||||||
public Day15() : base(15, "Rambunctious Recitation")
|
// seed array with initial values
|
||||||
{
|
for (_i = 1; _i < initial.Length + 1; _i++)
|
||||||
var initial = Input.First().Split(',').Select(int.Parse).ToArray();
|
_turns[initial[_i - 1]] = _i;
|
||||||
_turns = new int[30_000_000];
|
|
||||||
|
|
||||||
// seed array with initial values
|
|
||||||
for (_i = 1; _i < initial.Length + 1; _i++)
|
|
||||||
_turns[initial[_i - 1]] = _i;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
for (; _i != 2020; _i++)
|
|
||||||
{
|
|
||||||
var next = _turns[_current] > 0 ? _i - _turns[_current] : 0;
|
|
||||||
_turns[_current] = _i;
|
|
||||||
_current = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{_current}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
for (; _i != 30_000_000; _i++)
|
|
||||||
{
|
|
||||||
var next = _turns[_current] > 0 ? _i - _turns[_current] : 0;
|
|
||||||
_turns[_current] = _i;
|
|
||||||
_current = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{_current}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
for (; _i != 2020; _i++)
|
||||||
|
{
|
||||||
|
var next = _turns[_current] > 0 ? _i - _turns[_current] : 0;
|
||||||
|
_turns[_current] = _i;
|
||||||
|
_current = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{_current}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
for (; _i != 30_000_000; _i++)
|
||||||
|
{
|
||||||
|
var next = _turns[_current] > 0 ? _i - _turns[_current] : 0;
|
||||||
|
_turns[_current] = _i;
|
||||||
|
_current = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{_current}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
155
aoc2020/Day16.cs
155
aoc2020/Day16.cs
|
@ -1,91 +1,86 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 16: <see href="https://adventofcode.com/2020/day/16" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day16 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly Dictionary<string, List<Range>> _rules;
|
||||||
/// Day 16: <see href="https://adventofcode.com/2020/day/16" />
|
private readonly List<List<int>> _tickets;
|
||||||
/// </summary>
|
|
||||||
public sealed class Day16 : Day
|
public Day16() : base(16, "Ticket Translation")
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, List<Range>> _rules;
|
_tickets = new();
|
||||||
private readonly List<List<int>> _tickets;
|
_rules = new();
|
||||||
|
|
||||||
public Day16() : base(16, "Ticket Translation")
|
foreach (var line in Input)
|
||||||
{
|
{
|
||||||
_tickets = new List<List<int>>();
|
var spl = line.Split(": ", 2, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||||
_rules = new Dictionary<string, List<Range>>();
|
if (spl.Length == 2)
|
||||||
|
|
||||||
foreach (var line in Input)
|
|
||||||
{
|
{
|
||||||
var spl = line.Split(": ", 2, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
var rule = spl[1].Split(" or ").Select(s =>
|
||||||
if (spl.Length == 2)
|
|
||||||
{
|
{
|
||||||
var rule = spl[1].Split(" or ").Select(s =>
|
var r = s.Split('-').Select(int.Parse).ToList();
|
||||||
{
|
return new Range(r[0], r[1]);
|
||||||
var r = s.Split('-').Select(int.Parse).ToList();
|
}).ToList();
|
||||||
return new Range(r[0], r[1]);
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
_rules.Add(spl[0], rule);
|
_rules.Add(spl[0], rule);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
spl = line.Split(',');
|
spl = line.Split(',');
|
||||||
if (spl.Length > 1)
|
if (spl.Length > 1)
|
||||||
_tickets.Add(spl.Select(int.Parse).ToList());
|
_tickets.Add(spl.Select(int.Parse).ToList());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
var allValues = _tickets.Skip(1).SelectMany(t => t);
|
|
||||||
var allRules = _rules.Values.SelectMany(r => r);
|
|
||||||
return
|
|
||||||
$"{allValues.Where(t => !allRules.Any(r => r.Contains(t))).Sum()}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
var ticketFields = _tickets
|
|
||||||
// valid tickets
|
|
||||||
.Where(ticket => ticket
|
|
||||||
.All(t => _rules.Values
|
|
||||||
.SelectMany(r => r)
|
|
||||||
.Any(r => r.Contains(t))))
|
|
||||||
// group by index
|
|
||||||
.SelectMany(inner => inner.Select((item, index) => new {item, index}))
|
|
||||||
.GroupBy(i => i.index, i => i.item)
|
|
||||||
.Select(g => g.ToList())
|
|
||||||
.Select((val, i) => new {Value = val, Index = i})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var matchedRules = _rules
|
|
||||||
// find matching rules and indices
|
|
||||||
.SelectMany(x => ticketFields
|
|
||||||
.Where(y => y.Value.All(z => x.Value.Any(r => r.Contains(z))))
|
|
||||||
.Select(y => (x.Key, y.Index))
|
|
||||||
.ToList())
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
matchedRules.Sort((a, b) =>
|
|
||||||
matchedRules.Count(x => x.Key == a.Key) - matchedRules.Count(x => x.Key == b.Key));
|
|
||||||
|
|
||||||
while (matchedRules.Any(x => matchedRules.Count(y => y.Key == x.Key) > 1))
|
|
||||||
foreach (var (key, index) in matchedRules.Where(y =>
|
|
||||||
matchedRules.Count(z => z.Key == y.Key) == 1 &&
|
|
||||||
matchedRules.Count(z => z.Index == y.Index) > 1))
|
|
||||||
// filter matches by index
|
|
||||||
matchedRules = matchedRules
|
|
||||||
.Where(x => x.Index != index || x.Key == key)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var departureFields = matchedRules.Where(r => r.Key.StartsWith("departure"));
|
|
||||||
|
|
||||||
return
|
|
||||||
$"{departureFields.Aggregate(1L, (l, match) => l * _tickets.First()[match.Index])}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
var allValues = _tickets.Skip(1).SelectMany(t => t);
|
||||||
|
var allRules = _rules.Values.SelectMany(r => r);
|
||||||
|
return
|
||||||
|
$"{allValues.Where(t => !allRules.Any(r => r.Contains(t))).Sum()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var ticketFields = _tickets
|
||||||
|
// valid tickets
|
||||||
|
.Where(ticket => ticket
|
||||||
|
.All(t => _rules.Values
|
||||||
|
.SelectMany(r => r)
|
||||||
|
.Any(r => r.Contains(t))))
|
||||||
|
// group by index
|
||||||
|
.SelectMany(inner => inner.Select((item, index) => new { item, index }))
|
||||||
|
.GroupBy(i => i.index, i => i.item)
|
||||||
|
.Select(g => g.ToList())
|
||||||
|
.Select((val, i) => new { Value = val, Index = i })
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var matchedRules = _rules
|
||||||
|
// find matching rules and indices
|
||||||
|
.SelectMany(x => ticketFields
|
||||||
|
.Where(y => y.Value.All(z => x.Value.Any(r => r.Contains(z))))
|
||||||
|
.Select(y => (x.Key, y.Index))
|
||||||
|
.ToList())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
matchedRules.Sort((a, b) =>
|
||||||
|
matchedRules.Count(x => x.Key == a.Key) - matchedRules.Count(x => x.Key == b.Key));
|
||||||
|
|
||||||
|
while (matchedRules.Any(x => matchedRules.Count(y => y.Key == x.Key) > 1))
|
||||||
|
foreach (var (key, index) in matchedRules.Where(y =>
|
||||||
|
matchedRules.Count(z => z.Key == y.Key) == 1 &&
|
||||||
|
matchedRules.Count(z => z.Index == y.Index) > 1))
|
||||||
|
// filter matches by index
|
||||||
|
matchedRules = matchedRules
|
||||||
|
.Where(x => x.Index != index || x.Key == key)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var departureFields = matchedRules.Where(r => r.Key.StartsWith("departure"));
|
||||||
|
|
||||||
|
return
|
||||||
|
$"{departureFields.Aggregate(1L, (l, match) => l * _tickets.First()[match.Index])}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
228
aoc2020/Day17.cs
228
aoc2020/Day17.cs
|
@ -1,130 +1,126 @@
|
||||||
using System.Collections.Generic;
|
namespace aoc2020;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 17: <see href="https://adventofcode.com/2020/day/17" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day17 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly Dictionary<(int x, int y, int z), char> _plane;
|
||||||
/// Day 17: <see href="https://adventofcode.com/2020/day/17" />
|
private readonly Dictionary<(int x, int y, int z, int w), char> _plane4;
|
||||||
/// </summary>
|
|
||||||
public sealed class Day17 : Day
|
|
||||||
|
public Day17() : base(17, "Conway Cubes")
|
||||||
{
|
{
|
||||||
private readonly Dictionary<(int x, int y, int z), char> _plane;
|
_plane = new Dictionary<(int x, int y, int z), char>();
|
||||||
private readonly Dictionary<(int x, int y, int z, int w), char> _plane4;
|
_plane4 = new Dictionary<(int x, int y, int z, int w), char>();
|
||||||
|
var input = Input.ToList();
|
||||||
|
|
||||||
|
for (var x = 0; x < 32; x++)
|
||||||
public Day17() : base(17, "Conway Cubes")
|
|
||||||
{
|
|
||||||
_plane = new Dictionary<(int x, int y, int z), char>();
|
|
||||||
_plane4 = new Dictionary<(int x, int y, int z, int w), char>();
|
|
||||||
var input = Input.ToList();
|
|
||||||
|
|
||||||
for (var x = 0; x < 32; x++)
|
|
||||||
for (var y = 0; y < 32; y++)
|
for (var y = 0; y < 32; y++)
|
||||||
for (var z = 0; z < 32; z++)
|
for (var z = 0; z < 32; z++)
|
||||||
_plane[(x, y, z)] = '.';
|
_plane[(x, y, z)] = '.';
|
||||||
|
|
||||||
for (var x = 0; x < 32; x++)
|
for (var x = 0; x < 32; x++)
|
||||||
for (var y = 0; y < 32; y++)
|
for (var y = 0; y < 32; y++)
|
||||||
for (var z = 0; z < 32; z++)
|
for (var z = 0; z < 32; z++)
|
||||||
for (var w = 0; w < 32; w++)
|
for (var w = 0; w < 32; w++)
|
||||||
_plane4[(x, y, z, w)] = '.';
|
_plane4[(x, y, z, w)] = '.';
|
||||||
|
|
||||||
for (var y = 0; y < input.Count; y++)
|
for (var y = 0; y < input.Count; y++)
|
||||||
for (var x = 0; x < input[y].Length; x++)
|
for (var x = 0; x < input[y].Length; x++)
|
||||||
_plane[(x, y, 0)] = input[y][x];
|
_plane[(x, y, 0)] = input[y][x];
|
||||||
|
|
||||||
for (var y = 0; y < input.Count; y++)
|
for (var y = 0; y < input.Count; y++)
|
||||||
for (var x = 0; x < input[y].Length; x++)
|
for (var x = 0; x < input[y].Length; x++)
|
||||||
_plane4[(x, y, 0, 0)] = input[y][x];
|
_plane4[(x, y, 0, 0)] = input[y][x];
|
||||||
}
|
|
||||||
|
|
||||||
private static int Neighbors(IReadOnlyDictionary<(int x, int y, int z), char> plane, int x, int y, int z)
|
|
||||||
{
|
|
||||||
var neighbors = 0;
|
|
||||||
|
|
||||||
foreach (var i in new[] {-1, 0, 1})
|
|
||||||
foreach (var j in new[] {-1, 0, 1})
|
|
||||||
foreach (var k in new[] {-1, 0, 1})
|
|
||||||
{
|
|
||||||
if (i == 0 && j == 0 && k == 0) continue;
|
|
||||||
if (plane[((x + i) & 31, (y + j) & 31, (z + k) & 31)] == '#') neighbors++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return neighbors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<(int x, int y, int z), char> Iterate(
|
|
||||||
IReadOnlyDictionary<(int x, int y, int z), char> prev)
|
|
||||||
{
|
|
||||||
var next = new Dictionary<(int x, int y, int z), char>();
|
|
||||||
|
|
||||||
for (var z = 0; z < 32; z++)
|
|
||||||
for (var y = 0; y < 32; y++)
|
|
||||||
for (var x = 0; x < 32; x++)
|
|
||||||
{
|
|
||||||
var active = Neighbors(prev, x, y, z);
|
|
||||||
if (prev[(x, y, z)] == '#')
|
|
||||||
next[(x, y, z)] = active == 2 || active == 3 ? '#' : '.';
|
|
||||||
else
|
|
||||||
next[(x, y, z)] = active == 3 ? '#' : '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int Neighbors4(IReadOnlyDictionary<(int x, int y, int z, int w), char> plane, int x, int y,
|
|
||||||
int z, int w)
|
|
||||||
{
|
|
||||||
var neighbors = 0;
|
|
||||||
|
|
||||||
foreach (var i in new[] {-1, 0, 1})
|
|
||||||
foreach (var j in new[] {-1, 0, 1})
|
|
||||||
foreach (var k in new[] {-1, 0, 1})
|
|
||||||
foreach (var l in new[] {-1, 0, 1})
|
|
||||||
{
|
|
||||||
if (i == 0 && j == 0 && k == 0 && l == 0) continue;
|
|
||||||
if (plane[((x + i) & 31, (y + j) & 31, (z + k) & 31, (w + l) & 31)] == '#') neighbors++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return neighbors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<(int x, int y, int z, int w), char> Iterate4(
|
|
||||||
IReadOnlyDictionary<(int x, int y, int z, int w), char> prev)
|
|
||||||
{
|
|
||||||
var next = new Dictionary<(int x, int y, int z, int w), char>();
|
|
||||||
|
|
||||||
for (var z = 0; z < 32; z++)
|
|
||||||
for (var y = 0; y < 32; y++)
|
|
||||||
for (var x = 0; x < 32; x++)
|
|
||||||
for (var w = 0; w < 32; w++)
|
|
||||||
{
|
|
||||||
var active = Neighbors4(prev, x, y, z, w);
|
|
||||||
if (prev[(x, y, z, w)] == '#')
|
|
||||||
next[(x, y, z, w)] = active == 2 || active == 3 ? '#' : '.';
|
|
||||||
else
|
|
||||||
next[(x, y, z, w)] = active == 3 ? '#' : '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
var plane = _plane;
|
|
||||||
foreach (var _ in Enumerable.Range(0, 6))
|
|
||||||
plane = Iterate(plane);
|
|
||||||
|
|
||||||
return $"{plane.Values.Count(v => v == '#')}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
var plane = _plane4;
|
|
||||||
foreach (var _ in Enumerable.Range(0, 6))
|
|
||||||
plane = Iterate4(plane);
|
|
||||||
|
|
||||||
return $"{plane.Values.Count(v => v == '#')}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static int Neighbors(IReadOnlyDictionary<(int x, int y, int z), char> plane, int x, int y, int z)
|
||||||
|
{
|
||||||
|
var neighbors = 0;
|
||||||
|
|
||||||
|
foreach (var i in new[] { -1, 0, 1 })
|
||||||
|
foreach (var j in new[] { -1, 0, 1 })
|
||||||
|
foreach (var k in new[] { -1, 0, 1 })
|
||||||
|
{
|
||||||
|
if (i == 0 && j == 0 && k == 0) continue;
|
||||||
|
if (plane[((x + i) & 31, (y + j) & 31, (z + k) & 31)] == '#') neighbors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return neighbors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<(int x, int y, int z), char> Iterate(
|
||||||
|
IReadOnlyDictionary<(int x, int y, int z), char> prev)
|
||||||
|
{
|
||||||
|
var next = new Dictionary<(int x, int y, int z), char>();
|
||||||
|
|
||||||
|
for (var z = 0; z < 32; z++)
|
||||||
|
for (var y = 0; y < 32; y++)
|
||||||
|
for (var x = 0; x < 32; x++)
|
||||||
|
{
|
||||||
|
var active = Neighbors(prev, x, y, z);
|
||||||
|
if (prev[(x, y, z)] == '#')
|
||||||
|
next[(x, y, z)] = active == 2 || active == 3 ? '#' : '.';
|
||||||
|
else
|
||||||
|
next[(x, y, z)] = active == 3 ? '#' : '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int Neighbors4(IReadOnlyDictionary<(int x, int y, int z, int w), char> plane, int x, int y,
|
||||||
|
int z, int w)
|
||||||
|
{
|
||||||
|
var neighbors = 0;
|
||||||
|
|
||||||
|
foreach (var i in new[] { -1, 0, 1 })
|
||||||
|
foreach (var j in new[] { -1, 0, 1 })
|
||||||
|
foreach (var k in new[] { -1, 0, 1 })
|
||||||
|
foreach (var l in new[] { -1, 0, 1 })
|
||||||
|
{
|
||||||
|
if (i == 0 && j == 0 && k == 0 && l == 0) continue;
|
||||||
|
if (plane[((x + i) & 31, (y + j) & 31, (z + k) & 31, (w + l) & 31)] == '#') neighbors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return neighbors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<(int x, int y, int z, int w), char> Iterate4(
|
||||||
|
IReadOnlyDictionary<(int x, int y, int z, int w), char> prev)
|
||||||
|
{
|
||||||
|
var next = new Dictionary<(int x, int y, int z, int w), char>();
|
||||||
|
|
||||||
|
for (var z = 0; z < 32; z++)
|
||||||
|
for (var y = 0; y < 32; y++)
|
||||||
|
for (var x = 0; x < 32; x++)
|
||||||
|
for (var w = 0; w < 32; w++)
|
||||||
|
{
|
||||||
|
var active = Neighbors4(prev, x, y, z, w);
|
||||||
|
if (prev[(x, y, z, w)] == '#')
|
||||||
|
next[(x, y, z, w)] = active == 2 || active == 3 ? '#' : '.';
|
||||||
|
else
|
||||||
|
next[(x, y, z, w)] = active == 3 ? '#' : '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
var plane = _plane;
|
||||||
|
foreach (var _ in Enumerable.Range(0, 6))
|
||||||
|
plane = Iterate(plane);
|
||||||
|
|
||||||
|
return $"{plane.Values.Count(v => v == '#')}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
var plane = _plane4;
|
||||||
|
foreach (var _ in Enumerable.Range(0, 6))
|
||||||
|
plane = Iterate4(plane);
|
||||||
|
|
||||||
|
return $"{plane.Values.Count(v => v == '#')}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
148
aoc2020/Day18.cs
148
aoc2020/Day18.cs
|
@ -1,81 +1,75 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 18: <see href="https://adventofcode.com/2020/day/18" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day18 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly List<string> _expressions;
|
||||||
/// Day 18: <see href="https://adventofcode.com/2020/day/18" />
|
|
||||||
/// </summary>
|
public Day18() : base(18, "Operation Order")
|
||||||
public sealed class Day18 : Day
|
|
||||||
{
|
{
|
||||||
private readonly List<string> _expressions;
|
_expressions = Input.Select(line => line.Replace(" ", "")).ToList();
|
||||||
|
|
||||||
public Day18() : base(18, "Operation Order")
|
|
||||||
{
|
|
||||||
_expressions = Input.Select(line => line.Replace(" ", "")).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long Calculate(string expr, Func<char, int> precedence)
|
|
||||||
{
|
|
||||||
var postfixNotation = new StringBuilder();
|
|
||||||
var postfixStack = new Stack<char>();
|
|
||||||
|
|
||||||
foreach (var c in expr)
|
|
||||||
if (char.IsDigit(c))
|
|
||||||
{
|
|
||||||
postfixNotation.Append(c);
|
|
||||||
}
|
|
||||||
else if (c == '(')
|
|
||||||
{
|
|
||||||
postfixStack.Push(c);
|
|
||||||
}
|
|
||||||
else if (c == ')')
|
|
||||||
{
|
|
||||||
while (postfixStack.Count > 0 && postfixStack.Peek() != '(')
|
|
||||||
postfixNotation.Append(postfixStack.Pop());
|
|
||||||
|
|
||||||
postfixStack.TryPop(out _);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (postfixStack.Count > 0 && precedence(c) <= precedence(postfixStack.Peek()))
|
|
||||||
postfixNotation.Append(postfixStack.Pop());
|
|
||||||
|
|
||||||
postfixStack.Push(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (postfixStack.Count > 0)
|
|
||||||
postfixNotation.Append(postfixStack.Pop());
|
|
||||||
|
|
||||||
var expressionStack = new Stack<long>();
|
|
||||||
|
|
||||||
foreach (var c in postfixNotation.ToString())
|
|
||||||
if (char.IsDigit(c))
|
|
||||||
{
|
|
||||||
expressionStack.Push((long) char.GetNumericValue(c));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var a = expressionStack.Pop();
|
|
||||||
var b = expressionStack.Pop();
|
|
||||||
|
|
||||||
if (c == '+') expressionStack.Push(a + b);
|
|
||||||
if (c == '*') expressionStack.Push(a * b);
|
|
||||||
}
|
|
||||||
|
|
||||||
return expressionStack.Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return $"{_expressions.Sum(expr => Calculate(expr, c => c == '+' || c == '*' ? 1 : 0))}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return $"{_expressions.Sum(expr => Calculate(expr, c => c switch {'+' => 2, '*' => 1, _ => 0}))}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static long Calculate(string expr, Func<char, int> precedence)
|
||||||
|
{
|
||||||
|
var postfixNotation = new StringBuilder();
|
||||||
|
var postfixStack = new Stack<char>();
|
||||||
|
|
||||||
|
foreach (var c in expr)
|
||||||
|
if (char.IsDigit(c))
|
||||||
|
{
|
||||||
|
postfixNotation.Append(c);
|
||||||
|
}
|
||||||
|
else if (c == '(')
|
||||||
|
{
|
||||||
|
postfixStack.Push(c);
|
||||||
|
}
|
||||||
|
else if (c == ')')
|
||||||
|
{
|
||||||
|
while (postfixStack.Count > 0 && postfixStack.Peek() != '(')
|
||||||
|
postfixNotation.Append(postfixStack.Pop());
|
||||||
|
|
||||||
|
postfixStack.TryPop(out _);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (postfixStack.Count > 0 && precedence(c) <= precedence(postfixStack.Peek()))
|
||||||
|
postfixNotation.Append(postfixStack.Pop());
|
||||||
|
|
||||||
|
postfixStack.Push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (postfixStack.Count > 0)
|
||||||
|
postfixNotation.Append(postfixStack.Pop());
|
||||||
|
|
||||||
|
var expressionStack = new Stack<long>();
|
||||||
|
|
||||||
|
foreach (var c in postfixNotation.ToString())
|
||||||
|
if (char.IsDigit(c))
|
||||||
|
{
|
||||||
|
expressionStack.Push((long)char.GetNumericValue(c));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var a = expressionStack.Pop();
|
||||||
|
var b = expressionStack.Pop();
|
||||||
|
|
||||||
|
if (c == '+') expressionStack.Push(a + b);
|
||||||
|
if (c == '*') expressionStack.Push(a * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expressionStack.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{_expressions.Sum(expr => Calculate(expr, c => c == '+' || c == '*' ? 1 : 0))}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return $"{_expressions.Sum(expr => Calculate(expr, c => c switch { '+' => 2, '*' => 1, _ => 0 }))}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
100
aoc2020/Day19.cs
100
aoc2020/Day19.cs
|
@ -1,57 +1,51 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 19: <see href="https://adventofcode.com/2020/day/19" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day19 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly string[] _messages;
|
||||||
/// Day 19: <see href="https://adventofcode.com/2020/day/19" />
|
private readonly Dictionary<string, string[][]> _rules;
|
||||||
/// </summary>
|
private readonly Stack<string> _stack;
|
||||||
public sealed class Day19 : Day
|
|
||||||
|
public Day19() : base(19, "Monster Messages")
|
||||||
{
|
{
|
||||||
private readonly string[] _messages;
|
_rules = Input.TakeWhile(l => !string.IsNullOrWhiteSpace(l))
|
||||||
private readonly Dictionary<string, string[][]> _rules;
|
.Select(l => l.Split(':'))
|
||||||
private readonly Stack<string> _stack;
|
.Select(a => (key: a[0],
|
||||||
|
val: a[1].Split('|', StringSplitOptions.RemoveEmptyEntries)
|
||||||
public Day19() : base(19, "Monster Messages")
|
.Select(s => s.Split(' ', StringSplitOptions.RemoveEmptyEntries)).ToArray()))
|
||||||
{
|
.ToDictionary(a => a.key, a => a.val);
|
||||||
_rules = Input.TakeWhile(l => !string.IsNullOrWhiteSpace(l))
|
_messages = Input.Skip(_rules.Count + 1).ToArray();
|
||||||
.Select(l => l.Split(':'))
|
_stack = new Stack<string>();
|
||||||
.Select(a => (key: a[0],
|
|
||||||
val: a[1].Split('|', StringSplitOptions.RemoveEmptyEntries)
|
|
||||||
.Select(s => s.Split(' ', StringSplitOptions.RemoveEmptyEntries)).ToArray()))
|
|
||||||
.ToDictionary(a => a.key, a => a.val);
|
|
||||||
_messages = Input.Skip(_rules.Count + 1).ToArray();
|
|
||||||
_stack = new Stack<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string MakeRegexExpression(string key)
|
|
||||||
{
|
|
||||||
if (_stack.Count(s => s == key) > 10) return "x";
|
|
||||||
_stack.Push(key);
|
|
||||||
var sub = string.Join("|", _rules[key].Select(test => test.Length switch
|
|
||||||
{
|
|
||||||
1 => test[0][0] == '"' ? test[0].Trim('"') : MakeRegexExpression(test[0]),
|
|
||||||
_ => string.Join(string.Empty, test.Select(MakeRegexExpression))
|
|
||||||
}));
|
|
||||||
_stack.Pop();
|
|
||||||
return _rules[key].Length > 1 ? $"({sub})" : sub;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
var exp = new Regex($"^{MakeRegexExpression("0")}$");
|
|
||||||
return $"{_messages.Count(m => exp.IsMatch(m))}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
// fix rules 8 and 11
|
|
||||||
_rules["8"] = new[] {new[] {"42"}, new[] {"42", "8"}};
|
|
||||||
_rules["11"] = new[] {new[] {"42", "31"}, new[] {"42", "11", "31"}};
|
|
||||||
var exp = new Regex($"^{MakeRegexExpression("0")}$");
|
|
||||||
return $"{_messages.Count(m => exp.IsMatch(m))}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private string MakeRegexExpression(string key)
|
||||||
|
{
|
||||||
|
if (_stack.Count(s => s == key) > 10) return "x";
|
||||||
|
_stack.Push(key);
|
||||||
|
var sub = string.Join("|", _rules[key].Select(test => test.Length switch
|
||||||
|
{
|
||||||
|
1 => test[0][0] == '"' ? test[0].Trim('"') : MakeRegexExpression(test[0]),
|
||||||
|
_ => string.Join(string.Empty, test.Select(MakeRegexExpression))
|
||||||
|
}));
|
||||||
|
_stack.Pop();
|
||||||
|
return _rules[key].Length > 1 ? $"({sub})" : sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
var exp = new Regex($"^{MakeRegexExpression("0")}$");
|
||||||
|
return $"{_messages.Count(m => exp.IsMatch(m))}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
// fix rules 8 and 11
|
||||||
|
_rules["8"] = new[] { new[] { "42" }, new[] { "42", "8" } };
|
||||||
|
_rules["11"] = new[] { new[] { "42", "31" }, new[] { "42", "11", "31" } };
|
||||||
|
var exp = new Regex($"^{MakeRegexExpression("0")}$");
|
||||||
|
return $"{_messages.Count(m => exp.IsMatch(m))}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
271
aoc2020/Day20.cs
271
aoc2020/Day20.cs
|
@ -1,183 +1,178 @@
|
||||||
using System;
|
namespace aoc2020;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace aoc2020
|
/// <summary>
|
||||||
|
/// Day 20: <see href="https://adventofcode.com/2020/day/20" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day20 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly List<Tile> _allPermutations;
|
||||||
/// Day 20: <see href="https://adventofcode.com/2020/day/20" />
|
private readonly List<Tile> _topLefts;
|
||||||
/// </summary>
|
|
||||||
public sealed class Day20 : Day
|
public Day20() : base(20, "Jurassic Jigsaw")
|
||||||
{
|
{
|
||||||
private readonly List<Tile> _allPermutations;
|
var lines = new List<string>();
|
||||||
private readonly List<Tile> _topLefts;
|
var tiles = new List<Tile>();
|
||||||
|
var currentTileId = 0;
|
||||||
|
|
||||||
public Day20() : base(20, "Jurassic Jigsaw")
|
foreach (var line in Input)
|
||||||
{
|
if (line.StartsWith("Tile "))
|
||||||
var lines = new List<string>();
|
|
||||||
var tiles = new List<Tile>();
|
|
||||||
var currentTileId = 0;
|
|
||||||
|
|
||||||
foreach (var line in Input)
|
|
||||||
if (line.StartsWith("Tile "))
|
|
||||||
{
|
|
||||||
currentTileId = int.Parse(line.Split(' ', ':')[1]);
|
|
||||||
}
|
|
||||||
else if (line == "")
|
|
||||||
{
|
|
||||||
tiles.Add(new(currentTileId, lines.Select(l => l.ToCharArray()).ToArray()));
|
|
||||||
lines.Clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lines.Add(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lines.Any()) tiles.Add(new(currentTileId, lines.Select(l => l.ToCharArray()).ToArray()));
|
|
||||||
|
|
||||||
_allPermutations = tiles.SelectMany(t => t.AllPermutations()).ToList();
|
|
||||||
_topLefts = _allPermutations
|
|
||||||
.Where(t => !_allPermutations.Any(t2 => t.TileId != t2.TileId && t.LeftId == t2.RightId) &&
|
|
||||||
!_allPermutations.Any(t2 => t.TileId != t2.TileId && t.TopId == t2.BottomId))
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int Roughness(Tile arg)
|
|
||||||
{
|
|
||||||
var seaMonster = new[]
|
|
||||||
{
|
{
|
||||||
|
currentTileId = int.Parse(line.Split(' ', ':')[1]);
|
||||||
|
}
|
||||||
|
else if (line == "")
|
||||||
|
{
|
||||||
|
tiles.Add(new(currentTileId, lines.Select(l => l.ToCharArray()).ToArray()));
|
||||||
|
lines.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lines.Add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lines.Any()) tiles.Add(new(currentTileId, lines.Select(l => l.ToCharArray()).ToArray()));
|
||||||
|
|
||||||
|
_allPermutations = tiles.SelectMany(t => t.AllPermutations()).ToList();
|
||||||
|
_topLefts = _allPermutations
|
||||||
|
.Where(t => !_allPermutations.Any(t2 => t.TileId != t2.TileId && t.LeftId == t2.RightId) &&
|
||||||
|
!_allPermutations.Any(t2 => t.TileId != t2.TileId && t.TopId == t2.BottomId))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int Roughness(Tile arg)
|
||||||
|
{
|
||||||
|
var seaMonster = new[]
|
||||||
|
{
|
||||||
" # ",
|
" # ",
|
||||||
"# ## ## ###",
|
"# ## ## ###",
|
||||||
" # # # # # # "
|
" # # # # # # "
|
||||||
}.Select(s => s.ToArray()).ToArray();
|
}.Select(s => s.ToArray()).ToArray();
|
||||||
|
|
||||||
const int seaMonsterWidth = 20;
|
|
||||||
const int seaMonsterHeight = 3;
|
|
||||||
const int seaMonsterTiles = 15;
|
|
||||||
|
|
||||||
var placedTiles = new Dictionary<(int x, int y), Tile>();
|
const int seaMonsterWidth = 20;
|
||||||
bool NotPlaced(Tile tile) => placedTiles!.Values.All(t => t.TileId != tile.TileId);
|
const int seaMonsterHeight = 3;
|
||||||
char Grid(int i, int j) => placedTiles![(i / 8, j / 8)].Pixels[j % 8 + 1][i % 8 + 1];
|
const int seaMonsterTiles = 15;
|
||||||
|
|
||||||
bool HasSeaMonster((int x, int y) location)
|
var placedTiles = new Dictionary<(int x, int y), Tile>();
|
||||||
{
|
bool NotPlaced(Tile tile) => placedTiles!.Values.All(t => t.TileId != tile.TileId);
|
||||||
for (var j = 0; j < seaMonsterHeight; j++)
|
char Grid(int i, int j) => placedTiles![(i / 8, j / 8)].Pixels[j % 8 + 1][i % 8 + 1];
|
||||||
|
|
||||||
|
bool HasSeaMonster((int x, int y) location)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < seaMonsterHeight; j++)
|
||||||
for (var i = 0; i < seaMonsterWidth; i++)
|
for (var i = 0; i < seaMonsterWidth; i++)
|
||||||
{
|
{
|
||||||
if (seaMonster![j][i] == ' ') continue;
|
if (seaMonster![j][i] == ' ') continue;
|
||||||
if (Grid(location.x + i, location.y + j) != '#') return false;
|
if (Grid(location.x + i, location.y + j) != '#') return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
placedTiles[(0, 0)] = arg;
|
placedTiles[(0, 0)] = arg;
|
||||||
int x = 1, y = 0;
|
int x = 1, y = 0;
|
||||||
while (true)
|
while (true)
|
||||||
|
{
|
||||||
|
placedTiles.TryGetValue((x - 1, y), out var left);
|
||||||
|
placedTiles.TryGetValue((x, y - 1), out var top);
|
||||||
|
if (left == null && top == null) break;
|
||||||
|
|
||||||
|
var firstMatch = _allPermutations
|
||||||
|
.Where(t => (left is null || t.LeftId == left.RightId) &&
|
||||||
|
(top is null || t.TopId == top.BottomId))
|
||||||
|
.Where(NotPlaced)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (firstMatch is not null)
|
||||||
{
|
{
|
||||||
placedTiles.TryGetValue((x - 1, y), out var left);
|
placedTiles[(x, y)] = firstMatch;
|
||||||
placedTiles.TryGetValue((x, y - 1), out var top);
|
x++;
|
||||||
if (left == null && top == null) break;
|
|
||||||
|
|
||||||
var firstMatch = _allPermutations
|
|
||||||
.Where(t => (left is null || t.LeftId == left.RightId) &&
|
|
||||||
(top is null || t.TopId == top.BottomId))
|
|
||||||
.Where(NotPlaced)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (firstMatch is not null)
|
|
||||||
{
|
|
||||||
placedTiles[(x, y)] = firstMatch;
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var gridWidth = placedTiles.Keys.Max(t => t.x) + 1;
|
var gridWidth = placedTiles.Keys.Max(t => t.x) + 1;
|
||||||
var gridHeight = placedTiles.Keys.Max(t => t.y) + 1;
|
var gridHeight = placedTiles.Keys.Max(t => t.y) + 1;
|
||||||
|
|
||||||
var seaMonsterCount = Enumerable.Range(0, gridWidth * 8 - seaMonsterWidth)
|
var seaMonsterCount = Enumerable.Range(0, gridWidth * 8 - seaMonsterWidth)
|
||||||
.SelectMany(_ => Enumerable.Range(0, gridHeight * 8 - seaMonsterHeight), (i, j) => (i, j))
|
.SelectMany(_ => Enumerable.Range(0, gridHeight * 8 - seaMonsterHeight), (i, j) => (i, j))
|
||||||
.Count(HasSeaMonster);
|
.Count(HasSeaMonster);
|
||||||
|
|
||||||
if (seaMonsterCount == 0) return 0;
|
|
||||||
|
|
||||||
var roughness = 0;
|
if (seaMonsterCount == 0) return 0;
|
||||||
for (var j = 0; j < gridHeight; j++)
|
|
||||||
|
var roughness = 0;
|
||||||
|
for (var j = 0; j < gridHeight; j++)
|
||||||
for (var i = 0; i < gridWidth; i++)
|
for (var i = 0; i < gridWidth; i++)
|
||||||
if (Grid(x, y) == '#')
|
if (Grid(x, y) == '#')
|
||||||
roughness++;
|
roughness++;
|
||||||
|
|
||||||
return roughness - seaMonsterCount * seaMonsterTiles;
|
return roughness - seaMonsterCount * seaMonsterTiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return $"{_topLefts.Select(t => t.TileId).Distinct().Aggregate(1L, (acc, next) => acc * next)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return $"{_topLefts.Select(Roughness).First(r => r > 0)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private record Tile(int TileId, char[][] Pixels)
|
||||||
|
{
|
||||||
|
private const int Size = 10;
|
||||||
|
internal int TopId => GetId(z => (z, 0));
|
||||||
|
internal int BottomId => GetId(z => (z, Size - 1));
|
||||||
|
internal int LeftId => GetId(z => (0, z));
|
||||||
|
internal int RightId => GetId(z => (Size - 1, z));
|
||||||
|
|
||||||
|
private int GetId(Func<int, (int x, int y)> selector)
|
||||||
|
{
|
||||||
|
return Enumerable.Range(0, Size)
|
||||||
|
.Select(selector)
|
||||||
|
.Select((c, i) => (Pixels[c.x][c.y] == '#' ? 1 : 0) << i)
|
||||||
|
.Aggregate(0, (acc, next) => acc | next);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part1()
|
private Tile RotateClockwise()
|
||||||
{
|
{
|
||||||
return $"{_topLefts.Select(t => t.TileId).Distinct().Aggregate(1L, (acc, next) => acc * next)}";
|
return Transform((x, y, newPixels) => newPixels[x][Size - 1 - y] = Pixels[y][x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Part2()
|
private Tile Flip()
|
||||||
{
|
{
|
||||||
return $"{_topLefts.Select(Roughness).First(r => r > 0)}";
|
return Transform((x, y, newPixels) => newPixels[y][Size - 1 - x] = Pixels[y][x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private record Tile(int TileId, char[][] Pixels)
|
private Tile Transform(Action<int, int, char[][]> transformFunc)
|
||||||
{
|
{
|
||||||
private const int Size = 10;
|
var newPixels = Enumerable.Repeat(false, Size).Select(_ => new char[Size]).ToArray();
|
||||||
internal int TopId => GetId(z => (z, 0));
|
|
||||||
internal int BottomId => GetId(z => (z, Size - 1));
|
|
||||||
internal int LeftId => GetId(z => (0, z));
|
|
||||||
internal int RightId => GetId(z => (Size - 1, z));
|
|
||||||
|
|
||||||
private int GetId(Func<int, (int x, int y)> selector)
|
for (var y = 0; y < Size; y++)
|
||||||
{
|
|
||||||
return Enumerable.Range(0, Size)
|
|
||||||
.Select(selector)
|
|
||||||
.Select((c, i) => (Pixels[c.x][c.y] == '#' ? 1 : 0) << i)
|
|
||||||
.Aggregate(0, (acc, next) => acc | next);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Tile RotateClockwise()
|
|
||||||
{
|
|
||||||
return Transform((x, y, newPixels) => newPixels[x][Size - 1 - y] = Pixels[y][x]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Tile Flip()
|
|
||||||
{
|
|
||||||
return Transform((x, y, newPixels) => newPixels[y][Size - 1 - x] = Pixels[y][x]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Tile Transform(Action<int, int, char[][]> transformFunc)
|
|
||||||
{
|
|
||||||
var newPixels = Enumerable.Repeat(false, Size).Select(_ => new char[Size]).ToArray();
|
|
||||||
|
|
||||||
for (var y = 0; y < Size; y++)
|
|
||||||
for (var x = 0; x < Size; x++)
|
for (var x = 0; x < Size; x++)
|
||||||
transformFunc(x, y, newPixels);
|
transformFunc(x, y, newPixels);
|
||||||
|
|
||||||
return new(TileId, newPixels);
|
return new(TileId, newPixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal IEnumerable<Tile> AllPermutations()
|
internal IEnumerable<Tile> AllPermutations()
|
||||||
|
{
|
||||||
|
var tile = this;
|
||||||
|
for (var i = 1; i <= 8; i++)
|
||||||
{
|
{
|
||||||
var tile = this;
|
yield return tile;
|
||||||
for (var i = 1; i <= 8; i++)
|
if (i == 4) tile = Flip();
|
||||||
{
|
else if (i == 8) yield break;
|
||||||
yield return tile;
|
tile = tile.RotateClockwise();
|
||||||
if (i == 4) tile = Flip();
|
|
||||||
else if (i == 8) yield break;
|
|
||||||
tile = tile.RotateClockwise();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Format()
|
|
||||||
{
|
|
||||||
return $"Tile {TileId}:\n{string.Join("\n", Pixels.Select(p => new string(p)))}";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Format()
|
||||||
|
{
|
||||||
|
return $"Tile {TileId}:\n{string.Join("\n", Pixels.Select(p => new string(p)))}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
namespace aoc2020
|
namespace aoc2020;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Day 21: <see href="https://adventofcode.com/2020/day/21" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day21 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
public Day21() : base(21, "Allergen Assessment")
|
||||||
/// Day 21: <see href="https://adventofcode.com/2020/day/21" />
|
|
||||||
/// </summary>
|
|
||||||
public sealed class Day21 : Day
|
|
||||||
{
|
{
|
||||||
public Day21() : base(21, "Allergen Assessment")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
namespace aoc2020
|
namespace aoc2020;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Day 22: <see href="https://adventofcode.com/2020/day/22" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day22 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
public Day22() : base(22, "Crab Combat")
|
||||||
/// Day 22: <see href="https://adventofcode.com/2020/day/22" />
|
|
||||||
/// </summary>
|
|
||||||
public sealed class Day22 : Day
|
|
||||||
{
|
{
|
||||||
public Day22() : base(22, "Crab Combat")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
namespace aoc2020
|
namespace aoc2020;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Day 23: <see href="https://adventofcode.com/2020/day/23" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day23 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
public Day23() : base(23, "Crab Cups")
|
||||||
/// Day 23: <see href="https://adventofcode.com/2020/day/23" />
|
|
||||||
/// </summary>
|
|
||||||
public sealed class Day23 : Day
|
|
||||||
{
|
{
|
||||||
public Day23() : base(23, "Crab Cups")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
namespace aoc2020
|
namespace aoc2020;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Day 24: <see href="https://adventofcode.com/2020/day/24" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day24 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
public Day24() : base(24, "Lobby Layout")
|
||||||
/// Day 24: <see href="https://adventofcode.com/2020/day/24" />
|
|
||||||
/// </summary>
|
|
||||||
public sealed class Day24 : Day
|
|
||||||
{
|
{
|
||||||
public Day24() : base(24, "Lobby Layout")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
namespace aoc2020
|
namespace aoc2020;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Day 25: <see href="https://adventofcode.com/2020/day/25" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Day25 : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
public Day25() : base(25, "Combo Breaker")
|
||||||
/// Day 25: <see href="https://adventofcode.com/2020/day/25" />
|
|
||||||
/// </summary>
|
|
||||||
public sealed class Day25 : Day
|
|
||||||
{
|
{
|
||||||
public Day25() : base(25, "Combo Breaker")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
namespace aoc2020
|
namespace aoc2020;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Day X: <see href="https://adventofcode.com/2020/day/X" />
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DayX : Day
|
||||||
{
|
{
|
||||||
/// <summary>
|
public DayX() : base(X, "")
|
||||||
/// Day X: <see href="https://adventofcode.com/2020/day/X" />
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DayX : Day
|
|
||||||
{
|
{
|
||||||
public DayX() : base(X, "")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part1()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Part2()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override string Part1()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Part2()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,28 +1,26 @@
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace aoc2020
|
namespace aoc2020;
|
||||||
{
|
|
||||||
public static class Extensions
|
|
||||||
{
|
|
||||||
/// <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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Contains(this Range range, int i)
|
public static class Extensions
|
||||||
{
|
{
|
||||||
return i >= range.Start.Value && i <= range.End.Value;
|
/// <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;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static bool Contains(this Range range, int i)
|
||||||
|
{
|
||||||
|
return i >= range.Start.Value && i <= range.End.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,30 +1,27 @@
|
||||||
using System;
|
using System.Reflection;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace aoc2020
|
namespace aoc2020;
|
||||||
|
|
||||||
|
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))
|
||||||
var days = Assembly.GetExecutingAssembly().GetTypes()
|
.Select(t => Activator.CreateInstance(t) as Day)
|
||||||
.Where(t => t.BaseType == typeof(Day))
|
.OrderBy(d => d?.DayNumber);
|
||||||
.Select(t => (Day) Activator.CreateInstance(t))
|
|
||||||
.OrderBy(d => d.DayNumber);
|
|
||||||
|
|
||||||
if (args.Length == 1 && int.TryParse(args[0], out var dayNum))
|
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)
|
if (day != null)
|
||||||
day.AllParts();
|
day.AllParts();
|
||||||
else
|
|
||||||
Console.WriteLine($"Day {dayNum} invalid or not yet implemented");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
Console.WriteLine($"Day {dayNum} invalid or not yet implemented");
|
||||||
foreach (var d in days) d.AllParts();
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
foreach (var d in days) d?.AllParts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<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>
|
||||||
|
|
Loading…
Reference in New Issue