Add solution for 2021 day 08 part 2
This commit is contained in:
parent
6fa2536880
commit
ea82ee5cd0
@ -11,7 +11,7 @@
|
||||
| 05 | ✓ | ✓ | [Nim] |
|
||||
| 06 | ✓ | ✓ | [Inko] |
|
||||
| 07 | ✓ | ✓ | [Swift] |
|
||||
| 08 | ✓ | | [C#] |
|
||||
| 08 | ✓ | ✓ | [C#] |
|
||||
| 09 | ✓ | ✓ | [C] |
|
||||
| 10 | ✓ | ✓ | [OCaml] |
|
||||
| 11 | | | |
|
||||
|
@ -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
137
2021/day-08/part_two.cs
Normal 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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user