Add solution for 2021 day 08 part 2

This commit is contained in:
Patrick Auernig 2021-12-11 12:37:46 +01:00
parent 6fa2536880
commit ea82ee5cd0
4 changed files with 185 additions and 2 deletions

View File

@ -11,7 +11,7 @@
| 05 | ✓ | ✓ | [Nim] |
| 06 | ✓ | ✓ | [Inko] |
| 07 | ✓ | ✓ | [Swift] |
| 08 | ✓ | | [C#] |
| 08 | ✓ | | [C#] |
| 09 | ✓ | ✓ | [C] |
| 10 | ✓ | ✓ | [OCaml] |
| 11 | | | |

View File

@ -43,4 +43,50 @@ namespace Common {
}
}
}
public static class Permutation {
public static IEnumerable<T[]> Permutations<T>(this IEnumerable<T> input) {
return Permute(input, Enumerable.Empty<T>());
}
private static IEnumerable<T[]> Permute<T>(IEnumerable<T> memo, IEnumerable<T> pfx) {
if (memo.Any()) {
return
from t in memo.Select((a, b) => (a, b))
let next_memo = memo.Take(t.Item2).Concat(memo.Skip(t.Item2 + 1)).ToArray()
let next_pfx = pfx.Append(t.Item1)
from perms in Permute(next_memo, next_pfx)
select perms;
} else {
return new[] { pfx.ToArray() };
}
}
}
public abstract class Option<T> {
private Option() {}
public abstract bool IsSome();
public bool GetValue(out T val) {
if (this is Some s) {
val = s.Value;
return true;
}
val = default(T);
return false;
}
public sealed class Some : Option<T> {
public Some(T val) => Value = val;
public T Value { get; }
public override bool IsSome() => true;
}
public sealed class None : Option<T> {
public override bool IsSome() => false;
}
}
}

137
2021/day-08/part_two.cs Normal file
View File

@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Common;
using static Common.SegmentDisplay;
using static Common.Permutation;
class PartTwo {
private static readonly HashSet<int>[] VALID_POSITIONS = {
new HashSet<int>() {0, 1, 2, 4, 5, 6},
new HashSet<int>() {2, 5},
new HashSet<int>() {0, 2, 3, 4, 6},
new HashSet<int>() {0, 2, 3, 5, 6},
new HashSet<int>() {1, 2, 3, 5},
new HashSet<int>() {0, 1, 3, 5, 6},
new HashSet<int>() {0, 1, 3, 4, 5, 6},
new HashSet<int>() {0, 2, 5},
new HashSet<int>() {0, 1, 2, 3, 4, 5, 6},
new HashSet<int>() {0, 1, 2, 3, 5, 6},
};
public static void Main(string[] args) {
var seg_display = new SegmentDisplay(args[0]);
var output_sum = seg_display.Wirings.Sum(w => OutputNumber(w));
Console.WriteLine(output_sum);
}
private static int OutputNumber(Wiring wiring) {
var inputs = wiring.Inputs.OrderBy(x => x.Count).ToList();
var digit = 0;
if (Analyze(inputs).GetValue(out var segments)) {
var digit_idx = wiring.Outputs.Count - 1;
foreach (var output in wiring.Outputs) {
var segment_digit = GetOutputDigit(output, segments);
digit += segment_digit * (int)Math.Pow(10, digit_idx);
digit_idx--;
}
}
return digit;
}
private static int GetOutputDigit(HashSet<char> output, Dictionary<char, int> segments) {
var mapped_output = output.Select(v => segments[v]);
switch (output.Count) {
case 2: return 1;
case 3: return 7;
case 4: return 4;
case 7: return 8;
case 5:
foreach (var n in new[]{2, 3, 5}) {
if (!VALID_POSITIONS[n].Except(mapped_output).Any()) return n;
}
break;
case 6:
foreach (var n in new[]{0, 6, 9}) {
if (!VALID_POSITIONS[n].Except(mapped_output).Any()) return n;
}
break;
default:
throw new Exception("Invalid output length");
}
throw new Exception("No valid mapping for output");
}
private static Option<Dictionary<char, int>> Analyze(IEnumerable<HashSet<char>> inputs) {
return Analyze(inputs, new Dictionary<char, int>());
}
private static Option<Dictionary<char, int>> Analyze(
IEnumerable<HashSet<char>> inputs,
Dictionary<char, int> segments
) {
if (!inputs.Any()) return new Option<Dictionary<char, int>>.Some(segments);
var input = inputs.First();
var segment_count = input.Count;
var unmapped_input = input.Except(segments.Keys);
var mapped_input = input.Intersect(segments.Keys).Select(v => segments[v]);
switch (segment_count) {
case 2: return Analyze(1, unmapped_input, mapped_input, inputs, segments);
case 3: return Analyze(7, unmapped_input, mapped_input, inputs, segments);
case 4: return Analyze(4, unmapped_input, mapped_input, inputs, segments);
case 7: return new Option<Dictionary<char, int>>.Some(segments);
case 5:
foreach (var n in new[]{2, 3, 5}) {
var retval = Analyze(n, unmapped_input.ToList(), mapped_input.ToList(), inputs, segments);
if (retval.IsSome()) return retval;
}
break;
case 6:
foreach (var n in new[]{0, 6, 9}) {
var retval = Analyze(n, unmapped_input.ToList(), mapped_input.ToList(), inputs, segments);
if (retval.IsSome()) return retval;
}
break;
default:
throw new Exception("Invalid input length");
}
return new Option<Dictionary<char, int>>.None();
}
private static Option<Dictionary<char, int>> Analyze(
int num,
IEnumerable<char> unmapped_input,
IEnumerable<int> mapped_input,
IEnumerable<HashSet<char>> inputs,
Dictionary<char, int> segments
) {
if (!mapped_input.Except(VALID_POSITIONS[num]).Any()) {
foreach (var perm in Permutations(unmapped_input)) {
var new_segments = new Dictionary<char, int>(segments);
foreach (var pair in perm.Zip(VALID_POSITIONS[num].Except(mapped_input), (a, b) => (a, b))) {
new_segments.Add(pair.Item1, pair.Item2);
}
var retval = Analyze(inputs.Skip(1).ToList(), new_segments);
if (retval.IsSome()) return retval;
}
}
return new Option<Dictionary<char, int>>.None();
}
}

View File

@ -8,4 +8,4 @@
- [2018](2018/README.md) (0% completed)
- [2019](2019/README.md) (0% completed)
- [2020](2020/README.md) (16% completed)
- [2021](2021/README.md) (38% completed)
- [2021](2021/README.md) (40% completed)