From 07b84cfce1f960e4a2992ad39948e4af6165eeab Mon Sep 17 00:00:00 2001 From: Stefan Forstenlechner Date: Mon, 27 Dec 2021 14:30:25 +0100 Subject: [PATCH] Day 23 --- Day23.cs | 134 +++++++++++++++++++++++++++++++++++++++++++--------- day23/input | 2 + 2 files changed, 113 insertions(+), 23 deletions(-) diff --git a/Day23.cs b/Day23.cs index 82d3a7a..c50cbe2 100644 --- a/Day23.cs +++ b/Day23.cs @@ -4,39 +4,127 @@ var lines = File.ReadAllLines("day23/input") .ToList(); -var aStack = new Stack(); -var bStack = new Stack(); -var cStack = new Stack(); -var dStack = new Stack(); - -var stackSpace = new Dictionary, int>() {{aStack, 2}, {bStack, 4}, {cStack, 6}, {dStack, 8}}; -var moveCost = new Dictionary() {{'A', 1},{'B', 10},{'C', 100},{'D', 1000}}; var spaces = Enumerable.Repeat('.', 11).ToArray(); -foreach ((var stack, var space) in stackSpace) { +var charInfos = new Dictionary() { + {'A', new CharInfo(new Stack(), 2, 1)}, + {'B', new CharInfo(new Stack(), 4, 10)}, + {'C', new CharInfo(new Stack(), 6, 100)}, + {'D', new CharInfo(new Stack(), 8, 1000)}, +}; +var allStackPos = charInfos.Values.Select(i => i.stackPos).ToHashSet(); + +foreach (var charInfo in charInfos.Values) { int pos = 2; - while (pos < lines.Count && lines[pos][space+1] != '#') { - stack.Push(lines[pos][space+1]); + var chars = new List(); + while (pos < lines.Count && lines[pos][charInfo.stackPos+1] != '#') { + chars.Add(lines[pos][charInfo.stackPos+1]); pos++; } + chars.Reverse(); + chars.ForEach(c => charInfo.stack.Push(c)); } -Console.WriteLine("adsf"); +int maxStackDepth = charInfos.Values.Select(i => i.stack.Count).Max(); +long globalMinimumCost = long.MaxValue; +Solve(charInfos, spaces, 0L); +Console.WriteLine(globalMinimumCost); -long Solve(Dictionary, int> stackSpace, char[] spaces) { - if (spaces.Any(c => c != '.')) { - +void Solve(Dictionary charInfos, char[] spaces, long cost) { + if (cost >= globalMinimumCost) { + return; + } + if (Solved(charInfos, spaces)) { + if (cost < globalMinimumCost) { + globalMinimumCost = cost; + } + return; + } + bool spaceMoveToStack = false; + for (int i = 0; i < spaces.Length; i++) { + if (spaces[i] != '.' && CheckMoveFromSpaces(i, spaces)) { + spaceMoveToStack = true; + char moved = spaces[i]; + CharInfo charInfo = charInfos[spaces[i]]; + spaces[i] = '.'; + charInfo.stack.Push(moved); + long curCost = (Math.Abs(i - charInfo.stackPos) + (maxStackDepth - charInfo.stack.Count + 1)) * charInfo.cost; + Solve(charInfos, spaces, cost + curCost); + charInfo.stack.Pop(); + spaces[i] = moved; + } + } + if (spaceMoveToStack) { + return; + } + + foreach ((var key,var value) in charInfos) { + if (value.stack.Any(c => c != key)) { + for (int i = 0; i < spaces.Length; i++) { + if (spaces[i] != '.' || allStackPos.Contains(i) || CheckMoveToSpacesImpossible(value.stackPos, i, spaces)) { + continue; + } + var movedChar = value.stack.Pop(); + var movedCharInfo = charInfos[movedChar]; + spaces[i] = movedChar; + long curCost = (Math.Abs(i - value.stackPos) + (maxStackDepth - value.stack.Count)) * movedCharInfo.cost; + Solve(charInfos, spaces, cost + curCost); + value.stack.Push(movedChar); + spaces[i] = '.'; + } + } } - - // first check that all chars from spaces that can be moved to its corresponding stack has been moved - // if possible, call recursive (remember what has been moved and undo after call) - // iterate all stacks, check if stack contains element that does not fit. then move the top most element - // after move, call recursive - - // if move is not possible, return int max? each recursive all needs to optimize su-calls to minimum. hand down current minimum to check against? (can be done in second step. solve first?) - - } +int NumberOfChars(Dictionary charInfos, char[] spaces) { + return charInfos.Values.Select(i => i.stack.Count).Sum() + spaces.Count(c => c != '.'); +} + +bool CheckMoveToSpacesImpossible(int from, int to, char[] spaces) { + int min = Math.Min(from, to); + int max = Math.Max(from, to); + + for (int i = min; i <= max; i++) { + if (spaces[i] != '.') { + return true; + } + } + return false; +} + +bool CheckMoveFromSpaces(int posInSpaces, char[] spaces) { + CharInfo charInfo = charInfos[spaces[posInSpaces]]; + if (charInfo.stack.Any(c => !c.Equals(spaces[posInSpaces]))) { + return false; + } + + int min, max; + if (charInfo.stackPos == posInSpaces) { // should not happen + return true; + } else if (charInfo.stackPos > posInSpaces) { + min = posInSpaces + 1; + max = charInfo.stackPos; + } else { + min = charInfo.stackPos; + max = posInSpaces - 1; + } + + for (int i = min; i <= max; i++) { + if (spaces[i] != '.') { + return false; + } + } + return true; +} + +bool Solved(Dictionary charInfos, char[] spaces) { + if (spaces.All(c => c == '.') && charInfos.All(info => info.Value.stack.All(c => c == info.Key))) { + return true; + } + + return false; +} + +record CharInfo(Stack stack, int stackPos, long cost); #endif \ No newline at end of file diff --git a/day23/input b/day23/input index 0d24baf..d8f9d66 100644 --- a/day23/input +++ b/day23/input @@ -1,5 +1,7 @@ ############# #...........# ###B#C#C#B### + #D#C#B#A# + #D#B#A#C# #D#D#A#A# #########