This commit is contained in:
Stefan Forstenlechner 2021-12-27 14:30:25 +01:00
parent e41c655d6c
commit 07b84cfce1
2 changed files with 113 additions and 23 deletions

134
Day23.cs
View File

@ -4,39 +4,127 @@
var lines = File.ReadAllLines("day23/input")
.ToList();
var aStack = new Stack<char>();
var bStack = new Stack<char>();
var cStack = new Stack<char>();
var dStack = new Stack<char>();
var stackSpace = new Dictionary<Stack<char>, int>() {{aStack, 2}, {bStack, 4}, {cStack, 6}, {dStack, 8}};
var moveCost = new Dictionary<char, int>() {{'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<char, CharInfo>() {
{'A', new CharInfo(new Stack<char>(), 2, 1)},
{'B', new CharInfo(new Stack<char>(), 4, 10)},
{'C', new CharInfo(new Stack<char>(), 6, 100)},
{'D', new CharInfo(new Stack<char>(), 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<char>();
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<Stack<char>, int> stackSpace, char[] spaces) {
if (spaces.Any(c => c != '.')) {
void Solve(Dictionary<char, CharInfo> 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<char, CharInfo> 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<char, CharInfo> 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<char> stack, int stackPos, long cost);
#endif

View File

@ -1,5 +1,7 @@
#############
#...........#
###B#C#C#B###
#D#C#B#A#
#D#B#A#C#
#D#D#A#A#
#########