34
4
Create a program or function to unjumble a square of digits by flipping (reversing around the centre point) only rows and columns.
Input
Input will be a 9x9 grid of digits in the form of a 9 line string like the following:
986553229
264564891
759176443
643982153
567891234
526917874
685328912
891732537
117644378
This input format is non-negotiable - any solutions which are "creative" with the input format will be considered invalid.
Output
Output should be a list of flip moves which, when applied to the input in the given order, should recreate the target grid.
An example output (not a solution to the previous input example):
28IF5D3EAB9G3
This output format is also non-negotiable. There should be no newlines or spaces in the output, only the characters 1-9 and A-I (lower case characters are acceptable in place of upper case characters if you prefer).
The target grid (the state you need to recreate) is as follows:
123456789
234567891
345678912
456789123
567891234
678912345
789123456
891234567
912345678
The numbers 1-9 should be used as instructions to flip the rows, and the letters A-I should be used for the columns. This is shown below with the grid in its restored state.
ABCDEFGHI
|||||||||
vvvvvvvvv
1 -> 123456789
2 -> 234567891
3 -> 345678912
4 -> 456789123
5 -> 567891234
6 -> 678912345
7 -> 789123456
8 -> 891234567
9 -> 912345678
So an 8 means flip the second row from the bottom, and an F means flip the sixth column.
In the case that no solution is possible, the program should end without outputting anything at all.
Examples
Input:
987654321
234567891
345678912
456789123
567891234
678912345
789123456
891234567
912345678
Output:
1
In this case only the top row needs flipping to return to the goal state.
Input:
123456788
234567897
345678916
456789125
567891234
678912343
789123452
891234561
912345679
Output:
I
In this case only the final column (column I) needs flipping to recreate the goal state.
Input:
123456788
798765432
345678916
456789125
567891234
678912343
789123452
891234561
912345679
Output:
2I
In this case we need to flip row 2 and then flip column I to return to the goal state.
Notes:
- Please include an example usage in your answer.
- The output given does not have to be the shortest sequence that will return the goal state - any sequence which returns the goal state will do as long as it works (i.e. as long as I can test it)
- I'll endeavour to test each answer and upvote all those that work and have obviously had an attempt at golfing.
- This is an open-ended competition - I'll accept the shortest answer sometime next week, but if a newer valid answer comes along which is shorter at any point in the future I'll change the accepted answer to reflect that.
The bounty has been set at 200 reputation for the shortest answer received by 23:59:59 (GMT) on 26/01/2014The bounty was awarded to Howard for his 268 character GolfScript solution.
Testing
Please provide your program's output for the following three test grids with your answer:
986553229
264564891
759176443
643982153
567891234
526917874
685328912
891732537
117644378
927354389
194762537
319673942
351982676
567891234
523719844
755128486
268534198
812546671
813654789
738762162
344871987
341989324
567891234
576217856
619623552
194435598
926543271
I've created a small Python program to generate valid grids for testing purposes:
import random
def output(array):
print '\n'.join([''.join(row) for row in array])
def fliprow(rownum, array):
return [row[::1-2*(rownum==idx)] for idx,row in enumerate(array)]
def flipcol(colnum, array):
return zip(*fliprow(colnum, zip(*array)))
def randomflip(array):
op=random.randint(0,1)
row=random.randint(0,9)
if(op==1):
return fliprow(row, array)
else:
return flipcol(row, array)
def jumble(array):
arraycopy=array
for i in range(10, 1000):
arraycopy=randomflip(arraycopy)
return arraycopy
startarray=[
['1','2','3','4','5','6','7','8','9'],
['2','3','4','5','6','7','8','9','1'],
['3','4','5','6','7','8','9','1','2'],
['4','5','6','7','8','9','1','2','3'],
['5','6','7','8','9','1','2','3','4'],
['6','7','8','9','1','2','3','4','5'],
['7','8','9','1','2','3','4','5','6'],
['8','9','1','2','3','4','5','6','7'],
['9','1','2','3','4','5','6','7','8']]
print output(jumble(startarray))




8I just wrote a short solution that randomly flipped rows/columns until the sort was complete. After 500 million iterations it still had not solved the first puzzle you gave (where you only need to flip row 1). Randomness does not appear to be a usable solution to this problem! – Josh – 2014-01-15T15:20:10.447
3@Josh Not surprising. This problem appears to be very similar to solving a rubik's cube. I think some kind of breadth-first search would be the best brute force. That being said, the random algorithm theoretically has to terminate eventually, and appears to fit the rules specified. – Cruncher – 2014-01-15T16:49:59.740
The brute force would take 90^x, where x is the number of moves it takes to find the optimal solution, iterations. Does anyone know how many moves the optimal solution is on average? I guess memoization of already considered states helps a bit – Cruncher – 2014-01-15T16:56:43.033
4Brute force isn't needed. Consider the fact that each grid tile can only end up in one of four positions: its correct location, flipped X, flipped Y, or flipped XY. It may help you to mentally treat the grid as having (0,0) being the center-most tile. If you're solving tile (-2, 4), the only locations the target number could be is
(-2, 4),(2, 4),(2, -4), or(-2, -4). – Mr. Llama – 2014-01-15T18:21:16.593@GigaWatt I don't think that's true. I can get the upperleftmost 1 into
anysquare, so I'm not sure exactly what you're conjecturing. – Cruncher – 2014-01-15T21:28:57.257@Cruncher How do you do that? – Justin – 2014-01-15T21:48:58.493
2@Cruncher: Using whole row/column flips makes that impossible. For example, try to take the upperleftmost 1 (
A1) and move it toB1. You can get a1to the positionB1, but it'll be the tile fromB9, not the tile fromA1. Because we're only allowed whole row/column flips, the upperleftmost 1 will only ever be in one of the four outermost corners. If I've mistaken the rules, please let me know. – Mr. Llama – 2014-01-15T21:49:08.827@GigaWatt You are correct. Using only whole row/column flips means that the number in the upper left most corner will only ever be able to reach the other corner positions. – Gareth – 2014-01-15T22:50:23.077
Is it me, or does the very very first grid have no solution? – mniip – 2014-01-16T01:15:39.037
@mniip I used the python program given to generate that grid and the other 2 test cases. So either it can be solved or my program is buggy (which is possible, my python is poor :-) – Gareth – 2014-01-16T01:33:55.840
7Congratulations, Gareth. This is a very well-designed problem. Also, quite challenging. – DavidC – 2014-01-16T02:45:53.137
@DavidCarraher Thanks. I'm quite looking forward to trying it myself in python (though I may keep that code to myself :-) – Gareth – 2014-01-16T02:52:32.357
1@Gareth As you allow for functions, do you allow return instead of output? There is no big difference (for the code), but some languages (like Java) will be able to shave off some chars – Justin – 2014-01-16T05:17:37.083
@Quincunx Yes, returning a value from the function is acceptable, but it must be a string in the format required. – Gareth – 2014-01-16T06:33:11.707