# Escape from the magic prison

You're locked in one of three magical cells (yellow circles) located at the vertices of a triangle. In each cell there're three transporters numbered 1, 2 and 3, one of which transports you to the cell in the clockwise direction, one transports you to the cell in the counterclockwise direction, and the third transports you to itself, but you have no idea which does which, and the numbering system is not consistent between cells. The cells looks identical and eliminate any marks you make after each transportation. The only way to break from the cells is to make 3 consecutive transportations in the clockwise direction (blue arrows). What is the minimum number of transportations needed to guarantee your escape?

• Do all cells with the same number transport in the same direction? Commented Sep 3 at 15:28
• @ChrisCudmore Nope. For example, transporter 1 may transport clockwise in one cell and counterwise in another cell.
– Eric
Commented Sep 3 at 16:15
• @ChrisCudmore It would be a rather uninteresting puzzle if the only possible solutions were 111, 222, or 333. Commented Sep 3 at 16:42
• @NuclearHoagie I agree, but we do need to be specific about the details Commented Sep 3 at 16:56
• When I'm in a room, can I identify 1,2 & 3?
– JNF
Commented Sep 4 at 13:15

## Upper Bound = 36

These were found using a Depth-First Search with pruning.

$$36$$ presses:

111233233311312321212131213231313222
122233133322321312121232123132323111
123313332222321312121232123132323111
123323331111312321212131213231313222


More solutions

## Analysis of Solutions

solutions considered:

111233233311312321212131213231313222
1112133233312212321131233112213222131
1112321131221332331333213112311223222
1213323331221232113123311221322213111
1233133322321312121232123132323111222
1233231213131323132123232111333221222
1233332312131313231321232321112221221


This table shows how many of the 216 possible configurations are "unsolved" for each solution, after $$k$$ button presses: $$\begin{array} {c} \text{k} & 111233... & 111213... & 111232... & 121332... & 123313... & 123323... & 123333... \\ \hline 1 & 216 & 216 & 216 & 216 & 216 & 216 & 216 \\ 2 & 216 & 216 & 216 & 216 & 216 & 216 & 216 \\ 3 & 208 & 208 & 208 & 208 & 208 & 208 & 208 \\ 4 & 208 & 208 & 208 & 204 & 200 & 200 & 200 \\ 5 & 202 & 204 & 202 & 192 & 190 & 192 & 192 \\ 6 & 194 & 200 & 194 & 185 & 183 & 189 & 192 \\ 7 & 186 & 188 & 188 & 176 & 176 & 187 & 192 \\ 8 & 183 & 182 & 178 & 168 & 168 & 177 & 186 \\ 9 & 178 & 173 & 165 & 160 & 168 & 171 & 184 \\ 10 & 170 & 164 & 157 & 160 & 162 & 164 & 174 \\ 11 & 170 & 156 & 151 & 150 & 150 & 149 & 168 \\ 12 & 163 & 156 & 141 & 144 & 147 & 149 & 161 \\ 13 & 151 & 146 & 133 & 132 & 146 & 140 & 146 \\ 14 & 149 & 140 & 132 & 129 & 128 & 131 & 146 \\ 15 & 148 & 128 & 125 & 128 & 122 & 130 & 137 \\ 16 & 133 & 125 & 116 & 116 & 117 & 125 & 128 \\ 17 & 127 & 124 & 107 & 113 & 102 & 123 & 127 \\ 18 & 120 & 112 & 101 & 105 & 102 & 108 & 117 \\ 19 & 105 & 109 & 101 & 96 & 93 & 99 & 115 \\ 20 & 105 & 99 & 95 & 87 & 84 & 93 & 100 \\ 21 & 96 & 90 & 84 & 80 & 84 & 90 & 91 \\ 22 & 87 & 81 & 76 & 74 & 81 & 88 & 85 \\ 23 & 86 & 74 & 76 & 74 & 80 & 73 & 82 \\ 24 & 83 & 68 & 67 & 62 & 65 & 73 & 80 \\ 25 & 83 & 68 & 59 & 59 & 59 & 64 & 65 \\ 26 & 68 & 56 & 59 & 51 & 55 & 63 & 65 \\ 27 & 59 & 53 & 56 & 48 & 55 & 45 & 56 \\ 28 & 53 & 43 & 51 & 48 & 51 & 37 & 55 \\ 29 & 53 & 40 & 48 & 44 & 40 & 37 & 37 \\ 30 & 51 & 40 & 39 & 36 & 40 & 37 & 29 \\ 31 & 36 & 36 & 39 & 24 & 35 & 29 & 29 \\ 32 & 36 & 28 & 30 & 16 & 34 & 29 & 23 \\ 33 & 27 & 16 & 24 & 16 & 16 & 29 & 15 \\ 34 & 26 & 8 & 15 & 11 & 8 & 17 & 15 \\ 35 & 8 & 8 & 10 & 8 & 8 & 11 & 9 \\ 36 & 0 & 3 & 8 & 8 & 8 & 8 & 3 \\ 37 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ \end{array}$$

• Nicely done. Can I ask what heuristic you used for this search? Commented Sep 11 at 6:10
• Thanks! There are 216 configurations to consider, and I keep the candidates (partial button sequences) that "solve" the most configurations. Commented Sep 11 at 6:29
• Excellent work! Do you feel this can be improved? Commented Sep 11 at 11:39
• Well, I was wrong, 36 is possible! Commented Sep 11 at 16:17
• It's very interesting that the length 36 solution is lagging behind the length 37 solutions (in terms of number of prisonerss that have already escaped) for almost its entire length. We can see why a greedy algorithm, selecting a partial solution based on its prefix has a hard job of finding the optimal solution. Commented Sep 12 at 19:35

The best upper bound I've found is 39. Here are a few sequences which should solve every possible configuration:

111231222131212323231323213112213333131
111231222131212123332123231313212233113

• Why would you necessarily need to include every sequence of length 3? I'm not so convinced that this is the case! (What you certainly do need is to have a rotated copy of every sequence, possibly even multiple copies. But that might well be possible with less than 27 moves.) Commented Sep 6 at 13:12
• What is very interesting to me is that there are only two instances of "131" (and no rotations of it) in the entire string. As such, a lower bound just arguing along sequence frequency (up to rotation) can not even improve upon one occurence of 111,222,333 each and two occurences of the other eight classes. Now I wonder if there might even be a winning sequence that has only a single occurence of some specific class ... Commented Sep 6 at 13:52
• @TimSeifert: you're right, I just removed the lower bound. :) and added a few more 40-move sequences. Commented Sep 6 at 14:17
• What's the reasoning behind these 40-move solutions? Commented Sep 6 at 16:16
• @Lawrence: kind of. I started by generating random sequences until I got a satisfying solution, then I started brute-forcing random mutations on my shortest strings until they got shorter and shorter. :) Commented Sep 9 at 11:39

This is probably an extraordinarily weak bound, but to get things started, I claim that we can guarantee to get out in no more than

$$1944(=3\times 3\times 6^3)$$ turns.

To achieve this bound, observe that

at the beginning of the game, the world is in exactly one of $$3\times 6^3$$ possible states (as we have three possible starting locations and the buttons in each room have six possible ways of working each). Start by enumerating these possible worlds in any way we like.

Now, to find the strategy

we may start by playing the winning sequence from world 1. If that doesn't win, we simply continue by assuming we are in world 2 and play the sequence that would now win. (Since the states code all the button behaviours, there is no question as to where we are if this is indeed world 2.) In that manner we can progress through these $$648$$ hypotheses and play three moves for each of them. Since the starting state is among them, we are guaranteed to win eventually.

This can probably be cut down quite a bit. Right away, there are two obvious options. Firstly

any one 3-move sequence is winning for more than a single world. In fact, every single 3-move sequence is winning for exactly $$24=(3\times 2^3)$$ worlds (as, for every possible position that we're in, the two buttons in each room that are irrelevant may have two possible functions each.) Even though this improves the start, I don't see how to easily implement that insight, since the strategy above does depend on being able to compute our location for each hypothesis, which is obviously sensitive to the behaviour of all the buttons, not just the winning ones.

And, secondly

there is probably a way to enumerate the states such that we may interleave some of the segments instead of starting fresh each time. If maximal overlap is achievable, this will cut down the length (roughly) by a factor of 3.

But I didn't think about implementing these much more, this answer is mostly just to show that it can be done at all.

• Because the three cells have identical rules, you can assume the starting location is $1$ and then consider $3!^3=216$ scenarios. Commented Sep 3 at 23:29
• I think the pigeonhole principle guarantees you can pick 3-move sequences that win in at least $\lceil2/27\rceil$ of remaining worlds. Commented Sep 4 at 2:11
• Does this guarantee a win? I think we still need some knowledge about where we're starting to make sure we try all possibilities. Say you try the World 1 sequence, suppose it assumes you're in Room 1 and the winning sequence is 112, and that it doesn't work. Now you go to World 2 assuming you're in Room 2 and the sequence is 112, it doesn't work, and then you try World 3 assuming you're in Room 3 and the sequence in 112. But in reality you started in Room 1, and 112 took you to Room 2, back to Room 1, and then stayed put. Yet 112 still might have worked starting from Room 3... Commented Sep 4 at 14:12
• @NuclearHoagie A world in the sequence encodes not only the winning sequence but the behaviour of all buttons and our starting position (although this last bit is unneccessary as observed by RobPratt). In particular, when testing a world, we can calculate our current position, since we know where all the transporters so far would have brought us in that world. So the issue you bring up does not actually come up (but it is exactly the reason for including the behaviour of all buttons in the scenarios we consider). Commented Sep 4 at 14:46
• @NuclearHoagie Each world we are considering is the transporter settings plus the initial cell we started from before doing any moves. When testing each world, you have to take into account any moves you have done so far in previous tests to figure out which cell you would be in now in this assumed world. Commented Sep 4 at 15:07

I thought I'd throw my solution into the transporter as well.

I have a 93 move solution: not as good as ApexPolenta but this was without a computer.

Label the three rooms A, B, C around the circle. Suppose, starting in A, that 123 wins. Suppose you make the moves 123 123 123 231 123. I claim this wins no matter where you start or what the other transporters do.

Clearly this wins if we start in room A, so assume we're starting in room B. If 1 keeps you in room B, then you will then proceed to room C and room A, and then the next 123 wins (actually just the next 1). So assume that 1 takes you from B to A. From here, if the 2 takes you to room C, then you'd go back to A and again win with the next 123. Therefore, 2 keeps you in room A, and finally 3 takes you to room C, and this is the only situation that doesn't lead to a quick win.

Starting in room C, similar logic dictates that 1 keeps you in room C, 2 takes you to room B, and then 3 keeps you in room B (any other possibility will lead to a quick win). Thus we know exactly what the transporters do.

We just do not if we're in room B or C. If we're in B, the 231 wins. If we're in C, the 231 takes us to room A, and the 123 wins.

So you see we can guarantee a win if 123 wins in 15 moves. We can then do the same thing if 132 wins in another 15 moves.

Now suppose 112 wins. We can use similar logic to show that 112 112 121 is a guaranteed a win. A similar thing happens for 113, 221, 223, 331, 332, so this is 54 more moves.

If 111, 222, or 333 wins, we can just eliminate these with 111 222 333 (nine moves). This totals 93 moves.

• Maybe I'm misreading something, but why does this cover all possibilities? For instance, why should we win if the winning sequence (from A) is 321? I do see that this would give a strategy if you instead account for all 27 possible cases, but this would rather land at $6\times 15 + 18\times 12 + 3\times 3=315$ moves (not accounting for using possible overlap), which is still a notable improvement Commented Sep 4 at 18:12
• @TimSeifer Isn't 321 the same as 132? I labeled the rooms but the labels were arbitrary. Commented Sep 4 at 19:58
• @TimSeifert From what I understand, if the winning sequence is 3 different numbers in any order, then we label the rooms as follow: A the room that needs to play 1, B the next room and C the last one. Then we don't know which room we are in but everything is still covered. Commented Sep 4 at 21:58
• Ah I see now! You were right, I just got confused (thinking that your labeling was fixed throughout when it needn't be). But it's all there, nice strategy! Commented Sep 4 at 23:01
• You have 11 sequences to do (counting 111, 222, 333 as 3 different sequences). You can start a sequence using the last (1 or 2) move(s) of the previous one. I counted 15 theoretical overlaps but I only managed to achieve 14 when chaining all together. Still, -14 would bring your solution to 79, a nice improvement. Commented Sep 5 at 23:40

I cobbled together a Python script to test Tim's ideas, with some added insights:

The next 3 moves could be the solution to multiple hypotheses. Also, there's no need to test hypotheses one at a time. You can simulate what would happen with your current move list in all remaining hypotheses. Basically what Tim said, but implemented in brute force.

I still don't guarantee optimality, because

I'm basically using a greedy algorithm after discrete chunks of 3 moves. There may be some globally better strategy or some way to interleave between chunks of moves.

That being said, following the strategy set out in the code gives an improved upper bound of

66.

Edit: I've cleaned up the code a bit, and added tracking of how many correct steps have already been done in the room. With this update, the bound is improved to

51.

Code if you want to experiment with it:

#single step simulation of a move in a world
def step(move, world):

room = world[0][(3*world[1]): (3*world[1]+3)]
#anticlockwise
if move == room[0]:
world[1] = (world[1]-1) % 3
#reset clockwise steps
world[2] = 0
#clockwise
elif move == room[2]:
world[1] = (world[1]+1) % 3
#keep track of clockwise steps
world[2] += 1
#no move
else:
#reset clockwise steps
world[2] = 0

######################################################################################

#check if the trial 3 moves solves the given world
def isSolution(trial, world):

portals = world[0]
currentRoom = world[1]

#take into account that some rooms have some previous progress already
solution = \
(world[2]<3)*portals[(3*(currentRoom+0)+2) % 9] + \
(world[2]<2)*portals[(3*(currentRoom+1)+2) % 9] + \
(world[2]<1)*portals[(3*(currentRoom+2)+2) % 9]

return trial[:len(solution)] == solution

######################################################################################

#get the best move from the state of possible worlds.
#'best' defined as the choice that eliminates more worlds
def getBestMove(next3Moves, worlds):

#record best worlds removed, and the move that did it
best = 0
bestMove = ''

#try each of the possibilities
for trial in next3Moves:
current = 0
for world in worlds:
if isSolution(trial, world):
current += 1
if current>best:
best = current
bestMove = trial
return bestMove

######################################################################################

#run a simulation on all worlds and remove worlds that would have been solved
def simulate(trial, worlds):

i=0
while i<len(worlds):
#trial solves this world, delete it
if isSolution(trial, worlds[i]):
worlds.remove(worlds[i])
else:
#move between rooms
for move in trial:
step(move, worlds[i])
i+=1

######################################################################################

#all possible sets of next 3 moves
next3Moves = ['111','112','113','121','122','123','131','132','133','211','212','213','221','222','223','231','232','233','311','312','313','321','322','323','331','332','333']

#for constructing all room possibilities
p = ['123','132','213','231','312','321']

worlds = []

#construct room possibilities
for a in p:
for b in p:
for c in p:
#each world has the format [portal structure, current room, clockwise steps taken]
worlds.append([a+b+c,0,0])

moveCount = 0

#while there are still unsolved worlds:
while len(worlds)>0:
#find the next best move, and then simulate what happens in all possible worlds
nextMove = getBestMove(next3Moves, worlds)
print(nextMove)
simulate(nextMove, worlds)
moveCount += 3

print(moveCount)

• You could also try the greedy approach with different lookahead lengths (1, 2, 4,...), maybe even a dynamic one that grows when there are fewer states left. I'm also curious how well completely random sequences perform on average. Commented Sep 4 at 2:18
• @noedne If you choose randomly each time, the expected number of moves needed to escape is 39. How do you think the minimum number for guaranteed escape would compare to this number?
– Eric
Commented Sep 4 at 3:31
• Interesting that the resulting sequence is so short tbh. My hunch was that an optimal sequence should take around 81 turns (give or take), which seems to be way off now ... Commented Sep 4 at 14:48
• @TimSeifert I have a sequence which can complete every possible configuration in 45 moves (I was able to test it with a computer). Not sure how lower the optimal sequence is though, I feel like it can still be improved, especially considering that 39 Commented Sep 4 at 19:06
• @TimSeifert new approach! I was able to reduce the sequence down to 40 moves, but I still don't feel this is optimal. Commented Sep 5 at 21:09

I've reworked my code entirely in an attempt to find an optimum via A* search. I'm done encoding the worlds and simulation of moves, but I've yet to find a suitable heuristic.

My current heuristic is to assume that making a wrong move has no effect on a world (ie. Any progress towards escape is not reset, and you do not move room). Under these assumptions, a breadth-first search is performed from the given state. This heuristic is guaranteed to be admissible, as it represents a relaxation of the rules of the original problem.

In other words, if your computer is able to run this code, it will give you an optimal answer. I'm currently limited by hardware and inability to find a heuristic that's easier to calculate.

Side note - using the inadmissible heuristic of the number of unsolved worlds remaining quickly returns a solution of length 50.

Any assistance would be appreciated. Here's a brief summary of the model if you wish to experiment with it:

1. The configuration of portals is encoded as a string: [portal in 1st room going anticlockwise][portal in 1st room that moves nowhere][portal in 1st room going clockwise][same again for 2nd room][and 3rd room]. For example, if the room configuration is 132231321, then the portal in the 2nd room going clockwise would be the bolded one.
2. The state of a world is encoded as ([portal configuration], [current room], [clockwise steps taken]). As an example, ('132231321', 3, 1) means you are currently in the 3rd room, having previously taken 1 clockwise step already.
3. A node of the A* algorithm is given as ([previous move], [tuple of possible world states]).

Code below.

from astar import AStar
import copy

######################################################################################################

#single step simulation of a move in a world
def step(move, worlds, heuristicSim = False):

res = []

for world in worlds[1]:

#record initial values (these are sometimes not updated)
room = world[0][(3*world[1]): (3*world[1]+3)]
roomNum = world[1]
stepNum = world[2]
#anticlockwise (or no effect if solving relaxed problem)
if move == room[0] and not heuristicSim:
roomNum = (world[1]-1) % 3
#reset clockwise steps
stepNum = 0
#no move (or no effect if solving relaxed problem)
elif move == room[1] and not heuristicSim:
roomNum = world[1]
#reset clockwise steps
stepNum = 0
#clockwise
elif move == room[2]:
roomNum = (world[1]+1) % 3
#keep track of clockwise steps
stepNum = world[2] + 1

#if stepNum is 3, then the world is solved
if stepNum != 3:
res.append((world[0], roomNum, stepNum))

return (move, tuple(res))

######################################################################################################

def getHeuristic(worlds):

#assume a move has no effect on a world unless it makes progress
moveCount = 0
sim = copy.deepcopy(worlds)
return len(list(HeuristicSolver().astar(sim, goal)))

######################################################################################################

class HeuristicSolver(AStar):

def __init__(self):
pass

def heuristic_cost_estimate(self, n1, n2):
return 0

def distance_between(self, n1, n2):
return 1

def neighbors(self, node):
return [step('1', node, True), step('2', node, True), step('3', node, True)]

def is_goal_reached(self, current, goal):
return len(current[1])==0

######################################################################################################

class MazeSolver(AStar):

#No need for global parameters
def __init__(self):
pass

#Run BFS on the given state, with relaxed rules
def heuristic_cost_estimate(self, n1, n2):
return getHeuristic(n1)

#It always costs 1 move to, well, make 1 move through a portal
def distance_between(self, n1, n2):
return 1

#Try each of the portals
def neighbors(self, node):
return [step('1', node), step('2', node), step('3', node)]

#use length of possible world states as the goal (so that tracking of last moves can be used)
def is_goal_reached(self, current, goal):
return len(current[1])==0

######################################################################################################

#for constructing all room possibilities
p = ['123','132','213','231','312','321']

worlds = []

#construct room possibilities
for a in p:
for b in p:
for c in p:
#each world has the format [portal structure, current room, clockwise steps taken]
worlds.append((a+b+c,0,0))

#not really necessary, but it seems the goal state is not an optional argument
goal = ()

#solve the problem!
path = list(MazeSolver().astar(('0', tuple(worlds)), goal))
print(path)


• You are searching a heuristic for a lower bound on the remaining moves ? An idea: solve for a small but "representative and difficult" subset of the possible worlds, and use this subset as a heuristic for the complete solve. Commented Sep 10 at 8:41
• You can save the second parameter by rotating the rooms instead of keeping track of your position. ('132231321', 3, 1) really is the same as ('321132231', 1, 1) isn't it? This way you reduce the number of states by factor 3 Commented Sep 14 at 8:36

After looking at the problem, I think this problem resembles the "expectancy" problem in mathematics. And this is my way of solving it:

3 + 9 + 27 = 39.

You need at least 39 moves to guarantee your escape. So how does this simple equation solve the problem?

Basically, for the first move you have a 1/3 chance of picking the "correct" door (the one that transports you in the clockwise direction), so your expectancy for getting the right door is 3.

For the second move, it's the same logic, except you have a (1/3)^2 chance of getting 2 "correct" doors consecutively, so your expectancy for getting 2 right doors is 9.

The third move is the same, giving you an expectancy of 27.

Add all those up, and it's the desired answer (I believe).

This is my method of solving using my middle-school knowledge, so if there's any mistakes or scenarios which I have not taken into account for, please tell me, I'd be glad to learn more :D

New contributor
02熊正 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
• You are correct that a random strategy yields $39$ as the expected number of steps. But @TomSirgedas has shown that $36$ steps suffice. Commented Sep 14 at 18:24
• oh...i did not expect that
– 02熊正
Commented Sep 15 at 17:31

Step 1.

For every room, there exists a three step-combination that leads to a full clockwise circle. For every room, there exists one preliminary step that lets you reach this room from any room. This leads to a four-step solution that first reaches a specific start-room, then goes in a clockwise full circle.

As Jaan Scherphuis pointed out, this step does not take into account that the "winning" combination might not be started from the correct room, thus rendering the entire solution moot.

Step 2.

All 4-digit combinations of the digits 1,2,3 should be considered possible solutions. This can be reduced by some logic steps to reach a better solution (e.g. 1111 is not a possible solution, since it would already end after 111).

Step 3.

Combine the 81 partial solutions into a sequence that is 84 steps long. During this sequence, a clockwise rotation starting in each room is necessarily done. An example for one such sequence would be 1322311211313322122332323131212133132331132131111222232221113331221323211231233332123

Step 4.

This provides an upper bound of 82 since the three correct solutions might overlap and be at the end. This can further be reduced to 79 by reducing the number of partial solutions by 3 (1111,2222,3333 would not need to be fully run if they are solutions)

This attempt at an upper bound is thus not as strong as ApexPolenta's upper bound.

• Welcom to Puzzling SE! I'm afraid your solution does not work for the same reason a deBruijn sequence of all 3-move combinations does not work. Suppose 123 is the solution starting from the first cell. At some point you will try 1123, 2123, and 3123. Whichever room you are in, one of those three 4-move sequences will solve it, but you don't know which one. The problem is that you are not necessarily trying out all three sequences starting from the same cell. What if, each time you try one of these sequences, you are in the wrong cell for it to work? Commented Sep 4 at 14:52
• That is a really good point. I had just calculated from the status quo without taking into account that the states matter at each point. Will add this correction - but I fear that makes this attempt not really salvageable. Commented Sep 5 at 5:51

## Edit:

Yes, I am missing something. After it was explained in the comments, I understand what I'm missing, but I'm going to leave this answer so others can learn from my mistake.

Since I know it's wrong, please don't DV this anymore.

Maybe I'm missing something, but this seems pretty simple.

3 steps for minimum escape

And:

4 steps for minimum guaranteed escape*

We only need to go clockwise 3 steps, right? So the correct pattern is:

1231

If we start in cell:
1

We don't go anywhere, so that transportation doesn't count for us.

2

We go counterclockwise, so that transportation doesn't count for us.

3

We go clockwise, so that's our first success.

After that:

We will continue to go in a clockwise motion following the 1231231... pattern, so it doesn't matter if we need 3 transportations, 3 full revolutions, or 300. The only real problem is to "find" cell 1 and then the pattern guarantees we keep moving in the correct path. And regardless where we start, hitting 1 will take us to cell 1, so we can hit 2 knowing that it'll take us to cell 2, and 3 to go to cell 3, and then hit 1 to go back to cell 1 to continue the pattern, if needed.

*Maybe what I'm missing is if we don't know which order the cells are arranged in. My previous statements assumed that the cells are actually numbered in a clockwise manner. If not:

Reverse the pattern to change direction, so 3213213. The number of steps are the same.

You can figure out which direction the cells are numbered in by:

Going one direction the required number of steps, and it if doesn't release you, reverse the pattern.

So, the minimum number of steps to guarantee escape if we don't know if the cells are numbered in clockwise or counterclockwise order is:

7 using the pattern: 1231321

And that's my final answer. ;-)

• Yes, you're missing something - you don't know where any of the portals go. In the first room, the portal marked '1' could go clockwise, stay in the same room, or go anticlockwise. Same with the other two rooms, and each room is independent. Commented Sep 4 at 1:59
• What ApexPolenta said. The rooms are identical every time, so when you step into a portal, you essentially don't even know if you've moved at all, because you may have moved to a different space that looks identical. Commented Sep 4 at 13:22
• @ApexPolenta, thanks. I didn't realize that each individual transporter did different things in different cells. That was definitely the thing I was missing! Commented Sep 4 at 17:18