Find valid positions in a board - javascript

I'm looking at solving the Puzzle 15 game. Example.
Basically at each position, valid positions can only come vertically or horizontally. I am looking for an algorithm that can determine it at any given position in a board of 16 elements, 4 by 4.
Currently I have the positions hard coded
var rules = [
{ "0": [1, 4]},{ "1": [0, 2, 5] },{ "2": [1, 3, 6] },{ "3": [2, 7] },
{ "4": [0, 5, 8] },{ "5": [1, 4, 6, 9] },{ "6": [2, 5, 7, 10] },{ "7": [3, 6, 11] },
{ "8": [4, 9, 12] },{ "9": [5, 8, 10, 13]},{ "10": [6, 9, 11, 14] },{ "11": [7, 10, 15] },
{ "12": [8, 13] },{ "13": [12, 9, 14] },{ "14": [10, 13, 15] },{ "15": [11, 14] },
]
For example at position "0", only positions [1, 4] are valid to move from.
[ _, 1, 2, 3 ]
[ 4, 5, 6, 7 ]
[ 8, 9, 10, 11 ]
[ 0, 12, 13, 14 ]
What's a better way?

I'm not sure if I 100% understand your problem, but i hope this helps.
If I understand correctly:
You need a function that will tell you, which cells can be moved.
A cell can be moved only if its a direct neighbor of the empty cell.
i would suggest something like this:
// game grid, empty-cell = -1
const grid = [
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, -1, 15],
]
// Gets value from grid, return null when outside of array
function getCellValue(grid, row, col) {
if (grid[row] === undefined) return null;
if (grid[row][col] === undefined) return null;
return grid[row][col];
}
// Returns array of [row, col] cells,
// that are direct neighbors of the empty cell
function getEmptyCellNeighbors(grid) {
let cells = [];
grid.forEach((cols, row) => {
cols.forEach((value, col) => {
if (getCellValue(grid, row - 1, col) === -1) cells.push([row, col]);
if (getCellValue(grid, row + 1, col) === -1) cells.push([row, col]);
if (getCellValue(grid, row, col - 1) === -1) cells.push([row, col]);
if (getCellValue(grid, row, col + 1) === -1) cells.push([row, col]);
})
})
return cells;
}
// The empty cell(-1) is at[row = 3, col = 2]
// You can move 11, 14, 15 to the empty cell.
// The cuntion will return the[row, col] of cells 11, 14 & 15
console.log(getEmptyCellNeighbors(grid));
// returns => [
// [2, 2], // 11
// [3, 1], // 14
// [3, 3], // 15
// ]

Related

Checking for Duplicates Using For-In Loop

I'm doing a codewars challenge that checks if Sudoku grid is valid.
https://www.codewars.com/kata/529bf0e9bdf7657179000008/train/javascript
It returns false if there are duplicate values in 1) horizontal line, 2) vertical line, 3) 3x3 block, and 4) incomplete (if there are 0s). I'm stuck on checking the horizontal line.
I am using the values array to store the numbers then using the for in loop to check if it's a duplicate. If it is, return false. The problem in the code is checking the first horizontal line [5, 3, 4, 6, 7, 8, 9, 1, 2]. It returns false when checking 1 and I don't know why.
function validSolution(board) {
let valid = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// testing for 0's
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[i].length; j++) {
if (board[i][j] === 0) {
return false;
}
}
}
// testing horizontal line
for (let i = 0; i < board.length; i++) {
values = [];
for (let j = 0; j < board[i].length; j++) {
console.log(values);
console.log(board[i][j]);
if (board[i][j] in values) { // problem is here once the value reaches 1 on the first horizontal line.
console.log(board[i][j]);
return false;
} else {
values.push(board[i][j]);
}
}
return true;
}
}
console.log( // this array is a valid board and should return true.
validSolution([
[5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 7],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9],
])
);
I'm console logging both the element in the index and the value. Here is the result:
(0) []
5
(1) [5]
3
(2) [5, 3]
4
(3) [5, 3, 4]
6
(4) [5, 3, 4, 6]
7
(5) [5, 3, 4, 6, 7]
8
(6) [5, 3, 4, 6, 7, 8]
9
(7) [5, 3, 4, 6, 7, 8, 9]
1
1
false
I think Boolean algebra should not be underestimated
function check1to9valid( arrN )
{
let binVal = 0;
for (let v of arrN)
{
let bin = 2 ** v // Number(v)
if (binVal & bin) { binVal = 0; break; } // avoid duplicates
else { binVal |= bin; }
}
return (binVal === 0b1111111110 )
}
const validGrid =
[ [ 5, 3, 4, 6, 7, 8, 9, 1, 2 ]
, [ 6, 7, 2, 1, 9, 5, 3, 4, 8 ]
, [ 1, 9, 8, 3, 4, 2, 5, 6, 7 ]
, [ 8, 5, 9, 7, 6, 1, 4, 2, 3 ]
, [ 4, 2, 6, 8, 5, 3, 7, 9, 1 ]
, [ 7, 1, 3, 9, 2, 4, 8, 5, 6 ]
, [ 9, 6, 1, 5, 3, 7, 2, 8, 4 ]
, [ 2, 8, 7, 4, 1, 9, 6, 3, 5 ]
, [ 3, 4, 5, 2, 8, 6, 1, 7, 9 ]
]
let isValid = true
// testing horizontal lines
for (let arrLine of validGrid )
{
if (!check1to9valid( arrLine ))
{
isValid = false;
break;
}
}
console.log('all grid\'s lines are valid :', isValid )
// testing vertical lines
isValid = true
for (let i=0; i< 9; i++ )
{
if (!check1to9valid( validGrid.map(line=>line[i]) ))
{
isValid = false;
break;
}
}
console.log('all grid\'s columns are valid : ', isValid )

How do I rotate a single set of coordinates around an m x n matrix?

I have a single coordinate, say { x: 1, y: 2 } and a matrix size { x: 5, y: 6 }. I would like to rotate that single coordinate around the grid by 90 degrees (clockwise). I can rotate an entire grid by running:
function rotate90(a){
// transpose from http://www.codesuck.com/2012/02/transpose-javascript-array-in-one-line.html
a = Object.keys(a[0]).map(function (c) { return a.map(function (r) { return r[c]; }); });
// row reverse
for (i in a){
a[i] = a[i].reverse();
}
return a;
}
Which takes a grid from:
[1][2][3][4]
[5][6][7][8]
[9][0][1][2]
[3][4][5][6]
to
[3][9][5][1]
[4][0][6][2]
[5][1][7][3]
[6][2][8][4]
How can I do the same with a single coordinate? Some examples on a 4 x 4 grid might be:
0, 0 -> 0, 3
0, 3 -> 3, 3
3, 3 -> 3, 0
3, 0 -> 0, 0
1, 1 -> 1, 2
1, 2 -> 2, 2
2, 2 -> 2, 1
2, 1 -> 1, 1
Starting with a MxN array, (x,y) -> (y,M-x-1)
I used a rotate function inside of a Class when I wrote Tetris.
def rotate(self):
self.rotation = (self.rotation + 1) % len(self.figures[self.type])
I had a list of figures with the rotations in a matrix, the only thing is rather than going to 0 after 9, I continued on with 10.
figures = [
[[8, 9, 10, 11], [2, 6, 10, 14], [11, 10, 9, 8], [13, 9, 5, 1]], #0
[[4, 8, 9, 10], [6, 5, 9, 13], [14, 10, 9, 8], [12, 13, 9, 5]], #1
[[6, 8, 9, 10], [14, 5, 9, 13], [12, 10, 9, 8], [4, 5, 9, 13]], #2
[[5, 6, 10, 9], [5, 6, 10, 9], [5, 6, 10, 9], [5, 6, 10, 9]], #3
[[5, 6, 9, 8], [10, 14, 9, 5], [13, 12, 9, 10], [8, 4, 9, 13]], #4
[[4, 5, 9, 10], [6, 10, 9, 13], [14, 13, 9, 8], [12, 8, 9, 5]], #5
[[5, 8, 9, 10], [5, 10, 9, 13], [13, 10, 9, 8], [8, 13, 9, 5]], #6
]
Since I had multiple figures, I had them selected by random, but you can make it controlled as well
self.type = random.randint(0, len(self.figures) - 1)

Adding one line in sudoku checker break my code

function validSolution(board){
for(i=0;i<board.length;i++){
if (new Set(board[i]).size != 9) return false
//if (new Set(getVertical(i,board)).size != 9) return false
}
return true
}
let getVertical = (num,board) => {
let result = []
for(i=0;i<board.length;i++){
result.push(board[i][num])
}
console.log(result)
return result
}
I am working on sudoku checker if I am adding the commented line of code the tests that were passing are failing :( like the first 'if' statement disappeared
sample input (should be false) and it is until adding second 'if' statement
[[5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 0, 3, 4, 8],
[1, 0, 0, 3, 4, 2, 5, 6, 0],
[8, 5, 9, 7, 6, 1, 0, 2, 0],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 0, 1, 5, 3, 7, 2, 1, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 0, 0, 4, 8, 1, 1, 7, 9]]
The propblem is that you declare variable i without let keyword.
That means i is a global variable, so in getVertical function i store value 8 and main loop in validSolution skip to end and returns true

How to remove last element from every row of a matrix in javascript

I am trying to remove the last element from every row of a matrix in javascript. I am trying to use the "map" function but I am not successful.
Here is my code:
var matrixWithExtraInfo = [
[1, 2, 3, 4, "dog"],
[5, 6, 7, 8, "dog"],
[9, 10, 11, 12, "dog"],
[13, 14, 15, 16, "dog"],
[17, 18, 19, 20, "dog"]
];
var conciseMatrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20]
]
var conciseMatrix = matrixWithExtraInfo.map(function(index) {
console.log(index)
matrixWithExtraInfo[index].pop();
return matrixWithExtraInfo[index];
});
console.log(matrixWithExtraInfo);
I get
TypeError: Cannot read property 'pop' of undefined
The first argument to .map is the item you're iterating over, not the index.
Since each item here is an array, you can either .pop the array (which will mutate the existing array), or .slice the array (which will not mutate the existing array).
var matrixWithExtraInfo = [
[1,2,3,4,"dog"],
[5,6,7,8,"dog"],
[9,10,11,12,"dog"],
[13,14,15,16,"dog"],
[17,18,19,20,"dog"]
];
var conciseMatrix = [
[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16],
[17,18,19,20]
]
var conciseMatrix = matrixWithExtraInfo.map((arr) => {
arr.pop();
return arr;
});
console.log(matrixWithExtraInfo);
console.log(conciseMatrix);
(the above is weird - the structure you need is already in matrixWithExtraInfo, making another variable to hold it is confusing, but this is the closest to your original code)
var matrixWithExtraInfo = [
[1,2,3,4,"dog"],
[5,6,7,8,"dog"],
[9,10,11,12,"dog"],
[13,14,15,16,"dog"],
[17,18,19,20,"dog"]
];
var conciseMatrix = [
[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16],
[17,18,19,20]
]
var conciseMatrix = matrixWithExtraInfo.map(arr => arr.slice(0, -1));
console.log(matrixWithExtraInfo);
console.log(conciseMatrix);
If you want to mutate the existing array, an easy way is to use Array.forEach() to apply Array.pop() to each element:
var matrixWithExtraInfo = [
[1, 2, 3, 4, "dog"],
[5, 6, 7, 8, "dog"],
[9, 10, 11, 12, "dog"],
[13, 14, 15, 16, "dog"],
[17, 18, 19, 20, "dog"]
];
matrixWithExtraInfo.forEach(arr => arr.pop());
console.log(matrixWithExtraInfo);
Otherwise, just use Array.slice():
var matrixWithExtraInfo = [
[1, 2, 3, 4, "dog"],
[5, 6, 7, 8, "dog"],
[9, 10, 11, 12, "dog"],
[13, 14, 15, 16, "dog"],
[17, 18, 19, 20, "dog"]
];
var conciseMatrix = matrixWithExtraInfo.map(arr => arr.slice(0, -1));
console.log(conciseMatrix);
Map will return the element so by iterating all rows we just pop the element which will remove the last element from the each row. As we need a new matrix in different array we should use slice(not pop/splice) which will return the elements in new array and not modifying original matrix.
var matrixWithExtraInfo = [
[1,2,3,4,"dog"],
[5,6,7,8,"dog"],
[9,10,11,12,"dog"],
[13,14,15,16,"dog"],
[17,18,19,20,"dog"]
];
var conciseMatrix = [
[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16],
[17,18,19,20]
]
var conciseMatrix = matrixWithExtraInfo.map(row => row.slice(0, row.length-1));
console.log(matrixWithExtraInfo);
console.log(conciseMatrix);
Just adding _, in map function in your code should fix. function(_,index)
var matrixWithExtraInfo = [
[1, 2, 3, 4, "dog"],
[5, 6, 7, 8, "dog"],
[9, 10, 11, 12, "dog"],
[13, 14, 15, 16, "dog"],
[17, 18, 19, 20, "dog"]
];
var conciseMatrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20]
]
var conciseMatrix = matrixWithExtraInfo.map(function(_,index) {
console.log(index)
matrixWithExtraInfo[index].pop();
return matrixWithExtraInfo[index];
});
console.log(matrixWithExtraInfo);

How to loop 2D array in a anti-clock wise fashion?

Given a 2D array of m x n dimension, how can I loop through them in anti-clockwise fashion?
For example:
matrix = [
[ 1, 2, 3, 4 ],
[ 5, 6, 7, 8 ],
[ 9, 10, 11, 12 ],
[ 13, 14, 15, 16 ]
]
1st loop: 1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2
2nd loop: 6, 10, 11, 7, 6
I really don't mind if the implementation is given in ruby or js
My current solution is like this:
(1..rotate).each do
bottom_left_corner = i
top_right_corner = j
start_nth_layer = 1; end_nth_layer = matrix.length - 2
matrix.reverse_each do
matrix[bottom_left_corner].unshift(matrix[bottom_left_corner - 1].shift) if bottom_left_corner > 0
matrix[top_right_corner] << matrix[top_right_corner + 1].pop if top_right_corner < matrix.length - 1
bottom_left_corner -= 1; top_right_corner += 1
end
nth_layer(matrix, start_nth_layer, end_nth_layer)
end
Update
The output doesn't format doesn't matter, as long as it outputs the correct order.
Purpose of the problem
The purpose of this problem is traverse these arrays anti-clockwise, layer by layer, until no more layers. For each traversal, we shift the values in anti-clockwise. For example:
Iteration 1: Iteration 2: Iteration 3:
============== ============= ==============
1 2 3 4 2 3 4 8 3 4 8 12
5 6 7 8 1 7 11 12 2 11 10 16
9 10 11 12 => 5 6 10 16 => 1 7 6 15
13 14 15 16 9 13 14 15 5 9 13 14
This is Matrix Layer Rotation problem. Here is my full solution:
function matrixRotation(matrix, rotate) {
var r = matrix.length, c = matrix[0].length;
var depth = Math.min(r,c)/2;
for(var i=0;i<depth;i++) {
var x = i, y = i, n = (r-i*2 - 2)*2 + (c-i*2-2)*2+4, dir = 'down', index=0;
var buf = [];
while(index < n) {
buf.push(matrix[x][y]);
if(dir == 'down') {
if(x+1 >= r-i) {
dir = 'right';
y++;
} else {
x++;
}
} else if(dir == 'right') {
if(y+1 >= c-i) {
dir = 'up';
x--;
} else {
y++;
}
} else if(dir == 'up') {
if(x-1 <= i-1) {
dir = 'left';
y--;
} else {
x--;
}
} else if(dir == 'left') {
y--;
}
index++;
}
var move = rotate%n;
buf = [...buf.slice(buf.length-move), ...buf.slice(0, buf.length-move)]
x = i, y = i, dir = 'down', index = 0;
while(index < n) {
matrix[x][y] = buf[index];
if(dir == 'down') {
if(x+1 >= r-i) {
dir = 'right';
y++;
} else {
x++;
}
} else if(dir == 'right') {
if(y+1 >= c-i) {
dir = 'up';
x--;
} else {
y++;
}
} else if(dir == 'up') {
if(x-1 <= i-1) {
dir = 'left';
y--;
} else {
x--;
}
} else if(dir == 'left') {
y--;
}
index++;
}
}
matrix.map(row => console.log(row.join(' ')));
}
const matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
// rotate count
const r = 3
matrixRotation(matrix, r);
This approach should support any sizes of matrix and matrix[n]. Give it a try with various test cases if this works for you.
Note that I ignore any performance defects here.
var arr = [
[ 1, 2, 3, 4 ],
[ 5, 6, 7, 8 ],
[ 9, 10, 11, 12 ],
[ 13, 14, 15, 16 ]
],
result = [];
while ( arr.flat().length ) {
var res = [];
// 1. Left side
arr.forEach(x => res = res.concat( x.splice(0, 1) ));
// 2. Bottom side
if (arr.length) {
res = res.concat( ...arr.splice(arr.length - 1, 1) );
}
// 3. Right side
var tmp = [];
if (arr.flat().length) {
arr.forEach(x => tmp.push( x.splice(arr.length - 1, 1) ));
res = res.concat( ...tmp.reverse() );
}
// 4. Top side
if (arr.length) {
tmp = [].concat( ...arr.splice(0, 1) );
res = res.concat( tmp.reverse() );
}
result.push(res);
}
console.log(result);
I would write this in a layered fashion, writing matrix transposition logic (that is, flipping a matrix over the northwest-southeast diagonal), using that and a simple reverse to build a counter-clockwise rotation of the matrix, using that rotation to build a clockwise spiral, and finally using transpose again alongside the clockwise spiral to build a counter-clockwise spiral.
I chose this order because a clockwise spiral is more commonly requested, but it would be easy enough to build the counterclockwise spiral directly. Hint: rotateClockwise = m => transpose(reverse(m)).
const reverse = a => [...a].reverse();
const transpose = m => m[0].map((c, i) => m.map(r => r[i]))
const rotateCounter = m => reverse(transpose(m))
const spiralClockwise = m => m.length < 2
? m[0]
: m[0].concat(spiralClockwise(rotateCounter(m.slice(1))))
const spiralCounter = m => spiralClockwise(transpose(m))
console.log(spiralCounter([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]))
Note that the intermediate functions here are quite possibly useful in their own right. So this strikes me as a good way to break down the problem.
This is how I went about it in ruby:
def counter_clockwise!(arr)
return arr if arr.size <= 1
rotation = [
arr.map(&:shift)
.concat(arr.pop,
arr.map(&:pop).reverse,
arr.shift.reverse).compact
]
rotation.push(*send(__method__,arr)) unless arr.all?(&:empty?)
rotation
end
def counter_clockwise(arr)
counter_clockwise!(arr.map(&:dup))
end
Example:
arr = [
[ 1, 2, 3, 4 ],
[ 5, 6, 7, 8 ],
[ 9, 10, 11, 12 ],
[ 13, 14, 15, 16 ],
[ 17, 18, 19, 20 ],
[ 21, 22, 23, 24 ]
]
counter_clockwise(arr)
#=> [[1, 5, 9, 13, 17, 21, 22, 23, 24, 20, 16, 12, 8, 4, 2, 3],
# [6, 10, 14, 18, 19, 15, 11, 7]]
This method recursively processes the outside edges into groups ("Loops" in your original post). Obviously if you just wanted the counter clockwise spiral without the groups you could flatten the return value.
This will also process non M x N Matrices such as:
arr = [
[ 1, 2, 3, 4 , 72 ],
[ 5, 6, 7, 8 , 73 ],
[ 9, 10, 11 , 12 ],
[ 13, 14, 16 , 75 ],
[ 17, 18, 19, 20 , 76 ],
[ 21, 22, 23, 24 , 77 ]
]
counter_clockwise(arr)
#=> [[1, 5, 9, 13, 17, 21, 22, 23, 24, 77, 76, 75, 12, 73, 72, 4, 3, 2],
# [6, 10, 14, 18, 19, 20, 16, 11, 8, 7]]
If you want each edge and can guarantee M x N then this will work too
def counter_clockwise_edges(arr)
return arr if arr.size == 1
arr = arr.transpose
[arr.shift].push(*send(__method__,arr.map(&:reverse)))
end
counter_clockwise_edges(arr)
#=> [[1, 5, 9, 13, 17, 21],
[22, 23, 24],
[20, 16, 12, 8, 4],
[3, 2],
[6, 10, 14, 18],
[19, 15, 11, 7]]
The following is a modification of my answer to this SO question, which differs from this one only in that the array is traversed in the opposite direction.
arr = matrix.map(&:dup).transpose
out = []
loop do
out = out + arr.shift
break out if arr.empty?
arr = arr.transpose.reverse
end
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10, 11, 7]
The steps are as follows.
arr = matrix.map(&:dup).transpose
#=> [[1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]]
I've duped the elements of matrix so that the latter will not be mutated.
out = []
out = out + arr.shift
#=> [1, 5, 9, 13]
arr
#=> [[2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]]
arr = arr.transpose.reverse
#=> [[14, 15, 16], [10, 11, 12], [6, 7, 8], [2, 3, 4]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16]
arr
#=> [[10, 11, 12], [6, 7, 8], [2, 3, 4]]
arr = arr.transpose.reverse
#=> [[12, 8, 4], [11, 7, 3], [10, 6, 2]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4]
arr
#=> [[11, 7, 3], [10, 6, 2]]
arr = arr.transpose.reverse
#=> [[3, 2], [7, 6], [11, 10]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2]
arr
#=> [[7, 6], [11, 10]]
arr = arr.transpose.reverse
#=> [[6, 10], [7, 11]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10]
arr
#=> [[7, 11]]
arr = arr.transpose.reverse
#=> [[11], [7]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10, 11]
arr
#=> [[7]]
arr = arr.transpose.reverse
#=> [[7]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10, 11, 7]
arr
#=> []
As arr is now empty we break and return out.
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse
Given the array:
array =
[
[ '00', '01', '02', '03', '04', '05'],
[ '10', '11', '12', '13', '14', '15'],
[ '20', '21', '22', '23', '24', '25'],
[ '30', '31', '32', '33', '34', '35']
]
This returns the external loop:
external_ccw_round = [array.map(&:shift), array.pop, array.map(&:pop).reverse, array.shift.reverse].flatten
#=> ["00", "10", "20", "30", "31", "32", "33", "34", "35", "25", "15", "05", "04", "03", "02", "01"]
Leaving just the core
array #=> [["11", "12", "13", "14"], ["21", "22", "23", "24"]]
For matrix with more than one row.
This is a method with a recursive implementation
Works on any matrix 2D.
def ccw_scan(array, result=[])
return array if array.size <= 1
result << [array.map(&:shift), array.pop, array.map(&:pop).reverse, array.shift.reverse]
if array.size >= 2
then ccw_scan(array, result)
else result << array
end
result.flatten.compact
end
Call the method on the array:
ccw_scan(array)
#=> ["00", "10", "20", "30", "31", "32", "33", "34", "35", "25", "15", "05", "04", "03", "02", "01", "11", "21", "22", "23", "24", "14", "13", "12"]

Categories