Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 hours ago.
Improve this question
We have a pattern
5 6 7 0
4 1 8 0
3 2 9 0
12 11 10 0
in javascript how can we create this pattern user define we have to create mean user give you a number for how much number should we print.
I tries my best but I didn't found the suitable answer
const input = document.querySelector('input')
const result = document.querySelector('pre')
input.addEventListener('input', () => {
if (Number.isNaN(input.valueAsNumber)) {
result.textContent = ''
return
}
const matrix = getMatrix(input.valueAsNumber)
const formatted = matrix.map(row => row.join('\t')).join('\n')
result.textContent = formatted
})
function getMatrix(count) {
const dirs = [
[0, 1], // down
[-1, 0], // left
[0, -1], // right
[1, 0] // up
]
let dirIndex = 0
// side of the matrix
const side = Math.ceil(Math.sqrt(count))
// initialize the matrix with 0
const matrix = [...Array(side)].map(() => Array(side).fill(0))
// initial position
let x = Math.floor(side / 2)
let y = Math.floor((side - 1) / 2)
// length of the side of the spiral
let length = 1
for (let i = 1; i <= count;) {
for (let j = 0; j < Math.floor(length) && i <= count; j += 1, i += 1) {
matrix[y][x] = i
x += dirs[dirIndex][0]
y += dirs[dirIndex][1]
}
// 0.5 because side is longer by 0 every two turns
length += 0.5
dirIndex = (dirIndex + 1) % dirs.length
}
return matrix
}
<input type="number">
<pre></pre>
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I want to generate an ordered sequence of random numbers and put them in a table (array or object) like below, but I have no idea how to do it:
1
2
3
4
5
6
7
8
9
6
12
35
63
71
8
39
50
78
15
29
43
52
66
85
the result I want can be something like below, I just showed it in a table above to be more readable, as you see each column represented as a sub array below:
[[6,8, ],[12, ,15],[ , ,29],[35,39, ],[ , ,43],[ ,50,52],[63, ,66],[71,78, ],[ , ,85]]
or it can be an object like this, if result is an object each key-value pair represents a column:
{1:[6,8, ],2:[12, ,15],3:[ , ,29],4:[35,39, ],5:[ , ,43],6:[ ,50,52],7:[63, ,66],8:[71,78, ],9:[ , ,85]}
here are the rules:
column 1 must be from 1 to 9, column 2 must be from 10 to 19 ..., col 9 must be from 80 to 90
each column must have at least 1 number
numbers in each column must be ordered. but randomly placed.
Update
till now I create a sequence of ordered random numbers using this:
const randomNumber = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
const createSequence = () => {
const sequence = [];
for (let row = 0; row < 9; row++) {
let column = [];
while (true) {
let random;
if (row == 0) {
random = randomNumber(1, 9);
} else {
random = randomNumber(row * 10, row * 10 + 9);
}
if (!column.includes(random)) {
column.push(random);
}
if (column.length >= 3) {
column = column.sort();
break;
}
}
sequence.push(column);
}
console.log(sequence);
return sequence;
};
createSequence()
using above code I get something like this:
[
[
7,
8,
9
],
[
12,
16,
19
],
[
20,
23,
24
],
[
33,
35,
36
],
[
44,
46,
47
],
[
51,
56,
58
],
[
60,
66,
68
],
[
70,
73,
77
],
[
80,
84,
86
]
]
now I have to remove numbers randomly from the array, to achieve the goal, but I don't know how? any idea or solution (or a completely different approach) is appreciated.
thank you all.
Part of solving a problem like this is figuring out if there's a different representation that would make it easier to solve. Tables are usually arranged as a series of rows. However, treating the table as a series of columns makes solving this easier.
An additional, tricky issue is that the column ranges aren't same for all columns. Most columns have a range of 10 but the first column has a range of 9 and the last column has a range of 11.
The solution here generates values for all cells and then eliminates ~half of them, leaving at least one in each column.
const randRng = (min, max) => Math.floor(Math.random() * (max + 1 - min) + min);
const generateData = (rows, cols, p = 0.5) => {
const data = [];
for(let c = 0; c < cols; c++) {
const min = c == 0 ? 1 : c * 10;
const max = c == 0 ? 9 : c == cols - 1 ? min + 10 : min + 9;
// fill all the cells with unique values
const set = new Set();
do {
set.add(randRng(min, max));
} while(set.size < rows);
const sorted = Array.from(set).sort();
// filter out some of the cells, keep at least one
const keep = Math.floor(Math.random() * rows);
const values = sorted.map(
(v, i) => (keep == i || Math.random() < p ? v : null)
);
data.push(values);
}
return data;
};
const tableFromData = (data) => {
const table = [];
// add table header
table.push('<thead><tr>');
for(let c = 1; c <= data.length; c++) {
table.push(`<th>${c}</th>`);
}
table.push('</tr></thead>');
// swap cols/rows and convert to html
for(let r = 0; r < data[0].length; r++) {
table.push('<tr>');
for(let c = 0; c < data.length; c++) {
table.push(`<td>${ data[c][r] ?? " " }</td>`);
}
table.push('</tr>');
}
return table.join('');
};
const data = generateData(3, 9);
const table = tableFromData(data);
document.querySelector('table').insertAdjacentHTML('beforeend', table);
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid black;
}
th, td {
width: 3em;
text-align: center;
}
<table></table>
Note that, since we generate values for all cells and then filter them, distribution is such that first rows will tend to have values towards the beginning of the range, progressing to the last rows having values towards the end of the range.
There seems many different ways to approach this, but one way would be to create random numbers and insert them into a list, one at a time, where they would be in order.
To have the 2-d portion of the table it would just be another step while inserting. Sort on the 10's place, then in that index of the array you could insert based on the 1's place.
function MergeSortCaller() {
let array = [7, 2, 9, 3]
const auxiliaryArray = array.slice();
partition (array, 0, array.length - 1, auxiliaryArray);
}
function partition(
mainArray,
startIdx,
endIdx,
auxiliaryArray,
) {
if (startIdx === endIdx) return;
const middleIdx = Math.floor((startIdx + endIdx) / 2);
partition (auxiliaryArray, startIdx, middleIdx, mainArray);
partition (auxiliaryArray, middleIdx + 1, endIdx, mainArray);
doMerge (mainArray, startIdx, middleIdx, endIdx, auxiliaryArray);
}
function doMerge(
mainArray,
startIdx,
middleIdx,
endIdx,
auxiliaryArray,
) {
let k = startIdx;
let i = startIdx;
let j = middleIdx + 1;
while (i <= middleIdx && j <= endIdx) {
if (auxiliaryArray[i] <= auxiliaryArray[j]) {
mainArray[k++] = auxiliaryArray[i++];
} else {
mainArray[k++] = auxiliaryArray[j++];
}
}
while (i <= middleIdx) {
mainArray[k++] = auxiliaryArray[i++];
}
while (j <= endIdx) {
mainArray[k++] = auxiliaryArray[j++];
}
console.log(auxiliaryArray, mainArray)
}
MergeSortCaller()
Output:-
Aux -> 7 2 9 3
Main -> 2 7 9 3
Aux -> 7 2 9 3
Main -> 2 7 3 9
Aux -> 2 7 3 9
Main -> 2 3 7 9
This is working code of Merge Sort. But I am not able to get that how in the 3rd call of doMerge(), the auxilaryArray get changed even I don't make any change to it.
In the code all the changes are happening to mainArray.
PLZ help me...
Thanks...
Visit Graphical Structure for Visualization of mergesort it may help you.
I can accomplish this without a formula but I am working to create an array selection method that can select at what I would call almost random. The reason being I need to select in a certain as the array grows in powers of 2. The contents of the array indices does not matter.
[0] // select index 0
[0,1] // select index 1 then 0
[0,1,2,3] // 3, 1, 2, 0
[0,1,2,3,4,5,6,7] // 7, 3, 5, 1, 6, 2, 4, 0
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // 15,7,11,3,13,5,9,1,14,6,12,4,10,2,8
I finally came up with this pattern since it doesn't degrade as the array expands over powers of 2. The selection stays at a constant. This has nothing to do with sorting the arrays but just with selecting pre-sorted arrays in a certain order. I have looked far and wide for possible solutions but it has been a while since I have done serious math which I am sure this needs.
The pattern I can see is not obvious but I will try and explain it more. It has to do with a binary tree. At root you have [0].
[0]
[0,1]
[0,1,2,3]
[0,1,2,3,4,5,6,7]
// for example
___ 20 ___
/ \
10 30
/ \ / \
5 15 25 35
/ \ / \ / \ / \
1 7 12 18 23 27 31 37
I need to create a 3rd array that would have the proper order to insert without causing a rebalance.
[20,30,10,35,15,25,5,37,18,27,7,31,12,23,1]
This selection model continues to grow with the Btree which would cause the tree to not rebalance by inserting these values in a self balancing tree.
The following function will push a sorted array into another array in an order that would not cause a rebalence if the other array was actually an AVL tree. It's not the most efficient, but it shows an example of how it can be done.
var sorted = [1, 5, 7, 10, 12, 15, 18, 20, 23, 25, 27, 30, 31, 35, 37];
console.log("sorted: ", sorted)
function insertBalanced(sortedArray, avlTree) {
var size = sortedArray.length;
var result = avlTree;
var indexesUsed = [];
function halfIndexes(depth) {
var slices = Math.pow(2, depth);
for(var i = 1; i < slices;i++) {
var nextIndex = Math.floor(size * i / slices);
if (!indexesUsed.includes(nextIndex)) {
indexesUsed.push(nextIndex);
result.push(sortedArray[nextIndex]);
}
}
if (indexesUsed.length < size) {
halfIndexes(depth + 1);
}
};
return halfIndexes(1);
}
var someEmptyAvlTree = [];
insertBalanced(sorted, someEmptyAvlTree);
console.log("avlTree", someEmptyAvlTree);
I ended up finding a better pattern to fallow that is easier to implement in code. It also does not degrade. I will say DMoses method is also just as relevant. I ended up finding that a pattern of odds and even index rotation helped out.
root 40
/ \
20 60
/ \ / \
10 30 50 70
/ \ / \ / \ / \
5 15 25 35 45 55 65 75
/ \ / \ / \ / \ / \ / \ / \ / \
3 7 12 17 23 27 33 37 43 47 52 57 62 67 72 77
First separate each row into an array. If pulling from a balanced BTree the arrays will already be sorted least to greatest.
Here is the actual code I used.
// array holding all elements
const allArray = [[40],[20,60],[10,30,50,70],[5,15,25,35,45,55,65,75],
[3,7,12,17,23,27,33,37,43,47,52,57,62,67,72,77]];
// create sorted reverse index array
const refA = [];
for (let i = 0; i < allArray.length; i++) {
refA.push([]);
for(let j = allArray[i].length - 1; j >= 0; j--) {
refA[i].push(j);
}
}
const fillRefA = (prev: number[], current: number[]): number[] => {
const a = [];
const prefAOdds = prev.filter((val: number) => (val % 2) !== 0);
const prefAEvens = prev.filter((val: number) => (val % 2) === 0);
const currentAOdds = current.filter((val: number) => (val % 2) !== 0);
const currentAEvens = current.filter((val: number) => (val % 2) === 0);
const newAOdds = currentAOdds.filter((val: number) => !prefAOdds.includes(val));
const newAEvens = currentAEvens.filter((val: number) => !prefAEvens.includes(val));
for (let i = 0; i < prefAOdds.length; i++) {
a.push(newAOdds[i]);
a.push(prefAOdds[i]);
}
for (let i = 0; i < prefAOdds.length; i++) {
a.push(newAEvens[i]);
a.push(prefAEvens[i]);
}
return a;
};
for (let i = 2; i < refA.length; i++) {
refA[i] = fillRefA(refA[i - 1], refA[i]);
}
// Then finally put all the arrays into a master array in order of proper insertion.
const final = [];
for (let i = 0; i < allArray.length; i++) {
for (let j = 0; j < allArray[i].length; j++) {
final.push(a[i][refA[i][j]]);
}
}
// To explain what is going on here I can show a short index path.
//first you cannot work this method on the first item so you need to start at index of 2
// second you have to break evens and odds up but keep the order of previous insertion
[1,0] // odds [1], evens [0]
[3,2,1,0] // odds [3,1], evens [1,0];
// but extract previous array odds and evens
// so [3], [2]. and you have the previous odds and evens [1], [0]
// and insert them in order, odds then evens.
[3,1,2,0]
// again with the next row
[7,5] [6,4] [3,1] [2,0]
[7,3,5,1,6,2,4,0] // first you take the current then the previous
// and the next row.
[15,13,11,9] [14,12,10,8] [7,3,5,1] [6,2,4,0]
[15,7,13,3,11,5,9,1,14,6,12,4,10,2,8,0]
// This way no same node is on a branch is filled up before all nodes
// on the row at least have 1 filled then continue filling the leftovers.
// final insertion array
[40,60,20,70,30,50,10,75,35,55,15,65,25,45,5,77,37,67,17,57,27,47,
7,72,33,62,23,52,12,43,3]
given a matrix like this one:
1 2 3
4 5 6
7 8 9
which can be represented as a 2 dimensional array:
arr = [[1,2,3], [4,5,6], [7,8,9]];
rotate the array so that it is read diagonally at a 45 degree angle and prints out this:
1
4 2
7 5 3
8 6
9
I spent a while coming up with a solution that I don't even fully intuitively understand, but it works, at least for 3x3 and 4x4 matrices. I was hoping to see more logical and clean implementations.
Here's my solution:
arr = [[1,2,3,0],[4,5,6,0],[7,8,9,0], [0,0,0,0]];
// arr[i][j];
transform(arr);
function transform(ar) {
// the number of lines in our diagonal matrix will always be rows + columns - 1
var lines = ar.length + ar[0].length - 1;
// the length of the longest line...
var maxLen = ~~(ar.length + ar[0].length)/2;
var start = 1;
var lengths = [];
// this for loop creates an array of the lengths of each line, [1,2,3,2,1] in our case
for (i=0;i<lines; i++) {
lengths.push(start);
if (i+1 < maxLen) {
start++;
} else {
start--;
}
}
// after we make each line, we're going to append it to str
var str = "";
// for every line
for(j=0; j<lengths.length; j++) {
// make a new line
var line = "";
// i tried to do it all in one for loop but wasn't able to (idk if it's possible) so here we use a particular for loop while lengths of the lines are increasing
if (j < maxLen) {
// lengths[j] is equal to the elements in this line, so the for loop will run that many times and create that many elements
for(c=0; c<lengths[j]; c++) {
// if ar[r][c], the pattern here is that r increases along rows (as we add new lines), and decreases along columns. c stays the same as we add rows, and increases across columns
line += ar[lengths[j]-1-c][c] + " ";
// when we've added all the elements we need for this line, add it to str with a line break
if (c == lengths[j]-1) {
line += "\n"; str += line;
}
}
} else {
// when we're headed down or decreasing the length of each line
for (r=0; r<lengths[j]; r++) {
// the pattern here tripped me up, and I had to introduce another changing variable j-maxLen (or the distance from the center). r stays the same as rows increase and decreases across columns. c increases along rows and decreases across columns
line += ar[lengths[j]-r+j-maxLen][j-maxLen+r +1] + " ";
// that's all our elements, add the line to str;
if (r == lengths[j] -1) {
line += "\n"; str += line;
}
}
}
}
console.log(str);
}
The main idea is to partition the original matrix indexed by (i,j) according to i+j.
This is expressed in the code snippet rotated[i+j].push(arr[i][j]) below:
arr = [[1,2,3], [4,5,6], [7,8,9]];
var summax = arr.length + arr[0].length - 1; // max index of diagonal matrix
var rotated = []; // initialize to an empty matrix of the right size
for( var i=0 ; i<summax ; ++i ) rotated.push([]);
// Fill it up by partitioning the original matrix.
for( var j=0 ; j<arr[0].length ; ++j )
for( var i=0 ; i<arr.length ; ++i ) rotated[i+j].push(arr[i][j]);
// Print it out.
for( var i=0 ; i<summax ; ++i ) console.log(rotated[i].join(' '))
Output:
1
4 2
7 5 3
8 6
9
In Ruby
Produces same output:
puts arr.transpose.flatten.group_by.with_index { |_,k|
k.divmod(arr.size).inject(:+) }.values.map { |a| a.join ' ' }
function transform(ar) {
var result = [],
i, x, y, row;
for (i = 0; i < ar.length; i++) {
row = [];
for (x = 0, y = i; y >= 0; x++, y--) {
row.push(ar[y][x]);
}
result.push(row);
}
for (i = 1; i < ar[0].length; i++) {
row = [];
for (x = i, y = ar[0].length - 1; x < ar[0].length; x++, y--) {
row.push(ar[y][x]);
}
result.push(row);
}
return result;
}
This returns the rotated array, to print it out as you go just replace each result.push(row); line with console.log(row.join(" "));.
Here's my approach:
var origMatrix = [[1,2,3,4,5], [4,5,6,7,8], [9,10,11,12,13], [14,15,16,17,18], [19,20,21,22,23]];
var maxSize = origMatrix.length;//Presuming all internal are equal!
var rotatedMatrix = [];
var internalArray;
var keyX,keyY,keyArray;
for(var y=0;y<((maxSize * 2)-1);y++){
internalArray = [];
for(var x=0;x<maxSize;x++){
keyX = x;
keyY = y - x;
if(keyY > -1){
keyArray = origMatrix[keyY];
if(typeof(keyArray) != 'undefined' && typeof(keyArray[keyX]) != 'undefined'){
internalArray.push(keyArray[keyX]);
}
}
}
rotatedMatrix.push(internalArray);
}
//log results
for(var i=0;i<rotatedMatrix.length;i++){
console.log(rotatedMatrix[i]);
}
Here's a JSFiddle of it in action (open the Console to see the results)
The Idea: Walk the Diagonals and Clip
You could use the diagonal enumeration from Cantor, see Cantor pairing function,
which is used to show that the set N x N has the same cardinality as the set N (i.e. natural numbers can be mapped one to one to pairs of natural numbers) and combine it with a condition that one skips those values which lie outside the rectangular matrix.
The Cantor pairing function pi takes two natural numbers i and j, i.e. the pair (i, j) and maps it to a natural number k
pi : |N x |N -> |N : pi(i, j) = k
Use the reverse mapping to get this
pi^-1 : |N -> |N x |N : pi^-1(k) = (i, j)
i.e. one enumerates the cells of the "infinite Matrix" N x N diagonally.
So counting up k and applying the inverse function will give the proper pair of indices (i, j) for printing the rotated matrix.
Example:
0->(0, 0) 2->(0, 1) | 5->(0, 2) 9->(0, 3) . .
1->(1, 0) 4->(1, 1) | 8->(1, 2)
3->(2, 0) 7->(2, 2) |
---------------------+ <- clipping for 3 x 2 matrix
6->(3, 0)
.
.
Calculation of the Inverse Cantor Pair Function
For input k these formulas give the pair (i, j):
w = floor((sqrt(8*k + 1) - 1) / 2)
t = (w*w + w) / 2
j = k - t
i = w - j
See the link given above for a derivation.
Resulting Algorithm
Given a m x n matrix A: i from [0, .., m - 1] enumerates the rows, and j from [0, .., n - 1] enumerates the columns
Start at k = 0
calculate the corresponding index pair (i, j)
print the matrix value A[i, j] if the indices i and j lie within your matrix dimensions m and n
print a new line, once your i hit the top of the matrix, i.e. if i == 0
increment k
continue with step 2 until you arrived at the index pair (i, j) = (n - 1, n - 1)
Sample Implementation in JavaScript
Note: I tried this out in the MongoDB shell, using its print() function.
Helper functions
function sprint(k) {
var s = '' + k;
while (s.length < 3) {
s = ' ' + s;
}
return s;
}
function print_matrix(a) {
var m = a.row_size;
var n = a.column_size;
for (var i = 0; i < m; i++) {
var s = '';
for (var j = 0; j < n; j++) {
s += sprint(a.value[i][j]);
}
print(s);
}
}
The Inverse of the Cantor pairing function
// inverse of the Cantor pair function
function pi_inv(k) {
var w = Math.floor((Math.sqrt(8*k + 1) - 1) / 2);
var t = (w*w + w) /2;
var j = k - t;
var i = w -j;
return [i, j];
}
The algorithm
// "rotate" matrix a
function rot(a) {
var m = a.row_size;
var n = a.column_size;
var i_max = m - 1;
var j_max = n - 1;
var k = 0;
var s = '';
do {
var ij = pi_inv(k);
var i = ij[0];
var j = ij[1];
if ((i <= i_max) && (j <= j_max)) {
s += sprint(a.value[i][j]);
}
if (i == 0) {
print(s);
s = '';
}
k += 1
} while ((i != i_max) || (j != j_max));
print(s);
}
Example usage
// example
var a = {
row_size: 4,
column_size: 4,
value: [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16] ]
};
print('in:');
print_matrix(a);
print('out:');
rot(a);
Output for 4x4 Matrix
in:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
out:
1
5 2
9 6 3
13 10 7 4
14 11 8
15 12
16
This method works for any m x n Matrix, e.g. 4 x 5:
in:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
out:
1
6 2
11 7 3
16 12 8 4
17 13 9 5
18 14 10
19 15
20
or 4 x 3:
in:
1 2 3
4 5 6
7 8 9
10 11 12
out:
1
4 2
7 5 3
10 8 6
11 9
12