This commit is contained in:
parent
d3c7de189b
commit
d3df398bda
@ -18,20 +18,20 @@ namespace AOC2021.Test
|
||||
|
||||
Console.WriteLine($"Testing {request.Day} Part A, Test data");
|
||||
if (!string.IsNullOrEmpty(request.Answer.Day_A_Test))
|
||||
response.Answer.Day_A_Test = GetAOCDay(request.Day).ExecuteDay(new AOCRequest() { Input = test, Version = AOCVersion.A }).Answer;
|
||||
response.Answer.Day_A_Test = GetAOCDay(request.Day).ExecuteDay(new AOCRequest() { Input = test, Version = AOCVersion.A }).Answer.ToString();
|
||||
Console.WriteLine(response.Answer.Day_A_Test);
|
||||
Console.WriteLine($"Testing {request.Day} Part A, Input data");
|
||||
if (!string.IsNullOrEmpty(request.Answer.Day_A_Input))
|
||||
response.Answer.Day_A_Input = GetAOCDay(request.Day).ExecuteDay(new AOCRequest() { Input = input, Version = AOCVersion.A }).Answer;
|
||||
response.Answer.Day_A_Input = GetAOCDay(request.Day).ExecuteDay(new AOCRequest() { Input = input, Version = AOCVersion.A }).Answer.ToString();
|
||||
Console.WriteLine(response.Answer.Day_A_Input);
|
||||
|
||||
Console.WriteLine($"Testing {request.Day} Part B, Test data");
|
||||
if (!string.IsNullOrEmpty(request.Answer.Day_B_Test))
|
||||
response.Answer.Day_B_Test = GetAOCDay(request.Day).ExecuteDay(new AOCRequest() { Input = test, Version = AOCVersion.B }).Answer;
|
||||
response.Answer.Day_B_Test = GetAOCDay(request.Day).ExecuteDay(new AOCRequest() { Input = test, Version = AOCVersion.B }).Answer.ToString();
|
||||
Console.WriteLine(response.Answer.Day_B_Test);
|
||||
Console.WriteLine($"Testing {request.Day} Part B, Input data");
|
||||
if (!string.IsNullOrEmpty(request.Answer.Day_B_Input))
|
||||
response.Answer.Day_B_Input = GetAOCDay(request.Day).ExecuteDay(new AOCRequest() { Input = input, Version = AOCVersion.B }).Answer;
|
||||
response.Answer.Day_B_Input = GetAOCDay(request.Day).ExecuteDay(new AOCRequest() { Input = input, Version = AOCVersion.B }).Answer.ToString();
|
||||
Console.WriteLine(response.Answer.Day_B_Input);
|
||||
return response;
|
||||
}
|
||||
|
@ -73,6 +73,13 @@ namespace AOC2021.Tests
|
||||
var result = _tester.Test(request);
|
||||
Assert.IsTrue(request.Answer.Equals(result.Answer));
|
||||
}
|
||||
[TestMethod]
|
||||
public void Day8()
|
||||
{
|
||||
var request = new TestRequest() { Day = "day8", Answer = new Answer() { Day_A_Test = "26", Day_A_Input = "543", Day_B_Test = "", Day_B_Input = "" } };
|
||||
var result = _tester.Test(request);
|
||||
Assert.IsTrue(request.Answer.Equals(result.Answer));
|
||||
}
|
||||
|
||||
//[TestMethod]
|
||||
public void MapVsEnumberable()
|
||||
|
10
AOC2021.Test/Input/Day8_test.txt
Normal file
10
AOC2021.Test/Input/Day8_test.txt
Normal file
@ -0,0 +1,10 @@
|
||||
be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
|
||||
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
|
||||
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
|
||||
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
|
||||
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
|
||||
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
|
||||
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
|
||||
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
|
||||
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
|
||||
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce
|
@ -26,6 +26,7 @@ namespace AOC2021.Controllers
|
||||
[Route("day5")]
|
||||
[Route("day6")]
|
||||
[Route("day7")]
|
||||
[Route("day8")]
|
||||
public AOCResponse Day(AOCVersion version, [FromBody] string input, bool IgnoreLogMessages = false)
|
||||
{
|
||||
AOCRequest request = new AOCRequest() { Input = input, Version = version, IgnoreLogMessages = IgnoreLogMessages };
|
||||
|
42
AOC2021/Days/Day8.cs
Normal file
42
AOC2021/Days/Day8.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using AOC2021.Models;
|
||||
using AOC2021.Models.Day8;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AOC2021.Days
|
||||
{
|
||||
public class Day8 : AOCDay
|
||||
{
|
||||
protected override AOCResponse ExecutePartA()
|
||||
{
|
||||
var count = 0;
|
||||
var uniqueNumberOfLineSegments = new int[] { 2, 4, 3, 7 };
|
||||
var lines = GetSplitInput();
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var displayedDigits = line.Split("|")[1].Trim();
|
||||
foreach (var digit in displayedDigits.Split(" "))
|
||||
{
|
||||
if (uniqueNumberOfLineSegments.Contains(digit.Trim().Length))
|
||||
{
|
||||
Log($"{digit} has a length of {digit.Length} which is unique.");
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._response.Answer = count;
|
||||
return this._response;
|
||||
}
|
||||
|
||||
protected override AOCResponse ExecutePartB()
|
||||
{
|
||||
//be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb
|
||||
new SSDGenerator("be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb").Generate();
|
||||
|
||||
|
||||
return this._response;
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,6 @@ namespace AOC2021.Models
|
||||
}
|
||||
public AOCResponse ExecuteDay(AOCRequest request)
|
||||
{
|
||||
Console.WriteLine("Executing request " + Newtonsoft.Json.JsonConvert.SerializeObject(request));
|
||||
_request = request;
|
||||
var timer = new Stopwatch();
|
||||
try
|
||||
|
@ -12,7 +12,7 @@ namespace AOC2021.Models
|
||||
[DataMember]
|
||||
public DateTime Date { get { return DateTime.Now; } }
|
||||
[DataMember]
|
||||
public string Answer { get; set; }
|
||||
public object Answer { get; set; }
|
||||
[DataMember]
|
||||
public bool Status { get; set; }
|
||||
[DataMember]
|
||||
|
12
AOC2021/Models/Day8/SSD.cs
Normal file
12
AOC2021/Models/Day8/SSD.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AOC2021.Models.Day8
|
||||
{
|
||||
public enum SSD : int
|
||||
{
|
||||
_,A,B,C,D,E,F,G
|
||||
}
|
||||
}
|
286
AOC2021/Models/Day8/SSDGenerator.cs
Normal file
286
AOC2021/Models/Day8/SSDGenerator.cs
Normal file
@ -0,0 +1,286 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AOC2021.Models.Day8
|
||||
{
|
||||
public class SSDGenerator
|
||||
{
|
||||
public static string ZERO = "abcefg";
|
||||
public static string ONE = "cf";
|
||||
public static string TWO = "acdeg";
|
||||
public static string THREE = "acdfg";
|
||||
public static string FOUR = "bcdf";
|
||||
public static string FIVE = "abdfg";
|
||||
public static string SIX = "abdefg";
|
||||
public static string SEVEN = "acf";
|
||||
public static string EIGHT = "abcdefg";
|
||||
public static string NINE = "abcdfg";
|
||||
private string _numbers;
|
||||
private Dictionary<SSD, SSD?> _lookup;
|
||||
private Dictionary<SSD, List<SSD>> _possibleLookup;
|
||||
public SSDGenerator(string numbers)
|
||||
{
|
||||
_numbers = numbers;
|
||||
_lookup = new Dictionary<SSD, SSD?>();
|
||||
_possibleLookup = new Dictionary<SSD, List<SSD>>();
|
||||
foreach (SSD ssd in Enum.GetValues(typeof(SSD)))
|
||||
{
|
||||
if (ssd != SSD._)
|
||||
_lookup[ssd] = null;
|
||||
_possibleLookup[ssd] = new List<SSD>();
|
||||
}
|
||||
}
|
||||
public void Generate()
|
||||
{
|
||||
var one = GetPossibleNumbers(ONE).First();
|
||||
var seven = GetPossibleNumbers(SEVEN).First();
|
||||
var AcharDiff = CharDiff(one, seven);
|
||||
_lookup[SSD.A] = GetProperCode(AcharDiff); //We found the A value
|
||||
_possibleLookup[SSD.C] = GetPossibleSSD(one); //Can also be #1 or #7 with AcharDiff as removed valued
|
||||
_possibleLookup[SSD.F] = GetPossibleSSD(one); //Can also be #1 or #7 with AcharDiff as removed valued
|
||||
|
||||
//We know that #4 shares two of the same segments(C & F) as #1/#7. So we can remove possible values for that
|
||||
var four = GetPossibleNumbers(FOUR).First();
|
||||
//Remove all possible segments for C/F and assign what is left to B/D
|
||||
_possibleLookup[SSD.B] = GetPossibleSSD(four, _possibleLookup[SSD.C].Select(x => GetProperCode(x)).ToArray());
|
||||
_possibleLookup[SSD.D] = GetPossibleSSD(four, _possibleLookup[SSD.C].Select(x => GetProperCode(x)).ToArray());
|
||||
|
||||
//We have finished the unique digits. Now we move onto digits that have multiple possible values.
|
||||
|
||||
//Now we address the ones with 5 segments, #2, #3, #5. They all have the same possible numbers, so just use #2 as lookup
|
||||
var twoThreeFivePossible = GetPossibleNumbers(TWO);
|
||||
var simplifiedTwoThreeFive = twoThreeFivePossible.Select(x => RemoveKnownSSD(x)).ToArray();
|
||||
var possibleValuesForSegmentDG = FindInCommon(simplifiedTwoThreeFive);
|
||||
_possibleLookup[SSD.D].AddRange(GetPossibleSSD(possibleValuesForSegmentDG)); //Since D already has possible lookups, we add more
|
||||
_possibleLookup[SSD.G] = GetPossibleSSD(possibleValuesForSegmentDG);
|
||||
DeducePossibleLookups(); //Since we have overlapping possible values, we deduce the correct ones and simplify
|
||||
|
||||
PrintOutLookup();
|
||||
//Now we address the ones with 6 segments, #0, #6, #9. They all have the same possible numbers, so just use #0 as lookup
|
||||
var zeroSixNinePossible = GetPossibleNumbers(ZERO);
|
||||
var simplifiedZeroSixNine = zeroSixNinePossible.Select(x => RemoveKnownSSD(x)).ToArray();
|
||||
var possibleValuesForSegmentF = FindInCommon(simplifiedZeroSixNine); //F segment is in common with 0, 6, 9.
|
||||
_lookup[SSD.F] = GetProperCode(possibleValuesForSegmentF[0]); //Its a single char since its the only one in common with all 3 digits
|
||||
PrintOutLookup();
|
||||
DeducePossibleLookups();
|
||||
PrintOutLookup();
|
||||
foreach (var l in simplifiedZeroSixNine)
|
||||
Console.WriteLine(l);
|
||||
}
|
||||
|
||||
private void DeducePossibleLookups()
|
||||
{
|
||||
var reRunDeduce = false;
|
||||
//Remove any possible lookup that have matched to lookup
|
||||
foreach (var lookup in _lookup)
|
||||
{
|
||||
if (lookup.Value != null)
|
||||
{
|
||||
_possibleLookup[lookup.Key].Clear();
|
||||
}
|
||||
}
|
||||
|
||||
//Remove from Possible lookup any values that are already looked up.
|
||||
foreach (var pL in _possibleLookup)
|
||||
{
|
||||
foreach (var lookup in _lookup.Where(x => x.Value != null))
|
||||
{
|
||||
pL.Value.Remove(lookup.Value.GetValueOrDefault());
|
||||
}
|
||||
}
|
||||
|
||||
//Duplicate possible value check (implies the duplicate value is correct one)
|
||||
foreach (var pL in _possibleLookup)
|
||||
{
|
||||
var duplicateCount = pL.Value.GroupBy(x => x).Where(y => y.Count() > 1).Select(y => y.Key);
|
||||
if (duplicateCount.Any()) //Means we have a duplicate entry for one of the possible and it means THAT is the correct value
|
||||
{
|
||||
_lookup[pL.Key] = duplicateCount.First();
|
||||
pL.Value.Clear();
|
||||
reRunDeduce = true;
|
||||
}
|
||||
}
|
||||
|
||||
//If there is only one possible value implies that it is the answer
|
||||
foreach (var pL in _possibleLookup)
|
||||
{
|
||||
if (pL.Value.Count == 1)
|
||||
{
|
||||
_lookup[pL.Key] = pL.Value.First();
|
||||
pL.Value.Clear();
|
||||
reRunDeduce = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Indicates 6 / 7 values are found, meaning the next unused value is it.
|
||||
var lastOne = _lookup.Where(x => x.Value == null).Select(x => x.Key);
|
||||
if (lastOne.Count() == 1)
|
||||
{
|
||||
var selectedValues = _lookup.Select(x => x.Value);
|
||||
foreach (SSD ssd in Enum.GetValues(typeof(SSD)))
|
||||
{
|
||||
if (ssd == SSD._)
|
||||
continue;
|
||||
if (!selectedValues.Contains(ssd))
|
||||
{
|
||||
_lookup[lastOne.First()] = ssd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reRunDeduce)
|
||||
DeducePossibleLookups();
|
||||
}
|
||||
|
||||
private string[] GetPossibleNumbers(string searchingNumber)
|
||||
{
|
||||
var possibleNumbers = new List<string>();
|
||||
foreach (var number in _numbers.Split(" "))
|
||||
{
|
||||
if (searchingNumber.Length == number.Trim().Length)
|
||||
possibleNumbers.Add(String.Concat(number.OrderBy(c => c)));
|
||||
}
|
||||
return possibleNumbers.ToArray();
|
||||
}
|
||||
|
||||
private string RemoveKnownSSD(string s)
|
||||
{
|
||||
var knownSSDs = _lookup.Select(x => x.Value);
|
||||
var retVal = "";
|
||||
foreach (var c in s)
|
||||
{
|
||||
if (!knownSSDs.Contains(GetProperCode(c)))
|
||||
retVal += c;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private string FindInCommon(string[] values)
|
||||
{
|
||||
var retVal = "";
|
||||
var charArrays = values.Select(x => x.ToCharArray()).ToArray();
|
||||
var initial = charArrays[0];
|
||||
foreach (var c in initial)
|
||||
{
|
||||
bool contains = true;
|
||||
for (int i = 1; i < charArrays.Count(); i++)
|
||||
{
|
||||
if (!charArrays[i].Contains(c))
|
||||
contains = false;
|
||||
}
|
||||
if (contains)
|
||||
retVal += c;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private char CharDiff(string s1, string s2)
|
||||
{
|
||||
string diff = "";
|
||||
var high = s1.Length > s2.Length ? s1 : s2;
|
||||
var low = s1.Length <= s2.Length ? s1 : s2;
|
||||
foreach (char c in high)
|
||||
{
|
||||
if (low.IndexOf(c) == -1)
|
||||
diff += c;
|
||||
}
|
||||
if (diff.Length != 1)
|
||||
throw new Exception($"Char Diff has value {diff} for {s1} and {s2}");
|
||||
return diff[0];
|
||||
}
|
||||
|
||||
private List<SSD> GetPossibleSSD(string value, params char[] removedChars)
|
||||
{
|
||||
var retVal = new List<SSD>();
|
||||
foreach (var c in value)
|
||||
{
|
||||
if (!removedChars.Contains(c))
|
||||
retVal.Add(GetProperCode(c));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void PrintOutLookup()
|
||||
{
|
||||
foreach (var e in _lookup)
|
||||
{
|
||||
if (e.Key == SSD._)
|
||||
continue;
|
||||
Console.WriteLine($"{e.Key}: {e.Value}");
|
||||
}
|
||||
foreach (var e in _possibleLookup)
|
||||
{
|
||||
if (e.Key == SSD._)
|
||||
continue;
|
||||
Console.WriteLine($"P_{e.Key}: {string.Join(", ", e.Value)}");
|
||||
}
|
||||
}
|
||||
|
||||
public string GetProperCode(int x)
|
||||
{
|
||||
if (x == 0)
|
||||
return ZERO;
|
||||
if (x == 1)
|
||||
return ONE;
|
||||
if (x == 2)
|
||||
return TWO;
|
||||
if (x == 3)
|
||||
return THREE;
|
||||
if (x == 4)
|
||||
return FOUR;
|
||||
if (x == 5)
|
||||
return FIVE;
|
||||
if (x == 6)
|
||||
return SIX;
|
||||
if (x == 7)
|
||||
return SEVEN;
|
||||
if (x == 8)
|
||||
return EIGHT;
|
||||
if (x == 9)
|
||||
return NINE;
|
||||
return "";
|
||||
}
|
||||
|
||||
public SSD GetProperCode(char c)
|
||||
{
|
||||
c = c.ToString().ToLower()[0];
|
||||
if (c == 'a')
|
||||
return SSD.A;
|
||||
if (c == 'b')
|
||||
return SSD.B;
|
||||
if (c == 'c')
|
||||
return SSD.C;
|
||||
if (c == 'd')
|
||||
return SSD.D;
|
||||
if (c == 'e')
|
||||
return SSD.E;
|
||||
if (c == 'f')
|
||||
return SSD.F;
|
||||
if (c == 'g')
|
||||
return SSD.G;
|
||||
return SSD._;
|
||||
}
|
||||
|
||||
public char GetProperCode(SSD ssd)
|
||||
{
|
||||
if (ssd == SSD.A)
|
||||
return 'a';
|
||||
if (ssd == SSD.B)
|
||||
return 'b';
|
||||
if (ssd == SSD.C)
|
||||
return 'c';
|
||||
if (ssd == SSD.D)
|
||||
return 'd';
|
||||
if (ssd == SSD.E)
|
||||
return 'e';
|
||||
if (ssd == SSD.F)
|
||||
return 'f';
|
||||
if (ssd == SSD.G)
|
||||
return 'g';
|
||||
return ' ';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
19
AOC2021/Models/Day8/SSDNumber.cs
Normal file
19
AOC2021/Models/Day8/SSDNumber.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AOC2021.Models.Day8
|
||||
{
|
||||
public class SSDNumber
|
||||
{
|
||||
|
||||
|
||||
public SSDNumber()
|
||||
{
|
||||
|
||||
}
|
||||
public bool[] Layout { get; set; }
|
||||
public bool Finalized { get; set; }
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user