Day 23
This commit is contained in:
parent
e41c655d6c
commit
07b84cfce1
134
Day23.cs
134
Day23.cs
|
|
@ -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
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
#############
|
||||
#...........#
|
||||
###B#C#C#B###
|
||||
#D#C#B#A#
|
||||
#D#B#A#C#
|
||||
#D#D#A#A#
|
||||
#########
|
||||
|
|
|
|||
Loading…
Reference in New Issue