Can someone please help me understand the differences between these two programs? I was doing this RallyCoding Prep problem and wrote the first program (and it failed). Then I checked what others did to try and understand but it seems to me that the two programs do basically the same thing, written differently. Can someone help me understand why mine fails and the second program works?
Link to problem: https://www.rallycoding.com/problems/205
--My code--
let k = 16;
let length = Math.sqrt(k);
let height = length;
let arr = []
for(let i = 0; i < length; i++){
let row = [];
for(let x = 1; x <= k; x++){
row.push(x);
}
arr.push(row);
}
console.log(arr)
--Their code--
let k = 16
let c = 1;
const r = Math.sqrt(k);
const result = [];
while(c <= k) {
const block = [];
for (let i = 1; i <= r; i++) {
block.push(c);
c++;
}
result.push(block);
}
console.log(result)
I'm certain I'm missing something very obvious. I hope someone can help me understand this. Thank you!
Since the value of k = 16, the inner loop runs 16 times. So, the result produced by your code is
[
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
]
And the result produced by their code is
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
]
So, you can make these changes in your code to get the desired result.
let k = 16;
let length = Math.sqrt(k);
let height = length;
let arr = []
for(let i = 0; i < length; i++){
let row = [];
for(let x = 1; x <= length; x++){
row.push(x + i * length);
}
arr.push(row);
}
You code produces data like this: [[1, 2, 3], [1, 2, 3], ...]
(Each sub-array starts with 1)
You need to produce: [[1, 2, 3], [4, 5, 6], ...]
(Each sub array continues the sequence of the previous one)
the nested forloop you created loop over 16 times
for(let x = 1; x <= k; x++){ row.push(x); }
because K=16 so it will provide an array with 16 element.
the forloop keep runing intel it finish the job.but in the correction they use a "while" loop because The 'while' loop used only when the number of iteration are not exactly known.the are some diff between the two.
Here's a link you can find more
Related
const grades = [9, 8, 5, 7, 7, 4, 9, 8, 8, 3, 6, 8, 5, 6];
for (let i = 0; i < grades.length; i++) {
if (grades[i] >= 8) {
console.log(grades[i])
}
}
I'm trying to log how many items from the array fulfil the condition. the output I'm looking for is : 6 (because 6 of the numbers are equal or greater than 8)
tried
let count = 0;
for (let i = 0; i < grades.length; i++) {
if (grades[i]>= 8){
count++
console.log(count)
}
}
function countGreaterThan8(grades){
// initialize the counter
let counter = 0;
for (let i = 0; i < grades.length; i++) {
// if the condition satisfied counter will be incremented 1
if (grades[i] >= 8) {
counter++;
}
}
return counter;
}
const grades = [9, 8, 5, 7, 7, 4, 9, 8, 8, 3, 6, 8, 5, 6];
console.log(countGreaterThan8(grades)); // 6
You can call Array.filter to create a new array containing only items that fulfill the condition. You can then make use of the length of the array however you want. Like this
const grades = [9, 8, 5, 7, 7, 4, 9, 8, 8, 3, 6, 8, 5, 6];
const gradesThatPassCondition = grades.filter(grade => grade > 6);
console.log(gradesThatPassCondition.length);
I have an array such as:
[16, 20, 1, 4, 6, 8, 9, 22, 18, 14, 13, 12]
That I would like split into 6 different arrays based on ranges 1-4, 5-8, 9-12, 13-16, 17-20, 21-24.
What is the simplest way to do this with javascript?
You could use an interval for assigning the numbers to a specific slot.
var array = [16, 20, 1, 4, 6, 8, 9, 22, 18, 14, 13, 12],
interval = 4,
result = array.reduce(function (r, a) {
var slot = Math.floor((a - 1) / interval);
(r[slot] = r[slot] || []).push(a);
return r;
}, []);
console.log(result);
The solution using Array.prototype.filter() function:
var list = [16, 20, 1, 4, 6, 8, 9, 22, 18, 14, 13, 12], i
result = [];
// considering ranges `1-4, 5-8, 9-12, 13-16, 17-20, 21-24`
for (i = 1; i < 24; i+= 4) {
result.push(list.filter(function(d){
return ((i+4 > d) && d >= i); // check if the number between lower and upper bound
}));
}
console.log(result);
Simplest answer:
var numbers = [16, 20, 1, 4, 6, 8, 9, 22, 18, 14, 13, 12];
var array1 = []; // range 1-4
var array2 = []; // range 5-8
for(var i=0; i< numbers.length; i++) {
if(numbers[i]>= 1 && numbers[i] <= 4) {
array1[i] = numbers[i]
} else if(numbers[i]>= 5 && numbers[i] <= 8) {
array2[i] = numbers[i]
}
//... continue for remaining ranges
}
I have a function that picks all elements from a 2-dimensional array by its rows and returns a 1-dimensional array.
The array has a variable amount of columns and rows.
Example:
let arr = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
];
Returns:
[1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
The function i came up with:
convertList = (list) => {
let result = [];
let listTotalEntries = R.sum(R.map(R.length)(list));
let mod = R.modulo(R.__, list.length);
let counterRow = -1;
for (let i = 0; i < listTotalEntries; i++) {
if (mod(i) === 0) {
counterRow++;
}
if (list[mod(i)][counterRow]) {
result.push(list[mod(i)][counterRow]);
console.log(list[mod(i)][counterRow]);
}
}
console.log(result);
return result;
};
Question: This function works only with square matrices - how can i make it work with a variable length of the contained arrays?
Example:
let arr = [
[1, 2],
[],
[9, 10, 11, 12]
];
Should return:
[1, 9, 2, 10, 11, 12]
Thanks for your help!
Muff
You had a ramda.js tag in here. With Ramda, it's pretty simple, since there are two functions that will help:
const convertList = compose(flatten, transpose);
convertList(arr); //=> [1, 9, 2, 10, 11, 12]
transpose flips a matrix over its main diagonal, that is, changing rows to columns and vice versa. flatten turns a list of lists into a plain list. So composeing like this essentially creates the equivalent of list => flatten(transpose(list)).
You can see this in action on the Ramda REPL.
I suggest to go step-by-step through the arrays
var arr1 = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],
arr2 = [[1, 2], [], [9, 10, 11, 12]];
function single(array) {
var r = [],
max = Math.max.apply(null, array.map(function (a) { return a.length; })),
i = 0, j,
l = array.length;
while (i < max) {
for (j = 0; j < l ; j++) {
i in array[j] && r.push(array[j][i]);
}
i++;
}
return r;
}
document.write('<pre>' + JSON.stringify(single(arr1), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(single(arr2), 0, 4) + '</pre>');
Did you try this simple one?
var singleDimensionArr = arr.reduce(function(prev,current){return prev.concat(current)});
For example
[
[1, 2],
[],
[9, 10, 11, 12]
].reduce(function(prev,current){return prev.concat(current)});
outputs [1, 2, 9, 10, 11, 12]
Edit:
Based on the inputs from OP below, since the concatenation needs to happen column wise
var max = Math.max.apply(null, arr.map(function (a) { return a.length; }));
var finalArr = []; for( var i = 0; i < max; i++)
{
for( var j = 0; j < arr.length; j++)
{
arr[j][i] ? finalArr.push(arr[j][i]) : "";
}
}
console.log(arr);
This example makes a big sparse array putting each item where it would belong if the array were square. Then it filters out null values which occur where no input item was present.
let arr = [
[1, 2],
[],
[9, 10, 11, 12]
];
var out = arr.reduce(function(o,n,i,a) {
for (var j=0;j<n.length;j++){
o[a.length * j + i] = n[j];
}
return o;
},[]).filter(function(n) {
return n !== null;
});
alert(JSON.stringify(out));
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
var myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var Remve = [];
var i;
for(i=0;i<myNums.length;i++){
if(myNums[i] % 3 == 0){
Remve.push(myNums[i])
}else{
myNums.push(myNums[i])
}
}
document.write(myNums);
document.write(Remve);
Why is my push function not working when I am inserting the value in the same array?
When I am inserting in another array it works.
Dissecting the relevant parts of your code:
// Allocate an array containing three values that will match: [3, 6, 9]
var myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Get the length of myNums *every iteration*
for (i = 0; i < myNums.length; i++) {
if (myNums[i] % 3 == 0) {
...
} else {
// Append the value to myNums if it is evenly divisible by three
myNums.push(myNums[i])
}
}
This will hit an infinite loop.
On each iteration, myNums will look like:
[_1_, 2, 3, 4, 5, 6, 7, 8, 9, 10] // append 1
[1, _2_, 3, 4, 5, 6, 7, 8, 9, 10, 1] // append 2
[1, 2, _3_, 4, 5, 6, 7, 8, 9, 10, 1, 2]
[1, 2, 3, _4_, 5, 6, 7, 8, 9, 10, 1, 2] // append 4
[1, 2, 3, 4, _5_, 6, 7, 8, 9, 10, 1, 2, 4] // append 5
... and so on
Once you've hit the end of the collection, every iteration will append yet another value to the very end.
You can solve this pretty easily, if you don't want to hit the appended items:
var myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var Remve = [];
var i;
var l = myNums.length;
for (i = 0; i < l; i++) {
if (myNums[i] % 3 == 0) {
Remve.push(myNums[i])
} else {
myNums.push(myNums[i])
}
}
document.write(myNums);
document.write(Remve);
By caching the length first, you won't enter the infinite loop.
You can also push the undivisible items into a different array instead of onto the end of the current one, which will solve the problem equally well.
A) You are constantly checking myNums.length, while inserting values into it.
B) It IS working, as you can see the same values appearing in myNums over and over again. But this is an infinite loop.
C) Console.log(Rmve); shows that you are indeed selecting for numbers divisible by 3.
Your current code is generating an infinite loop, your exit condition is never met.
Notice that myNums.length is constantly increased since you're adding new elements inside loop.
You should get array length before start iterating
var myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var Remve = [];
var i;
var arrayLength = myNums.length; // get length BEFORE starting for loop
for(i=0; i < arrayLength; i++){
if(myNums[i] % 3 == 0){
Remve.push(myNums[i])
}else{
myNums.push(myNums[i])
}
}
alert(myNums);
alert(Remve);
It is running in an infinite loop. You are pushing value in a same array so the array length keeps on increasing and it will never end.
var myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var Remve = [];
var i;
for(i=0;i<myNums.length;i++){
if(myNums[i] % 3 == 0){
Remve.push(myNums[i])
}else{
myNums.push(myNums[i]) //problematic line
}
}
You didn't say what you meant by "not working," and I'm not sure what you're trying to do, but I saw a problem. The loop was going off of the length of the array, which was changing each time the array ran after the 9th iteration, causing an infinite loop. Saving that in a static variable fixed this:
var myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var Remve = [];
var i;
var myNumLength = myNums.length;
for(i=0;i<myNumLength;i++){
if(myNums[i] % 3 == 0){
Remve.push(myNums[i])
}else{
myNums.push(myNums[i])
}
}
document.write(myNums);
document.write('<br>');
document.write(Remve);
Update: new code:
var originalNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var newNums = [];
var removedNums = [];
var i;
var myNumLength = originalNums.length;
for(i=0;i<myNumLength;i++){
if(originalNums[i] % 3 == 0){
removedNums.push(originalNums[i])
}else{
newNums.push(originalNums[i])
}
}
document.write(newNums);
document.write('<br>');
document.write(removedNums);
Update again
var myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var removedNums = [];
var i;
var myNumLength = myNums.length;
for(i=0;i<myNumLength;i++){
if(myNums[i] % 3 == 0){
removedNums.push(myNums[i]);
myNums.splice(i, 1);
i--;
}
}
document.write(myNums);
document.write('<br>');
document.write(removedNums);
Use a separate array (myNumsArr) to store the values instead of myNums. Your current code will result in infinite loop.
var myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var myNumsArr = [];
var Remve = [];
var i;
for(i=0;i<myNums.length;i++){
if(myNums[i] % 3 == 0){
Remve.push(myNums[i])
}else{
myNumsArr.push(myNums[i])
}
}
myNums = myNums.concat(myNumsArr);
I've a for loop in javascript shown below. How to convert it to lodash for loop?
In such scenarios using lodash is advantageous over javascript for loop?
I've not used lodash much. Hence please advice.
for (var start = b, i = 0; start < end; ++i, ++start) {
// code goes here
}
You can use lodash range
https://lodash.com/docs/4.17.4#range
_.range(5, 10).forEach((current, index, range) => {
console.log(current, index, range)
})
// 5, 0, [5, 6, 7, 8, 9, 10]
// 6, 1, [5, 6, 7, 8, 9, 10]
// 7, 2, [5, 6, 7, 8, 9, 10]
// 8, 3, [5, 6, 7, 8, 9, 10]
// 9, 4, [5, 6, 7, 8, 9, 10]
// 10, 5, [5, 6, 7, 8, 9, 10]
I will imagine that b = 3 and end = 10 if I run your code and print the variables here is what I will get:
var b = 3;
var end = 10;
for (var start = b, i = 0; start < end; ++i, ++start) {
console.log(start, i);
}
> 3 0
> 4 1
> 5 2
> 6 3
> 7 4
> 8 5
> 9 6
To perform this with lodash (or underscore) I will first generate an array with range then iterate over it and gets the index on each iteration.
Here is the result
var b = 3;
var end = 10;
// this will generate an array [ 3, 4, 5, 6, 7, 8, 9 ]
var array = _.range(b, end);
// now I iterate over it
_.each(array, function (value, key) {
console.log(value, key);
});
And you will get the same result. The complexity is the same as the previous one (so no performance issue).
It seems there is no lodash way for writing loose for loops (those not iterating over a collection), but here is a simplified version of it:
for (var i = 0; i < end - b; i++) {
var start = i + b;
// code goes here
}