Refactor move to take a number of cups to move in day 23
parent
0ef1fc62e8
commit
c980fdf735
|
@ -131,86 +131,45 @@ class CupGraph {
|
||||||
CupGraph::const_iterator(*this, start), CupGraph::const_iterator(*this, CupGraph::const_iterator::END));
|
CupGraph::const_iterator(*this, start), CupGraph::const_iterator(*this, CupGraph::const_iterator::END));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Move the cup at key to be clockwise to dest
|
|
||||||
*
|
|
||||||
* **This is not used in the final solution, but is kept for posterity**
|
|
||||||
*
|
|
||||||
* @param key The cup to move
|
|
||||||
* @param dest The cup that will be counterclockwise to key (i.e. key will be clockwise to dest)
|
|
||||||
*/
|
|
||||||
void move(int key, int dest) {
|
|
||||||
auto keyIt = this->neighbors.left.find(key);
|
|
||||||
auto destIt = this->neighbors.left.find(dest);
|
|
||||||
if (keyIt == this->neighbors.left.end() || destIt == this->neighbors.left.end()) {
|
|
||||||
throw std::out_of_range("Item not in map");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto counterclockwiseFromKeyIt = this->neighbors.right.find(key);
|
|
||||||
if (counterclockwiseFromKeyIt == this->neighbors.right.end()) {
|
|
||||||
throw std::invalid_argument("Key has no counterclockwise neighbor");
|
|
||||||
}
|
|
||||||
|
|
||||||
int clockwiseFromKey = keyIt->second;
|
|
||||||
int clockwiseFromDest = destIt->second;
|
|
||||||
int counterclockwiseFromKey = counterclockwiseFromKeyIt->second;
|
|
||||||
// Unfortunately, using replace doesn't work because we expect that each side has exactly one of each element,
|
|
||||||
// so doing this shuffle is not possible with replace, without some serious edgecasing.
|
|
||||||
this->neighbors.right.erase(key);
|
|
||||||
this->neighbors.left.erase(key);
|
|
||||||
this->neighbors.left.erase(dest);
|
|
||||||
|
|
||||||
// Stitch the counterclockwise neighbor to be the one clockwise to keyIt
|
|
||||||
this->neighbors.left.insert({counterclockwiseFromKey, clockwiseFromKey});
|
|
||||||
// Stitching the key to have the same neighbor as the destination did
|
|
||||||
this->neighbors.left.insert({key, clockwiseFromDest});
|
|
||||||
// Stitch the destination to be adjacent to the key
|
|
||||||
this->neighbors.left.insert({dest, key});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The same as move, but moves key, key's neighbor, and key's neighbor's neighbor, at once
|
* The same as move, but moves key, key's neighbor, and key's neighbor's neighbor, at once
|
||||||
* @param key The key to move
|
* @param key The key to move
|
||||||
* @param dest The destination to move to
|
* @param dest The destination to move to
|
||||||
*/
|
*/
|
||||||
void move3(int key, int dest) {
|
void move(int key, int dest, int numToMove) {
|
||||||
auto keyIt = this->neighbors.left.find(key);
|
auto keyIt = this->neighbors.left.find(key);
|
||||||
auto destIt = this->neighbors.left.find(dest);
|
auto destIt = this->neighbors.left.find(dest);
|
||||||
if (keyIt == this->neighbors.left.end() || destIt == this->neighbors.left.end()) {
|
if (keyIt == this->neighbors.left.end() || destIt == this->neighbors.left.end()) {
|
||||||
throw std::out_of_range("Item not in map");
|
throw std::out_of_range("Item not in map");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the two elements after the key.
|
|
||||||
auto keyIt2 = this->neighbors.left.find(keyIt->second);
|
|
||||||
if (keyIt2 == this->neighbors.left.end()) {
|
|
||||||
throw "Invalid state: elements are not linked together";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto keyIt3 = this->neighbors.left.find(keyIt2->second);
|
|
||||||
if (keyIt3 == this->neighbors.left.end()) {
|
|
||||||
throw "Invalid state: elements are not linked together";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto counterclockwiseFromKeyIt = this->neighbors.right.find(key);
|
auto counterclockwiseFromKeyIt = this->neighbors.right.find(key);
|
||||||
if (counterclockwiseFromKeyIt == this->neighbors.right.end()) {
|
if (counterclockwiseFromKeyIt == this->neighbors.right.end()) {
|
||||||
throw std::invalid_argument("Key has no counterclockwise neighbor");
|
throw std::invalid_argument("Key has no counterclockwise neighbor");
|
||||||
}
|
}
|
||||||
|
|
||||||
int key3 = keyIt3->first;
|
auto endOfRangeIt = keyIt;
|
||||||
int clockwiseFromKey3 = keyIt3->second;
|
for (int i = 1; i < numToMove; i++) {
|
||||||
|
endOfRangeIt = this->neighbors.left.find(endOfRangeIt->second);
|
||||||
|
if (endOfRangeIt == this->neighbors.left.end()) {
|
||||||
|
throw "Invalid state: elements are not linked together";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int endOfRangeKey = endOfRangeIt->first;
|
||||||
|
int clockwiseFromEndOfRangeKey = endOfRangeIt->second;
|
||||||
int clockwiseFromDest = destIt->second;
|
int clockwiseFromDest = destIt->second;
|
||||||
int counterclockwiseFromKey = counterclockwiseFromKeyIt->second;
|
int counterclockwiseFromKey = counterclockwiseFromKeyIt->second;
|
||||||
// Unfortunately, using replace doesn't work because we expect that each side has exactly one of each element,
|
// Unfortunately, using replace doesn't work because we expect that each side has exactly one of each element,
|
||||||
// so doing this shuffle is not possible with replace, without some serious edgecasing.
|
// so doing this shuffle is not possible with replace, without some serious edgecasing.
|
||||||
this->neighbors.right.erase(key);
|
this->neighbors.right.erase(key);
|
||||||
this->neighbors.left.erase(key3);
|
this->neighbors.left.erase(endOfRangeKey);
|
||||||
// this->neighbors.left.erase(key);
|
|
||||||
this->neighbors.left.erase(dest);
|
this->neighbors.left.erase(dest);
|
||||||
|
|
||||||
// Stitch the counterclockwise neighbor to be the one clockwise to the final element in our range
|
// Stitch the counterclockwise neighbor to be the one clockwise to the final element in our range
|
||||||
this->neighbors.left.insert({counterclockwiseFromKey, clockwiseFromKey3});
|
this->neighbors.left.insert({counterclockwiseFromKey, clockwiseFromEndOfRangeKey});
|
||||||
// Stitching the final element of our range to have the same neighbor as the destination did
|
// Stitching the final element of our range to have the same neighbor as the destination did
|
||||||
this->neighbors.left.insert({key3, clockwiseFromDest});
|
this->neighbors.left.insert({endOfRangeKey, clockwiseFromDest});
|
||||||
// Stitch the destination to be adjacent to the key
|
// Stitch the destination to be adjacent to the key
|
||||||
this->neighbors.left.insert({dest, key});
|
this->neighbors.left.insert({dest, key});
|
||||||
}
|
}
|
||||||
|
@ -362,7 +321,9 @@ void runGame(int startingCup, CupGraph &graph, int numIterations) {
|
||||||
|
|
||||||
// Since we move three at a time, we only need to get the first picked up cup
|
// Since we move three at a time, we only need to get the first picked up cup
|
||||||
int firstPickedUpCup = graph.getNext(currentCup);
|
int firstPickedUpCup = graph.getNext(currentCup);
|
||||||
graph.move3(firstPickedUpCup, destinationCup);
|
using tupleType = typename std::result_of<decltype (&getPickedUpCups)(int, const CupGraph &)>::type;
|
||||||
|
constexpr auto numCupsToMove = std::tuple_size<tupleType>::value;
|
||||||
|
graph.move(firstPickedUpCup, destinationCup, numCupsToMove);
|
||||||
|
|
||||||
currentCup = graph.getNext(currentCup);
|
currentCup = graph.getNext(currentCup);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue