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:
|
||||
- name: run
|
||||
image: mcr.microsoft.com/dotnet/sdk:latest
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0
|
||||
commands:
|
||||
- dotnet test
|
||||
- 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
|
||||
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;
|
||||
|
||||
namespace aoc2020.test
|
||||
namespace aoc2020.test;
|
||||
|
||||
[TestClass]
|
||||
public class DayTests
|
||||
{
|
||||
[TestClass]
|
||||
public class DayTests
|
||||
[DataTestMethod]
|
||||
[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]
|
||||
[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)
|
||||
{
|
||||
// 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");
|
||||
// create day instance
|
||||
var s = Stopwatch.StartNew();
|
||||
var day = Activator.CreateInstance(dayType) as Day;
|
||||
s.Stop();
|
||||
Assert.IsNotNull(day, "failed to create day object");
|
||||
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in constructor");
|
||||
|
||||
// part 1
|
||||
s.Reset();
|
||||
s.Start();
|
||||
var part1Actual = day.Part1();
|
||||
s.Stop();
|
||||
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in part1");
|
||||
Assert.AreEqual(part1, part1Actual, $"Incorrect answer for Day {day.DayNumber} Part1");
|
||||
// part 1
|
||||
s.Reset();
|
||||
s.Start();
|
||||
var part1Actual = day.Part1();
|
||||
s.Stop();
|
||||
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in part1");
|
||||
Assert.AreEqual(part1, part1Actual, $"Incorrect answer for Day {day.DayNumber} Part1");
|
||||
|
||||
// part 2
|
||||
s.Reset();
|
||||
s.Start();
|
||||
var part2Actual = day.Part2();
|
||||
s.Stop();
|
||||
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in part2");
|
||||
Assert.AreEqual(part2, part2Actual, $"Incorrect answer for Day {day.DayNumber} Part2");
|
||||
}
|
||||
// part 2
|
||||
s.Reset();
|
||||
s.Start();
|
||||
var part2Actual = day.Part2();
|
||||
s.Stop();
|
||||
Console.WriteLine($"{s.ScaleMilliseconds()}ms elapsed in 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>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,48 +1,44 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +1,31 @@
|
|||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 1: <see href="https://adventofcode.com/2020/day/1" />
|
||||
/// </summary>
|
||||
public sealed class Day01 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 1: <see href="https://adventofcode.com/2020/day/1" />
|
||||
/// </summary>
|
||||
public sealed class Day01 : Day
|
||||
private readonly ImmutableHashSet<int> _entries;
|
||||
|
||||
public Day01() : base(1, "Report Repair")
|
||||
{
|
||||
private readonly ImmutableHashSet<int> _entries;
|
||||
|
||||
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 "";
|
||||
}
|
||||
_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 "";
|
||||
}
|
||||
}
|
||||
|
|
100
aoc2020/Day02.cs
100
aoc2020/Day02.cs
|
@ -1,56 +1,52 @@
|
|||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 2: <see href="https://adventofcode.com/2020/day/1" />
|
||||
/// </summary>
|
||||
public sealed class Day02 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 2: <see href="https://adventofcode.com/2020/day/1" />
|
||||
/// </summary>
|
||||
public sealed class Day02 : Day
|
||||
private readonly ImmutableList<Password> _passwords;
|
||||
|
||||
public Day02() : base(2, "Password Philosophy")
|
||||
{
|
||||
private readonly ImmutableList<Password> _passwords;
|
||||
|
||||
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; }
|
||||
}
|
||||
_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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
/// Day 3: <see href="https://adventofcode.com/2020/day/3" />
|
||||
/// </summary>
|
||||
public sealed class Day03 : Day
|
||||
private readonly string[] _grid;
|
||||
private readonly int _width;
|
||||
|
||||
public Day03() : base(3, "Toboggan Trajectory")
|
||||
{
|
||||
private readonly string[] _grid;
|
||||
private readonly int _width;
|
||||
|
||||
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();
|
||||
}
|
||||
_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.First, s.Second))
|
||||
.Aggregate((acc, i) => acc * i)
|
||||
.ToString();
|
||||
}
|
||||
}
|
||||
|
|
330
aoc2020/Day04.cs
330
aoc2020/Day04.cs
|
@ -1,188 +1,182 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 4: <see href="https://adventofcode.com/2020/day/4" />
|
||||
/// </summary>
|
||||
public sealed class Day04 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 4: <see href="https://adventofcode.com/2020/day/4" />
|
||||
/// </summary>
|
||||
public sealed class Day04 : Day
|
||||
private readonly List<Passport> _passports;
|
||||
|
||||
public Day04() : base(4, "Passport Processing")
|
||||
{
|
||||
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>();
|
||||
|
||||
var a = new List<string>();
|
||||
foreach (var line in Input)
|
||||
if (line == "")
|
||||
{
|
||||
if (line == "")
|
||||
{
|
||||
_passports.Add(Passport.Parse(a));
|
||||
a.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
a.Add(line);
|
||||
_passports.Add(Passport.Parse(a));
|
||||
a.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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()
|
||||
// birth year
|
||||
if (int.TryParse(_byr, out var byr))
|
||||
{
|
||||
if (!IsValid) return false;
|
||||
|
||||
// birth year
|
||||
if (int.TryParse(_byr, out var byr))
|
||||
{
|
||||
if (byr < 1920 || byr > 2002)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (byr < 1920 || byr > 2002)
|
||||
return false;
|
||||
}
|
||||
|
||||
// issuance year
|
||||
if (int.TryParse(_iyr, out var iyr))
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Passport Parse(IEnumerable<string> list)
|
||||
// issuance year
|
||||
if (int.TryParse(_iyr, out var iyr))
|
||||
{
|
||||
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;
|
||||
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[..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;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 5: <see href="https://adventofcode.com/2020/day/5" />
|
||||
/// </summary>
|
||||
public sealed class Day05 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 5: <see href="https://adventofcode.com/2020/day/5" />
|
||||
/// </summary>
|
||||
public sealed class Day05 : Day
|
||||
private readonly ImmutableHashSet<int> _ids;
|
||||
|
||||
public Day05() : base(5, "Binary Boarding")
|
||||
{
|
||||
private readonly ImmutableHashSet<int> _ids;
|
||||
|
||||
public Day05() : base(5, "Binary Boarding")
|
||||
{
|
||||
_ids = Input
|
||||
.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()}";
|
||||
}
|
||||
_ids = Input
|
||||
.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()}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,54 +1,50 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 6: <see href="https://adventofcode.com/2020/day/6" />
|
||||
/// </summary>
|
||||
public sealed class Day06 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 6: <see href="https://adventofcode.com/2020/day/6" />
|
||||
/// </summary>
|
||||
public sealed class Day06 : Day
|
||||
private readonly int _countPart1;
|
||||
private readonly int _countPart2;
|
||||
|
||||
public Day06() : base(6, "Custom Customs")
|
||||
{
|
||||
private readonly int _countPart1;
|
||||
private readonly int _countPart2;
|
||||
|
||||
public Day06() : base(6, "Custom Customs")
|
||||
var alphabet = "abcedfghijklmnopqrstuvwxyz".ToCharArray();
|
||||
_countPart1 = 0;
|
||||
_countPart2 = 0;
|
||||
var s = new HashSet<char>();
|
||||
var lines = new HashSet<string>();
|
||||
foreach (var line in Input)
|
||||
{
|
||||
var alphabet = "abcedfghijklmnopqrstuvwxyz".ToCharArray();
|
||||
_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())
|
||||
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);
|
||||
}
|
||||
|
||||
public override string Part1()
|
||||
if (s.Any())
|
||||
{
|
||||
return $"{_countPart1}";
|
||||
}
|
||||
|
||||
public override string Part2()
|
||||
{
|
||||
return $"{_countPart2}";
|
||||
_countPart1 += s.Count;
|
||||
_countPart2 += alphabet.Count(a => lines.All(l => l.Contains(a)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 7: <see href="https://adventofcode.com/2020/day/7" />
|
||||
/// </summary>
|
||||
public sealed class Day07 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 7: <see href="https://adventofcode.com/2020/day/7" />
|
||||
/// </summary>
|
||||
public sealed class Day07 : Day
|
||||
private readonly Dictionary<string, IEnumerable<(int, string)?>> _rules;
|
||||
|
||||
public Day07() : base(7, "Handy Haversacks")
|
||||
{
|
||||
private readonly Dictionary<string, IEnumerable<(int, string)?>> _rules;
|
||||
|
||||
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)
|
||||
_rules = Input.Select(rule =>
|
||||
{
|
||||
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}";
|
||||
}
|
||||
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();
|
||||
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>
|
||||
/// Day 8: <see href="https://adventofcode.com/2020/day/8" />
|
||||
/// </summary>
|
||||
public sealed class Day08 : Day
|
||||
private readonly (string instruction, int value)[] _instructions;
|
||||
private int _accumulator;
|
||||
private int _currentInstruction;
|
||||
|
||||
public Day08() : base(8, "Handheld Halting")
|
||||
{
|
||||
private readonly (string instruction, int value)[] _instructions;
|
||||
private int _accumulator;
|
||||
private int _currentInstruction;
|
||||
_instructions = Input.Select(ParseLine).ToArray();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
switch (_instructions[_currentInstruction].instruction)
|
||||
{
|
||||
visited[_currentInstruction] = true;
|
||||
|
||||
switch (_instructions[_currentInstruction].instruction)
|
||||
{
|
||||
case "acc":
|
||||
_accumulator += _instructions[_currentInstruction].value;
|
||||
break;
|
||||
case "jmp":
|
||||
_currentInstruction += _instructions[_currentInstruction].value;
|
||||
continue;
|
||||
}
|
||||
|
||||
_currentInstruction++;
|
||||
case "acc":
|
||||
_accumulator += _instructions[_currentInstruction].value;
|
||||
break;
|
||||
case "jmp":
|
||||
_currentInstruction += _instructions[_currentInstruction].value;
|
||||
continue;
|
||||
}
|
||||
|
||||
return _currentInstruction == _instructions.Length;
|
||||
_currentInstruction++;
|
||||
}
|
||||
|
||||
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}";
|
||||
}
|
||||
return _currentInstruction == _instructions.Length;
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
/// Day 9: <see href="https://adventofcode.com/2020/day/9" />
|
||||
/// </summary>
|
||||
public sealed class Day09 : Day
|
||||
private readonly long[] _list;
|
||||
private long _part1;
|
||||
|
||||
public Day09() : base(9, "Encoding Error")
|
||||
{
|
||||
private readonly long[] _list;
|
||||
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 "";
|
||||
}
|
||||
_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 "";
|
||||
}
|
||||
}
|
||||
|
|
106
aoc2020/Day10.cs
106
aoc2020/Day10.cs
|
@ -1,59 +1,55 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 10: <see href="https://adventofcode.com/2020/day/10" />
|
||||
/// </summary>
|
||||
public sealed class Day10 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 10: <see href="https://adventofcode.com/2020/day/10" />
|
||||
/// </summary>
|
||||
public sealed class Day10 : Day
|
||||
private readonly int[] _adapters;
|
||||
private readonly long[] _memo;
|
||||
|
||||
public Day10() : base(10, "Adapter Array")
|
||||
{
|
||||
private readonly int[] _adapters;
|
||||
private readonly long[] _memo;
|
||||
|
||||
public Day10() : base(10, "Adapter Array")
|
||||
{
|
||||
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)}";
|
||||
}
|
||||
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)}";
|
||||
}
|
||||
}
|
||||
|
|
215
aoc2020/Day11.cs
215
aoc2020/Day11.cs
|
@ -1,91 +1,87 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 11: <see href="https://adventofcode.com/2020/day/11" />
|
||||
/// </summary>
|
||||
public sealed class Day11 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 11: <see href="https://adventofcode.com/2020/day/11" />
|
||||
/// </summary>
|
||||
public sealed class Day11 : Day
|
||||
public Day11() : base(11, "Seating System")
|
||||
{
|
||||
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);
|
||||
|
||||
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}";
|
||||
Console.Clear();
|
||||
foreach (var line in Grid)
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
|
||||
public override string Part2()
|
||||
public LifeGame StepPart1()
|
||||
{
|
||||
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 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++)
|
||||
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++)
|
||||
next.Grid[y][x] = Grid[y][x] switch
|
||||
{
|
||||
|
@ -94,29 +90,29 @@ namespace aoc2020
|
|||
_ => Grid[y][x]
|
||||
};
|
||||
|
||||
// next.PrintBoard();
|
||||
return next;
|
||||
}
|
||||
// next.PrintBoard();
|
||||
return next;
|
||||
}
|
||||
|
||||
private char At(int y, int x)
|
||||
{
|
||||
return x < 0 || y < 0 || x >= _w || y >= _h ? '.' : Grid[y][x];
|
||||
}
|
||||
private char At(int y, int 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 + 0, x - 1), At(y + 0, x + 1),
|
||||
At(y + 1, x - 1), At(y + 1, x + 0), At(y + 1, x + 1)
|
||||
}.Count(c => c == '#');
|
||||
}
|
||||
}
|
||||
|
||||
public LifeGame StepPart2()
|
||||
{
|
||||
var next = new LifeGame {_h = _h, _w = _w, Grid = Grid.Select(s => s.ToArray()).ToArray()};
|
||||
for (var y = 0; y < _h; y++)
|
||||
public LifeGame StepPart2()
|
||||
{
|
||||
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++)
|
||||
next.Grid[y][x] = Grid[y][x] switch
|
||||
{
|
||||
|
@ -125,33 +121,32 @@ namespace aoc2020
|
|||
_ => Grid[y][x]
|
||||
};
|
||||
|
||||
// next.PrintBoard();
|
||||
return next;
|
||||
}
|
||||
// next.PrintBoard();
|
||||
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, +0, -1), TraceRay(y, x, +0, +1),
|
||||
TraceRay(y, x, +1, -1), TraceRay(y, x, +1, +0), TraceRay(y, x, +1, +1)
|
||||
}.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;
|
||||
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>
|
||||
/// Day 12: <see href="https://adventofcode.com/2020/day/12" />
|
||||
/// </summary>
|
||||
public sealed class Day12 : Day
|
||||
public Day12() : base(12, "Rain Risk")
|
||||
{
|
||||
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>
|
||||
/// Day 13: <see href="https://adventofcode.com/2020/day/13" />
|
||||
/// </summary>
|
||||
public sealed class Day13 : Day
|
||||
private readonly long[] _buses;
|
||||
private readonly long _earliest;
|
||||
private readonly string[] _fullSchedule;
|
||||
|
||||
public Day13() : base(13, "Shuttle Search")
|
||||
{
|
||||
private readonly long[] _buses;
|
||||
private readonly long _earliest;
|
||||
private readonly string[] _fullSchedule;
|
||||
_earliest = long.Parse(Input.First());
|
||||
_fullSchedule = Input.Last().Split(',');
|
||||
_buses = _fullSchedule.Where(c => c != "x").Select(long.Parse).ToArray();
|
||||
}
|
||||
|
||||
public Day13() : base(13, "Shuttle Search")
|
||||
{
|
||||
_earliest = long.Parse(Input.First());
|
||||
_fullSchedule = Input.Last().Split(',');
|
||||
_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)
|
||||
public override string Part1()
|
||||
{
|
||||
for (var i = _earliest; ; i++)
|
||||
if (_buses.Any(b => i % b == 0))
|
||||
{
|
||||
if (id != "x")
|
||||
{
|
||||
var increment = long.Parse(id);
|
||||
while (((result += multiplier) + i) % increment != 0)
|
||||
{
|
||||
}
|
||||
var bus = _buses.First(b => i % b == 0);
|
||||
return $"{bus * (i - _earliest)}";
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 14: <see href="https://adventofcode.com/2020/day/14" />
|
||||
/// </summary>
|
||||
public sealed class Day14 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 14: <see href="https://adventofcode.com/2020/day/14" />
|
||||
/// </summary>
|
||||
public sealed class Day14 : Day
|
||||
public Day14() : base(14, "Docking Data")
|
||||
{
|
||||
public Day14() : base(14, "Docking Data")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public override string Part1()
|
||||
{
|
||||
var writes = new Dictionary<ulong, ulong>();
|
||||
ulong mask = 0, bits = 0;
|
||||
public override string Part1()
|
||||
{
|
||||
var writes = new Dictionary<ulong, ulong>();
|
||||
ulong mask = 0, bits = 0;
|
||||
|
||||
foreach (var line in Input)
|
||||
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)
|
||||
foreach (var line in Input)
|
||||
if (line.StartsWith("mask = "))
|
||||
{
|
||||
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 str = line.Split("mask = ", 2)[1];
|
||||
mask = bits = 0;
|
||||
for (var i = 35; i >= 0; --i)
|
||||
switch (str[35 - i])
|
||||
{
|
||||
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;
|
||||
case 'X':
|
||||
mask |= 1UL << i;
|
||||
break;
|
||||
case '1':
|
||||
bits |= 1UL << i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
memory[addr] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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>
|
||||
/// Day 15: <see href="https://adventofcode.com/2020/day/15" />
|
||||
/// </summary>
|
||||
public sealed class Day15 : Day
|
||||
private readonly int[] _turns;
|
||||
private int _current;
|
||||
private int _i;
|
||||
|
||||
public Day15() : base(15, "Rambunctious Recitation")
|
||||
{
|
||||
private readonly int[] _turns;
|
||||
private int _current;
|
||||
private int _i;
|
||||
var initial = Input.First().Split(',').Select(int.Parse).ToArray();
|
||||
_turns = new int[30_000_000];
|
||||
|
||||
public Day15() : base(15, "Rambunctious Recitation")
|
||||
{
|
||||
var initial = Input.First().Split(',').Select(int.Parse).ToArray();
|
||||
_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}";
|
||||
}
|
||||
// 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}";
|
||||
}
|
||||
}
|
||||
|
|
155
aoc2020/Day16.cs
155
aoc2020/Day16.cs
|
@ -1,91 +1,86 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 16: <see href="https://adventofcode.com/2020/day/16" />
|
||||
/// </summary>
|
||||
public sealed class Day16 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 16: <see href="https://adventofcode.com/2020/day/16" />
|
||||
/// </summary>
|
||||
public sealed class Day16 : Day
|
||||
private readonly Dictionary<string, List<Range>> _rules;
|
||||
private readonly List<List<int>> _tickets;
|
||||
|
||||
public Day16() : base(16, "Ticket Translation")
|
||||
{
|
||||
private readonly Dictionary<string, List<Range>> _rules;
|
||||
private readonly List<List<int>> _tickets;
|
||||
_tickets = new();
|
||||
_rules = new();
|
||||
|
||||
public Day16() : base(16, "Ticket Translation")
|
||||
foreach (var line in Input)
|
||||
{
|
||||
_tickets = new List<List<int>>();
|
||||
_rules = new Dictionary<string, List<Range>>();
|
||||
|
||||
foreach (var line in Input)
|
||||
var spl = line.Split(": ", 2, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||
if (spl.Length == 2)
|
||||
{
|
||||
var spl = line.Split(": ", 2, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||
if (spl.Length == 2)
|
||||
var rule = spl[1].Split(" or ").Select(s =>
|
||||
{
|
||||
var rule = spl[1].Split(" or ").Select(s =>
|
||||
{
|
||||
var r = s.Split('-').Select(int.Parse).ToList();
|
||||
return new Range(r[0], r[1]);
|
||||
}).ToList();
|
||||
var r = s.Split('-').Select(int.Parse).ToList();
|
||||
return new Range(r[0], r[1]);
|
||||
}).ToList();
|
||||
|
||||
_rules.Add(spl[0], rule);
|
||||
}
|
||||
else
|
||||
{
|
||||
spl = line.Split(',');
|
||||
if (spl.Length > 1)
|
||||
_tickets.Add(spl.Select(int.Parse).ToList());
|
||||
}
|
||||
_rules.Add(spl[0], rule);
|
||||
}
|
||||
else
|
||||
{
|
||||
spl = line.Split(',');
|
||||
if (spl.Length > 1)
|
||||
_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;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 17: <see href="https://adventofcode.com/2020/day/17" />
|
||||
/// </summary>
|
||||
public sealed class Day17 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 17: <see href="https://adventofcode.com/2020/day/17" />
|
||||
/// </summary>
|
||||
public sealed class Day17 : Day
|
||||
private readonly Dictionary<(int x, int y, int z), char> _plane;
|
||||
private readonly Dictionary<(int x, int y, int z, int w), char> _plane4;
|
||||
|
||||
|
||||
public Day17() : base(17, "Conway Cubes")
|
||||
{
|
||||
private readonly Dictionary<(int x, int y, int z), char> _plane;
|
||||
private readonly Dictionary<(int x, int y, int z, int w), char> _plane4;
|
||||
_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();
|
||||
|
||||
|
||||
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 x = 0; x < 32; x++)
|
||||
for (var y = 0; y < 32; y++)
|
||||
for (var z = 0; z < 32; z++)
|
||||
_plane[(x, y, z)] = '.';
|
||||
for (var z = 0; z < 32; 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 z = 0; z < 32; z++)
|
||||
for (var w = 0; w < 32; w++)
|
||||
_plane4[(x, y, z, w)] = '.';
|
||||
for (var z = 0; z < 32; z++)
|
||||
for (var w = 0; w < 32; 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++)
|
||||
_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++)
|
||||
_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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 18: <see href="https://adventofcode.com/2020/day/18" />
|
||||
/// </summary>
|
||||
public sealed class Day18 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 18: <see href="https://adventofcode.com/2020/day/18" />
|
||||
/// </summary>
|
||||
public sealed class Day18 : Day
|
||||
private readonly List<string> _expressions;
|
||||
|
||||
public Day18() : base(18, "Operation Order")
|
||||
{
|
||||
private readonly List<string> _expressions;
|
||||
|
||||
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}))}";
|
||||
}
|
||||
_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 }))}";
|
||||
}
|
||||
}
|
||||
|
|
100
aoc2020/Day19.cs
100
aoc2020/Day19.cs
|
@ -1,57 +1,51 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 19: <see href="https://adventofcode.com/2020/day/19" />
|
||||
/// </summary>
|
||||
public sealed class Day19 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 19: <see href="https://adventofcode.com/2020/day/19" />
|
||||
/// </summary>
|
||||
public sealed class Day19 : Day
|
||||
private readonly string[] _messages;
|
||||
private readonly Dictionary<string, string[][]> _rules;
|
||||
private readonly Stack<string> _stack;
|
||||
|
||||
public Day19() : base(19, "Monster Messages")
|
||||
{
|
||||
private readonly string[] _messages;
|
||||
private readonly Dictionary<string, string[][]> _rules;
|
||||
private readonly Stack<string> _stack;
|
||||
|
||||
public Day19() : base(19, "Monster Messages")
|
||||
{
|
||||
_rules = Input.TakeWhile(l => !string.IsNullOrWhiteSpace(l))
|
||||
.Select(l => l.Split(':'))
|
||||
.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))}";
|
||||
}
|
||||
_rules = Input.TakeWhile(l => !string.IsNullOrWhiteSpace(l))
|
||||
.Select(l => l.Split(':'))
|
||||
.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))}";
|
||||
}
|
||||
}
|
||||
|
|
271
aoc2020/Day20.cs
271
aoc2020/Day20.cs
|
@ -1,183 +1,178 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
namespace aoc2020;
|
||||
|
||||
namespace aoc2020
|
||||
/// <summary>
|
||||
/// Day 20: <see href="https://adventofcode.com/2020/day/20" />
|
||||
/// </summary>
|
||||
public sealed class Day20 : Day
|
||||
{
|
||||
/// <summary>
|
||||
/// Day 20: <see href="https://adventofcode.com/2020/day/20" />
|
||||
/// </summary>
|
||||
public sealed class Day20 : Day
|
||||
private readonly List<Tile> _allPermutations;
|
||||
private readonly List<Tile> _topLefts;
|
||||
|
||||
public Day20() : base(20, "Jurassic Jigsaw")
|
||||
{
|
||||
private readonly List<Tile> _allPermutations;
|
||||
private readonly List<Tile> _topLefts;
|
||||
var lines = new List<string>();
|
||||
var tiles = new List<Tile>();
|
||||
var currentTileId = 0;
|
||||
|
||||
public Day20() : base(20, "Jurassic Jigsaw")
|
||||
{
|
||||
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[]
|
||||
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[]
|
||||
{
|
||||
" # ",
|
||||
"# ## ## ###",
|
||||
" # # # # # # "
|
||||
}.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>();
|
||||
bool NotPlaced(Tile tile) => placedTiles!.Values.All(t => t.TileId != tile.TileId);
|
||||
char Grid(int i, int j) => placedTiles![(i / 8, j / 8)].Pixels[j % 8 + 1][i % 8 + 1];
|
||||
const int seaMonsterWidth = 20;
|
||||
const int seaMonsterHeight = 3;
|
||||
const int seaMonsterTiles = 15;
|
||||
|
||||
bool HasSeaMonster((int x, int y) location)
|
||||
{
|
||||
for (var j = 0; j < seaMonsterHeight; j++)
|
||||
var placedTiles = new Dictionary<(int x, int y), Tile>();
|
||||
bool NotPlaced(Tile tile) => placedTiles!.Values.All(t => t.TileId != tile.TileId);
|
||||
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++)
|
||||
{
|
||||
if (seaMonster![j][i] == ' ') continue;
|
||||
if (Grid(location.x + i, location.y + j) != '#') return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
placedTiles[(0, 0)] = arg;
|
||||
int x = 1, y = 0;
|
||||
while (true)
|
||||
placedTiles[(0, 0)] = arg;
|
||||
int x = 1, y = 0;
|
||||
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.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[(x, y)] = firstMatch;
|
||||
x++;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
placedTiles[(x, y)] = firstMatch;
|
||||
x++;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
var gridWidth = placedTiles.Keys.Max(t => t.x) + 1;
|
||||
var gridHeight = placedTiles.Keys.Max(t => t.y) + 1;
|
||||
var gridWidth = placedTiles.Keys.Max(t => t.x) + 1;
|
||||
var gridHeight = placedTiles.Keys.Max(t => t.y) + 1;
|
||||
|
||||
var seaMonsterCount = Enumerable.Range(0, gridWidth * 8 - seaMonsterWidth)
|
||||
.SelectMany(_ => Enumerable.Range(0, gridHeight * 8 - seaMonsterHeight), (i, j) => (i, j))
|
||||
.Count(HasSeaMonster);
|
||||
|
||||
if (seaMonsterCount == 0) return 0;
|
||||
var seaMonsterCount = Enumerable.Range(0, gridWidth * 8 - seaMonsterWidth)
|
||||
.SelectMany(_ => Enumerable.Range(0, gridHeight * 8 - seaMonsterHeight), (i, j) => (i, j))
|
||||
.Count(HasSeaMonster);
|
||||
|
||||
var roughness = 0;
|
||||
for (var j = 0; j < gridHeight; j++)
|
||||
if (seaMonsterCount == 0) return 0;
|
||||
|
||||
var roughness = 0;
|
||||
for (var j = 0; j < gridHeight; j++)
|
||||
for (var i = 0; i < gridWidth; i++)
|
||||
if (Grid(x, y) == '#')
|
||||
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;
|
||||
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));
|
||||
var newPixels = Enumerable.Repeat(false, Size).Select(_ => new char[Size]).ToArray();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 y = 0; y < Size; y++)
|
||||
for (var x = 0; x < Size; x++)
|
||||
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;
|
||||
for (var i = 1; i <= 8; i++)
|
||||
{
|
||||
yield return tile;
|
||||
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)))}";
|
||||
yield return tile;
|
||||
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)))}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
/// Day 21: <see href="https://adventofcode.com/2020/day/21" />
|
||||
/// </summary>
|
||||
public sealed class Day21 : Day
|
||||
public Day21() : base(21, "Allergen Assessment")
|
||||
{
|
||||
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>
|
||||
/// Day 22: <see href="https://adventofcode.com/2020/day/22" />
|
||||
/// </summary>
|
||||
public sealed class Day22 : Day
|
||||
public Day22() : base(22, "Crab Combat")
|
||||
{
|
||||
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>
|
||||
/// Day 23: <see href="https://adventofcode.com/2020/day/23" />
|
||||
/// </summary>
|
||||
public sealed class Day23 : Day
|
||||
public Day23() : base(23, "Crab Cups")
|
||||
{
|
||||
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>
|
||||
/// Day 24: <see href="https://adventofcode.com/2020/day/24" />
|
||||
/// </summary>
|
||||
public sealed class Day24 : Day
|
||||
public Day24() : base(24, "Lobby Layout")
|
||||
{
|
||||
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>
|
||||
/// Day 25: <see href="https://adventofcode.com/2020/day/25" />
|
||||
/// </summary>
|
||||
public sealed class Day25 : Day
|
||||
public Day25() : base(25, "Combo Breaker")
|
||||
{
|
||||
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>
|
||||
/// Day X: <see href="https://adventofcode.com/2020/day/X" />
|
||||
/// </summary>
|
||||
public sealed class DayX : Day
|
||||
public DayX() : base(X, "")
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
namespace aoc2020;
|
||||
|
||||
public static bool Contains(this Range range, int i)
|
||||
{
|
||||
return i >= range.Start.Value && i <= range.End.Value;
|
||||
}
|
||||
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)
|
||||
{
|
||||
return i >= range.Start.Value && i <= range.End.Value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,27 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
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))
|
||||
.Select(t => (Day) Activator.CreateInstance(t))
|
||||
.OrderBy(d => d.DayNumber);
|
||||
var days = Assembly.GetExecutingAssembly().GetTypes()
|
||||
.Where(t => t.BaseType == typeof(Day))
|
||||
.Select(t => Activator.CreateInstance(t) as Day)
|
||||
.OrderBy(d => d?.DayNumber);
|
||||
|
||||
if (args.Length == 1 && int.TryParse(args[0], out var dayNum))
|
||||
{
|
||||
var day = days.FirstOrDefault(d => d.DayNumber == dayNum);
|
||||
if (day != null)
|
||||
day.AllParts();
|
||||
else
|
||||
Console.WriteLine($"Day {dayNum} invalid or not yet implemented");
|
||||
}
|
||||
if (args.Length == 1 && int.TryParse(args[0], out var dayNum))
|
||||
{
|
||||
var day = days.FirstOrDefault(d => d?.DayNumber == dayNum);
|
||||
if (day != null)
|
||||
day.AllParts();
|
||||
else
|
||||
{
|
||||
foreach (var d in days) d.AllParts();
|
||||
}
|
||||
Console.WriteLine($"Day {dayNum} invalid or not yet implemented");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var d in days) d?.AllParts();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -11,4 +13,11 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Collections.Generic"/>
|
||||
<Using Include="System.Collections.Immutable"/>
|
||||
<Using Include="System.Text"/>
|
||||
<Using Include="System.Text.RegularExpressions"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
Loading…
Reference in New Issue