Find the N traversal of the Matrix / 2D array - javascript

given matrix / 2D array
1 2 3
4 5 6
7 8 9
we have to print
7 4 1 5 9 6 3 in javascript without using inbuilt functions

Here's a hint.
Assuming your matrix is presented as a 1-d array of integers:
m = [1,2,3,4,5,6,7,8,9];
which is logically assumed to be a "square" size (1x1, 2x2, 3x3, 4x4, etc...)
So the above array is logically assumed to be:
1 2 3
4 5 6
7 8 9
Let's use a helper function to help us obtain any that value at any given (x,y) position. With (0,0), being the top left value of the matrix
let getVal = (m, col, row) => {
let rowlen = Math.round(Math.sqrt(m.length));
let index = row * rowlen + col;
return m[index];
}
Hence, getVal(m, 0, 0) returns 1 for the top left corner and getVal(m,2,2) returns 9 for the value in the bottom right corner.
Now with that little helper function provided, do you think you can implement the three for loops for "going up from the bottom left", "diagonal from top left to bottom right", and "going up from the bottom right"?

var output= "";
var length = matrix.length;
// console.log(length)
for(var i = length - 1; i >= 0; i--){
output= output+ matrix[i][0] + " ";
}
// console.log(bag);
for(var j = 1; j < length; j++){
output= output+ matrix[j][j] + " ";
}
// console.log(bag);
for(var k = length - 2; k >= 0; k--){
output= output+ matrix[k][length - 1] + " ";
}
console.log(output);
}

Related

Trying to solve a zigzag pattern for an algorithm question

The question is as follows:
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string s, int numRows);
Example 1:
Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"
Example 2:
Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P I N
A L S I G
Y A H R
P I
I have written the following code, but I am stuck in terms of how to flag the row as one time to be downward moving, where I increment the start row, but when it's zigzagging back to the top, it should be decremented. I am unable to figure out the logic to make this work without affecting the downward movement. Any help would be appreciated.
const convert = (s, numRows) => {
let startRow = 0
let endRow = numRows - 1
let startColumn = 0
let endColumn = Math.floor((s.length / 2) - 1)
s = s.split('')
let results = []
// to setup the columns
for (let i = 0; i < numRows; i++) {
results.push([])
}
while (startRow <= endRow && startColumn <= endColumn && s.length) {
for (let i = startRow; i <= endRow; i++) {
results[i][startColumn] = s.shift()
}
for (let i = endRow - 1; i >= startRow; i--) {
results[i][startColumn + 1] = s.shift()
startColumn++
}
//this line seems to be the issue
startRow++
}
return results
}
console.log(convert('PAYPALISHIRING', 4))
I rewrote your while loop as follows where I simply walk a "zigzag" pattern! Hopefully, it is simple enough to understand.
let c=0, row=0,col=0, down=0;
while(c<s.length) {
results[row][col]=s[c];
if(down==0) { // moving down
row++;
if(row==numRows) {
down = 1;
col++;
row-=2;
}
} else { // moving up
row--;
col++;
if(row==0) {
down=0;
}
}
c++;
}
Ps. Above code does not handle numRows < 3 so you have to manage them before this loop.
My precalculus is a little rusty, but the logic behind this problem seems like a sine wave. I made a math error somewhere in creating the sin equation that prevents this from working (r never equals c with the current paramaters), but hopefully this will help if this is the direction you choose to go in.
/*If x-axis is position in string, and y-axis is row number...
n=number of rows
Equation for a sin curve: y = A sin(B(x + C)) + D
D=vertical shift (y value of mid point)
D=median of 1 and n
n: median:
1 1
2 1.5
3 2
4 2.5
5 3
6 3.5
7 4
median=(n+1)/2
D=(n+1)/2
A=amplitude (from the mid-point, how high does the curve go)
median + amplitude = number of rows
amplitude = number of rows - median
A=n-D
C=phase shift
Phase shift for a sin curve starting at its lowest point: 3π/2
(so at time 1, row number is 1, and curve goes up from there)
C=3π/2
Period is 2π/B
n p
3 4
4 6
5 8
6 10
period=2(n-1)
2(n-1)=2π/B
B(2(n-1)=2π
B=2π/2(n-1)
B=π/(n-1)
Variables:
s = string
n = number of rows
c = current row number being evaluated
p = position in string
r = row number
*/
var output='';
function convert(s,n) {
D=(n+1)/2
A=n-D
C=(3*Math.PI)/2
B=Math.PI/(n-1)
for (c=1;c<=n;c++) { //loop from 1st row to number of rows
for (p=1;p<=s.length;p++) { //loop from 1st to last character in string
r=A*Math.sin(B*(p+C))+D //calculate the row this character belongs in
if (r==c) { output+= s.charAt(r) } //if the character belongs in this row, add it to the output variable. (minus one because character number 1 is at position 0)
}}
//do something with output here
}

Sum of Array of Odd numbers - JS

Given the triangle of consecutive odd numbers:
1
3 5
7 9 11
13 15 17 19
21 23 25 27 29
// Calculate the row sums of this triangle from the row index (starting at index 1) e.g.:
rowSumOddNumbers(1); // 1
rowSumOddNumbers(2); // 3 + 5 = 8
I tried to solve this using for loops:
function rowSumOddNumbers(n){
let result = [];
// generate the arrays of odd numbers
for(let i = 0; i < 30; i++){
// generate sub arrays by using another for loop
// and only pushing if the length is equal to current j
let sub = [];
for(let j = 1; j <= n; j++){
// if length === j (from 1 - n) keep pushing
if(sub[j - 1].length <= j){
// and if i is odd
if(i % 2 !== 0){
// push the i to sub (per length)
sub.push(i);
}
}
}
// push everything to the main array
result.push(sub);
}
// return sum of n
return result[n + 1].reduce(function(total, item){
return total += item;
});
}
My code above is not working. Basically I was planning to 1st generate an array of odd numbers less than 30. Next I need to create a sub array base on the length of iteration (j) that would from 1 - n (passed). Then finally push it to the main array. And then use reduce to get the sum of all the values in that index + 1 (since the index starts at 1).
Any idea what am I missing and how to make this work?
Most code problems involve some analysis first in order to spot patterns which you can then convert into code. Looking at the triangle, you'll see the sum of each row follows a pattern:
1: 1 === 1 ^ 3
2: 3 + 5 = 8 === 2 ^ 3
3: 7 + 9 + 11 = 27 === 3 ^ 3
... etc
So from the analysis above you can see that your code could probably be simplified slightly - I won't post an answer, but think about using Math.pow.
No need for any loops.
function rowSumOddNumbers(n) {
// how many numbers are there in the rows above n?
// sum of arithmetic sequence...
let numbers_before_n_count = (n - 1) * n / 2;
let first_number_in_nth_row = numbers_before_n_count * 2 + 1;
let last_number_in_nth_row = first_number_in_nth_row + 2 * (n - 1);
// sum of arithmetic sequence again...
return n * (first_number_in_nth_row + last_number_in_nth_row) / 2;
}

Calculating the area of an irregular polygon using JavaScript

I got this as an assignment, but I'm stuck on implementing the area portion. The assignment is already turned in (finished about 80%). I still want to know how to implement this, though. I am stuck on line 84-86. Here is the prompt.
Prompt: Calculate the area of irregularly shaped polygons using JS
INPUT: a nested array of 3-6 coordinates represented as [x,y] (clockwise order)
OUTPUT: area calculated to 2 significant figures
Pseudocode:
loop the input and check for error cases:
a. array length < 3 or array length > 6
b. array is not empty
c. numbers within -10 and 10 range
loop to each inner array, and multiply x and y in the formula below:
sum_x_to_y = (X0 *Y1) + (X1* Y2)...X(n-1)* Yn
sum_y_to_x = (Y0 * X1) + (Y1-X2)...Y(n-1)* Xn
ex:
(0, -10) (7,-10) (0,-8) (0,-10)
| x | y |
| 0 |-10 |
| 7 |-10 |
| 0 |-8 |
| 0 |-10 |
sum_x_to_y = 0*-10 + 7*-8 + 0*-10 = -56
sum_y_to_x = -10*7 + -10*0 + -8*0 = -70
area = (sum_y_to_x - sum_x_to_y) / (2.00)
ex: area = -70 -(-56) = 57/2 = 7
return area.toPrecision(2) to have one sig fig
function PaddockArea(array_coords) {
var sum_x_to_y = 0;
var sum_y_to_x = 0;
var arr_size = array_coords.length;
if (arr_size === 0) {
//check for empty array
console.log("Invalid input. Coordinates cannot be empty.");
}
if (arr_size < 3 || arr_size > 7) {
//check input outside of 3-6 range
console.log("Input out of range.");
}
for (var i = 0; i < arr_size; i++) {
for (var j = 0; j < array_coords[i].length; j++) {
//test for inner coordinates -10 to 10 range
if (array_coords[i][j] < -10 || array_coords[i][j] > 10) {
console.log("Coordinates outside of -10 to 10 range.");
}
// I NEED TO IMPLEMENT TO calc for AREA here
sum_x_to_y += array_coords[i][j] * array_coords[j][i];
sum_y_to_x += array_coords[j][i] * array_coords[i][j];
var area = (sum_y_to_x - sum_x_to_y) / 2;
console.log(area.toPrecision(2) + "acres");
}
}
}
If you're just using Simpson's rule to calculate area, the following function will do the job. Just make sure the polygon is closed. If not, just repeat the first coordinate pair at the end.
This function uses a single array of values, assuming they are in pairs (even indexes are x, odd are y). It can be converted to using an array of arrays containing coordinate pairs.
The function doesn't do any out of bounds or other tests on the input values.
function areaFromCoords(coordArray) {
var x = coordArray,
a = 0;
// Must have even number of elements
if (x.length % 2) return;
// Process pairs, increment by 2 and stop at length - 2
for (var i=0, iLen=x.length-2; i<iLen; i+=2) {
a += x[i]*x[i+3] - x[i+2]*x[i+1];
}
return Math.abs(a/2);
}
console.log('Area: ' + areaFromCoords([1,1,3,1,3,3,1,3,1,1])); // 4
console.log('Area: ' + areaFromCoords([0,-10, 7,-10, 0,-8, 0,-10,])); // 7
Because you haven't posted actual code, I haven't input any of your examples. The sequence:
[[1,0],[1,1],[0,0],[0,1]]
is not a polygon, it's a Z shaped line, and even if converted to a unit polygon can't resolve to "7 acres" unless the units are not standard (e.g. 1 = 184 feet approximately).

rotate a matrix 45 degrees in javascript

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

Coderbyte Array Addition Solution -- For Loop with a For Loop

I'm trying to understand the logic in a solution to the Array Addition CoderByte problem. Here is the question prompt -- "Using the JavaScript language, have the function ArrayAdditionI(arr) take the array of numbers stored in arr and return the string true if any combination of numbers in the array can be added up to equal the largest number in the array, otherwise return the string false. For example: if arr contains [4, 6, 23, 10, 1, 3] the output should return true because 4 + 6 + 10 + 3 = 23. The array will not be empty, will not contain all the same elements, and may contain negative numbers."
This is a solution that works, but I get lost with the for loop within the for loop. Why isn't it always the case that i = j since the for loops both start with their counters at 0. So wouldn't it always be 0 = 0?
function ArrayAdditionI(arr) {
arr.sort(function(a,b){return a - b})
var largest = arr.pop();
var sum = 0;
for (var i = 0; i < arr.length; i++){
sum += arr[i];
for (var j = 0; j < arr.length; j++){
if (i != j) {
sum += arr[j];
if (sum == largest) {
return true;
}
}
}
for (var k = 0; k < arr.length; k++) {
if (i != k) {
sum -= arr[k];
if (sum == largest) {
return true;
}
}
}
sum = 0;
}
// code goes here
return false;
}
Thanks!
i_made_that & user3085131:
To further explain the k loop, it is used to work back through and subtract array values in the order that they were initially added, to yield new results not otherwise obtainable.
Without the k loop you can't solve many potential arrays (although it will actually pass the coderbyte test cases due to lack of appropriate test).
Consider [1,2,3,98,100]...this should pass since 2+98 = 100. However it won't without the k loop. If you log the results of sum without the k, you would see:
3 (1 + 2)
6 (3 + 3)
104 (6 + 98)
3 (2 + 1)
6 (3 + 3)
104 (6 + 98)
4 (3 + 1)
6 (4 + 2)
104 (6 + 98)
99 (98 + 1)
101 (99 + 2)
104 (101 + 3)
With the k loop however, on the second iteration of i it will pass as it will subtract 1 from 104, and then 3 from 103 to reach 100.
The thing is, is that you have 2 for loops inside the for loop with the "i" variable.
variable "i" is always going to be 0 until you finish iterating thru the 2 for loops that are inside.
for(var i=0){
for(var j=0){}
for(var k=0){}
}

Categories