mirror of
https://github.com/parnic/advent-of-code-2022.git
synced 2025-06-16 13:40:13 -05:00
Day 13 solution
I am not completely happy with this data structure, but it's functional enough. I wanted to implement comparers and equality overrides for the classes to make part 2 shorter, but it would have come at the cost of a bunch of boilerplate code, so whatever.
This commit is contained in:
@ -60,6 +60,7 @@
|
|||||||
<EmbeddedResource Include="inputs\12a.txt" />
|
<EmbeddedResource Include="inputs\12a.txt" />
|
||||||
<EmbeddedResource Include="inputs\13.txt" />
|
<EmbeddedResource Include="inputs\13.txt" />
|
||||||
<None Remove="inputs\14.txt" />
|
<None Remove="inputs\14.txt" />
|
||||||
|
<EmbeddedResource Include="inputs\13a.txt" />
|
||||||
<EmbeddedResource Include="inputs\14.txt" />
|
<EmbeddedResource Include="inputs\14.txt" />
|
||||||
<None Remove="inputs\15.txt" />
|
<None Remove="inputs\15.txt" />
|
||||||
<EmbeddedResource Include="inputs\15.txt" />
|
<EmbeddedResource Include="inputs\15.txt" />
|
||||||
|
1357
inputs/13.txt
1357
inputs/13.txt
File diff suppressed because it is too large
Load Diff
23
inputs/13a.txt
Normal file
23
inputs/13a.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
[1,1,3,1,1]
|
||||||
|
[1,1,5,1,1]
|
||||||
|
|
||||||
|
[[1],[2,3,4]]
|
||||||
|
[[1],4]
|
||||||
|
|
||||||
|
[9]
|
||||||
|
[[8,7,6]]
|
||||||
|
|
||||||
|
[[4,4],4,4]
|
||||||
|
[[4,4],4,4,4]
|
||||||
|
|
||||||
|
[7,7,7,7]
|
||||||
|
[7,7,7]
|
||||||
|
|
||||||
|
[]
|
||||||
|
[3]
|
||||||
|
|
||||||
|
[[[]]]
|
||||||
|
[[]]
|
||||||
|
|
||||||
|
[1,[2,[3,[4,[5,6,7]]]],8,9]
|
||||||
|
[1,[2,[3,[4,[5,6,0]]]],8,9]
|
209
src/13.cs
Normal file
209
src/13.cs
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace aoc2022;
|
||||||
|
|
||||||
|
internal class Day13 : Day
|
||||||
|
{
|
||||||
|
abstract class entry
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class packet : entry
|
||||||
|
{
|
||||||
|
public packet(params entry[] _entries)
|
||||||
|
{
|
||||||
|
entries = new List<entry>(_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly List<entry> entries;
|
||||||
|
public packet? parent;
|
||||||
|
|
||||||
|
public override string ToString() => $"[{string.Join(",", entries)}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
class entryint : entry
|
||||||
|
{
|
||||||
|
public entryint(int _num)
|
||||||
|
{
|
||||||
|
num = _num;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly int num;
|
||||||
|
public override string ToString() => $"{num}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly List<(packet, packet)> packets = new();
|
||||||
|
internal override void Parse()
|
||||||
|
{
|
||||||
|
packet? one = null;
|
||||||
|
packet? two = null;
|
||||||
|
foreach (var line in Util.Parsing.ReadAllLines("13"))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(line))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (one == null)
|
||||||
|
{
|
||||||
|
one = parsePacket(line);
|
||||||
|
}
|
||||||
|
else if (two == null)
|
||||||
|
{
|
||||||
|
two = parsePacket(line);
|
||||||
|
|
||||||
|
packets.Add((one, two));
|
||||||
|
one = null;
|
||||||
|
two = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private packet parsePacket(string line)
|
||||||
|
{
|
||||||
|
packet? curr = new();
|
||||||
|
|
||||||
|
StringBuilder sb = new();
|
||||||
|
for (int i = 1; i < line.Length-1; i++)
|
||||||
|
{
|
||||||
|
var ch = line[i];
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '[':
|
||||||
|
packet embedded = new() { parent = curr };
|
||||||
|
curr!.entries.Add(embedded);
|
||||||
|
curr = embedded;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ']':
|
||||||
|
if (sb.Length > 0)
|
||||||
|
{
|
||||||
|
curr!.entries.Add(new entryint(int.Parse(sb.ToString())));
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Clear();
|
||||||
|
curr = curr!.parent;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
if (sb.Length > 0)
|
||||||
|
{
|
||||||
|
curr!.entries.Add(new entryint(int.Parse(sb.ToString())));
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Clear();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sb.Append(ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sb.Length > 0)
|
||||||
|
{
|
||||||
|
curr!.entries.Add(new entryint(int.Parse(sb.ToString())));
|
||||||
|
}
|
||||||
|
|
||||||
|
return curr!;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool? isValid((packet, packet) pair)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < pair.Item1.entries.Count; i++)
|
||||||
|
{
|
||||||
|
if (pair.Item2.entries.Count <= i)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var left = pair.Item1.entries[i];
|
||||||
|
var right = pair.Item2.entries[i];
|
||||||
|
if (left is entryint li && right is entryint ri)
|
||||||
|
{
|
||||||
|
if (li.num < ri.num)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (li.num > ri.num)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (left is packet ll && right is packet rl)
|
||||||
|
{
|
||||||
|
var valid = isValid((ll, rl));
|
||||||
|
if (valid.HasValue)
|
||||||
|
{
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var one = left as packet;
|
||||||
|
var two = right as packet;
|
||||||
|
if (left is entryint ei1)
|
||||||
|
{
|
||||||
|
one = new packet(ei1);
|
||||||
|
}
|
||||||
|
else if (right is entryint ei2)
|
||||||
|
{
|
||||||
|
two = new packet(ei2);
|
||||||
|
}
|
||||||
|
|
||||||
|
var valid = isValid((one!, two!));
|
||||||
|
if (valid.HasValue)
|
||||||
|
{
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pair.Item1.entries.Count < pair.Item2.entries.Count)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override string Part1()
|
||||||
|
{
|
||||||
|
List<int> validIndices = new();
|
||||||
|
for (int i = 0; i < packets.Count; i++)
|
||||||
|
{
|
||||||
|
var pair = packets[i];
|
||||||
|
var valid = isValid(pair);
|
||||||
|
if (valid != false)
|
||||||
|
{
|
||||||
|
validIndices.Add(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"Sum of valid indices (1-based): <+white>{validIndices.Sum()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override string Part2()
|
||||||
|
{
|
||||||
|
var sentinels = new List<packet>
|
||||||
|
{
|
||||||
|
parsePacket("[[2]]"),
|
||||||
|
parsePacket("[[6]]"),
|
||||||
|
};
|
||||||
|
var l = new List<packet>(sentinels);
|
||||||
|
foreach (var p in packets)
|
||||||
|
{
|
||||||
|
l.Add(p.Item1);
|
||||||
|
l.Add(p.Item2);
|
||||||
|
}
|
||||||
|
l.Sort((a, b) => isValid((a, b)) != false ? -1 : 1);
|
||||||
|
|
||||||
|
int total = 1;
|
||||||
|
foreach (var s in sentinels)
|
||||||
|
{
|
||||||
|
total *= l.FindIndex(p => p.ToString() == s.ToString()) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"Sum of sentinel packet indices (1-based) after sorting: <+white>{total}";
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user