This commit is contained in:
2023-12-20 00:59:40 -06:00
parent 677ae62853
commit 11fc463922
5 changed files with 262 additions and 0 deletions

View File

@ -70,6 +70,9 @@
<EmbeddedResource Include="inputs\18a.txt" />
<EmbeddedResource Include="inputs\19.txt" />
<EmbeddedResource Include="inputs\19a.txt" />
<EmbeddedResource Include="inputs\20.txt" />
<EmbeddedResource Include="inputs\20a.txt" />
<EmbeddedResource Include="inputs\20b.txt" />
</ItemGroup>
<ItemGroup>

58
inputs/20.txt Normal file
View File

@ -0,0 +1,58 @@
%hm -> lg
%ph -> gr, cd
%xs -> st, zf
%xc -> vv, bn
%fx -> lx, st
%dn -> zc
%nd -> lg, tc
%pd -> dn, lg
%pc -> gr
%lx -> gp
%tc -> kj
%tl -> nn
%kk -> xs
%gq -> pd
%xq -> st, xj
%nn -> bn, xc
&st -> kk, fx, hz, lx, zb
&hb -> rx
%xj -> st, vq
%sz -> gr, ph
%bz -> kx
%vq -> st
%vv -> hh, bn
%gp -> st, hz
&js -> hb
%lf -> bn, qg
broadcaster -> nd, fx, mc, lf
%cd -> vr
%vr -> qc, gr
%kx -> kc, lg
%jr -> bn, tl
&gr -> cz, dh, mc, qc, js, nj, cd
%qg -> hq
%mc -> gr, cz
%nl -> st, ch
%hz -> nl
%kt -> gr, jc
%zc -> lg, qn
%vj -> rs
&zb -> hb
%kc -> gq
%qc -> kt
&bn -> qg, hq, rs, lf, bs, vj, tl
%cz -> dh
&bs -> hb
%jc -> gr, pc
%nj -> sz
%kj -> lg, bz
%hh -> jv, bn
%hq -> vj
%dh -> nj
%ch -> st, kk
%jv -> bn
%rs -> jr
%zf -> xq, st
%qn -> hm, lg
&lg -> gq, bz, tc, nd, rr, kc, dn
&rr -> hb

5
inputs/20a.txt Normal file
View File

@ -0,0 +1,5 @@
broadcaster -> a, b, c
%a -> b
%b -> c
%c -> inv
&inv -> a

5
inputs/20b.txt Normal file
View File

@ -0,0 +1,5 @@
broadcaster -> a
%a -> inv, con
&inv -> b
%b -> con
&con -> output

191
src/20.cs Normal file
View File

@ -0,0 +1,191 @@
namespace aoc2023;
internal class Day20 : Day
{
private record command(bool state, string source, string target);
abstract class module(string n, IList<string> o)
{
protected readonly string name = n;
public readonly List<string> outputs = [..o];
public abstract void Signal(string source, bool state, Queue<command> queue);
public abstract void Reset();
}
private class flipflop(string n, IList<string> o) : module(n, o)
{
private bool state;
public override void Signal(string source, bool pulse, Queue<command> queue)
{
if (pulse)
{
return;
}
state = !state;
foreach (var r in outputs)
{
queue.Enqueue(new command(state, name, r));
}
}
public override void Reset()
{
state = false;
}
}
private class conjunction(string n, IList<string> o) : module(n, o)
{
public readonly Dictionary<string, bool> inputs = [];
public override void Signal(string source, bool state, Queue<command> queue)
{
inputs[source] = state;
bool send = !inputs.All(r => r.Value);
foreach (var r in outputs)
{
queue.Enqueue(new command(send, name, r));
}
}
public override void Reset()
{
foreach (var i in inputs)
{
inputs[i.Key] = false;
}
}
}
private readonly Dictionary<string, module> modules = [];
private readonly List<string> broadcastReceivers = [];
internal override void Parse()
{
var lines = Util.Parsing.ReadAllLines($"{GetDay()}");
foreach (var line in lines)
{
var split = line.Split(" -> ");
if (split[0].StartsWith('%'))
{
var n = split[0][1..];
var receivers = split[1].Split(", ");
modules.Add(n, new flipflop(n, receivers));
}
else if (split[0].StartsWith('&'))
{
var n = split[0][1..];
var receivers = split[1].Split(", ");
modules.Add(n, new conjunction(n, receivers));
}
else if (split[0] == "broadcaster")
{
broadcastReceivers.AddRange(split[1].Split(", "));
}
else
{
throw new Exception();
}
}
foreach (var m in modules.Where(m => m.Value is conjunction))
{
foreach (var i in modules.Where(m2 => m2.Value.outputs.Contains(m.Key)))
{
(m.Value as conjunction)!.inputs.TryAdd(i.Key, false);
}
}
}
internal override string Part1()
{
modules.ForEach(m => m.Value.Reset());
Queue<command> q = [];
long lows = 0;
long highs = 0;
for (int i = 0; i < 1000; i++)
{
lows++;
foreach (var r in broadcastReceivers)
{
q.Enqueue(new command(false, "broadcaster", r));
}
while (q.TryDequeue(out command? result))
{
if (result.state)
{
highs++;
}
else
{
lows++;
}
if (modules.TryGetValue(result.target, out module? value))
{
value.Signal(result.source, result.state, q);
}
}
}
return $"{lows} low signals * {highs} high signals = <+white>{lows*highs}";
}
internal override string Part2()
{
modules.ForEach(m => m.Value.Reset());
Queue<command> q = [];
var rxin = modules.First(m => m.Value.outputs.Contains("rx"));
var rxinin = modules.Where(m => m.Value.outputs.Contains(rxin.Key)).ToDictionary();
Dictionary<string, long> loops = [];
bool seenRx = false;
long presses = 0;
while (!seenRx)
{
presses++;
foreach (var r in broadcastReceivers)
{
q.Enqueue(new command(false, "broadcaster", r));
}
while (q.TryDequeue(out command? result))
{
if (result is {target: "rx", state: false})
{
seenRx = true;
break;
}
if (!modules.TryGetValue(result.target, out module? value))
{
continue;
}
if (!result.state && rxinin.Any(m => m.Key == result.target))
{
if (loops.TryAdd(result.target, presses))
{
if (loops.Count == rxinin.Count)
{
seenRx = true;
break;
}
}
}
value.Signal(result.source, result.state, q);
}
}
// technically this should use LCM, but they're all prime.
return $"rx will receive a low pulse after <+white>{loops.Aggregate(1L, (curr, m) => curr * m.Value)}<+black> button presses";
}
}