How to efficiently build up this string? - javascript

I have a number that is divisible by 4, e.g. 20. Now I need to create a string that looks as follows:
(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16), (17, 18, 19, 20)
So, all the numbers from 1 to 20, grouped in packages of 4, wrapped in parentheses, and everything separated by commas.
My current approach looks like this:
const placeholders = [];
for (let i = 0; i < events.length; i++) {
const base = i * 4 + 1;
placeholders.push(`(${base}, ${base + 1}, ${base + 2}, ${base + 3})`);
}
const result = placeholders.join(',');
Is there a way to do this a) more efficiently, and b) in a more readable way?

var results = [];
for(var i = 1; i <= events.length * 4; i++){
var m = i % 4;
results.push((m==1 ? "(" : "") + i + (m==0 ? ")" : ""));
}
results = results.join(", ");
More readable? Probably not. More efficient? They run about the same.
The best take-away is probably that you could change your loop such that it starts at 1.

Just tried. Don't know efficient or not.
res = '(';
for (i = 1; i <= 20; i++) {
var mod = i % 4;
(mod == 1 && i != 1) ? res += ',(' : '';
res += i;
res += (mod != 0) ? ',' : ')';
}

Related

How can I return "1-5" if the array is [1,2,3,4,5] in JavaScript?

I am trying to make a program that returns ["1-5"] if I give [1,2,3,4,5].
I have made it but I can't filter it. So I want a code that will filter my output code. Or any code that is better than mine.
let array = [1,2,3,5,6,7,8,10,11, 34, 56,57,];
let x = [];
for(let i = 0; i < array.length; i++){
for(let j = 0; j < array.length; j++){
if(array[i] + j == array[j]){
x.push(array[i] + "-" + array[j]);
}
if(array[j] > array[i] + j && array[j + 1]){
let y = array.slice(j, array.length)
array = y;
i, j = 0;
}
if(array[i] - array[i + 1] != -1 && array[i + 1] - array[i] != 1 && array[i + 1] != undefined){
x.push(array[i]);
}
}
}
console.log(x);
The phrasing of the question makes this somewhat difficult to answer, but based on your code snippet I can gather that you are either:
Attempting to find the range of the entire array OR
Attempting to find contiguous ranges within the array
Based on these interpretations, you could answer this question as follows:
function detectRange(a) {
// clone a
const b = [...a]
// remove first value
const min = max = b.splice(0, 1)[0]
// compute range
const range = b.reduce(({min, max}, i) => {
if(i < min) min = i
if(i > max) max = i
return { min, max }
}, {min, max})
return range
}
function detectRanges(a) {
// clone a
const b = [...a]
// remove first value
const min = max = b.splice(0, 1)[0]
// init ranges array
const ranges = [ ]
// compute ranges
const range = b.reduce(({min, max}, i) => {
if(i === max + 1) {
return {min , max: i}
} else {
ranges.push({min, max})
return {min: i, max: i}
}
}, {min, max})
// push the remaining range onto the array
ranges.push(range)
return ranges
}
function printRange(r) {
console.log(`["${r.min}-${r.max}"]`)
}
function printRanges(r) {
r.forEach(i => {
printRange(i)
})
}
// detect and print range of whole array
printRange(detectRange([1, 2, 3, 5, 6, 7, 8, 10, 11, 34, 56, 57]))
// detect and print only contiguous ranges within array
printRanges(detectRanges([1, 2, 3, 5, 6, 7, 8, 10, 11, 34, 56, 57]))
If you assume that the list is sorted, we only need to traverse the list sequentially. There's no need to have double-nested loops. If you maintain sufficient states, you can determine whether you are in a group and you merely manage the start versus the last element in the group.
To simplify things I made use of ES6 string interpolation ${start}-${last}.
let array = [1,2,3,5,6,7,8,10,11, 34, 56,57];
let result = [ ];
let hasStart = false;
let start = 0;
let last = 0;
for (let num of array) {
if (!hasStart) {
hasStart = true;
last = start = num;
continue;
}
if (num === last + 1) {
last = num;
continue;
}
result.push( start === last ? start : `${start}-${last}` );
last = start = num;
}
if (hasStart) {
result.push( start === last ? start : `${start}-${last}` );
}
console.log(result);
Input: [1,2,3,4,5]
Output: ["1-5"]
So I assume you want to get string in format:
["smallestelement-largestelement"]
var input1 = [1,2,3,4,5]
console.log( "["+'"'+Math.min(...input1)+"-"+Math.max(...input1)+'"'+"]")
If what you want is string in format:
["firstelement-lastelement"]
var input1 = [1,2,3,4,5]
console.log( "["+'"'+input1[0]+"-"+input1.pop()+'"'+"]")
If you have an integer array, and if you want to output the range, you could natively sort() it (you can also provide rules for sorting) and use shift() for the first element and slice(-1) for the last:
let arr = [4,1,5,3].sort();
console.log(arr.shift()+'-'+arr.slice(-1));
As said in the comments, you should clarify if you wish "1-57" for the snippet array, or describe your use case more broadly.
const array = [1, 2, 3, 5, 6, 7, 8, 10, 11, 34, 56, 57];
let s = null;
const result = array.sort((a, b) => a - b).reduce((p, c, i, arr) => {
if (!s) s = c;
if (c + 1 !== arr[i + 1]) {
p.push(s === c ? s : `${s}-${c}`);
s = null;
}
return p
}, [])
console.log(result);

Even Position Element

I am having difficulties solving the following math problem:
'Write a JS function that finds the elements at even positions in an array.
The input comes as an array of number elements.
The output must be displayed into element with id result like a text/string.'
Input : [1, 2, 3, 4, 5, 6, 7, 8, 9]
Output: 1 x 3 x 5 x 7 x 9
This is my code until now:
function evenPosition(arr) {
let evenIndexes = [];
let oddIndexes = [];
for (let i = 1; i < arr.length + 1; i++) {
if (i % 2 !== 0) {
oddIndexes.push(i)
} else {
evenIndexes.push(i)
}
}
}
evenPosition([1, 2, 3, 4, 5, 6, 7, 8, 9])
I cannot sort the elements though as it is shown in the output... Can you guys please help?
Is this you want?
function evenPosition(arr) {
let str = "";
for (let i = 0; i < arr.length; i++) {
if (i % 2 !== 0) {
str += " x ";
} else {
str += arr[i];
}
}
return str;
}
console.log(evenPosition([1, 2, 3, 4, 5, 6, 7, 8, 9]))
The example in the OP is incorrect. In the array [1, 2, 3, 4, 5, 6, 7, 8, 9], the odd values are at even indexes and the even values are at odd indexes. So the result of replacing the values at even indexes should be "x 2 x 4 x 6 x 8 x".
There are of course many ways to achieve the required outcome, e.g.
// Return string with values at even indexes replaced by "x"
function evenPosition(arr) {
let acc = 'x';
return arr.slice(-(arr.length - 1)).reduce(
(acc, curr, i) => acc += ' ' + (i%2? 'x' : curr), acc
);
}
// Indexes start at 0, so even numbers are at odd indexes
let a = [1,2,3,4,5,6,7,8,9];
console.log('Input: ' + a + ' Output: ' + evenPosition(a));
// Array with ellisions (sparse)
let b = [1,,,,5,6,,,9,10];
console.log('Input: ' + b + ' Output: ' + evenPosition(b));
// Using map and join
console.log('Input: ' + a +
' Output: ' + (a.map((v, i) => i%2? v : 'x').join(' ')));
You can use array's join method to convert array into string with the character's you want to join. Something like this.
function evenPosition(arr) {
let evenArr = [];
for (let i = 0; i < arr.length; i++) {
if (i % 2 === 0) {
evenArr.push(arr[i]);
}
}
return evenArr.join(" x ");
}
console.log(evenPosition([1, 2, 3, 4, 5, 6, 7, 8, 9]))
If you want to sort the array also then you can return something like this.
return evenArr.sort().join(" x ");

Avoid using nested loops to find the max-sized sub-string of an array?

Added maximum number according to the input length should be returned.
For example, if the length is 2 then the max among arr[0] + arr[1], arr[1] + arr[2], arr[2] + arr[3] should be returned.
Input is array and length.
I solved this in a real job interview but I think there will be a way not to use nested loop.
const add = (arr, len) => {
let rtnVal = 0
for (let i = len - 1; i < arr.length; i++) {
let temp_idx = i;
let temp_sum = 0;
for (let j = 0; j < len; j++) {
temp_sum = (temp_sum || 0) + arr[temp_idx]
temp_idx -= 1
}
if (temp_sum > rtnVal) {
rtnVal = temp_sum
}
}
return rtnVal
}
console.log(add([1, 2, 3, 4, 5, 6, 7, 8, 9], 4))
I expect the output 30
// enhanced nested loop
const add = (arr, len) => {
let rtnVal = 0;
for(let i=len-1;i<arr.length;i++){
let sum = 0
for(let j=i;j>=i-len+1;j--){
sum += arr[j]
}
if (sum > rtnVal) rtnVal = sum
}
return rtnVal
}
console.log(add([9, 9, 9, 4, 5, 6, 7, 8, 9], 3))
Use a moving window. Add up len numbers starting at the beginning. Then continue through the array adding the next number and subtracting the trailing number.
const add = (arr, len) => {
return arr.reduce((a,v,i,arr) => {
a.running += v;
if(i >= len) {
a.running -= arr[i-len];
}
if(i+1 >= len && a.largest < a.running) {
a.largest = a.running;
}
return a;
}, {
largest: Number.NEGATIVE_INFINITY,
running: 0
}).largest;
}
console.log(add([1,2,3,4,5,6,7,8,9],4)); // 30
console.log(add([-1,-1,-1,-1],2)); // -2
console.log(add([1],1)); // 1
Assuming its sorted like your example. You can use negative slice to select from end and then reduce the array.
const add = (arr, len) => arr.slice(len > arr.len ? arr.len : -len).reduce((total, num) => total + num)
console.log(add([1, 2, 3, 4, 5, 6, 7, 8, 9], 4))

Javascript check random number duplicated

I have this random number from 1 to 10 and an array from 1 to 10 but missing an 8 and 2. I want JS to figure that out and push either 8 or 2 into the array.
Javascript:
var arr = [1, 3, 5, 6, 9, 4, 7, 10];
var num = Math.floor((Math.random() * 10) + 1);
for (i = 0; i < arr.length; i++) {
while (num == arr[i]) {
num = Math.floor((Math.random() * 10) + 1);
}
arr.push(num);
Unfortunately, it does make a new number but duplicate with the previous compared number. Please help.
You can look for the missing numbers and random an element in that array:
var arr = [1, 3, 5, 6, 9, 4, 7, 10];
// Build array of missing numbers
var missingNumbers = [];
for (var i = 1; i <= 10; i++) {
if (arr.indexOf(i) < 0) {
missingNumbers.push(i);
}
}
// Pick one of them at random
var randomNumber = missingNumbers[Math.floor(Math.random() * missingNumbers.length)];
// Push it into the array
arr.push(randomNumber);
// Show results
console.log(randomNumber);
console.log(arr);
.as-console-wrapper {
max-height: 100% !important;
}
You can try this as well
var arr =[1,3,5,6,9,4,7,10];
var num=parseInt((Math.random()*10)+1)
while(arr.indexOf(num)!=-1){
num=parseInt((Math.random()*10)+1);
}
arr.push(num)
console.log(arr)
In above example I am taking a number randomly and checking in loop that, The number is present in the array or not
while(arr.indexOf(num)!=-1)
if number will not be there then inside loop again I am generating again a number and checking. When I got a number which is not present then the loop body will not be execute and I am pushing that number in array.
As you said that only one number you want either 8 or 2
I figured it out.
var arr = [1, 3, 5, 6, 9, 4, 7, 10];
var num = Math.floor((Math.random() * 10) + 1);
for (i = 0; i < arr.length; i++) {
while (num == arr[i]) {
num = Math.floor((Math.random() * 10) + 1); }
arr.push(num);}
basically if it is duplicated, I simply put i=0 to loop again until it is unique. It might not be efficient.
The function find returns an array filled with all the duplicated numbers. It's optimized
function find(a, b) {
let result = [];
for(let i=0; i<a.length; i++) {
let num = NumbersList[i];
if(b[num] == 0) {
b[num] = 1;
} else if (b[num] == 1) {
b[num] = 2;
result.push(num);
}
}
console.log("Duplicated numbers: " +result.length);
return result;
}
var NumbersList = new Array();
var value = 30000;
for(let i=0; i<value; i++) {
let x = Math.floor((Math.random() * value) + 1);
NumbersList.push(x);
}
var map = new Array(NumbersList.length).fill(0);
var t0 = performance.now();
find(NumbersList, map);
var t1 = performance.now();
console.log("Call to find with " +value+ " numbers took " + (t1 - t0) + " milliseconds.");

The numbers in my javascript will not add

So I need the code to use addition on random numbers in the array. If the sum is greater then ten, it should say "over" else it would be "under."
`
function arraries(){
var oneten = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
document.getElementById('demo').innerHTML = addy(oneten);
}
function addy(oneten){
var n;
var output;
var sum = "";
for (i = 0; i < 4; i++){
n = Math.floor((Math.random() * 10) + 1);
sum += parseFloat(oneten[n])}
if (sum > 10){
return "over";
}
else { return "under";}
}
The problem here is that the debugger decipher the numbers as strings. While running the sum would equal "1234" instead of 10 (which is 1 + 2 + 3 + 4) and thus it will always return "over". How can I make sure that the data will be treat as actually numbers instead of strings? I used parseFloat and parseInt but I got the same results
Mabybe you can try to set sum = 0, because like this js will concatenate into a string instead of into a int
Shouldn't you declare the sum variable as a number? Also, you don't need parseFloat function, the oneten array elements are already typeof number.
Another thing - Math.random() * 10) + 1 loss numbers from the 1 - 10 range and in your case it will return undefined because there's no item in the oneten array with index 10. Use Math.random() * 10 instead, which will return numbers from 0 - 9 range.
function arraries() {
var oneten = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
document.getElementById('demo').innerHTML = addy(oneten);
}
function addy(oneten) {
var n;
var output;
var sum = 0;
for (i = 0; i < 4; i++) {
n = Math.floor((Math.random() * 10));
sum += oneten[n];
}
console.log(sum);
if (sum > 10) {
return "over";
} else {
return "under";
}
}
arraries();
<p id='demo'></p>
type coercion in javascript
var s = "1";
var i = 1;
var i = i+1;
// 2 int + int = int
var s2 = s+1;
// "11" str + int = str
var s3 = i+"1";
// "11" int + str = str

Categories

Resources