From 229cbfd476378714b7a3fd4d8d4303973599d9f4 Mon Sep 17 00:00:00 2001 From: Premek Vysoky Date: Mon, 11 Dec 2023 00:07:51 +0100 Subject: [PATCH] 2023 Day 8 --- src/2023/08/Program.cs | 49 ++++++++++++++++++++++++++++++++++- src/Common/CircularCounter.cs | 39 ++++++++++++++++++++++++++++ src/Common/Resources.cs | 30 ++++++++++++++++++++- 3 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 src/Common/CircularCounter.cs diff --git a/src/2023/08/Program.cs b/src/2023/08/Program.cs index b7b8954..a2a5f5b 100644 --- a/src/2023/08/Program.cs +++ b/src/2023/08/Program.cs @@ -1,3 +1,50 @@ -using AdventOfCode.Common; +using System.Text.RegularExpressions; +using AdventOfCode.Common; var lines = Resources.GetInputFileLines(); +var instructionCounter = new CircularCounter(lines.First()); +var instructionRegex = new Regex("[A-Z0-9]{3}"); +var rawInstructions = lines + .Skip(1) + .Select(line => instructionRegex.Matches(line)) + .ToDictionary(m => m[0].Value, m => (m[1].Value, m[2].Value)); +var instructions = rawInstructions.Keys + .ToDictionary(name => name, name => new Instruction(name)); + +foreach (var instruction in instructions) +{ + var i = rawInstructions[instruction.Key]; + instruction.Value.Left = instructions.TryGetValue(i.Item1, out var v1) ? v1 : null!; + instruction.Value.Right = instructions.TryGetValue(i.Item2, out var v2) ? v2 : null!; +} + +var part2 = instructions + .Where(p => p.Key.EndsWith('A')) + .Select(p => p.Value) + .Select(i => GetInstructionCount(i.Name)) + .FindLowestCommonDenominator(); + +Console.WriteLine($"Part 1: {GetInstructionCount("AAA")}"); +Console.WriteLine($"Part 2: {part2}"); + +int GetInstructionCount(string startInstruction) +{ + var current = instructions[startInstruction]; + var counter = instructionCounter!.GetEnumerator(); + while (current.Name[2] != 'Z') + { + current = counter.Current == 'L' ? current.Left : current.Right; + counter.MoveNext(); + } + + var value = instructionCounter.Counter; + instructionCounter.Counter = 0; + + return value; +} + +file record Instruction(string Name) +{ + public Instruction Left { get; set; } = null!; + public Instruction Right { get; set; } = null!; +} diff --git a/src/Common/CircularCounter.cs b/src/Common/CircularCounter.cs new file mode 100644 index 0000000..40389b6 --- /dev/null +++ b/src/Common/CircularCounter.cs @@ -0,0 +1,39 @@ +using System.Collections; + +namespace AdventOfCode.Common; + +public class CircularCounter(string instructions) : IEnumerable +{ + public int Counter { get; set; } + + public IEnumerator GetEnumerator() => new InstructionEnumerator(instructions, this); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + private class InstructionEnumerator(string instructions, CircularCounter parent) : IEnumerator + { + private readonly string _instructions = instructions; + private readonly CircularCounter _parent = parent; + private int _index = 0; + + public char Current => _instructions[_index]; + + object IEnumerator.Current => _instructions[_index]; + + public void Dispose() { } + + public bool MoveNext() + { + _parent.Counter++; + _index++; + _index %= _instructions.Length; + return true; + } + + public void Reset() + { + _parent.Counter = 0; + _index = 0; + } + } +} + diff --git a/src/Common/Resources.cs b/src/Common/Resources.cs index 41dc14a..707db02 100644 --- a/src/Common/Resources.cs +++ b/src/Common/Resources.cs @@ -116,8 +116,36 @@ public static int Multiply(this IEnumerable values) => values.Aggregate(1, (acc, v) => acc * v); public static long MultiplyAsLong(this IEnumerable values) - => values.Aggregate(1L, (acc, v) => acc * v); + => values.Aggregate(1, (acc, v) => acc * v); public static long Multiply(this IEnumerable values) => values.Aggregate(1L, (acc, v) => acc * v); + + public static long FindLowestCommonDenominator(this IEnumerable numbers) + { + long lcm = numbers.First(); + foreach (int number in numbers.Skip(1)) + { + lcm = GetLeastCommonMultiple(lcm, number); + } + + return lcm; + } + + public static long GetGreatestCommonDivisor(long a, long b) + { + while (b != 0) + { + long temp = b; + b = a % b; + a = temp; + } + + return a; + } + + public static long GetLeastCommonMultiple(long a, long b) + { + return a * b / GetGreatestCommonDivisor(a, b); + } }