How to programmatically solve the 15 (moving numbers) puzzle? - puzzle

all of you have probably seen the moving number/picture puzzle. The one where you have numbers from 1 to 15 in a 4x4 grid, and are trying to get them from random starting position to
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15
My girlfriend or some of my non-programmer friends can solve this with some mumbo-jumbo magic, that they can't explain to me. I can't solve the puzzle.
The most promising approach I have found out is to solve first row, then I'd get
1 2 3 4
X X X X
X X X X
X X X
then first column without touching solved cells
1 2 3 4
5 X X X
9 X X X
13 X X
then second row to
1 2 3 4
5 6 7 8
9 X X X
13 X X
then second column
1 2 3 4
5 6 7 8
9 10 X X
13 14 X
the problem is, that remaining X (random) tiles are sometimes in unsolvable position and this is where my solution fails. But I feel as if I'm on the right path.
My program does the solving of specified row/column by trying to get number X to specified position without messing up the correct cells, if possible. But it can't do the last 3 tiles on 2x2 grid. What am I missing?

Make sure that your puzzle is solvable first. Not all are.
Otherwise your strategy looks sound.

You're definitely on the right track, but rather than solving by row/column iteratively to the point of being left with a 2x2, solve until you have a minimum 3x3 and then solve just that grid. 3x3 is the smallest size you need to properly re-order the grid (while 2x2 doesn't give you the complete flexibility you may need as you've already discussed). This approach is scalable too - you can solve 5x5, 10x10 etc.

I think The most effective way of solving this, is using additive patterns, with an admisible heuristic, and IDA* algorithm. As described here - http://www.aaai.org/Papers/JAIR/Vol22/JAIR-2209.pdf. (I think Felner told us he found a way which is quite better, but I don't remember exactly what it was (bidirectional A*?), but anyhow this should be sufficient (-: ).
Anyhow this course was long ago, so I recommend reading the article..
HTH. Take care.

This site has a nice explanation about 3x3 grids, you could probably extend it to 4x4 quite easily.

By reduction the only possible case you can't solve must be of the form
1 3
2 X
and you want to get it to
1 2
3 X
by using an additional row and column you can move those to the proper positions with a simple precomputed sequence

The solution strategy described by the original poster will always work for a standard solvable 15-puzzle. If Axarydax can reduce a 15-puzzle to the state s/he described and still be unable to solve it, then it was impossible to begin with. Let me explain.
If we treat the blank space in the puzzle as one of the tiles, then each legal move involves swapping that blank "tile" for an adjacent tile. This allows us to regard motions on the puzzle as permutations on 16 characters. That is, elements of the symmetric group S16. Each primitive move is a "swap" or transposition between only two elements (one of which is the blank).
Because the puzzle begins and ends with the blank tile in the lower right, the blank tile must move an even number of times for the puzzle to be solved. (This is easiest to see by imagining an overlaid checkerboard pattern on top of the puzzle -- after an odd number of moves the blank would be on a different color square.) That means that the solution enacted must be a product of evenly many permutations, so it must be an element of the alternating group A16, which has exactly half of S16. (Of the 16! permutations of S16, 16!/2 permutations are even, and 16!/2 are odd. Moreover even*even=even, even*odd = odd, and odd*odd=even.)
If the necessary correcting permutation happens to be odd, it's not possible to solve the puzzle, no matter what you do. If the necessary correcting permutation is even, and if Axarydax follows the strategy described, then the permutation required for the remaining 2x2 block will necessarily be an even permutation fixing the blank square. The only even permutations of only three elements are the rotations 1->2->3->1 (cycle notation (123)) and 1->3->2->1 (cycle notation (132)). These are easily performed on the remaining four squares without disturbing the others.
Since it's implausible that the Axarydax cannot figure out these trivial solutions of the 2x2 blocks, I suspect that either s/he has been pranked, or the 15-puzzle being attempted is nonstandard in some way.

There are always up to 4 move positions from any given one. I wonder whether the simple algorithm that goes over all options building 2-4 tree will reach the "solved" position or the stack overflow :)

Related

VB.Net - Recursion or Iteration

first post here because I've got a problem thats got me stumped. I am creating a calculation tool for a project at uni, now I'm not in an it degree but for this project I havent had problem too difficult until now.
Basically I am doing design work for a building, where each floor of the building can be allocated one of 9 possible designs. By then allocating solutions to each of these then calculating costs I am trying to find the most efficient combination.
Normally I would just use some nested loops to find the best design, no problems, but for the calculation tool I am required to change the number of floors, and therefore the number of nested loops, which I am unfamiliar with how to do.
The General structure is this
1- X Number of Floors.
9 Possible designs for each floor.
Based on each combination a cost must be calculated, and if it is within the best 5 results it will be stored.
There is a total of 9^x total solutions.
So
Floor = 1
For Solution = 1 to 9
Floor = 2
For Solution = 1 to 9
CalculateCost()
if CalculateCost < Best Then
Write, Floor1 Solution Value, Floor2 Solution Value to Output
Etc...
Now I am using Vb.net, and do not really know how to do recursion. If someone could simply point me in the way of a resource that may help me on this issue I would be very grateful.
Edit - Whilst I have tried to simplify, the cost of design implementation changes based on various other factors, so I can't simply just take the cheapest design for all. I have tried to solve this through practical theory and so far found so solution, therefore the brute force method is required
You're already using For loops to try each solution for each given floor, but you're manually iterating through your Floor variable. It seems you have 9 independently declared variables with the schema FloorX Solution Value. Given all of these things, I think what you really need is a dynamic array. Here's some rough code using this approach:
Dim FloorSolutionValues() As Byte ' I'm assuming values of 1-9
Dim NumberOfFloors As Integer ' Get this from the user
ReDim FloorSolutionValues(NumberOfFloors - 1)
For CurrentFloor As Integer = 0 To NumberOfFloors - 1
For CurrentSolution As Byte = 1 To 9
If CalculateCost() < FloorSolutionValues(CurrentFloor) Then
FloorSolutionValues(CurrentFloor) = CurrentSolution
End If
Next
Next
I'm making some assumptions that may or may not be true, but this should get you on the right path.

Generate a series of pseudo-random sequences to remove sequential bias

I have n things that are going to be tested by t testers. Each tester is subject to order bias (that is, they may give higher ratings to things they test earlier - or the reverse), so I want to eliminate that. One way to do that would be to generate a random testing sequence for each tester.
For example, with n=5, m=2:
Tester 1 Tester 2
4 2
2 5
5 4
1 3
3 1
Notice that in this generated sequence however, both testers test thing 5 immediately after thing 2. Also, things 3 and 1 both appear towards the end of the testing, for both testers. This is sub-optimal.
My question: how can I generate an optimal set of sequences, maximising the chance of each thing appearing at every different position, and minimising the repetition of individual sequences.
Harder question: how much more optimal would that be than the naive (pseudo-)random generation? Can that be quantified?
This isn't a homework question, although it may sound like it :) (It's for a wine tasting...)
I really wasn't sure whether this should go in math.stackexchange, cs.stackexchange, or here. Ultimately I actually want to implement this, so...

Extremely slow query using CONNECT BY Oracle 10

I have a table challenge containing about 12000 rows. Every point connects to the four points around it, for example 100 connects to 99 101 11 and 189. I tried this with a small scale table and it worked just fine but as I increased the size of the table the query became exponentially slower and now it won't even finish. Here's my query
SELECT level, origin, destination
FROM challenge
WHERE destination = 2500
START WITH origin = 1
CONNECT BY NOCYCLE PRIOR destination = origin;
Any advice on how to optimize this query would be greatly appreciated.
So you're finding every path from node 1 to node 2500 in a degree-4 graph (rectangular lattice?) of thousands of nodes. I expect there'll be quite a lot of them. Did the challenge just ask you to count them? Because I think the point was that you have to figure out how many there are by doing math, not brute force computation.
For example, if it's a 50x50 rectangular grid with node 1 and node 2500 in opposite corners, then the minimum path length is 100 steps. A path of 100 steps will have 50 of them horizontal and 50 of them vertical, and they can come in any order. Figure out how many ways you can arrange a string of 50 H's and 50 V's and you might find it's a number that even the mighty Oracle will have a bit of a problem with. (Generating the rows, that is. Doing the calculation just requires large integer arithmetic, which Oracle can probably do quite quickly once you tell it the formula.)
And your query is actually worse than that. It doesn't ask only for minimum-length paths. So it will also return all the paths of length 102 that take a step away from the destination somewhere along the way. And paths of length 104 that take 2 backward steps. And paths of length 2498 that visit almost all of the nodes! Counting those paths is more complicated than counting the short paths because you have to exclude the ones that cross themselves.

Minimising greatest distance moved

I'm trying to find if there are any solutions for a problem I've got.
I've got X people and Y positions to place them in. Sometimes there might be more people than positions, but in the default case X==Y.
I want to allocate the people such that the distance that any one person has to move is minimized.
So if I had people 1-5 and positions A-E:
1 2 3 4 5
A B C D E
The trivial implementation I already had was assigning {A2, B3, C4, D5, E1}, which resulted in E moving much further than anyone else, when I would prefer if the matchup was {A1, B2, C3, D4, E5}, which means everyone else moves a little further, but the worst case is much smaller.
I'm currently creating an array for each person, containing each position, sorted by distance (ascending). Then I reverse sort the arrays of all the people such that the player with the highest distance to his best position is first. I allocate him to a position, then remove that position from the list of each other player, and reverse sort and repeat until all positions are filled.
This gives me reasonable results, but seems very inefficient (removing elements from each array and resorting each time)
Obviously the problem doesn't have to deal with people and distances to positions, but can be said to be allocating resources, where each resource can perform a task with a certain fitness, and I want to avoid using a tool that is grossly unsuitable for a given task, even if it means every tool is doing a task that is slightly unsuitable, if that makes sense.
I suspect that there is some classic optimization problem that I'm mirroring here, but I don't know which one.
Move everyone to the middle. That is, for each person; if they are the i'th leftmost person then they go in the i'th slot.
Proof of optimality:
Jumping over someone isn't advantageous because you could just shift those people a lesser amount and yourself a lesser amount and the amount of moves used is the same.
ex: A _ B _ _ C _ _ 1 2 3
A must move at least 7 slots to get to the boundary, then position himself on a square.
B must move at least 5 ...
C must move at least 2 ...
Then we see we have 1,2,3 moves left to allocate, so jumping over each other still always resolves in 7+5+2+1+2+3 moves. And in the case where there are characters to the right, if any of those jump over leftmost characters then that means a left character has to make additional moves to be on the right side of the slots.
Therefore jumping leads to a equal or greater number of moves, it is never advantageous.
Now since jumping gains nothing the only operations are to move or stop. If character i moves to a slot after i, then someone to the right of him will have to jump over leftwards or they can't all be aligned. Likewise if character i ends up before slot i, someone to the left will have to jump over him towards the right.
That wasn't so bad

comparing/intersecting compare criteria

If there's any open source code that does this already I'm interested in hearing about it. But I haven't seen it yet so I'm trying to roll my own.
Example:
variable x = compareCriteriaBetween 3 and 6
variable y = compareCriteriaLesserThanOrEqual 5
The difficult part for me is finding an elegant way to compare the compareCriteria and create an intersection. In the example the intersection between the two is 'between 3 and 5'.
How can I implement this in a 'tell don't ask' manner? Note that compareCriteria can be completely unrelated (eg startsWithLetter versus betweenNumber).
If you only have constants in your expressions you should be safe from undecidability (I think!). Problems arise as soon as you can express e.g. general statements about integers with +-*/ (see Peano arithmetic).
Even if you stay within the realm of decidability, there exists no algorithm that can take arbitrary statements P(x) and Q(x) and compute a statement R(x) equivalent to P(x) & Q(x) for all x, where x can range over any domain (integers, strings, matrices, real numbers, complex numbers, logical statements [whoops, back into undecidable territory!], ...). You need domain specific tricks to get there, and strictly delimited languages in which P, Q and R are formulated. There exist software products for certain domains -- one of them is called Mathematica...
Try to get back to basics: what problem are you trying to solve?
If you are just interested in simple criteria like less equal or between on integers/floats, you can rewrite between 3 and 6 as (greater equal 3 and less equal 6). If you combine this with a logical and with less equal 5 you can use Boolean algebra to obtain (greater equal 3 and (less equal 6 and less equal 5)) before simplifying the inner parenthesis to just less equal 5 and rewriting the result as between 3 and 5.