Files
2021/src/14.cs
Parnic 41f0d167e4 Report more accurate timings
The string colorizer is slow (but apparently only the first time it runs, for some reason?), printing can be slow, who knows what else the framework is doing, etc., so manually inserting Stop()s exactly where we want the timings to stop is the most reliable way to handle this. I like the elegance of the disposable solution, but my goal here is to measure the actual algorithm, not anything else.

A slightly restructuring would make it so I don't have to do this; if main.cs was receiving a string from Part1 and Part2 instead of having each day individually print its own results, we could scope timings to exclude any console writing. But whatever.

I also went ahead and made 17 only run once since I was using the same result to answer part 1 and 2. I've since discovered that part 1 is far simpler and can be found without solving the entire problem space, but whatever.
2021-12-17 10:57:33 -06:00

118 lines
3.1 KiB
C#

using System.Text;
namespace aoc2021;
internal class Day14 : Day
{
internal override void Go()
{
var lines = Util.ReadAllLines("inputs/14.txt");
string template = string.Empty;
Dictionary<string, char> rules = new();
foreach (var line in lines)
{
if (string.IsNullOrEmpty(template))
{
template = line;
}
else if (!string.IsNullOrEmpty(line))
{
var pair = line.Split(" -> ");
rules.Add(pair[0], pair[1][0]);
}
}
Part1(template, rules);
Part2(template, rules);
}
private static void Part1(string template, Dictionary<string, char> rules)
{
using var t = new Timer();
string curr = template;
Dictionary<char, int> frequencies = new();
foreach (var pair in rules)
{
frequencies[pair.Key[0]] = 0;
frequencies[pair.Key[1]] = 0;
}
for (int i = 0; i < 10; i++)
{
StringBuilder sb = new();
for (int j = 0; j < curr.Length - 1; j++)
{
sb.Append(curr[j]);
sb.Append(rules[curr[j..(j + 2)]]);
}
sb.Append(curr[^1]);
curr = sb.ToString();
}
foreach (var c in curr)
{
frequencies[c]++;
}
var least = frequencies.Min(x => x.Value);
var most = frequencies.Max(x => x.Value);
t.Stop();
Logger.Log($"<+black>> part1: <+white>{most - least}<r>");
}
private static void Part2(string template, Dictionary<string, char> rules)
{
using var t = new Timer();
Dictionary<string, long> pairs = new();
Dictionary<char, long> frequencies = new();
foreach (var pair in rules)
{
pairs[pair.Key] = 0;
frequencies[pair.Key[0]] = 0;
frequencies[pair.Key[1]] = 0;
}
for (int i = 0; i < template.Length - 1; i++)
{
var pair = template[i..(i + 2)];
pairs[pair]++;
frequencies[template[i]]++;
}
frequencies[template[^1]]++;
for (int round = 0; round < 40; round++)
{
foreach (var pair in pairs.ToList())
{
pairs[pair.Key] -= pair.Value;
frequencies[rules[pair.Key]] += pair.Value;
var np1 = $"{pair.Key[0]}{rules[pair.Key]}";
var np2 = $"{rules[pair.Key]}{pair.Key[1]}";
pairs[np1] += pair.Value;
pairs[np2] += pair.Value;
}
}
long least = long.MaxValue;
long most = long.MinValue;
foreach (var pair in frequencies)
{
if (pair.Value < least)
{
least = pair.Value;
}
if (pair.Value > most)
{
most = pair.Value;
}
}
t.Stop();
Logger.Log($"<+black>> part2: <+white>{most - least}<r>");
}
}