PDA

View Full Version : Here's a Puzzle I wish to solve with actionscript



kikon
February 15th, 2009, 08:02 PM
I posted this in "Actionscript 1.0-2.0" but I feel it's more appropriate here:

Imagine six squares touching in two rows (3x2) layout. Now let's say I call the first square "0", the second "1", third "2" and so on going left to right, then onto the second row like so:

0 1 2
3 4 5

Here's the puzzle: How many different ways can you move around this configuration without going back to the same square, and what are those configurations of numbers?

If I start at 0, I can move to 1,3 or 4. (NOTICE you can move diagonally!)
If I start at 1, I can move to 0,2,3,4,5
If I start at 2, I can move to 1,4,5


Here are some of the possibilities if I start from 0, the top-left square:

0143
01452
01425
015243
01542
01543
03124
03125
03145
03142
03152
03154
... and many more... 34 total if I start at 0, I believe.


I am trying to have an array store all the possible ways to go around a 3x2, grid, but would like to expand it to a 3x3, 4x4 or any other configuration of squares. My code right now doesn't do anything really, because I'm not exactly sure how to go about solving this. Please share if you have ANY suggestions or ideas!


// These are the values where you can move to in a grid of 3x2. Example,
// starting at 0, you can go to either 1,3 or 4.
values = new Array(0, 1, 2, 3, 4, 5);
trace("length of values is:"+values.length);
possibilities = new Array([1, 3, 4], [0, 2, 3, 4, 5], [1, 4, 5], [0, 1, 4], [0, 1, 2, 3, 5], [1, 2, 4]);


//declaring new array, "sizes". I store the length of the sub sections in this array.
sizes = new Array();
for (var i = 0; i<possibilities.length; i++) {
sizes[i] = possibilities[i].length;
}
trace(sizes);//output is 3,5,3,3,5,3

solutions1 = new Array();

counter = 0;
for (var j = 0; j<values.length; j++) {
//solutions2[j] = new Array(values.length);
for (var i = 0; i<sizes[j]; i++) {
trace("j is:"+j);
trace("i is:"+i);
trace("counter is:"+counter);
//trace([j]+" "+[i]);
trace("solutions are:"+" "+values[j]+","+possibilities[j][i]);


solutions1[counter] = values[j]+"+"+possibilities[j][i];


//increase the counter for storing values in solutions 1 array
counter = counter+1;
//trace(solutions[j][counter]);
}

}

trace("solutions array1 is:"+solutions1);





trace("End");

bluemagica
February 16th, 2009, 10:35 AM
ermm, i dont know what you are trying to do exactly, but to me this can be quite easy to do if you consider it as a string of numbers! Just fix all the digits except the last two, and rotate them, then release one more digit and rotate it! While you do this, keep pushing the numbers in a array, and if they already exist, just skip to next!
example: 0123
fix 01, rotate 23
0123
0132
fix 0, rotate 123
0123 --> skip this one
0312
0213
fix none, rotate all
0123 --> skip this one
3012
3201
3210
.....
....
so on


you can make a recursive function for this!

kikon
February 17th, 2009, 08:48 PM
ermm, i dont know what you are trying to do exactly, but to me this can be quite easy to do if you consider it as a string of numbers! Just fix all the digits except the last two, and rotate them, then release one more digit and rotate it! While you do this, keep pushing the numbers in a array, and if they already exist, just skip to next!
example: 0123
fix 01, rotate 23
0123
0132
fix 0, rotate 123
0123 --> skip this one
0312
0213
fix none, rotate all
0123 --> skip this one
3012
3201
3210
.....
....
so on


you can make a recursive function for this!


Thanks for the reply... I'd have to play with what you described. I spent the last couple of days coming up with this code that solves for all unique ways to move around on any sized matrix. This script works great, except it crashes when columns and rows are greater than 4; In other words, anything larger than a 4x4 matrix. AAAAAAAhhHHHHH

If you can help me figure out why flash freezes past this point, that'd be sweet!
Copy my code into a blank flash document and look at the output to see what's happening:


/////////////////////////////////////////////////////////////////////////////
///////////////Uniqe Matrix Number Generator By Walter Zelhofer//////////////
///////////////////////////////Created 2-17-2009/////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////WARNING: This script will run any matrix smaller//////////////
///////////////than a 4x4. Anything larger will make the flash //////////////
///////////////player unresponsive. Damn it! //////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

/*------------------------------Settings------------------------------------*/


columns = 3;

rows = 2;

/*------------------------------Create Matrix--------------------------------*/



total_boxes = columns*rows;
// push numbers into the values array in single line array
values = new Array();
for (i=0; i<total_boxes; i++) {
values.push(i);
}

// create a new nested array from the values array based on the columns and rows
//the rest of the script depends on this nested array to find the possible_moves
//for each square. In other words, to find each square's neighbor(s), the put them
//into a nested array called values_nested.

values_nested = new Array();
counter = 0;
for (i=0; i<rows; i++) {
values_nested[i] = new Array();
for (j=0; j<columns; j++) {
values_nested[i][j] = values[counter];
counter += 1;
}
}
trace("single line values are:"+values);
trace("the nested values_nested now are:"+values_nested);
trace("NOTE: The two lists of values above should appear identical! One is a nested array the other isn't.")



for (i=0; i<values_nested.length; i++) {
trace("-------values_nested"+"["+i+"]"+values_nested[i]);
}


// Now we use this entire procedure to come up with the array: possible_moves.
possible_moves = new Array();
TempArray = new Array();
TempLength = new Array();
counter = 0;
for (i=0; i<values_nested.length; i++) {

for (j=0; j<values_nested[i].length; j++) {

//Starting with the first value in the first row
//Go left & right 1 spot to find immediate neighbors and store these values, IF POSSIBLE

//Check to my immediate left:
if ((j-1)>=0) {
TempArray.push(values_nested[i][j-1]);
counter += 1;
}
//Check to my immediate right:
if ((j+1)<values_nested[i].length) {
TempArray.push(values_nested[i][j+1]);
counter += 1;

}
//Go to row Above me, if there is one, and store the value I hit in this SAME index position, j
// This would be the square directly above me
if ((i-1)>=0) {
TempArray.push(values_nested[i-1][j]);
counter += 1;
//Now in this row above me, store the value to the LEFT of my Index, j, IF there is one:
if ((j-1)>=0) {
TempArray.push(values_nested[i-1][j-1]);
counter += 1;
}
//Now in this row above me, store the value to the RIGHT of my Index, j, IF there is one:
if ((j+1)<values_nested[i-1].length) {
TempArray.push(values_nested[i-1][j+1]);
counter += 1;
}
}
//Go row BELOW me, if there is one, and store the value I hit in the same index position, j
if ((i+1)<values_nested.length) {
TempArray.push(values_nested[i+1][j]);
counter += 1;
//Now in this row below me, store the value to the LEFT of my Index, j, IF there is one:
if ((j-1)>=0) {
TempArray.push(values_nested[i+1][j-1]);
counter += 1;
}
//Now in this row below me, store the value to the RIGHT of my index, j, IF there is one:
if ((j+1)<values_nested[i+1].length) {
TempArray.push(values_nested[i+1][j+1]);
counter += 1;

}
}
TempLength.push(counter);
counter = 0;
}
}
//trace("possible_moves:"+possible_moves);

//trace("TempLength:"+TempLength);
counter = 0;
for (i=0; i<total_boxes; i++) {
possible_moves[i] = new Array();

for (j=0; j<TempLength[i]; j++) {
possible_moves[i][j] = TempArray[counter];
counter += 1;

}
}
//trace("possible_moves:"+possible_moves);
for (i=0; i<possible_moves.length; i++) {
//trace("possible_moves"+"["+i+"]:"+possible_moves[i]);

}
//This function allows us to sort on an array of numbers
function sortByNumber(a, b) {
return (a>b);
}
for (i=0; i<possible_moves.length; i++) {
possible_moves[i].sort(sortByNumber);
//trace("ran the sort function");

}
//trace("possible_moves:"+possible_moves);
for (i=0; i<possible_moves.length; i++) {
trace("possible_moves"+"["+i+"]:"+possible_moves[i]);

}
/*---------------------------Functions----------------------------------------------*/

function arrayLastNumbers(arrayName:Array) {
TempArray = new Array();
for (i=0; i<arrayName.length; i++) {
TempString = arrayName[i];
TempString = TempString.split("");
TempLength = TempString.length;
TempArray[i] = TempString[TempString.length-1];
}
return arrayName;
}
function nestTempArray() {
counter = 0;
TempArray2 = new Array();// this will be the nested version of TempArray
for (i=0; i<TempLengths.length; i++) {
TempArray2[i] = new Array();
for (j=0; j<TempLengths[i]; j++) {
TempArray2[i][j] = TempArray[counter];
counter += 1;
}
}
return arrayName;
}
function arrayCombineResults(arrayNameOLD:Array, arrayNameNEW:Array) {
//Combine results
counter = 0;
for (i=0; i<arrayNameOLD.length; i++) {
for (j=0; j<TempArray2[i].length; j++) {
arrayNameNEW[counter] = arrayNameOLD[i]+""+TempArray2[i][j];
counter += 1;
}
}
}
function arrayFindPossibleMoves(arrayName:Array) {
counter = 0;
TempLengths = new Array();//This will be the temp array to hold the lengths of the
//groups of numbers that will come out. We need this to make our multidimensional array later
for (i=0; i<TempArray.length; i++) {
SearchPosition = TempArray[i];
TempLengths[i] = possible_moves[SearchPosition].length;
//store these lengths into another array temprorarily
for (j=0; j<possible_moves[SearchPosition].length; j++) {
arrayName[counter] = TempArray[i]+""+possible_moves[SearchPosition][j];
counter += 1;
}
}
return arrayName;
}
function arrayRemoveDuplicates(arrayName:Array) {
var arrayName:Array = arrayName.sort();
var i:Number = arrayName.length;
while (--i>0) {
while (arrayName[i] == arrayName[i-1]) {
arrayName.splice(i-1,1);
Duplicates = true;
}
}
return arrayName;
}
function arrayoverwriteWithNoDuplicates(arrayName:Array) {
TempArray = new Array();
for (i=0; i<arrayName.length; i++) {
Duplicates = false;
TempString = arrayName[i];
TempString2 = TempString;
TempString = TempString.split("");
_root.arrayRemoveDuplicates(TempString);
if (Duplicates == false) {
TempArray.push(TempString2);
}
}
_root.arrayName = TempArray;
return arrayName;
trace("End Duplicate Check");
}
TempArray = values;
for (i=1; i<values.length; i++) {
var solutions:Array = this["answer"+i]=new Array();
}

arrayFindPossibleMoves(answer1);
trace("answer1:"+answer1);
trace("total for answer1:"+answer1.length);

//This will be the temp array to hold the lengths of the
//groups of numbers that will come out. We need this to make our multidimensional array later



/*-----------------------Procedure for Calling the above functions--------------------*/




arrayLastNumbers(answer1);
arrayFindPossibleMoves(answer2);
arrayLastNumbers(answer2);
//trace("UnNested TempArray:"+TempArray);
nestTempArray();
//Combine results
arrayCombineResults(answer1,answer2);
//Check for duplicates process here
//trace("create nested array from answer2 with duplicates");
arrayoverwriteWithNoDuplicates(answer2);
answer2 = arrayName;
trace("answer2:"+answer2);
trace("total for answer2:"+answer2.length);
//Now Do the same thing for the other arrays. Since these are all the same, I throw them
//into a loop.
for (k=2; k<values.length-1; k++) {
l = k+1;
arrayLastNumbers(_root["answer"+k]);
arrayFindPossibleMoves(_root["answer"+l]);
//-------------------------------------------THIS NEEDS TO BE A NESTED ARRAY
arrayLastNumbers(_root["answer"+l]);
//trace("UnNested TempArray:"+TempArray);
nestTempArray();
//Combine results
arrayCombineResults(_root["answer"+k],_root["answer"+l]);
//trace("answer2 w Dups:"+answer2);
//Check for duplicates process here
//trace("create nested array from answer2 with duplicates");
arrayoverwriteWithNoDuplicates(_root["answer"+l]);
_root["answer"+l] = arrayName;
trace("answer"+l+":"+_root["answer"+l]);
trace("total for answer"+l+":"+_root["answer"+l].length);
}




/////////////////////////////////////////END///////////////////////////////////////////
trace("End Of Output");

Favardin
February 18th, 2009, 05:20 AM
Let's tackle the important issue first: why your program crashes.

Assume that for every field on a 4x4 matrix we have an average of 5 positions to move to. One position will be the field we already visited, so it comes down to about 4 choices. The average length of a path will probably be slightly more than half the fields, so let's be optimistic and say 8. The total number of different path will then be about 16 (Fields) * 8 (Path Length) ^ 4 = 65 536. Not very much: it is definitely possible to generate those.

Now, what is wrong with your method? Well, if I understand your code right (it is pretty convoluted), there are some methods with quadratic running time you call on arrays and... strings? Anyway, imagine doing 65 536^2 = 4 294 967 296 calculations! And you use about the same amount of memory....

So, the tip by bluemagica is a good start. Next you should think about a good data structure to store the values -- arrays are not a good choice for that! A triewould be much better (http://en.wikipedia.org/wiki/Trie).

Finally, you can use the symmetries of the problem to your advantage: for example, the top-right corner has the same paths as the top-left, only mirrored over the vertical middle! On a 4x4 field you only have to calculate the movements on fields 0, 1 and 5 (using your notation), all other paths can be derived from those by mirroring --- which cuts the amount of computation (and memory, if you do the conversion on-the-fly) by 80%!

Oh, and your problem is muchto tackle if you use recursion.

kikon
March 21st, 2009, 05:28 AM
Hmm where can I find information on how to write a trie with actionscript? I read the article on the link you posted, I'm a bit confused.