Related
This is the quicksort algorithm I wrote:
var arr = [0, 2, 5, 10, 3, 22, 12, 8, 20];
let quickSort = (arr) => {
let len = arr.length;
if (len === 1) {
return arr;
};
let pivot = arr.length - 1;
const rightArr = [];
const leftArr = [];
for (let i = 0; i < len - 1; i++) {
let j = i + 1;
if (arr[j] > arr[pivot]) {
rightArr.push(arr[j]);
} else {
leftArr.push(arr[j]);
};
};
if (leftArr.length > 0 && rightArr.length > 0) {
return [...quickSort(leftArr), pivot, ...quickSort(rightArr)];
} else if (leftArr.length > 0 && rightArr.length <= 0) {
return [...quickSort(leftArr), pivot];
} else {
return [pivot, ...quickSort(rightArr)];
};
};
console.log(quickSort(arr));
The output is: [20, 1, 2, 3, 4, 5, 6, 8, 22]
My question is: why do I get the wrong output and how do I fix this ?
There is much wrong with this code, but the problem arises from adding pivot to the list instead of arr[pivot], pivot being the index
I am trying to generate sprial matrix in javascript.
question
Given an integer A, generate a square matrix filled with elements from 1 to A^2 in spiral order.
input : 3
[ [ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ] ]
when input is 4
[ [1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7] ]
my approach is to create 2d array with 0 value and after that they will fill values.
let generateMatrix = function(A) {
let arr = [], counter = 1;
for (let i = 0; i < A; i++) {
let items = []
for (let j = 0; j < A; j++) {
items.push(0)
}
arr.push(items)
}
var spiralMatrix = function(arr) {
if (arr.length > 1) {
for (let i = 0; i < arr[0].length; i++) {
arr[0][i] = counter++;
}
}
return arr
}
return spiralMatrix(arr)
}
console.log(generateMatrix(2))
You could take loops for each edges and loop until no more ranges are avaliable.
function spiral(length) {
var upper = 0,
lower = length - 1,
left = 0,
right = length - 1,
i = 0,
j = 0,
result = Array.from({ length }, _ => []),
value = 1;
while (true) {
if (upper++ > lower) break;
for (; j < right; j++) result[i][j] = value++;
if (right-- < left) break;
for (; i < lower; i++) result[i][j] = value++;
if (lower-- < upper) break;
for (; j > left; j--) result[i][j] = value++;
if (left++ > right) break;
for (; i > upper; i--) result[i][j] = value++;
}
result[i][j] = value++;
return result;
}
var target = document.getElementById('out'),
i = 10;
while (--i) target.innerHTML += spiral(i).map(a => a.map(v => v.toString().padStart(2)).join(' ')).join('\n') + '\n\n';
<pre id="out"></pre>
This bit of code should do what you are trying to.
// This is your Editor pane. Write your JavaScript hem and
// use the command line to execute commands
let generateMatrix = function(A) {
let arr = [],
counter = 1;
for (let i = 0; i < A; i++) {
let items = [];
for (let j = 0; j < A; j++) {
items.push(0);
}
arr.push(items);
}
var spiralMatrix = function(arr) {
let count = 1;
let k = 0; // starting row
let m = arr.length; // ending row
let l = 0; // starting column
let n = arr[0].length; //ending column
while (k < m && l < n) {
// top
for (var i = l; i < n; i++) {
arr[k][i] = count;
count++;
}
k++;
// right
for (var i = k; i < m; i++) {
arr[i][n - 1] = count;
count++;
}
n--;
// bottom
if (k < m) {
for (var i = n - 1; i >= l; i--) {
arr[m - 1][i] = count;
count++;
}
m--;
}
// left
if (l < n) {
for (var i = m - 1; i >= k; i--) {
arr[i][l] = count;
count++;
}
l++;
}
}
return arr;
};
return spiralMatrix(arr);
};
console.log(generateMatrix(4));
This is in some ways the reverse of an answer I gave to another question. We can recursively build this up by slicing out the first row and prepending it to the result of rotating the result of a recursive call on the remaining numbers:
const reverse = a =>
[...a] .reverse ();
const transpose = m =>
m [0] .map ((c, i) => m .map (r => r [i]))
const rotate = m =>
transpose (reverse (m))
const makeSpiral = (xs, rows) =>
xs .length < 2
? [[... xs]]
: [
xs .slice (0, xs .length / rows),
... rotate(makeSpiral (xs .slice (xs .length / rows), xs.length / rows))
]
const range = (lo, hi) =>
[...Array (hi - lo + 1)] .map ((_, i) => lo + i)
const generateMatrix = (n) =>
makeSpiral (range (1, n * n), n)
console .log (generateMatrix (4))
A sharp eye will note that rotate is different here from the older question. transpose (reverse (m)) returns a clockwise rotated version of the input matrix. reverse (transpose (m)) returns a counter-clockwise rotated one. Similarly, here we rotate the result of the recursive call before including it; whereas in the other question we recurse on the rotated version of the matrix. Since we're reversing that process, it should be reasonably clear why.
The main function is makeSpiral, which takes an array and the number of rows to spiral it into and returns the spiraled matrix. (If rows is not a factor of the length of the array, the behavior might be crazy.) generateMatrix is just a thin wrapper around that to handle your square case by generating the initial array (using range) and passing it to makeSpiral.
Note how makeSpiral works with rectangles other than squares:
makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 2) //=>
// [
// [ 1, 2, 3, 4, 5, 6],
// [12, 11, 10, 9, 8, 7]
// ]
makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 3) //=>
// [
// [ 1, 2, 3, 4],
// [10, 11, 12, 5],
// [ 9, 8, 7, 6]
// ]
makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 4) //=>
// [
// [ 1, 2, 3],
// [10, 11, 4],
// [ 9, 12, 5],
// [ 8, 7, 6]
// ]
makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 6) //=>
// [
// [ 1, 2],
// [12, 3],
// [11, 4],
// [10, 5],
// [ 9, 6],
// [ 8, 7]
// ]
The other functions -- range, reverse, transpose, and rotate -- are general purpose utility functions for working with arrays or matrices.
Here's one solution.
I keep the current "moving direction" in dx and dy, such that the next matrix element indices are given by x+dx and y+dy.
If the next item is already filled or is out of bounds, I change this direction clockwise. Otherwise, I fill it with the next value.
const size = 6;
const matrix = Array(size).fill().map(() => Array(size).fill(0));
let x = -1;
let y = 0;
let dx = 1;
let dy = 0;
function changeDirection() {
if (dx === 1) {
dx = 0;
dy = 1;
} else if (dy === 1) {
dy = 0;
dx = -1;
} else if (dx === -1) {
dx = 0;
dy = -1;
} else {
dx = 1;
dy = 0;
}
}
for (let i = 0; i < size * size; i++) {
const yNext = y + dy;
const xNext = x + dx;
const nextRow = matrix[yNext] || [];
const nextItemContent = nextRow[xNext];
if (nextItemContent === undefined || nextItemContent > 0) {
changeDirection();
i--;
continue;
}
y = yNext;
x = xNext;
matrix[y][x] = i + 1;
}
const result = document.getElementById('result');
matrix.forEach(row => {
row.forEach(value => {
result.innerHTML += value.toString().padStart(3);
});
result.innerHTML += '\n';
});
<pre id="result"></pre>
I'm calculating the index, each number should go in a linear array
console.clear();
Array.prototype.range = function(a, b, step) {
step = !step ? 1 : step;
b = b / step;
for(var i = a; i <= b; i++) {
this.push(i*step);
}
return this;
};
const spiral = function(dimen) {
"use strict";
const dim = dimen;
const dimw = dim;
const dimh = dim;
var steps = [1, dimh, -1, -dimh];
var stepIndex = 0;
var count = 1;
var countMax = dimw
var dec = 0
var index = 0;
var arr = [];
arr = arr.range(1, dimh * dimw)
const newArr = arr.reduce((coll, x, idx) => {
index += steps[stepIndex]
coll[index-1] = idx+1;
if (count === countMax) {count = 0; stepIndex++; dec++;}
if (dec === 1) {dec = -1; countMax--}
if (stepIndex == steps.length) {stepIndex = 0}
count++;
return coll;
}, []);
var ret = []
while (newArr.length) {
ret.push(newArr.splice(0,dimw))
}
return ret
}
console.log(spiral(3))
console.log(spiral(4))
console.log(spiral(5))
var n=14; // size of spiral
var s=[]; // empty instruction string
function emp() {} // no move
function xpp() {xp++;} // go right
function xpm() {xp--;} // go left
function ypp() {yp++;} // go down
function ypm() {yp--;} // go up
var r=[xpp,ypp,xpm,ypm]; // instruction set
s.push(emp); // push 'no move' (used for starting point)
var c=n-1;
while (c-->0) s.push(r[0]); // push first line - uses a different rule
for (var i=1;i<2*n-1;i++) { // push each leg
c=Math.floor((2*n-i)/2);
while (c-->0) s.push(r[i%4]);
}
var sp=new Array(n); // spiral array
for (var i=0;i<n;i++) sp[i]=new Array(n);
var xp=0; // starting position
var yp=0;
for (var i=0;i<n*n;i++) {
s[i](); // execute next instruction
sp[yp][xp]=i+1; // update array
}
for (var i=0;i<n;i++) console.log(sp[i].toString()); // log to console
This code makes a macro of functions to generate a run sequence, for example:
'right4, down4, left4, up3, right3, down2, left2, up1, right1
and then implements it.
Here is a solution to Spiral Matrix from leetcode, maybe this can help
https://leetcode.com/problems/spiral-matrix/
var spiralOrder = function(matrix) {
if (matrix.length == 0) {
return [];
}
let result = [];
let rowStart = 0;
let rowEnd = matrix.length - 1;
let colStart = 0;
let colEnd = matrix[0].length - 1;
while (true) {
// top
for (let i = colStart; i <= colEnd; i++) {
result.push(matrix[rowStart][i]);
}
rowStart++;
if (rowStart > rowEnd) {
return result;
}
// right
for (let i = rowStart; i <= rowEnd; i++) {
result.push(matrix[i][colEnd]);
}
colEnd--;
if (colEnd < colStart) {
return result;
}
// bottom
for (let i = colEnd; i >= colStart; i--) {
result.push(matrix[rowEnd][i]);
}
rowEnd--;
if (rowEnd < rowStart) {
return result;
}
// left
for (let i = rowEnd; i >= rowStart; i--) {
result.push(matrix[i][colStart]);
}
colStart++;
if (colStart > colEnd) {
return result;
}
}
return result;
};
console.log(
spiralOrder([[2, 3, 4], [5, 6, 7], [8, 9, 10], [11, 12, 13], [14, 15, 16]])
);
console.log(spiralOrder([[7], [9], [6]]));
console.log(spiralOrder([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]));
console.log(spiralOrder([[1, 2, 3], [4, 5, 6], [7, 8, 9]]));
Here's my answer using only one for loop -
function matrix(n) {
const arr = [];
let row = 0;
let column = 0;
let counter = 1;
let edge = n - 1;
let leftToRightRow = false;
let topToBottomCol = false;
let rightToLeftRow = false;
let bottomToTopCol = false;
for (i = 0; i < n * n; i++) {
if (column <= edge && !leftToRightRow) {
if (!Array.isArray(arr[row])) {
arr[row] = []; // if array is not present at this index, then insert one
}
arr[row][column] = counter;
if (column == edge) {
row = row + 1;
leftToRightRow = true;
} else {
column = column + 1;
}
counter = counter + 1;
} else if (column === edge && !topToBottomCol) {
if (!Array.isArray(arr[row])) {
arr[row] = []; // if array is not present at this index, then insert one
}
arr[row][column] = counter;
if (row === edge) {
column = column - 1;
topToBottomCol = true;
} else {
row = row + 1;
}
counter = counter + 1;
} else if (column >= 0 && !rightToLeftRow) {
arr[row][column] = counter;
if (column === 0) {
row = row - 1;
rightToLeftRow = true;
} else {
column = column - 1;
}
counter = counter + 1;
} else if (row >= n - edge && !bottomToTopCol) {
arr[row][column] = counter;
if (row === n - edge) {
column = column + 1;
bottomToTopCol = true;
//setting these to false for next set of iteration
leftToRightRow = false;
topToBottomCol = false;
rightToLeftRow = false;
edge = edge - 1;
} else {
row = row - 1;
}
counter = counter + 1;
}
}
return arr;
}
Solution is implemented in C++, but only logic matter then you can do it in any language:
vector<vector<int> > Solution::generateMatrix(int A) {
vector<vector<int>> result(A,vector<int>(A));
int xBeg=0,xEnd=A-1;
int yBeg=0,yEnd=A-1;
int cur=1;
while(true){
for(int i=yBeg;i<=yEnd;i++)
result[xBeg][i]=cur++;
if(++xBeg>xEnd) break;
for(int i=xBeg;i<=xEnd;i++)
result[i][yEnd]=cur++;
if(--yEnd<yBeg) break;
for(int i=yEnd;i>=yBeg;i--)
result[xEnd][i]=cur++;
if(--xEnd<xBeg) break;
for(int i=xEnd;i>=xBeg;i--)
result[i][yBeg]=cur++;
if(++yBeg>yEnd) break;
}
return result;
}
Solition in c#:
For solving this problem we use loops for each moving directions
public IList<int> SpiralOrder(int[][] matrix) {
var result = new List<int>();
var n = matrix[0].Length;
var m = matrix.Length;
var i = 0;
var j = 0;
var x = 0;
var y = 0;
while (true)
{
//left to right moving:
while (x <= n - 1 - i)
{
result.Add(matrix[y][x]);
x++;
}
if (result.Count == n * m)
return result;
x--;y++;
//up to down moving:
while (y <= m - 1 - j)
{
result.Add(matrix[y][x]);
y++;
}
if (result.Count == n * m)
return result;
y--;x--;
//right to left moving:
while (x >= j)
{
result.Add(matrix[y][x]);
x--;
}
if (result.Count == n * m)
return result;
x++;y--;
//down to up moving:
while (y > j)
{
result.Add(matrix[y][x]);
y--;
}
if (result.Count == n * m)
return result;
y++;x++;
i++;
j++;
}
}
I am trying to implement binary search in javascript. I don't know what is going wrong with my script. The page becomes unresponsive whenever I click the search button.Thanks in advance.
var i,print,arr;
arr = [1,2,3,4,5,6,7,8,9,10];
print = document.getElementById("showArray");
for(i = 0; i < arr.length; i++){
print.innerHTML += arr[i] + " ";
}
function binarySearch(searchValue){
var lowerIndex, higherIndex, middleIndex,writeResult;
lowerIndex = 0;
higherIndex = arr.length;
writeResult = document.getElementById("showResult");
while(lowerIndex <= higherIndex){
middleIndex = (higherIndex + lowerIndex) / 2;
if(searchValue == arr[middleIndex]){
writeResult.innerHTML = "PRESENT";
consol.log('Present');
break;
}
else if(searchValue > arr[middleIndex]){
lowerIndex = middleIndex + 1;
}
else if(searchValue < arr[middleIndex]){
higherIndex = middleIndex - 1;
}
}
}
<button onclick = "binarySearch(1)">SEARCH</button>
<p id = "showArray" style = "font-size: 40px; padding:0px;"> </p>
<p id = "showResult">Result is:</p>
Try something like
Array.prototype.br_search = function (target)
{
var half = parseInt(this.length / 2);
if (target === this[half])
{
return half;
}
if (target > this[half])
{
return half + this.slice(half,this.length).br_search(target);
}
else
{
return this.slice(0, half).br_search(target);
}
};
l= [0,1,2,3,4,5,6];
console.log(l.br_search(5));
The main problem, you have is not to use the integer part of the calculation for the middleIndex. This makes it impossible to check for a value at a given index of the array, because the index must be an integer number.
var i,
print = document.getElementById("showArray"),
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (i = 0; i < arr.length; i++) {
print.innerHTML += arr[i] + " ";
}
function binarySearch(searchValue) {
var lowerIndex = 0,
higherIndex = arr.length - 1,
middleIndex,
writeResult = document.getElementById("showResult");
while (lowerIndex <= higherIndex) {
middleIndex = Math.floor((higherIndex + lowerIndex) / 2);
if (searchValue == arr[middleIndex]) {
writeResult.innerHTML = "PRESENT " + middleIndex;
break;
}
if (searchValue > arr[middleIndex]) {
lowerIndex = middleIndex + 1;
} else {
higherIndex = middleIndex - 1;
}
}
}
<button onclick="binarySearch(2)">SEARCH</button>
<p id="showArray" style="font-size: 40px; padding:0px;"> </p>
<p id="showResult">Result is:</p>
An iterative example of binary search without break.
Running time: log2(n)
function search(array, target) {
let min = array[0]
let max = array.length - 1;
let guess;
while (max >= min) {
guess = Math.floor((min+max)/2);
if (array[guess] === target) {
return guess;
} else if (array[guess] > target) {
max = guess - 1;
} else {
min = guess + 1;
}
}
return -1;
}
const primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97];
console.log(search(primes, 67));
I'm trying to come up with a solution that takes in a matrix like this:
[[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]
and returns an array traversing the array as a spiral, so in this example:
[1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]
I'm having trouble getting this recursive solution to work, in which the result array takes the first array, the final elements of the rest of the arrays, the bottom array in reverse order, and then the first elements of the middle arrays, and then reforms the array without that outer "shell" so that it can be recursively called on what's left until there's an array of one element in the center or a 2x2 matrix (my base cases, although the latter might not be necessary...)
My solution, which doesn't work, is as follows. Any suggestions on how I can make this work?
var spiralTraversal = function(matriks){
var result = [];
var goAround = function(matrix) {
var len = matrix[0].length;
if (len === 1) {
result.concat(matrix[0]);
return result;
}
if (len === 2) {
result.concat(matrix[0]);
result.push(matrix[1][1], matrix[1][0]);
return result;
}
if (len > 2) {
// right
result.concat(matrix[0]);
// down
for (var j=1; j < matrix.length - 1; j++) {
result.push(matrix[j][matrix.length -1]);
}
// left
for (var l=matrix.length - 2; l > 0; l--) {
result.push(matrix[matrix.length - 1][l]);
}
// up
for (var k=matrix.length -2; k > 0; k--) {
result.push(matrix[k][0]);
}
}
// reset matrix for next loop
var temp = matrix.slice();
temp.shift();
temp.pop();
for (var i=0; i < temp.length - 1; i++) {
temp[i] = temp[i].slice(1,-1);
}
goAround(temp);
};
goAround(matriks);
};
🌀 Spiral Array (ES6)
ES6 allows us to keep it simple:
function spiral(matrix) {
const arr = [];
while (matrix.length) {
arr.push(
...matrix.shift(),
...matrix.map(a => a.pop()),
...(matrix.pop() || []).reverse(),
...matrix.map(a => a.shift()).reverse()
);
}
return arr;
}
Your code is very close but it is doing more than it needs to do. Here I simplify and bug fix:
var input = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]];
var spiralTraversal = function(matriks){
var result = [];
var goAround = function(matrix) {
if (matrix.length == 0) {
return;
}
// right
result = result.concat(matrix.shift());
// down
for (var j=1; j < matrix.length - 1; j++) {
result.push(matrix[j].pop());
}
// bottom
result = result.concat(matrix.pop().reverse());
// up
for (var k=matrix.length -2; k > 0; k--) {
result.push(matrix[k].shift());
}
return goAround(matrix);
};
goAround(matriks);
return result;
};
var result = spiralTraversal(input);
console.log('result', result);
Running it outputs:
result [1, 2, 3, 4, 12, 16, 15, 14, 13, 5, 6, 7, 8, 11, 10, 9]
JSFiddle: http://jsfiddle.net/eb34fu5z/
Important things:
concat on Array returns the result -- it does not mutate the caller so you need to save the result of the concat like so: result = result.concat(otherArray)
check the terminating condition at top of recursive array
for each pass, do the expected (top, right, bottom, left)
return the result
Here is how I would do it but I would add error checking to verify the array has an equal number of "rows" and "columns". So assuming the input is valid, here we go:
var input = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]];
function run(input, result) {
if (input.length == 0) {
return result;
}
// add the first row to result
result = result.concat(input.shift());
// add the last element of each remaining row
input.forEach(function(rightEnd) {
result.push(rightEnd.pop());
});
// add the last row in reverse order
result = result.concat(input.pop().reverse());
// add the first element in each remaining row (going upwards)
var tmp = [];
input.forEach(function(leftEnd) {
tmp.push(leftEnd.shift());
});
result = result.concat(tmp.reverse());
return run(input, result);
}
var result = run(input, []);
console.log('result', result);
Which outputs:
result [1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10]
The general idea is we know for each pass we need to do these things:
Add the first array in input
Add the last item from each remaining array in input
Add the last array in input
Add the first item from each remaining array in input
So if we do the recursion with doing that at each pass, we can accomplish the spiraling.
JSFiddle: http://jsfiddle.net/2v6k5uhd/
This solution is for any kind of matrix (m * n), not just square(m * m). Below example takes 5*4 matrix and prints in spiral format.
var matrix = [[1,2,3,4], [14,15,16,5], [13,20,17,6], [12,19,18,7], [11,10,9,8]];
var row = currentRow = matrix.length, column = currentColumn = matrix[0].length;
while(currentRow > row/2 ){
// traverse row forward
for(var i = (column - currentColumn); i < currentColumn ; i++) { console.log(matrix[row - currentRow][i]); }
// traverse column downward
for(var i = (row - currentRow + 1); i < currentRow ; i++) { console.log(matrix[i][currentColumn - 1]) }
// traverse row backward
for(var i = currentColumn - 1; i > (column - currentColumn) ; i--) { console.log(matrix[currentRow - 1][i - 1]); }
// traverse column upward
for(var i = currentRow - 1; i > (row - currentRow + 1) ; i--) { console.log(matrix[i - 1][column - currentColumn]) }
currentRow--;
currentColumn--;
}
Your algorithm seems fine, there is only one mistake There are a few things, some more hard to spot than others.
The concat method does not alter the array (like push does), but returns a new array that contains all the elements from the original array and the arguments. The result is not mutated.
To fix this, you could either
use result = result.concat(…);
make it an explicit loop where you do result.push(…) (like the down, left and up ones you already wrote) or
use result.push.apply(result, …) to push multiple values at once
Your "left" or "up" loop does miss one element, the bottom left one. Either when going left, you need advance to the first element (use >= 0 in the condition), or when going up you will need to start in the last instead of the second-to-last row (matrix.length-1)
In the loop that shrinks the matrix for the next iteration you forgot the last row, it needs to be for (var i=0; i < temp.length; i++) (not temp.length-1). Otherwise you get very unfortunate results.
Your base case should be 0 (and 1), not (1 and) 2. This will both simplify your script and avoid errors (in edge cases).
You expect your matrices to be square, but they could be rectangular (or even have lines of uneven length). The .length you are accessing might be not the one you expect - better doublecheck and throw an error with a descriptive message.
Both spiralTraversal and goAround are missing a return statement for the (recursive) call. They just fill up result but don't return anything.
Recursive Solution:
Instead of going around, I just go over the top row, and the rightmost column, then recursively call the function on the "reversed" matrix.
var input = [
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9,10,11,12],
[13,14,15,16]
];
let spiral = (mat) => {
if(mat.length && mat[0].length) {
mat[0].forEach(entry => { console.log(entry)})
mat.shift();
mat.forEach(item => {
console.log(item.pop())
});
spiral(reverseMatrix(mat))
}
return;
}
let reverseMatrix = (mat) => {
mat.forEach(item => {
item.reverse()
});
mat.reverse();
return mat;
}
console.log("Clockwise Order is:")
spiral(input)
Here my function :
let array_masalah = [
[1,2,3,4],
[5,6,7,8],
[9, 10, 11, 12],
[13, 14, 15,16],
];
let array_masalah_2 = [
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
];
function polaSpiral(array_masalah) {
function spiral(array) {
if (array.length == 1) {
return array[0];
}
var firstRow = array[0]
, numRows = array.length
, nextMatrix = []
, newRow
, rowIdx
, colIdx = array[1].length - 1
for (colIdx; colIdx >= 0; colIdx--) {
newRow = [];
for (rowIdx = 1; rowIdx < numRows; rowIdx++) {
newRow.push(array[rowIdx][colIdx]);
}
nextMatrix.push(newRow);
}
firstRow.push.apply(firstRow, spiral(nextMatrix));
return firstRow
}
console.log(spiral(array_masalah));
}
polaSpiral(array_masalah) // [ 1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10 ]
polaSpiral(array_masalah_2) // [ 1, 2, 3, 4, 5, 10, 15, 20, 19, 18, 17, 16, 11, 6, 7, 8, 9, 14, 13, 12 ]
While not recursive, it at least outputs the correct answer of:
result: [ 1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10 ]
I'd say the only weird thing about this is having to "reset" the variables i,j after each while loop. Also, there's probably a cleaner recursive solution.
var array = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
];
function spiralTraversal(array) {
let discovered = new Set();
let result = [];
let totalSpots = array.length * array[0].length;
let direction = 'right';
for (var i = 0; i < array.length; i ++) {
for (var j = 0; j < array[i].length; j++) {
while (totalSpots) {
while (direction === 'right' && !!bounds(array, i, j) && !discovered.has(array[i][j])) {
discovered.add(array[i][j]);
result.push(array[i][j]);
totalSpots--;
j++;
}
direction = 'down';
i++;
j--;
while (direction === 'down' && !!bounds(array,i, j) && !discovered.has(array[i][i])) {
discovered.add(array[i][j]);
result.push(array[i][j]);
totalSpots--;
i++;
}
direction = 'left';
j--;
i--;
while (direction === 'left' && !!bounds(array, i, j) && !discovered.has(array[i][j])) {
discovered.add(array[i][j]);
result.push(array[i][j]);
totalSpots--;
j--;
}
direction = 'up';
i--;
j++
while (direction === 'up' && bounds(array, i, j) && !discovered.has(array[i][j])) {
discovered.add(array[i][j]);
result.push(array[i][j]);
totalSpots--;
i--;
}
direction = 'right';
j++;
i++;
}
}
}
return result;
}
function bounds(array, i, j){
if (i < array.length && i >= 0 && j < array[0].length && j >= 0) {
return true;
} else {
return false;
}
};
const spiralOrder = matrix => {
if (!matrix || matrix.length === 0) {
return [];
}
let startRow = 0;
let startCol = 0;
let ans = [];
let endCol = matrix[0].length - 1;
let endRow = matrix.length - 1;
while (startRow <= endRow && startCol <= endCol) {
for (let i = startCol; i <= endCol; i++) {
ans.push(matrix[startRow][i]);
}
startRow++;
for (let i = startRow; i <= endRow; i++) {
ans.push(matrix[i][endCol]);
}
endCol--;
if (startRow <= endRow) {
for (let i = endCol; i >= startCol; i--) {
ans.push(matrix[endRow][i]);
}
endRow--;
}
if (startCol <= endCol) {
for (let i = endRow; i >= startRow; i--) {
ans.push(matrix[i][startCol]);
}
startCol++;
}
}
return ans;
};
let input = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
//Output: [1, 2, 3, 6, 9, 8, 7, 4, 5];
spiralOrder(input);
Below is a Javascript solution. I have added comments to the code so you can follow along with the process :)
var array = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
];
var n = array.length;
//create empty 2d array
var startRow = 0;
var endRow = n - 1;
var startColumn = 0;
var endColumn = n - 1
var newArray = [];
// While loop is used to spiral into the 2d array.
while(startRow <= endRow && startColumn <= endColumn) {
// Reading top row, from left to right
for(var i = startColumn; i <= endColumn; i++) {
newArray.push(array[startColumn][i]);
}
startRow++; // Top row read.
// Reading right column from top right to bottom right
for(var i = startRow; i <= endRow; i++) {
newArray.push(array[i][endColumn]);
}
endColumn--; // Right column read
// Reading bottom row, from bottom right to bottom left
for(var i = endColumn; i >= startColumn; i--) {
newArray.push(array[endRow][i]);
}
endRow--; // Bottom row read
// Reading left column, from bottom left to top left
for(var i = endRow; i >= startRow; i--) {
newArray.push(array[i][startColumn]);
}
startColumn++; // left column now read.
} // While loop will now spiral in the matrix.
console.log(newArray);
:)
ES6 JS version with clockwise and anticlockwise spiral traversal.
function traverseSpiral(arr2d,directionMap,initialPos){
// Initializing length.
const len = arr2d.length;
let totalElementsTraversed =0;
// Elements in the first line is equal to the array length.
// (as this is a square matrix)
let elementsInLine=len;
let elementsTraversedInRow = 0;
let linesCompleted = 1;
let direction = initialPos[0] === 0 ? 'r' : 'd';
// Function to move in the desired direction.
const move = checkDirectionAndMove(initialPos);
const spiralArray = [];
while( totalElementsTraversed!==len*len){
// On Each line completion
if(elementsTraversedInRow===elementsInLine){
linesCompleted++;
// Reset elements traversed in the row.
elementsTraversedInRow =0;
// After each line completion change direction.
direction = directionMap.get(direction);
// For every 2 traversed lines elements in the line will decrease.
if(linesCompleted % 2===0) elementsInLine--;
}
// Update elements traversed
totalElementsTraversed+=1
elementsTraversedInRow+=1;
// Move in the defined direction
const [ down,right] = move(direction);
spiralArray.push(arr2d[down][right]);
}
return spiralArray;
}
function checkDirectionAndMove(initialPosition) {
// Unpack array to variables
let [down,right] = initialPosition;
// Return function.
return (direction)=> {
// Switch based on right/left/up/down direction.
switch(direction){
case 'r':
right++;
break;
case 'l':
right--;
break;
case 'd':
down++;
break;
default :
down--;
}
return [down,right]
}
}
// If current direction is right move down and so on....
const clockWiseMap = new Map(Object.entries({
'r':'d',
'd':'l',
'l':'u',
'u':'r'
}));
// If current direction is right move up and so on....
const antiClockWiseMap = new Map(Object.entries({
'r':'u',
'd':'r',
'l':'d',
'u':'l'
}));
// Spiral traversal in the clockwise direction.
const clockWiseSpiralTraversal = traverseSpiral(
[[1, 2, 3, 4, 5],
[16, 17, 18, 19, 6],
[15, 24, 25, 20, 7],
[14, 23, 22, 21, 8],
[13, 12, 11, 10, 9]],
clockWiseMap,
[0,-1]
)
// Spiral traversal in the anti-clockwise direction.
const antiClockWiseSpiralTraversal = traverseSpiral(
[[1, 2, 3, 4, 5],
[16, 17, 18, 19, 6],
[15, 24, 25, 20, 7],
[14, 23, 22, 21, 8],
[13, 12, 11, 10, 9]],
antiClockWiseMap,
[-1,0]
)
console.log("Clock wise traversal :", clockWiseSpiralTraversal)
console.log("Anti-clock wise traversal :",antiClockWiseSpiralTraversal)
Returns :
Clock wise traversal : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 ]
Anti-clock wise traversal : [ 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 17, 24, 23, 22, 21, 20, 19, 18, 25 ]
Main used techniques and others:
Closure, Arrow functions,
Higher-order functions, Conditional/ternary operator, Array destructuring,
and JS map.
I'm use to C#:
public static IList<int> spiralTraversal (int[,] matrix)
{
IList<int> list = new List<int>();
// Get all bounds before looping.
int bound0 = matrix.GetUpperBound(0);
int bound1 = matrix.GetUpperBound(1);
int totalElem = (bound0+1) * (bound1+1);
int auxbound0 = 0;
int auxbound1 = 0;
string direction = "left";
int leftCtrl = 0;
int rightCtrl = 0;
int upCtrl = 0;
int downCtrl = 0;
for (int i=0;i< totalElem;i++)
{
if (direction == "down")
{
list.Add(matrix[auxbound0, auxbound1]);
if (auxbound0 == bound0 - downCtrl)
{
direction = "right";
auxbound1 -= 1;
downCtrl += 1;
continue;
}
else
{
auxbound0 += 1;
}
}
if (direction == "left")
{
list.Add(matrix[auxbound0, auxbound1]);
if (auxbound1 == bound1 - leftCtrl)
{
direction = "down";
auxbound0 += 1;
leftCtrl += 1;
continue;
}
else
{
auxbound1 += 1;
}
}
if (direction == "up")
{
list.Add(matrix[auxbound0, auxbound1]);
if (auxbound0 == 1 + upCtrl)
{
direction = "left";
auxbound1 += 1;
upCtrl += 1;
continue;
}
else
{
auxbound0 -= 1;
}
}
if (direction == "right")
{
list.Add(matrix[auxbound0, auxbound1]);
if (auxbound1 == rightCtrl)
{
direction = "up";
auxbound0 -= 1;
rightCtrl += 1;
continue;
}
else
{
auxbound1 -= 1;
}
}
}
return list;
}
This solution takes spiral array and converts it to Ordered Array.
It Sorts Spiral Matrix with the format of Top, Right, Bottom, Left.
const matrix = [
[1, 2, 3, 4, 5],
[16, 17, 18, 19, 6],
[15, 24, 25, 20, 7],
[14, 23, 22, 21, 8],
[13, 12, 11, 10, 9],
];
function getOrderdMatrix(matrix, OrderdCorner) {
// If the Matrix is 0 return the OrderdCorner
if (matrix.length > 0) {
//Pushes the top of the matrix to OrderdCorner array
OrderdCorner.push(...matrix.shift());
let left = [];
/*Pushes right elements to the Orderdcorner array and
Add the left elements to the left array */
for (let i = 0; i < matrix.length; i++) {
OrderdCorner.push(matrix[i][matrix[i].length - 1])
matrix[i].pop(); //Remove Right element
if (matrix[i].length > 0) {
//Starts from the last element of the left corner
left.push(matrix[(matrix.length - 1) - i][0])
matrix[(matrix.length - 1) - i].shift();
}
}
/* If the array length is grater than 0 add the bottom
to the OrderdCorner array */
if (matrix.length > 0) {
OrderdCorner.push(...matrix.pop().reverse());
}
//Ads the left array to the OrderdCorner array
OrderdCorner.push(...left);
return getOrderdMatrix(matrix, OrderdCorner);
} else {
return OrderdCorner
}
}
console.log(getOrderdMatrix(matrix,[]));
Returns
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
Here's a configurable version :
function spiral(n) {
// Create 2D array of size n*n
var matrix = new Array(n);
for(var i=0; i < matrix.length; i++) {
matrix[i] = new Array(n);
}
for(var i=0; i < n;i++) {
for(var j=0; j < n; j++) {
matrix[i][j] = 0;
}
}
var startNum = 0;
var rowNum = 0;
function spin(rowNum) {
// right
for(var j=rowNum; j < (n-rowNum); j++) {
startNum++;
matrix[rowNum][j] = startNum;
}
if(startNum === (n*n)) {
return; // exit if number matches to the size of the matrix. ( 16 = 4*4 )
}
// down
for(var i=(rowNum+1); i < (n-(rowNum+1)); i++) {
startNum++;
matrix[i][n-(rowNum+1)] = startNum;
}
if(startNum === (n*n)) {
return; // exit if number matches to the size of the matrix. ( 16 = 4*4 )
}
// left
for(var j=(n-(1+rowNum)); j >= rowNum; j--) {
startNum++;
matrix[(n-(1+rowNum))][j] = startNum;
}
if(startNum === (n*n)) {
return; // exit if number matches to the size of the matrix. ( 16 = 4*4 )
}
//top
for(var i=(n-(2+rowNum)); i > rowNum; i--) {
startNum++;
matrix[i][rowNum] = startNum;
}
if(startNum === (n*n)) {
return; // exit if number matches to the size of the matrix. ( 16 = 4*4 )
}
spin(rowNum+1);
}
spin(rowNum);
console.log(matrix)
}
spiral(6);
Example : https://jsfiddle.net/dino_myte/276ou5kb/1/
I have written an article for a while about this beautiful toy problem, I really enjoy it. you might need to check out my solution.
you can follow me on Medium and you can check my article from here.
var spiralTraversal = function (matrix, result = []) {
// TODO: Implement me!
// if the length of the matrix ==0 we will return the result
if (matrix.length == 0) {
return result;
}
// we need to push the elements inside the first element of the array then delete this element
while (matrix[0].length) {
result.push(matrix[0].shift());
}
//top right to bottom right
matrix.forEach((row) => {
result.push(row.pop());
});
//bottom right to bottom left
while (matrix[matrix.length - 1].length) {
result.push(matrix[matrix.length - 1].pop());
}
//reverse again so we can retraverse on the next iteration
matrix.reverse();
//filter out any empty arrays
matrix = matrix.filter((element) => element.length);
//recursive case
result = spiralTraversal(matrix, result);
//return the result and filter any undefined elements
return result.filter((element) => element);
};
I'm working on an algorithm to return the difference of any pair of numbers, such that the larger integer in the pair occurs at a higher index (in the array) than the smaller integer.
Examples...
Array: [2, 3, 10, 2, 4, 8, 1]
Solution: 10 - 2 = 8
Output: 8
Array: [7, 9, 5, 6, 3, 2]
Solution: 9 - 7 = 2
Output: 2
Here is what I have but it doesn't work for all tests...
var a = [22, 2, 4, 5, 6, 444, 1, 666];
// declare variables
var minNumber = a[0], // initilize to first element
maxNumber = a[0], // --- ^
minNumberIndex = 0, // min index
maxNumberIndex = a.length - 1; // max index
// loop through each element in array
for(i = 0; i < a.length; i++) {
// find min
if (a[i] < minNumber && i < maxNumberIndex) {
minNumber = a[i];
minNumberIndex = i;
}
// find max
if (a[i] >= maxNumber && i > minNumberIndex) {
maxNumber = a[i];
maxNumberIndex = i;
}
}
// return results
console.log("max: \t" + maxNumber);
console.log("min: \t" + minNumber + "index: " + minNumberIndex);
console.log(maxNumber - minNumber);
Please help!
O(n) solution:
function maxDifference(arr) {
let maxDiff = -1;
let min = arr[0];
for (let i = 0; i < arr.length; i++) {
if (arr[i] > min && maxDiff < arr[i] - min) {
maxDiff = arr[i] - min;
}
if (arr[i] < min) {
min = arr[i];
}
}
return maxDiff;
}
console.log(maxDifference([1, 2, 3])); //2
console.log(maxDifference(3, 2, 1)); //-1
console.log(maxDifference([2, 3, 10, 2, 4, 8, 1])); //8
console.log(maxDifference([7, 9, 5, 6, 3, 2])); //2
console.log(maxDifference([22, 2, 4, 5, 6, 444, 1, 666])); //665
console.log(maxDifference([7, 9, 5, 6, 3, 2])); //2
console.log(maxDifference([666, 555, 444, 33, 22, 23])); //1
console.log(maxDifference([2, 3, 10, 2, 4, 8, 1])); //8
let MaxDifference = arr => {
let maxDiff = null;
for(let x = 0; x < arr.length; x++){
for(let y = x+1; y < arr.length; y++){
if(arr[x] < arr[y] && maxDiff < (arr[y] - arr[x])){
maxDiff = arr[y] - arr[x]
}
}
}
return maxDiff === null ? -1 : maxDiff;
}
You can have two arrays. Lets call them minlr and maxrl.
minlr - Where minlr[i] stores the minimum value till index i when going from left to right in the original array.
maxrl - Where maxrl[i] stores the maximum value till index i when going from right to left in the original array.
Once you have these 2 arrays, you iterate the arrays and find the max difference between maxrl[i] and minlr[i].
In your above examples:
minlr = {2,2,2,2,2,2,1};
maxrl = {10,10,10,8,8,8,1};
So the answer in this case would be 10 - 2 = 8.
minlr = {7,7,5,5,3,2};
maxrl = {9,9,6,6,3,2};
So the answer in this case would be 9 - 7 = 2
es6 version:
var a = [2, 3, 10, 2, 4, 8, 1];
var min = a[0];
var max = a[a.length-1];
var init = [[0,min], [a.length -1,max]];
var r = a.reduce((
res, e,i
)=>{
var [[mini, min ], [maxi ,max]] = res;
var t = res;
if(e<min && i<maxi){
t = [[i, e ], [maxi ,max]];
}
if(e>=max && i>mini){
t = [[mini, min ], [i ,e]];
}
return t;
}, init);
console.log(r[1][1]-r[0][1]);
Is this ok? for each item in the array, it looks at earlier items and adds the difference to the internal 'diffs' array (if the current item is greater). I then return the the largest value within the diffs array.
var findMaxDiff = function(arr){
var diffs = [];
for(var i = 1; i < arr.length; i++){
for(var j = 0; j < i; j++){
if(arr[i] > arr[j]){
diffs.push(arr[i]-arr[j]);
}
}
}
return Math.max.apply( Math, diffs );
}
Looping through the array and using recursion like so:
function maxDifference(a){
var maxDiff = a[1] - a[0];
for(var i = 2; i<a.length-1; i++){
var diff = a[i] - a[0];
maxDiff = diff>maxDiff ? diff : maxDiff;
}
if(a.length>1){
a.shift();
var diff = maxDifference(a);
maxDiff = diff>maxDiff ? diff : maxDiff;
}
return maxDiff;
}
var x = [2, 3, 10, 2, 4, 8, 1];
maxDifference(x); // returns 8
x = [7, 9, 5, 6, 3, 2];
maxDifference(x) // returns 2
In linear time and constant memory:
function maxDiff (nums) {
var diff = 0, left = 0, right = 0, cur_right = 0, cur_left = 0;
for (var i = 0; i < nums.length; i++) {
if (nums[i] < nums[cur_left]) {
cur_left = i;
if (cur_left > cur_right) {
cur_right = cur_left;
}
}
if (nums[i] >= nums[cur_right]) {
cur_right = i;
}
if (nums[cur_right] - nums[cur_left] > diff) {
diff = nums[cur_right] - nums[cur_left];
right = cur_right;
left = cur_left;
}
}
return [diff, left, right];
}
If you're only interested in what the difference is, and not where the numbers occur, you don't need left and right.
var maxDiff = function() {
var list = Array.prototype.slice.call(arguments, 0)[0];
var start = new Date().getTime();
if((list !== null) && (toString.call(list) !== "[object Array]")) {
console.warn("not an array");
return;
}
var maxDiff = list[1] - list[0];
var min_element = list[0];
var i, j;
for(i = 1; i < list.length; i++) {
if(list[i] - min_element > maxDiff) {
maxDiff = list[i] - min_element;
}
if(list[i] < min_element) {
min_element = list[i];
}
}
var end = new Date().getTime();
var duration = end - start;
console.log("time taken:: " + duration + "ms");
return maxDiff;
};
maxdiff = 0;
a = [2, 3, 10, 2, 4, 8, 1]
for (i=a.length-1; i >= 0; i--) {
for (j=i-1; j >= 0; j--) {
if (a[i] < a[j] ) continue;
if (a[i] -a[j] > maxdiff) maxdiff = a[i] -a[j]
}
}
console.log(maxdiff || 'No difference found')
we can use es6 + es2020 latest feature to fix this issue
function maxDiff(arr) {
var diff=0
if(arr?.length) diff=arr?.length?Math.max(...arr)-Math.min(...arr):0
return diff;
}
console.log(maxDiff([1, 2, 3])); //2
console.log(maxDiff([3, 2, 1])); //2
console.log(maxDiff([2, 3, 10, 2, 4, 8, 1])); //9
console.log(maxDiff([7, 9, 5, 6, 3, 2])); //7
console.log(maxDiff([22, 2, 4, 5, 6, 444, 1, 666])); //665
console.log(maxDiff([7, 9, 5, 6, 3, 2])); //7
console.log(maxDiff([666, 555, 444, 33, 22, 23])); //644
console.log(maxDiff([-0, 1, 2, -3, 4, 5, -6])); //11
console.log(maxDiff([2])); //0
console.log(maxDiff([])); //0
var a = [22, 2, 4, 5, 6, 444, 1, 666];
function solution(a) {
const max = Math.max.apply(null,a);
const min = Math.min.apply(null,a);
const diff = max-min;
return diff
}
console.log(solution(a))
you actually don't need any looping, just use Math.max(), Math.min(), and [].indexOf() to do the heavy-lifting for you:
function findDiff(a){
var max=Math.max.apply(0, a),
slot=a.lastIndexOf(max),
min=Math.min.apply(0, a.slice(0, slot));
if(a.length && !slot && !min-.153479 )return findDiff(a.slice(1));
return max-min;
}
//ex: findDiff([7, 9, 5, 6, 3, 2]) == 2
//ex: findDiff([666, 555, 444 , 33, 22, 23]) == 1
//ex: findDiff([2, 3, 10, 2, 4, 8, 1]) == 8