Sei sulla pagina 1di 4

A Solver Algorithm for ActionXLs Cube Escape

Noah Santorello April 21, 2009

The Problem

We wish to devise a polynomial-time ecient algorithm that nds an optimal solution path through a level of Cube Escape or determine that a solution doesnt exist. We dene the length of path p = (ta , tb ) between two tiles ta , tb to be the smallest number of cube moves required to get from ta to tb , denoted by L(p). Let S be the set of all solutions to a level C. We dene an optimal solution path to be a path p such that for all paths r S, L(p) L(r). Notice we are looking for an optimal solution instead of the optimal solution, since there could be two solution paths p, p with L(p) = L(p ) and such that for all r S, L(r) L(p). That is, there could exist a level with two or more solution paths of equal length, but for which no solution of a smaller length exists.

The Algorithm

The algorithm employs a dynamic programming approach. First, we will present the na ve algorithm, and then we will present the optimization that makes it ecient. Our algorithm is simplestarting from the start tile in the level, we will explore every possible legal move from the current tile to the current and surrounding tiles, employing all three ip, hop, and roll actions. This method explores every possible move within the level, which innately means that we will create a tree of all possible move sequences in the level. We will expand the tree in a breadth-rst manner. As a result, the rst path that nds its way to the ending tile will be a shortest path solution to the level. Thus, when we nd such a path, we will return it and terminate. It is important to notice two things about our current algorithm. First, it is unable to tell whether or not a level has a solution. Since our algorithm only terminates when it nds a solution, it will not terminate until it nds one. Thus, if a solution does not exist, it will not terminate. This will be remedied later with our optimiation. Second, it is horribly inecient. Along a solution path, there exists a minimum of two moves at every possible tilethe move going forward to the end tile and the move going backward to the start tile. Just in the process of nding only a solution path p, we will be constructing a tree with at least 2L(p) nodes. In most cases, there will even exist more than one possible move o of a tile. Thus, our algorithm currently lacks some necessary features for it to be useful and also runs in exponential, O(cn ) time.

However, a small realization allows us to improve upon this algorithm to the point that it becomes extremely ecient. Given a tile t, the bottom color b of the cube, and the color d of the cube facing the positive x direction, we can dene a game conguration a = (t, b, d). The optimization comes from realizing that we are looking for the shortest solution path. When executing the above brute-force algorithm, we store every conguration we encounter. Then, when executing the brute force algorithm we ensure that before branching out, we check to see if the current conguration has been seen. If it hasnt, we branch as usual. However, what if it has? It is important to realize that if weve already seen this conguration before, weve technically explored that subtree. So since another branch has already visited this node with the same conguration, we end the branch and expand it no further. We can do this because, as mentioned, we are only interested in nding a shortest solution path. Thus, if the already-visited conguration was part of a shortest solution path, then another branch in our tree has already been in that conguration before this visit. Since its been there before the visit, it means that a shorter path has been found to that tile. Using a recursive argument, we can extend this to the ending tile, so that when we rst encounter the ending tile, we can be condent that this is a shortest solution path. The correctness of this argument will be proven formally later. To store the congurations (t, b, d) of each state, we simply build a three-dimensional array of bit ags; one dimension for each of the three parts of the conguration. We can build an array out of this since we can convert each of t, b, d to indices. We could represent each color as an integer, starting from zero, and could simply assign each tile a number starting from zero as an id. Notice that for a given b value, there are only four possible d values. Thus, if there are n tiles on the board, we will need a bit matrix of size 6 4 n = 24n bits, or 24n = 3n bytes. Thus, a fairly large level with 100 tiles will only require 300 bytes of 8 space to run our algorithm. Thus, our algorithm has memory usage that is linear (with low coecient) in the number of tiles on the board. To formalize our algorithm, we present pseudocode for it.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:

B bit ag matrix Q path queue s starting path (start tile conguration) dene func C(x) current conguration of path x enqueue s; ag s in B while Q is not empty do p dequeue element of Q if C(p) is an ending conguration then return p end if for each possible conguration m B reachable from C(p) do / p {p, m}; ag m in B; enqueue p end for end while return no solution
2

Proof of Correctness

Claim 1. The algorithm terminates. Proof. Our while condition is that the path queue is not empty. Since we dequeue from the path queue once per loop iteration, we know that our algorithm will only cease to terminate if we continue to place paths into the queue. The start path is placed into the queue only once. After that, the only things that are placed into the queue are paths with possible future congurations that are not agged as visited in the bit ag matrix. Since every time a conguration is placed into the queue it is agged, the algorithm will only ever enqueue as many paths as there are dierent possible congurations. Thus, since our algorithm removes a path from the queue on every iteration and the number of enqueue operations our algorithm performs is bounded, we know our algorithm will eventually terminate. 2 Claim 2. The algorithm correctly returns the optimal (shortest) solution path, if one exists. Proof. It is obvious that the brute force version of the algorithm is able to nd a shortest solution path, if one exists. We must show the our modications to the brute force algorithm preserve its correctness. Note that our modication restricted when we were allowed to enqueue paths into the path queue so that we could only enqueue a path if its next move puts it in an unvisited conguration. We will undeniably destroy the brute force algorithms capability to search through the space of all possible paths that can be played in the game; however, we do not destroy the discovery of the shortest solution path. We prove this by contradiction. If the path p being explored is a shortest solution path s, then the next conguration c that p wants to move to could not have already been visited. If c was already visited, that means that another path p beat p to c along s. If this was the case, then p will end up exploring all of its options, which includes exploring the rest of s to the end tile. Thus, if c was visited before p by p , then L(p) L(p ); if L(p) > L(p ), we have a contradiction; if L(p) = L(p ), then the level has two or more shortest solutions and it doesnt matter which one we explore, so throwing out p and pursuing p will still yield an optimal solution. 2 Claim 3. The algorithm correctly reports no solution when there is no solution path. Proof. Our algorithm correctly nds a shortest solution path, if one exists, by Claim 2. Thus, if our algorithm doesnt nd one, the while loop will terminate after exploring all possible congurations (by Claim 1) and return no solution. 2

Runtime Analysis

All operations in the pseudocode take constant time. However, searching over all possible successive congurations reachable from a tile might not be so obvious on how to do in constant time. If we construct a hash map of points to tiles, then we can check for adjacent tiles by checking the map at points up, down, left, and right of the current tiles location. We can nd edges in this manner in constant time (since there are at most four possible adjacent tiles, and eight with elevator tiles). It should be easy to see that all other lines of the pseudocode take constant time as well.
3

For a level with n tiles, there are 24n possible congurations (and possible loop iterations). Additionally, the foreach loop runs as many times as there are edges from the current conguration, which means it runs in O(e). Thus, our algorithms running time is O(24n e) = O(ne), meaning that its runtime is a linear function of the number of tiles and the interconnectedness of the tiles. Note that building the hash map takes O(n) time to construct1 , since all we are doing is dumping tiles into a map. It is unlikely that we will need to nd a more ecient algorithm than this one (or that such an algorithm actually exists).

1 Thanks to Shu Song who pointed out this improvement to the old algorithm, which used an adjacency graph that took O(n2 ) time to construct.

Potrebbero piacerti anche