how to generate spiral matrix in javascript? - javascript

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++;
}
}

Related

generating random sudoku puzzles in javascript results in unsolvable boards

im trying to generate random sudoku puzzles that can be solved, but am having trouble. i am able to create a 9x9 two-dimensional array with values, but oftentimes, the values have repeated in their own row. how can I prevent this from happening? below is my function which should return a sudoku board with emptied spots to solve.
function pattern (r, c, base, side) { return (base * (r % base) + Math.floor(r / base) + c) % side; }
function shuffle (s) { return s.sort(function () { return Math.random() - 0.5; }); }
function getGrid () {
var X = 0;
var base = 3;
var side = base * base;
var rows = [], columns = [], numbers = [], b = [], newB = [];
for (var x = 0; x < base; x++) {
for (var y = 0; y < base; y++) {
rows.push(X * base + y);
columns.push(x * base + y);
}
}
rows = shuffle(rows);
columns = shuffle(columns);
for (var n = 1; n < base * base + 1; n++) { numbers.push(n); }
numbers = shuffle(numbers);
for (var r = 0; r < rows.length; r++) {
for (var c = 0; c < columns.length; c++) {
b.push(numbers[pattern(rows[r], columns[c], base, side)]);
}
}
while (b.length) { newB.push(b.splice(0, 9)); }
console.log(newB); // before removing some items, complete puzzle
var squares = side * side;
var emptySpots = Math.floor((squares * 3) / 4);
for (var cell = 0; cell < squares; cell++) {
if (Math.random() < 0.4) { newB[Math.floor(cell / side)][cell % side] = X; }
}
console.log(newB); // after removing some items, unsolved puzzle
return newB;
}
here is an example of an output which i have recieved from this function:
0: (9) [6, 3, 7, 0, 1, 5, 2, 8, 9]
1: (9) [7, 1, 2, 0, 0, 0, 6, 4, 8]
2: (9) [6, 3, 7, 4, 1, 0, 2, 8, 9]
3: (9) [6, 0, 0, 4, 1, 5, 2, 8, 0]
4: (9) [7, 0, 0, 0, 0, 3, 6, 0, 8]
5: (9) [0, 5, 0, 8, 3, 0, 0, 0, 4]
6: (9) [7, 1, 0, 0, 0, 0, 6, 4, 8]
7: (9) [0, 0, 6, 0, 0, 0, 0, 9, 4]
8: (9) [0, 5, 6, 8, 3, 0, 7, 9, 4]
this isn't a solvable sudoku board, as there are values repeated in the same row/column/square. does anyone have any ideas?
getGrid();
function pattern (r, c, base, side) { return (base * (r % base) + Math.floor(r / base) + c) % side; }
function shuffle (s) { return s.sort(function () { return Math.random() - 0.5; }); }
function getGrid () {
var X = 0;
var base = 3;
var side = base * base;
var rows = [], columns = [], numbers = [], b = [], newB = [];
for (var x = 0; x < base; x++) {
for (var y = 0; y < base; y++) {
rows.push(X * base + y);
columns.push(x * base + y);
}
}
rows = shuffle(rows);
columns = shuffle(columns);
for (var n = 1; n < base * base + 1; n++) { numbers.push(n); }
numbers = shuffle(numbers);
for (var r = 0; r < rows.length; r++) {
for (var c = 0; c < columns.length; c++) {
b.push(numbers[pattern(rows[r], columns[c], base, side)]);
}
}
while (b.length) { newB.push(b.splice(0, 9)); }
console.log(newB); // before removing some items, complete puzzle
var squares = side * side;
var emptySpots = Math.floor((squares * 3) / 4);
for (var cell = 0; cell < squares; cell++) {
if (Math.random() < 0.4) { newB[Math.floor(cell / side)][cell % side] = X; }
}
console.log(newB); // after removing some items, unsolved puzzle
return newB;
}
EDIT: i made the same program in python which worked perfectly, and i attempted to rewrite the same function in javascript, but the results are different. here is the working version in python:
def get_board():
global _board
global empty
base = 3
side = base * base
def pattern(r, c): return (base * (r % base) + r // base + c) % side
def shuffle(s): return sample(s, len(s))
rows = [g * base + row for g in shuffle(range(base)) for row in shuffle(range(base))]
columns = [g * base + column for g in shuffle(range(base)) for column in shuffle(range(base))]
numbers = shuffle(range(1, base * base + 1))
_board = [[numbers[pattern(r, c)] for c in columns] for r in rows]
squares = side * side
empties = squares * 3 // 4
for p in sample(range(squares), empties): _board[p // side][p % side] = empty
could someone tell me how the algorithms differ?
I made one just for fun (before the Python algorithm, because I didn't know the restriction), unoptimised with the first algorithm that came to mind.
const getColumn = (colNumber, lines) =>
{
const col = [];
for (let i = 0; i < lines.length; ++i)
{
const line = lines[i];
col.push(line[colNumber]);
}
return col;
};
const getAllowed = (column, picks) =>
{
const choosable = [];
for (let i = 0; i < picks.length; ++i)
{
const pick = picks[i];
if (!column.includes(pick))
{
choosable.push(pick);
}
}
return choosable;
};
function getSquare(colNumber, lineNumber, lines)
{
const detected = [];
if (!lineNumber)
{
return detected;
}
let startCol = Math.floor(colNumber / 3) * 3;
let endCol = startCol + 3;
let startLine = Math.floor(lineNumber / 3) * 3;
let endLine = Math.min(startLine + 3, lines.length);
for (let i = startCol; i < endCol; ++i)
{
for (let j = startLine; j < endLine; ++j)
{
const item = lines[j][i];
if (item !== undefined)
{
detected.push(item);
}
}
}
return detected;
}
const generateRandomLine = (lines) =>
{
const line = [];
let selectables = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let i = 0; i < 9; ++i)
{
const column = getColumn(i, lines);
let allowed;
// Remove column items
allowed = getAllowed(column, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
// Remove line items
allowed = getAllowed(line, allowed);
// remove square items
const square = getSquare(i, lines.length, lines);
allowed = getAllowed(square, allowed);
const random = allowed.length > 1 ? Math.floor(Math.random() * allowed.length) : 0;
const chosen = allowed[random];
if (chosen === undefined)
{
return false;
}
line.push(chosen);
selectables.splice(selectables.indexOf(chosen), 1);
}
return line;
};
const generateGrid = () =>
{
let iterations;
do
{
const grid = [];
iterations = 0;
do
{
++iterations;
if (iterations > 500)
{
iterations = -1;
// Invalid
break;
}
const line = generateRandomLine(grid);
if (!line)
{
continue;
}
grid.push(line);
} while (grid.length < 9);
if (iterations !== -1)
{
return grid;
}
} while (true);
};
const displayGrid = () =>
{
const grid = generateGrid();
for (let i = 0; i < grid.length; ++i)
{
const line = grid[i];
console.log(JSON.stringify(line));
}
};
displayGrid();
PS: ~ 2h:10min
EDIT 1: Recheck Sudoku rules
EDIT 2: Hack & bug

Why does forEach return undefined?

Here is my code to solve leetcode- Two sum
let nums = [2, 7, 11, 15];
let target = 9;
for (let i = 0; i < nums.length; i++) {
let x = target - nums[i];
if (nums[i + 1] === x) {
console.log([i, i+1]) // [0, 1]
return [i, i + 1];
}
} //it ok
nums.forEach((item, index) => {
let x = target - nums[index];
if (nums[index + 1] === x) {
console.log([index, index + 1]);// [0, 1]
return [index,index+1]
}
}); // undefined
I use forEach instead of for(...), both console.log are same, but forEach returns undefined. Why?
You can use JS map
because the forEach always return undefined
let nums = [2, 7, 11, 15],
target = 9;
let m = {};
nums.map((value, index) => {
m[value] = index;
});
for (i = 0; i < nums.length; i++) {
let diff = target - nums[i];
if (m.hasOwnProperty(diff)) {
console.log(i, m[diff]);
}
}

Recursion problem on Codewars Kata - Snail Trail

Very new to coding so please bear with me. I am attempting to solve this Kata on Codewars: https://www.codewars.com/kata/snail/train/javascript
Basically given an array like
[
[1, 2, 3, 4],
[12,13,14,5],
[11,16,15,6],
[10,9, 8, 7]
];
It would return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16].
A snail trail spiraling around the outside of the matrix and inwards.
I am just solving for the case where the matrix is n x n where n is > 1 and an even number for now.
I got it working by declaring outputarray outside the function but I want that array to be declared within the function, hence the inclusion of this line: var outputarray = outputarray || [];
Not sure where I am going wrong.
snail = function(array) {
if (array.length == 0) {
return outputarray
}
var n = array[0].length - 1;
var outputarray = outputarray || [];
for (var i = 0; i <= n; i++) {
outputarray.push(array[0].splice(0, 1));
}
for (var i = 1; i <= n; i++) {
outputarray.push(array[i].splice(n, 1));
}
for (var i = n - 1; i >= 0; i--) {
outputarray.push(array[n].splice(i, 1));
}
for (var i = n - 1; i > 0; i--) {
outputarray.push(array[i].splice(0, 1));
}
array.pop();
array.shift();
snail(array);
}
Here's a non-recursive approach that doesn't mutate the input array. It works by keeping track of the top-left coordinate x, y and the size n of the spiral.
snail = function(array) {
const { length } = array;
const result = [];
let x = 0;
let y = 0;
let n = length;
while (n > 0) {
// travel right from top-left of spiral
for (let i = x; i < x + n; ++i) result.push(array[y][i]);
// shrink spiral and move top of spiral down
n--; y++;
// travel down from top-right of spiral
for (let i = y; i < y + n; ++i) result.push(array[i][x + n]);
// travel left from bottom-right of spiral
for (let i = x + n - 1; i >= x; --i) result.push(array[y + n - 1][i]);
// shrink spiral
n--;
// travel up from bottom-left of spiral
for (let i = y + n - 1; i >= y; --i) result.push(array[i][x]);
// move left of spiral right
x++;
}
return result;
}
console.log(snail([[1, 2, 3, 4], [12, 13, 14, 5], [11, 16, 15, 6], [10, 9, 8, 7]]));
One option is to define another function inside snail, which calls itself recursively, while also defining the outputarray inside snail. That way, outputarray isn't exposed to the outer scope, but the recursive function can still see it.
Also note that splice returns an array, so right now, your outputarray gets composed of an array of arrays. Spread into push instead to fix it, so that the outputarray becomes an array of numbers:
const input = [
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
];
const snail = (array) => {
const outputarray = [];
const iter = () => {
if (array.length == 0) {
return
}
var n = array[0].length - 1;
for (var i = 0; i <= n; i++) {
outputarray.push(...array[0].splice(0, 1));
}
for (var i = 1; i <= n; i++) {
outputarray.push(...array[i].splice(n, 1));
}
for (var i = n - 1; i >= 0; i--) {
outputarray.push(...array[n].splice(i, 1));
}
for (var i = n - 1; i > 0; i--) {
outputarray.push(...array[i].splice(0, 1));
}
array.pop();
array.shift();
iter(array);
};
iter(array);
return outputarray;
}
console.log(snail(input));
You could take some borders for the left, right, upper and lower indices and loop until no more indices are available.
function snail(array) {
var upper = 0,
lower = array.length - 1,
left = 0,
right = array[0].length - 1,
i = upper,
j = left,
result = [];
while (true) {
if (upper++ > lower) break;
for (; j < right; j++) result.push(array[i][j]);
if (right-- < left) break;
for (; i < lower; i++) result.push(array[i][j]);
if (lower-- < upper) break;
for (; j > left; j--) result.push(array[i][j]);
if (left++ > right) break;
for (; i > upper; i--) result.push(array[i][j]);
}
result.push(array[i][j]);
return result;
}
console.log(...snail([[1, 2, 3, 4], [12, 13, 14, 5], [11, 16, 15, 6], [10, 9, 8, 7]]));
This may not be according to the rules (or spirit?) of the kata, however, you can just glue it all together and sort.
function snail(trail) {
const numeric = (a, b) => a - b
const gather = (items, item) => items.push(parseInt(item, 10)) && items
const inline = (route, points) => points.reduce(gather, route) && route
const order = paths => paths.reduce(inline, []).sort(numeric)
return order(trail)
}
const trail = [
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
]
console.log(JSON.stringify(snail(trail)))
Try this:
const input = [
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
];
function snail(array) {
var res = [];
if (!array.length) return res;
var next = array.shift();
if (next) res = res.concat(next);
for (var i = 0; i < array.length; i++) {
res.push(array[i].pop());
}
next = array.pop()
if (next) res = res.concat(next.reverse());
for (var i = array.length - 1; i >= 0; i--) {
res.push(array[i].shift());
}
return res.concat(snail(array));
}
console.log(snail(input));
Here's my two cents, using the customary recursion:
function f(A){
return A.length > 1 ? A.splice(0,1)[0].concat(
f(A[0].map((c, i) => A.map(r => r[i])).reverse())) : A[0]
}
var A = [[ 1, 2, 3, 4], [12,13,14, 5], [11,16,15, 6], [10, 9, 8, 7]]
console.log(JSON.stringify(f(A)))

Javascript: Bubble Sort

I have made a bubble sort algorithm (sorta) using JS. It works sometimes, but the problem is that it only iterates through the array once. Here is my code:
function bubble(arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] > arr[i + 1]) {
var a = arr[i]
var b = arr[i + 1]
arr[i] = b
arr[i + 1] = a
}
}
return arr;
}
Another bubble sort implementation:
const bubbleSort = array => {
const arr = Array.from(array); // avoid side effects
for (let i = 1; i < arr.length; i++) {
for (let j = 0; j < arr.length - i; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
};
You need an inner loop to complete the sort correctly:
function bubble(arr) {
var len = arr.length;
for (var i = 0; i < len ; i++) {
for(var j = 0 ; j < len - i - 1; j++){ // this was missing
if (arr[j] > arr[j + 1]) {
// swap
var temp = arr[j];
arr[j] = arr[j+1];
arr[j + 1] = temp;
}
}
}
return arr;
}
document.write(bubble([1,9,2,3,7,6,4,5,5]));
Please look at the following sequence:
[5, 4, 3, 2, 1]
Now lets say you need to sort this in the ascending order using bubble sort.
So, you iterate the array and swap adjacent elements which are ordered otherwise.
Here is what you will get after the completion of the iteration
[4, 3, 2, 1, 5]
Now if you do this another time, you will get this:
[3, 2, 1, 4, 5]
Likewise, you need to repeat the iteration enough times to get it sorted fully. This means you need 2 nested loops. The inner loop is to iterate the array and the outer loop is to repeat the iteration.
Please see the step-by-step example of this article.
const bubbleSort = (array)=>{
let sorted = false;
let counter =0;
while(!sorted){
sorted = true;
for(let i =0; i < array.length -1 -counter; i++){
if(array[i] > array[i+1]){
helper(i,i+1,array);
sorted = false;
}
}
counter++;
}
return array;
}
//swap function
function helper(i,j, array){
return [array[i],array[j]] = [array[j],array[i]]
}
let array=[8,5,2,9,5,6,3];
console.log(bubbleSort(array))
var array = [6,2,3,7,5,4,1];
function bubbleSort(arr) {
for(let j=0;j<arr.length;j++) {
for(let i = 0; i < arr.length; i++) {
if(arr[i]>arr[i+1] && (i+1 < arr.length)) {
var temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
}
return arr;
}
console.log(bubbleSort(array));
My bubble sort with just a while loop :
function bubbleSort(arr){
var sorted = false
while (!sorted){
sorted = true;
arr.forEach(function (element, index, array){
if (element > array[index+1]) {
array[index] = array[index+1];
array[index+1] = element;
sorted = false;
}
});
}
}
function bubble(arr) {//You need Two Loops for Bubble sort
for (var i = 0; i < arr.length; i++) {//Outer Loop
for(var j=0; j < arr.length - 1; j++){//Inner Loop
if (arr[j] > arr[j + 1]) {
var a = arr[j]
var b = arr[j + 1]
arr[j] = b
arr[j + 1] = a
}
}
}
return arr;
}
Another form of bubble sort includes starting at the end of the array and placing the smallest element first and going till the largest. This is the code:
function bubbleSort(items) {
var length = items.length;
for (var i = (length - 1); i >= 0; i--) {
//Number of passes
for (var j = (length - i); j > 0; j--) {
//Compare the adjacent positions
if (items[j] < items[j - 1]) {
//Swap the numbers
var tmp = items[j];
items[j] = items[j - 1];
items[j - 1] = tmp;
}
}
}
}
Note Bubble sort is one of the slowest sorting algorithms.
It works for me. I commented the code for more understanding
bubbleSort = (numbersArray) => {
const arrayLenght = numbersArray.length;
for (let i = 0; i < arrayLenght; i++) {
for(let j = 0; j < arrayLenght; j++) {
// Print only to debug
// console.log(`i: ${i} - j: ${j}`);
// console.log(`numbersArray[i]: ${numbersArray[i]} | numbersArray[j]: ${numbersArray[j]}`);
// Check if current number is greater than the next number
if (numbersArray[j] > numbersArray[j + 1]) {
// Store current value to generate swap
const currentNumber = numbersArray[j];
// Now the current position get value of the next position
// And de next position get value of the current position
numbersArray[j] = numbersArray[j + 1];
numbersArray[j + 1] = currentNumber;
}
}
}
// Debug: Print the sorted array
console.log(`sorted array: ${numbersArray.toString()}`);
}
const numbers = [
[3, 10, 5, 7],
[8, 5, 2, 9, 5, 6, 3],
[4, 50, 28, 47, 9, 2097, 30, 41, 11, 3, 68],
[3, 10, 5, 7, 8, 5, 2, 9, 5, 6, 3]
];
numbers.forEach(element => {
bubbleSort(element);
});
Output:
sorted array: 3,5,7,10
sorted array: 2,3,5,5,6,8,9
sorted array: 3,4,9,11,28,30,41,47,50,68,2097
sorted array: 2,3,3,5,5,5,6,7,8,9,10
var arr = [5, 3, 4, 1, 2, 6];
function sort (arr) {
for(let i=0; i < arr.length - 1; i++) {
if(arr[i] > arr[i+1]) {
let b = arr[i+1];
arr[i+1] = arr[i];
arr[i] = b;
i = -1; // Resets the loop
}
}
return arr;
}
console.log(sort(arr));
Try this (performance upgrade):
function bubbleSort(inputArr, reverse = false) {
const len = inputArr.length;
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
let a = inputArr[i];
let b = inputArr[j];
if (reverse ? a < b : a > b) {
const tmp = inputArr[j];
inputArr[j] = inputArr[i];
inputArr[i] = tmp;
}
}
}
return inputArr;
}
Use:
arr = [234,2,4,100, 1,12,5,23,12];
console.log(bubbleSort(arr)); // or console.log(bubbleSort(arr, true));
You need another loop:
var arr = [2, 1]
for(let i = 0;i<arr.length;i++){
for(let b = 0; b<arr.length;i++){
if(arr[b] > arr[b+1]){
var first = arr[b]
var second = arr[b + 1]
arr[b] = second
arr[b + 1] = first
}
}
}
Hope this helps I would recommend using quick sort if you want a high efficiency though.
const bubbleSort = (inputArr) => {
const len = inputArr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len; j++) {
if (inputArr[j] > inputArr[j + 1]) {
let tmp = inputArr[j];
inputArr[j] = inputArr[j + 1];
inputArr[j + 1] = tmp;
}
}
}
return inputArr;
};
const numbers = [50, 30, 10, 40, 60];
console.log(bubbleSort(numbers));
// Output: [ 10, 30, 40, 50, 60 ]
function bubbleSort(array) {
var done = false;
while (!done) {
//alert(1)
done = true;
for (var i = 1; i < array.length; i += 1) {
if (array[i - 1] > array[i]) {
//alert(2)
done = false;
var tmp = array[i - 1];
array[i - 1] = array[i];
array[i] = tmp;
}
}
}
return array;
}
Another way would be like this:
function bubbleSort(arr) {
let swapped;
do {
swapped = false;
for (var i = 0; i < arr.length; i++) {
if (arr[i] > arr[i + 1]) {
swapped = true;
var tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
}
}
} while (swapped);
return arr;
}
let myArray = [8, 1, 2, 5, 51, 13, 15, 33, 123, 100, 22];
console.log(bubbleSort(myArray));
Explanation:
In this function we are going to declare a swapped variable that is being set to false inside the DO WHILE loop, this is being done as a fail-safe not to end up with an infinite loop.
Inside the loop, we have another FOR loop which iterates through the given array and checks if the current value is greater than the next (which we don't want, we need ascending order).
When the IF the condition is true, we are going to swap the variables and assign true for the swapped variable, this is done because we want to keep on the DO WHILE loop untill everything is sorted.
package hasan;
public class hssd {
public static void main(String[] args) {
int t=9;
int g=20;
for (t=g;t>19;++t){
System.out.println(7);
int f=12;
int r=15;
for(r=f;r>5;++r)
System.out.println(r+1000000000+"*"+1000000000);
}
}
}

Find maximum difference in array

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

Categories