generating random sudoku puzzles in javascript results in unsolvable boards - javascript

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

Related

Permutations of small and large elements

If the array is : 2,3,7,9; then the ways in which we can have permutations are:
2 7 3 9
2 9 3 7
3 7 2 9
3 9 2 7
7 9 2 3
so total ways are 5.
Here the restriction is :
Once an element is selected the next element must be larger than it.
The next element after this must be smaller than the previous one, and so on until the last element.
I have below code, but I am not able to get the logic for permutaions:
let array = [2, 3, 7, 9];
array.sort((a, b) => a - b);
let res = [];
let n = array.length;
let i = 0;
let j = n - 1;
let k = 0;
while (i < j) {
res[k++] = array[i++];
res[k++] = array[j--];
}
if (n % 2 != 0) {
res[k++] = arr[i];
}
console.log(res);
Based on comments:
function Factorial(n) {
var res=1;
for (var i = 2; i <= n; i++)
res = res * i;
return res;
}
let n = 4;
let A = [];
let C = [];
let a = Factorial(n);
for(let i=0; i<=n;i++) {
A[i] = 0;
}
A[1] = 1;
for(let k=0; k<n; k++) {
let b = Factorial(k)*Factorial(n-k);
A[k] = a/b * A[k]*A[n-k]/2;
}
console.log(A);
prints [0, 0, 0, 0]
This kind of permutation is called zigzag or alternating permutations
It is known that the number of such permutations of n elements might be described with recurrent formula:
A(n+1) = Sum(k=0..n){C(n,k)*A(k)*A(n-k)} / 2
where A(n) is number of permutation of n items, initial A[] = 1, C(n,k) is binomial coefficient
So we can fill array with calculated entries step-by step
function cnk(n, k) {
let res = 1;
for (let i = 0; i < k; i++)
res = res * (n - i) / (i + 1);
return res;
}
let m = 15;
let A = [1,1];
for (let i = 0; i < m-1; i++) {
A.push(0);
}
for (let n = 2; n < m; n++)
for (let k = 0; k <= n; k++)
A[n + 1] += A[k] * A[n - k] * cnk(n, k) / 2;
console.log(A);
[1, 1, 1, 2, 5, 16, 61, 272, 1385, 7936, 50521, 353792, 2702765,
22368256, 199360981, 1903757312]

how to generate spiral matrix in 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++;
}
}

Javascript Counting Sort implementation

Is this a good way or the best way to implement Counting Sort in Javascript?
Can't find a standard JS Counting Sort example.
function countingSort(arr){
var helper = []; // This helper will note how many times each number appeared in the arr
// Since JS arrary is an object and elements are not continuously stored, helper's Space Complexity minor that n
for(var i = 0; i<arr.length; i++){
if(!helper[arr[i]]){
helper[arr[i]] = 1;
}else{
helper[arr[i]] += 1;
}
}
var newArr = [];
for(i in helper){
while(helper[i]>0){
newArr.push(parseInt(i));
helper[i]--;
}
}
return newArr;
}
var arr = [5,4,3,2,1,0];
console.log(countingSort(arr)); // [0, 1, 2, 3, 4, 5]
The code is correct, with some comments:
In general, the use of for..in on arrays is discouraged, but unless you define enumerable properties on the Array prototype (which is a bad idea anyway), your use of it is fine to me
You could improve the part where you loop to push the same value several times. This can be done in "one" go by concatenating Array(helper[i]).fill(i) to the results.
You could also use reduce to make the function more functional programming style. In the extreme, it could look like this:
function countingSort(arr){
return arr.reduce( (acc, v) => (acc[v] = (acc[v] || 0) + 1, acc), [] )
.reduce( (acc, n, i) => acc.concat(Array(n).fill(i)), [] );
}
// Sample run:
var arr = [5,4,3,2,1,0];
console.log(countingSort(arr)); // [0, 1, 2, 3, 4, 5]
counting sort is to start by initializing an auxiliary array of length k, that will hold the count of each number. Each index has an initial value of 0. After that, you loop through the input array and increase the “count” for each value by 1 every time you encounter that number in the array. Now, the auxiliary array holds the number of times each element is in the input array. The last step is to loop from the minimum value to the maximum value. In this loop, you’ll loop through each corresponding value in the count array, and add the elements who’s count is greater than 0 to the array in sequential order. You add each item by using a secondary incrementing variable (e.g. if we’re using “i” to loop from the min to max values, then we’ll use “j” to loop through the array), then increasing that second incrementing variable so the next item is placed in the next highest array index, and finally you decrease the value of the current item in the count array so that you don’t add too many of elements that value.
const countingSort = (arr, min, max) => {
const count = {};
// First populate the count object
for (let i = min; i <= max; i++) {
count[i] = 0;
}
for (let i = 0; i < arr.length; i++) {
count[arr[i]] += 1;
}
/* Now, count is indexed by numbers, with values corresponding to occurrences, eg:
* {
* 3: 1,
* 4: 0,
* 5: 2,
* 6: 1,
* 7: 0,
* 8: 0,
* 9: 1
* }
*/
// Then, iterate over count's properties from min to max:
const sortedArr = [];
for (let i = min; i <= max; i++) {
while (count[i] > 0) {
sortedArr.push(i);
count[i]--;
}
}
return sortedArr;
};
console.log(countingSort([3, 6, 5, 5, 9], 3, 9));
const countingSort = (arr, min, max) => {
let counters = [...Array(max+1)].map(e => 0);
let result = []
for(let i = min; i < max; i++){
counters[arr[i]] += 1
}
for(let j = min; j <= max; j++){
while( counters[j] > 0){
result.push(j)
counters[j]--
}
}
return result
}
const countingSort = (arr, min, max) => {
const count = {};
// First populate the count object
for (let i = min; i <= max; i++) {
count[i] = 0;
}
for (let i = 0; i < arr.length; i++) {
count[arr[i]] += 1;
}
/* Now, count is indexed by numbers, with values corresponding to occurrences, eg:
* {
* 3: 1,
* 4: 0,
* 5: 2,
* 6: 1,
* 7: 0,
* 8: 0,
* 9: 1
* }
*/
// Then, iterate over count's properties from min to max:
const sortedArr = [];
for (let i = min; i <= max; i++) {
while (count[i] > 0) {
sortedArr.push(i);
count[i]--;
}
}
return sortedArr;
};
console.log(countingSort([3, 6, 5, 5, 9], 3, 9));
const countingSort = (arr, min, max) => {
const count = {};
// First populate the count object
for (let i = min; i <= max; i++) {
count[i] = 0;
}
for (let i = 0; i < arr.length; i++) {
count[arr[i]] += 1;
}
/* Now, count is indexed by numbers, with values corresponding to occurrences, eg:
* {
* 3: 1,
* 4: 0,
* 5: 2,
* 6: 1,
* 7: 0,
* 8: 0,
* 9: 1
* }
*/
// Then, iterate over count's properties from min to max:
const sortedArr = [];
for (let i = min; i <= max; i++) {
while (count[i] > 0) {
sortedArr.push(i);
count[i]--;
}
}
return sortedArr;
};
console.log(countingSort([3, 6, 5, 5, 9], 3, 9));
let a = [2, 1, 1, 0, 2, 5, 4, 0, 2, 8, 7, 7, 9, 2, 0, 1, 9];
let max = Math.max(...a);
let min = Math.min(...a);
function countingSort(arr) {
const count = [];
for (let i = min; i <= max; i++) {
count[i] = 0;
}
for (let i = 0; i < arr.length; i++) {
count[arr[i]]++;
}
const sortedArr = [];
for (let i = min; i <= max; i++) {
while (count[i] > 0) {
sortedArr.push(i);
count[i]--;
}
}
return sortedArr;
}
console.log(countingSort(a));
The simplest way to solve this problem you write like this:
const range = (start, stop, step) => {
if (typeof stop == "undefined") {
stop = start;
start = 0;
}
if (typeof step == "undefined") step = 1;
if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) return [];
let result = [];
for (let i = start; step > 0 ? i < stop : i > stop; i += step)
result.push(i);
return result;
};
const numbers = [1, 2, 2, 2, 1, 3, 3, 1, 2, 4, 5];
const max = Math.max.apply(Math, numbers);
let count = Array.apply(null, Array(max + 1)).map(() => 0);
for (x of numbers)
count[x] += 1;
let arr = [];
for (x in range(max + 1))
for (i in range(count[x]))
arr.push(parseInt([x]));
console.log(arr);

Expanding the power (x+y)ⁿ into a sum - how to compute coefficients?

The power (x+y)n can be expanded into a sum of terms of the form ai xb yc where the coefficient ai of each term is a positive integer.
I'm looking for a function that computes the Array of all these coefficients ai given n.
Example 1: For n = 1: (x+y)1 = 1x + 1y => return [1, 1]
Example 2: For n = 2: (x+y)2 = 1x2 + 2xy + 1y2 => return [1, 2, 1]
For n = 3 the result would be [1, 3, 3, 1] and so on.
A simple implementation of this could be:
function Tartaglia(n) {
var row = new Array(2);
row[0] = [1];
for (i=1; i<= n; i++) {
if (i > 1) {
row[0] = row[1];
}
row[1] = new Array(i+1);
row[1][0] = 1;
row[1][i] = 1;
for (j=1; j<i; j++){
row[1][j] = row[0][j-1] + row[0][j];
}
}
return row[1];
}
window.onload = function() {
document.getElementById('compute').addEventListener('click', function (e) {
var n = document.getElementById('iVal').value;
document.getElementById('result').innerHTML = JSON.stringify(Tartaglia(n), 4, 4);
}, false);
}
<input id="iVal" type="number">
<button id="compute">Compute</button>
<div id="result"></div>
Suffice it to build a pascal triangle and return the last row :
function powMatrix(n){
var result = [];
result[0] = [1];
result[1] = [1,1];
for (var row = 2; row < n+1; row++){
result[row] = [1];
for (var col = 1; col <= row -1; col++){
result[row][col] = result[row-1][col] + result[row-1][col-1];
result[row].push(1);
}
}
return result[n];
}
console.log(powMatrix(3)); //-->[ 1, 3, 3, 1 ]
console.log(powMatrix(4)); //-->[ 1, 4, 6, 4, 1 ]
console.log(powMatrix(5)); //-->[ 1, 5, 10, 10, 5, 1 ]
We can exploit fact that the coefficients ai are - according to the Binomial theorem - binomial coefficients. Those can easily be computed in O(n) as:
function binomial_coeffs(n) {
var half = n >> 1, coeffs = new Array(n + 1);
coeffs[0] = coeffs[n] = 1;
for (var i = 1, coef = 1; i <= half; ++i) {
coeffs[n - i] = coeffs[i] = coef *= (n - i + 1) / i;
}
return coeffs;
}
console.log(...binomial_coeffs(0)); // 1
console.log(...binomial_coeffs(1)); // 1 1
console.log(...binomial_coeffs(2)); // 1 2 1
console.log(...binomial_coeffs(3)); // 1 3 3 1
console.log(...binomial_coeffs(10)); // 1 10 45 120 210 252 210 120 45 10 1

Finding all combinations in javascript

I am creating a game and I need to generate some game pieces. Each piece is an array consisting of 4 numbers(each represents a property of the piece) ranging from 0-2. I need to generate all combinations to get all the game pieces.
So I would need [1, 0, 2, 0], [2, 0, 0, 1], [0, 0, 0, 0], [1, 0, 1, 0] etc..
There should be 81 total combinations of [a, b, c, d] where each variable is a number 0-2.
I am using javascript but any psudocode would be helpful.
Any help is appreciated. Thanks!
Mine
var arr=[];
for (var str,i=0;i<81;i++) {
str = i.toString(3);
arr.push(("000"+str).slice(-4)); // Hmm, I thought slice returned an array.
}
Here is an update taking into account the comments from #katspaugh and #herby
var arr=[];
for (var str,i=81;i<162;i++) {
str = i.toString(3);
arr.push((str).slice(-4).split('').map(Number));
}
If it is a homework, tag it as such.
var BASE = 3, LEN = 4, LIMIT = Math.round(Math.pow(BASE, LEN));
var c = [];
for (var i = 0; i < LIMIT; ++i) {
var item = [];
for (var j = 0, k = i; j < LEN; ++j, k = Math.floor(k/BASE)) {
item.push(k % BASE);
}
c.push(item);
}
Here is a more tricky solution but showing the math behind it better, hopefully:
var BASE = 3, LEN = 4;
var powers = [];
for (var i = 0, LIMIT = 1; i < LEN; ++i, LIMIT *= BASE) {
powers.push(LIMIT);
}
var c = [];
for (i = 0; i < LIMIT; ++i) {
c.push(powers.map(function(basePower) {
return Math.floor(i/basePower) % BASE;
}));
}
var BASE = 3, COMB_LEN = 4
var max = parseInt(new Array(COMB_LEN + 1).join(BASE - 1), BASE),
comb = new Array(COMB_LEN + 1).join(0).split('').map(Number)
var combinations = [], i, n
for (i = 0; i <= max; i++) {
n = i.toString(BASE).split('').map(Number)
combinations.push(
comb.slice(0, COMB_LEN - n.length).concat(n)
)
}

Categories