Files
2021/src/08.cs
Parnic 1330d1eb66 Day 8
I hate almost everything about this solution. It's all awful and a product of constantly adjusting how I was solving the problem to try and get the correct answer, so there are vestigial pieces of each road I headed down. Then I ended up using some combination of all of those pieces to get the actual answer, and...well it just needs to be overhauled dramatically. But it works, so I guess mission accomplished.
2021-12-08 10:57:36 -06:00

175 lines
6.2 KiB
C#

namespace aoc2021
{
internal class Day08
{
internal static void Go()
{
Logger.Log("Day 8");
Logger.Log("-----");
var lines = File.ReadAllLines("inputs/08.txt");
List<(List<string>, List<string>)> puzzle = new();
foreach (var line in lines)
{
var portions = line.Split(" | ");
puzzle.Add((new List<string>(portions[0].Split(' ')), new List<string>(portions[1].Split(' '))));
}
Part1(puzzle);
Part2(puzzle);
Logger.Log("");
}
private static void Part1(List<(List<string>, List<string>)> lines)
{
using var t = new Timer();
int count = 0;
foreach (var line in lines)
{
foreach (var combo in line.Item2)
{
switch (combo.Length)
{
case 2: // 1
case 4: // 4
case 3: // 7
case 7: // 8
count++;
break;
}
}
}
Logger.Log($"part1: {count}");
}
private static void Part2(List<(List<string>, List<string>)> lines)
{
using var t = new Timer();
long sum = 0;
foreach (var line in lines)
{
var segments = new char[7];
var one = line.Item1.First(x => x.Length == 2);
var four = line.Item1.First(x => x.Length == 4);
var seven = line.Item1.First(x => x.Length == 3);
var eight = line.Item1.First(x => x.Length == 7);
var len5 = line.Item1.Where(x => x.Length == 5); // 2, 3, 5
var len6 = line.Item1.Where(x => x.Length == 6); // 0, 6, 9
// top
segments[0] = seven.First(x => !one.Contains(x));
// bottom
foreach (var pattern in len6)
{
var leftover = pattern.Where(x => !seven.Contains(x) && !four.Contains(x));
if (leftover.Count() == 1)
{
segments[6] = leftover.First();
}
}
var three = len5.First(seg => seg.Contains(segments[0]) && seg.Contains(segments[6]) && seg.Contains(one[0]) && seg.Contains(one[1]));
// center
segments[3] = three.First(x => x != segments[0] && x != segments[6] && !one.Contains(x));
// bottom left
segments[4] = eight.First(x => x != segments[0] && !four.Contains(x) && x != segments[6]);
// top left
segments[1] = eight.First(x => !three.Contains(x) && x != segments[4]);
var two = len5.First(x => x.Where(y => y != segments[0] && y != segments[6]).Except(four).Count() == 1);
//var five = len5.First(x => x != two && x != three);
var nine = len6.First(x => !x.Except(four).Except(new List<char>() { segments[0], segments[6] }).Any());
var zero = len6.First(x => !x.Contains(segments[3]));
var six = len6.First(x => x != zero && x != nine);
// bottom right
segments[5] = six.Except(two).First(x => x != segments[1]);
// top right
segments[2] = one.First(x => x != segments[5]);
int num = 0;
for (int i = 0; i < line.Item2.Count; i++)
{
var numInt = FindNum(segments, line.Item2[i]);
num += numInt * (int)Math.Pow(10, (line.Item2.Count - i - 1));
}
sum += num;
}
Logger.Log($"part2: {sum}");
}
private static int FindNum(char[] segments, string num)
{
// i already solved for each number in part2, so it's kind of dumb to rebuild my own set of numbers here,
// but this is all left over from my various different attempts to solve this different ways.
// and it works, so whatever.
var zero = new List<char>() { segments[0], segments[1], segments[2], segments[4], segments[5], segments[6] };
var six = new List<char>() { segments[0], segments[1], segments[3], segments[4], segments[5], segments[6] };
var nine = new List<char>() { segments[0], segments[1], segments[2], segments[3], segments[5], segments[6] };
var two = new List<char>() { segments[0], segments[2], segments[3], segments[4], segments[6] };
var three = new List<char>() { segments[0], segments[2], segments[3], segments[5], segments[6] };
var five = new List<char>() { segments[0], segments[1], segments[3], segments[5], segments[6] };
switch (num.Length)
{
case 2:
return 1;
case 3:
return 7;
case 4:
return 4;
case 7:
return 8;
case 6:
if (num.All(x => zero.Contains(x)))
{
return 0;
}
else if (num.All(x => six.Contains(x)))
{
return 6;
}
else if (num.All(x => nine.Contains(x)))
{
return 9;
}
throw new Exception();
case 5:
if (num.All(x => two.Contains(x)))
{
return 2;
}
else if (num.All(x => three.Contains(x)))
{
return 3;
}
else if (num.All(x => five.Contains(x)))
{
return 5;
}
throw new Exception();
default:
throw new Exception();
}
throw new Exception();
}
}
}