Array to Object with Values in a Range - javascript

I have a crazy requirement here. I am not sure how to make it work well, may be I thought of getting the community's help here. This is the first time here for me. Let me explain my situation clearly.
I have an array of, say 10 elements.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reverse();
Now I need to create an object of keys containing the array elements, but their values should be like:
First 5 to be "high".
Next 3 to be "medium".
Rest 2 to be "low".
I do have the above information in another array:
var capacity = [5, 3, 2];
The above three values (high, medium, low) are static. Not sure how to proceed from here. I am not sure if I should be using a for loop hardcoded like:
var obj = {};
for (var i = 0; i < capacity[0]; i++)
obj[arr[i]] = "high";
for (; i < capacity[0] + capacity[1]; i++)
obj[arr[i]] = "medium";
for (; i < capacity[0] + capacity[1] + capacity[2]; i++)
obj[arr[i]] = "low";
Not sure if this is the right way to proceed. Any pointers for the right direction? Thanks.
Snippet
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reverse();
var capacity = [5, 3, 2];
var obj = {};
for (var i = 0; i < capacity[0]; i++)
obj[arr[i]] = "high";
for (; i < capacity[0] + capacity[1]; i++)
obj[arr[i]] = "medium";
for (; i < capacity[0] + capacity[1] + capacity[2]; i++)
obj[arr[i]] = "low";
console.log(obj);

Related

Print alternatively one element from the last and one from the first (JavaScript)

Print alternatively one element from the last and one from the first (JavaScript)
input
1, 3, 6, 3, 2, 8
output:
8, 1, 2, 3, 3, 6
You can use the below approach
var array = [];
var size = prompt('Enter Array Size'); //Maximum Array size
for(var i=0; i<size; i++) {
//Taking Input from user
array[i] = prompt('Enter Element ' + (i+1));
}
//Print the array in the console.
console.log("Array Input: "+array.join(','));
let output = [];
let l = array.length - 1;
for (let i = 0; i <= l; i++, l--) {
if (i>=array.length/2) {
console.log(array[i]);
break;
}
output.push(array[l]);
output.push(array[i]);
}
console.log("Resultant Array: "+output.join(','));
Anyways you can try the below logic.
const input = [1, 3, 6, 3, 2, 8];
let output = [];
for (var i = 0; i < input.length / 2; i++) {
output.push(input[i]);
output.push(input[input.length - (i + 1)]);
}

LeetCode 768: Constructing a variation on a solution for Max Chunks To Make Sorted

LeetCode's Max Chunks To Make Sorted II challenge is:
Given an array arr of integers (not necessarily distinct), we split
the array into some number of "chunks" (partitions), and individually
sort each chunk. After concatenating them, the result equals the
sorted array.
What is the most number of chunks we could have made?
Example:
Input: arr = [2, 1, 3, 4, 4]
Output: 4
Explanation:
We can split into two chunks, such as [2, 1], [3, 4, 4].
However, splitting into [2, 1], [3], [4], [4] is the highest number of chunks possible.
The algorithm underlying the following solution is (the algorithm and the solution were posted as a comment on the solution page by a user named #benevolent. Unfortunately, I can't link to its comment):
If the largest number from arr[0] to (including) arr[k] is less than or equal to the smallest
number from arr[k+1] to the end, then we can split into two valid
chunks.
To illustrate:
left right
[......max] [min......]
To know the minimum element from k to arr.length-1, we can just
precompute from right to left.
The solution:
function maxChunksToSorted(arr) {
var minRight = Array(arr.length).fill(Number.MAX_SAFE_INTEGER);
for (var i = arr.length-2; i >= 0; --i) {
minRight[i] = Math.min(minRight[i+1], arr[i+1]);
}
var maxLeft = Number.MIN_SAFE_INTEGER;
var ans = 0;
for (var i = 0; i < arr.length; ++i) {
maxLeft = Math.max(maxLeft, arr[i]);
if (maxLeft <= minRight[i]) {
ans += 1
}
}
return ans;
};
console.log("expects: 1", "got:", maxChunksToSorted([5, 4, 3, 2, 1]));
console.log("expects: 4", "got:", maxChunksToSorted([2, 1, 3, 4, 4]));
My question:
I was trying to make a "mirror image" of the above solution, by "flipping" every action (e.g, the use of min becomes max, <= becomes >, and so on).
My maxArr indeed mirrors minRight (e.g., for [2, 1, 3, 4, 4], my maxArr is [MIN_SAFE_INTEGER, 1, 3, 4, 4], while the original minRight is [1, 3, 4, 4, MAX_SAFE_INTEGER]), but it clearly doesn't work, and I can't put my finger on the reason for that.
What's my fundamental problem?
Let me stress that I'm not looking for some other working solution. I'd like to understand what went wrong with my mirror solution, if it's even possible to make this mirror, and if not - what's the fundamental reason for that.
function maxChunksToSorted(arr) {
var maxArr = Array(arr.length).fill(Number.MIN_SAFE_INTEGER);
for (var i = 1; i <= arr.length; ++i) {
maxArr[i] = Math.max(maxArr[i-1], arr[i]);
}
var minLeft = Number.MAX_SAFE_INTEGER;
var ans = 0;
for (var i = 0; i < arr.length; ++i) {
minLeft = Math.min(minLeft, arr[i]);
if (minLeft > maxArr[i]) {
ans += 1
}
}
return ans;
};
console.log("expects: 1", "got:", maxChunksToSorted([5, 4, 3, 2, 1]));
console.log("expects: 4", "got:", maxChunksToSorted([2, 1, 3, 4, 4]));
This should do the job:
function chunk(list){
let sortedList = list.slice();
sortedList.sort();
var beginIndex = -1; var biggestFound;
var foundFirst = false; var foundLast = false;
for(var i = 0; i < list.length; i++){
if(beginIndex == -1) {
if(list[i] == sortedList[i]) print(list[i]);
else {beginIndex = i; biggestFound = list[i];}
}
else{
if(list[i] == sortedList[beginIndex]) foundFirst = true;
if(list[i] > biggestFound) biggestFound = list[i];
if(biggestFound == sortedList[i]) foundLast = true;
if(foundFirst && foundLast){
print(list.slice(beginIndex, i - beginIndex + 1));
foundFirst = false; foundLast = false; beginIndex = -1;
}
}
}
}
chunk([2,1,3,4,4]);
As I commented, if a chunk starts at position i, it must contain the element that corresponds to the position i in the sorted array and if it ends in position j, it must contain the element in the index j of the sorted array.
When both of these conditions are satisfied, you close the chunk and start a new one.
The complexity is O(n lg(n)), where n is the size of the array.

divisibleByThreePairSum, I get pair repeats

i'm just beginning to learn javascript and this is my first question on stackoverflow, so feel free to criticize me if i'm approaching this the wrong way.
var divisibleByThreePairSum = function(array) {
var pairs = [];
for (var i = 0; i < array.length; i++) {
for (var j = i++; j < array.length; j++) {
var sum = array[i] + array[j];
if (sum % 3 === 0) {
pairs.push([i, j]);
}
}
}
return pairs;
}
console.log(divisibleByThreePairSum([3,1,0,2,1,3,2,0]));
This gives me the answer;
[ [ 1, 3 ], [ 1, 6 ], [ 3, 4 ], [ 5, 5 ], [ 5, 7 ], [ 7, 7 ] ]
[Finished in 0.2s]
For the second "for" loop, I formatted it like so, (j = i++) as to avoid repeats like [1, 3], [3, 1], but I can't seem to get rid of getting pairs like [5, 5], and [7, 7]. Is there any possible ways to format the code differently so that this doesn't happen? Again, I apologize if this was asked improperly; i'll definitely be using this site more often so please let me know if i'm doing anything wrong "question format" wise, Thanks!
Issue is j = i++. This will assign value of i to j and then increment value of i. This will also result in skipping of alternate values of i as it is incremented twice.
for(var i = 0; i< 5; i++){
for(var j = i++; j< 5; j++){
console.log(i,j)
}
}
You should rather use j=i+1. This will sent next value and will not increment value of i
var divisibleByThreePairSum = function(array) {
var pairs = [];
for (var i = 0; i < array.length; i++) {
for (var j = i+1; j < array.length; j++) {
var sum = array[i] + array[j];
if (sum % 3 === 0) {
pairs.push([i, j]);
}
}
}
return pairs;
}
console.log(divisibleByThreePairSum([3, 1, 0, 2, 1, 3, 2, 0]));

How to slice an array in a custom pattern?

I have this array:
var x = [1,2,3,4,5,"a","b","c",9,10];
I would like to slice this array into this pattern:
var x = [[1,2,3],[2,3,4],[3,4,5],[4,5,"a"],[5,"a","b"],["a","b","c"],["b","c",9],["c",9,10]];
I used the following code and been able to get [[1,2,3],[4,5,"a"],["b","c",9],[10,11,12]] . But it doesn't work for me. I need to get the pattern above.
var stream = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var x = ["a", "b", "c"];
var ad_time = 6;
var result = [];
var ad_index = stream.indexOf(ad_time);
if (~ad_index) {
for (var i = 0; i < x.length; i++) {
stream[ad_index + i] = x[i];
}
}
while (stream.length > 0) {
var chunk = stream.splice(0, 3);
result.push(chunk);
}
console.log(JSON.stringify(result));
Thanks in advence!
This code should do it:
var x = [1,2,3,4,5,"a","b","c",9,10];
var new_array = [];
for (var i = 0; i < x.length - 2; i++) {
new_array.push(x.slice(i, i + 3));
}
You can achieve it with a simple for loop:
var x = [1,2,3,4,5,"a","b","c",9,10];
var result = [];
for (var i = 0, il = x.length - 2; i < il; i++) {
result.push([x[i], x[i + 1], x[i + 2]]);
}
console.log(result);
EDIT: Array.slice() is more elegant, however it is much slower. On Chrome it is 80% - 85% slower according to this test. If you don't need to worry about performance, choose whichever you like. For example if you need to slice 8 elements from the array, then using x.slice(i + 8) is easier to write and read than [x[i], x[i + 1], x[i + 2], x[i + 3], ...]. However if performance matters, then direct access might be a better choice.

Split an array by its index

Suppose I have an array:
var ay=[0,1,2,3,4,5,6,7,8,9];
Now I want to get two array:
var ay1=[0,2,4,6,8];
var ay2=[1,3,5,7,9];
What is efficient way?
Update:
I know the simple loop and modulo operator method(as elclanrs said) like this:
var ay1=[],ay2=[];
for(var i=0,len=ay.length;i++){
if(i%2==0){
ay2.push(ay[i]);
} else
ay1.push(ay[i]);
}
But I just wonder if there is any other efficient or cool way I do not know yet.
That is why I ask this simple question. I am not asking how to do , I am asking how to do better if possible!
So I do not think this post deserved the down-votes.
Let's say we generalize this problem a bit. Instead of just splitting an array's alternating elements into two arrays, why not allow for the array to be split in the same way into three, four, or more individual arrays?
It turns out it's about as easy to allow for any number of arrays as it is to do just two.
Think of the array like a rope made up of strands, and whatever number of strands you have in the rope, you want to unravel it. You could do it like this:
// "Unravel" an array as if it were a rope made up of strands, going
// around the rope and pulling off part of each strand one by one.
// 'rope' is the array and 'count' is the number of strands.
// Return an array of arrays, where the outer array has length 'count'
// and the inner arrays represent the individual strands.
function unravel( rope, count ) {
// Create each strand
var strands = [];
for( var i = 0; i < count; i++ ) {
strands.push( [] );
}
// Unravel the rope into the individual strands
for( var i = 0, n = rope.length; i < n; i++ ) {
strands[ i % count ].push( rope[i] );
}
return strands;
}
var rope = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
var s = unravel( rope, 2 );
console.log( s[0], s[1] );
var s = unravel( rope, 3 );
console.log( s[0], s[1], s[2] );
var s = unravel( rope, 5 );
console.log( s[0], s[1], s[2], s[3], s[4] );
This logs:
[0, 2, 4, 6, 8] [1, 3, 5, 7, 9]
[0, 3, 6, 9] [1, 4, 7] [2, 5, 8]
[0, 5] [1, 6] [2, 7] [3, 8] [4, 9]
Note that in the second case (count=3) one of the strands is longer than the other two—which is to be expected since 10 is not evenly divisible by 3.
Why not use a modulus function?
for (var i = 0; i < ay.length; i++) {
if (i%2 == 0)
{
ay1[i] = ay[i];
}
else
{
ay2[i] - ay[i];
}
}
var ay=[0,1,2,3,4,5,6,7,8,9];
var ay1 = [];
var ay2 = [];
for (var i = 0; i < ay.length; i++)
if (i % 2) ay2.push(ay[i]);
else ay1.push(ay[i]);
console.log(ay1, ay2);
http://jsfiddle.net/MPAAC/
var ay1=new Array();
var ay2=new Array();
for (var i = 0, len = ay.length; i < len; i++) {
//Check the i is odd or even
//insert any one of the array
}
Why not use the array's filter method?
var ay = [0,1,2,3,4,5,6,7,8,9];
var odds = ay.filter(function(val){ return val % 2 === 1; });
var evens = ay.filter(function(val){ return val % 2 === 0; });
With a shim from the above link being available if you need to support IE8
Here's one way:
var ay = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var ay1 = [];
var ay2 = [];
for(var i = 0; i < ay.length; i++) {
if(i % 2 == 0) {
ay1.push(ay[i]);
}else{
ay2.push(ay[i]);
}
}
funciton isEven(x) {
return x % 2 == 0;
}
function isOdd(x) {
return ! isEven(x);
}
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
arrEven = arr.filter(isEven),
arrOdd = arr.filter(isOdd);
Here is a variant, just because I can. Is it "the most efficient"? Heck no; but it has the same bounds - O(1) for a constant-sized number of result lists.
It's cool and super flexible - it's really just a "partition" variant that can unzip to n (possibly non-distinct) sequences. Most other answers given are all based on a specialized partition implementation that doesn't utilize a HoF, so I consider this superior in that aspect ;-) It should be a good exercise to work through how this works.
function unzip(arr) {
var conds = Array.prototype.slice.call(arguments, 1);
// Requires ES5 or a shim for `Array.map`.
var res = conds.map(function () { return [] });
for (var i = 0; i < arr.length; i++) {
for (var k = 0; k < conds.length; k++) {
if (conds[k](i, arr[i])) {
res[k].push(arr[i]);
}
}
}
return res;
}
r = unzip([0,1,2,3,4],
function (i) { return !(i % 2) }, // even
function (i) { return i % 2 }); // odd
alert(r[0] + " || " + r[1]);
If underscore.js is already being used (why not?) then a groupBy approach can be used.

Categories