How to get the remainder of multiple array values? - javascript

I'm creating something fun for myself just to improve my knowledge and im currently stuck at this problem, where I need to get the remainder of 2 array values.
It's gonna be hard to explain with words, so I'll try my best to write it out. The code below will display 20 lines with numbers, for example, the first numbers are gonna be 1441 and 1468, what I need is to subtract the first number and the second number to get the first numbers results/remainder, which is gonna be 1441-1468, which results to -27, and then the 2nd number is gonna subtract the number 3rd number in the array, which comes after 1468.
Simpler explanation:
1441 - this is the first number, that subtracts the number below
1468 - this is the number, that gets subtracted and as a result you get the sum. Then this number subtracts the number below, which is 1445, and so forth.
1445.
const axios = require('axios');
async function getStats() {
let res = await axios.get(`https://api.faceit.com/stats/api/v1/stats/time/users/57c80380-a00f-47ff-996f-8e541156e3c0/games/csgo?size=20`);
let data = res.data;
return data;
}
getStats()
.then(stats => {
let eloArr = [];
for (let i=0; i < stats.length; i++) {
eloArr.push(stats[i].elo);
console.log(eloArr[i]);
}
});

This is what is understand from your question and try to solve your issue.
const arr = [1441,1468,1445,1512,1621,1000];
let finalAnswer = [];
for(let i = 1;i<arr.length;i++)
{
finalAnswer.push(arr[i-1] - arr[i]);
}
console.log(finalAnswer);

Not totally sure what you want as a final result. Maybe this would work for you.
getStats()
.then(stats => {
let eloArr = [stats[0].elo];
console.log(eloArr[0]);
let total = stats[0].elo;
for (let i = 1; i < stats.length; i++) {
eloArr.push(stats[i].elo);
console.log(stats[i].elo);
total -= stats[i].elo;
}
console.log(total);
});

After some hours of trying to figure this problem out, I settled on the easiest solution. It's not by far the best solution, but works for what I need.
This is what I wanted to get as a final result - https://repl.it/repls/HelpfulNoxiousDigits

Related

Trying to use 'reduce' instead of regular for loop

I am trying to get the total 'stargazers_count' from a particular user's github repo. This code, using 'for' loop is working. But I would like to use 'reduce'. I am posting what I tried. Can someone point to me where I am wrong?
The JSON can be viewed with this url,using your github username:
https://api.github.com/users/${your username}/repos
This is the working code using for loop:
axios.get(response.data.repos_url)
.then((res) => {
let starCount = 0;
for(let i=0; i<res.data.length; i++) // find out the total number of github stars
{
starCount += res.data[i].stargazers_count;
}
response.data.NoOfStars = starCount; // add the total stars as a property in response object
This is what I tried with 'reduce':
axios.get(response.data.repos_url)
.then((res) => {
let starCount = 0;
const reducer = (acc, currVal) => acc + currVal.stargazers_count;
arr = res.data;
starCount = arr.reduce(reducer);
This did not work. If I can get a brief explanation of where and why I am wrong, it will be helpful.
You need to provide a starting value for your accumulator, otherwise reduce will assume that the first array element is the starting value and this would lead to a NaN result.
starCount = arr.reduce(reducer,0);

Unable to pass an array as argument of a javascript function

I'm trying to implement the quickSort algorithm in javascript, i have to extract 10,000 numbers from a txt file, pass them into an array, and pass this as an argument of my quickSort function, using the fs module of nodejs. The code is able to read the 10,000 numbers, and to convert them from an array of string to an array of number, but when i try to pass the array into my function, only 3472 numbers are passed, which i don't understand.
const fs = require('fs');
// Reading the data from the file containing the 10,000 numbers
const file = fs.readFileSync('./quickSort.txt', 'utf-8');
//Checking if it has read all the numbers correctly
console.log(file); // Displays the 10,000 numbers as strings in an array
// Convert them from string to integer
const finalFile = file.split('\n').map(e => {
return parseInt(e, 10);
})
// Checking if it has converted each element of the array to an integer
//console.log(finalFile) displays the array, with the 10,000 elements converted to integers
// Initialize a counter for the comparaisons made by the quickSort algorithm
let comparisons = 0;
// Sort them using quick sort
function quick_Sort(origArray) {
if (origArray.length <= 1) {
return origArray;
} else {
// Checking if the array has been correctly passed as an argument
console.log(origArray.length); //Displays 3742 instead of 10,000
var left = [];
var right = [];
var newArray = [];
var pivot = origArray.pop();
var length = origArray.length;
// I have tried comparisons += length - 1; too, but i doesn't work
comparisons += length;
for (var i = 0; i < length; i++) {
if (origArray[i] <= pivot) {
left.push(origArray[i]);
} else {
right.push(origArray[i]);
}
}
for (var i = 0; i < right.length; i++) {
comparisons++;
if (right[i] < pivot) {
return right.splice(i, 0, pivot);
}
}
return newArray.concat(quick_Sort(left), quick_Sort(right));
}
}
// Display the result
const result = quick_Sort(finalFile);
// expected output: 25
console.log(result);
Thank you very much.
Edit: In fact the problem of the size comes from the last for loop of the function, if i delete it, and insert the pivot between like that, it works (thanks to StardustGogeta) :
return newArray.concat(quick_Sort(left), pivot, quick_Sort(right));
This is a logical error. You need to change
return newArray.concat(quick_Sort(left), quick_Sort(right));
to
return newArray.concat(quick_Sort(left), pivot, quick_Sort(right));
With that change, the program works for me. The problem is that you are accidentally getting rid of (via .pop()) approximately 1/3 of your input values (the pivot values) during sorting.
try this:
const finalFile = file.split('\r?\n').map(.....)
Your parsing code works for me except for one issue: parseInt returns NaN for the last new line so you need to remove the last element from the array like this: finalFile.pop();. However this does not explain why you are seeing such a difference in the number of elements. There must be something different either in the code or the file you posted.

Algorithm to Sort a List of n Number of Items by Comparing them Against One Another in Pairs

I will try to be specific as possible as I can't find anything on this through the Google gods.
I have a list of 10 movies. I would like to display the movies in pairs. The user picks their favorite of the two. The next pair is displayed. The user picks their favorite of those two, so on and so on until I can faithfully output the list in their order of preference from 1-10.
I'm doing this in Javascript, but even just a way to do it that is language agnostic would be great. No need to worry about syntax or UI stuff.
With three movies it's pretty easy (initial order of movies and order of pairs shouldn't matter):
1.sw
2.esb
3.rotj
example 1
1vs2: winner = 2
2vs3: winner = 2
1vs3: winner = 1
Sorted List: 2,1,3
example 2
1vs3: winner = 1
1vs2: winner = 2
2vs3: winner = 2
Sorted List: 2,1,3
First time posting so if I need to be more specific, need to have exact syntax, etc., please don't hesitate to let me know.
The minimum number of comparisons required to sort 10 items is 22. (See https://oeis.org/A036604). Do you really think your users will suffer through 22 "which movie do you like better?" questions? And do you honestly believe that the result will be useful? You'll have many cases where a user will say that he liked movie A better than B, and B better than C, but he liked movie C better than he liked movie A. So now you have the problem that:
A > B
B > C
C > A
And there's no reasonable way to resolve that conflict.
In short, your user interface is flawed. You can try to build it, but your users won't like it and your results will not be reliable.
A better interface would be to list the 10 movies and allow the users to arrange them in order of preference. Or let the user rate the movies on a scale from 1 to 5. But expecting users to answer 22 questions and get a complete ordering is a fool's errand.
The basic problem is easy. We have a ton of sorting algorithms that will work with O(n log(n)) comparisons. For instance mergesort:
// Split the array into halves and merge them recursively
function mergeSort (arr) {
if (arr.length === 1) {
// return once we hit an array with a single item
return arr
}
const middle = Math.floor(arr.length / 2) // get the middle item of the array rounded down
const left = arr.slice(0, middle) // items on the left side
const right = arr.slice(middle) // items on the right side
return merge(
mergeSort(left),
mergeSort(right)
)
}
// compare the arrays item by item and return the concatenated result
function merge (left, right) {
let result = []
let indexLeft = 0
let indexRight = 0
while (indexLeft < left.length && indexRight < right.length) {
if (left[indexLeft] < right[indexRight]) {
result.push(left[indexLeft])
indexLeft++
} else {
result.push(right[indexRight])
indexRight++
}
}
return result.concat(left.slice(indexLeft)).concat(right.slice(indexRight))
}
So in principle you need to simply replace left[indexLeft] < right[indexRight] with an arbitrary comparison function that asks the user, gets an answer, and then continues.
Now there is a catch. The catch is that you need to make this code asynchronous. When you go to ask the user, you need to ask the user, then return to inside your code. If you're using node at the console, then you can do this with async/await. If you are not, then you'll need to figure out how to do it with promises. Modifying mergeSort is easy, just make the end into:
return Promise.all([mergeSort(left), mergeSort(right)]
).then(function (values) {return merge(values[0], values[1])});
The trick is in turning the loop inside of merge into a function that takes the current state of your iteration, and returns a promise that asks the question, then either returns the final sorted array, or returns a promise that handles the next iteration.
Since this looks like homework, whose whole purpose is to make you face that mental challenge, I'll leave my answer off here. Fair warning, I gave you a hint about how to do it, but if you're just learning about async code your head is SUPPOSED to spin as you figure it out.
To determine all possible combinations from your array try the following loop. Assuming order does not matter and we do not want repeats:
var arr = [1,2,3,4,5,6,7,8,9,10]
var arr_count = arr.length
var combinations_array = []
for (i = 0; i < arr_count; i++) {
var combinations = arr_count - (i+1)
for (y = 0; y < combinations; y++) {
combination = [arr[i],arr[(combinations - y)]];
combinations_array.push(combination);
}
}
In your example I'd pass Movie ID's into arr then iterate through the combinations_array to determine which combination of movies should be displayed next.
To produce a list of pairs, I would use a nested loop like this:
var items = [1,2,3,4,5,6,7,8,9,10],
result = [],
x = 0,
y = 0;
for (x = items.length; x--;)
{
for(y = x; y--;)
{
result.push({ a: items[x], b: items[y] });
}
}
console.debug(result);
The second loop is initialised from the outer loops incrementor so that you don't end up with duplicates.
Once you have the pairs, you should be able to build the ui from that.
Hope it helps!

Optimizing solution of Sum of Pairs: Codewars

I want a help in optimising a solution of a problem, I already sort out the problem, but my code is not good enough for handling large array -
codeWars : Sum of Pairs - problem
Here is my code -
var sum_pairs=function(e, sum){
var result=null;
var arrLen=e.length;
for(let i=0;i<arrLen-1;i++){
let nextIndex=e.slice(i+1,arrLen).indexOf(sum-e[i]);
if(nextIndex>=0){
result=[e[i],e[nextIndex+1+i]];
arrLen=nextIndex+1+i;
}
}
return result;
}
Well, I know this is not a good solution. Anyway, this passes all the test cases but failed when it encounter large array -
Result On codewars
I want to know how to optimise this code, and also Learn any technique to writing a good code.
One solution is to use Set data structure to memorize the numbers all ready iterated over. Then we can check for each element if there has been a number which sums to s. The set has an average constant time complexity for insert and search making the algorithm linear in time (and space).
var sum_pairs=function(ints, s){
if (ints.length < 2) return undefined; //not enough numbers for pair.
let intSet = new Set()
intSet.add(ints[0]);
for (let i=1; i < ints.length; ++i){
let needed = s-ints[i];
if (intSet.has(needed)){//check if we have already seen the number needed to complete the pair.
return [needed,ints[i]];
}
intSet.add(ints[i]);//if not insert the number in set and continue.
}
return undefined;//No answer found
}
function sumPairs (ints, s) {
if (ints.length<2) return undefined
let inSet = new Set()
for (let i= 0;i<ints.length;i++){
let need = s-ints[i]
if( inSet.has(need)){
return [need,ints[i]]
}
inSet.add(ints[i])
}
return undefined
}

Numeric sort of a stream that keeps alpha order when the number is the same

I tried a few of the regex sorts I found on SO, but I think they may not like the + symbol in the stream i'm needing to sort.
So I'm getting a data stream that looks like this (3 to 30 letters '+' 0 to 64000 number)
userString = "AAA+800|BBB+700|CCC+600|ZZZ+500|YYY+400|XXX+300|XXA+300|XXZ+300";
the output needs to be in the format:
array[0] = "XXA+300" // 300 being the lowest num and XXA being before XXX
array[...]
array[7] = "AAA+800"
I wish to order it from lowest num to highest num and reversed.
Here is my inefficient code. which loops 8x8 times. (my stream maybe 200 items long)
It works, but it looks messy. Can someone help me improve it so it uses less iterations?
var array = userString.split('|');
array.sort();
for(var i=0; i<len; i++) { // array2 contains just the numbers
bits = array[i].split('+');
array2[i] = bits[1];
}
array2.sort();
if(sort_order==2)
array2.reverse();
var c=0;
for(var a=0;a<len;a++) { // loop for creating array3 (the output)
for(var i=0; i<len ; i++) { // loop thru array to find matching score
bits = array[i].split('+');
if(bits[1] == array2[a]) { // found matching score
array3[c++] = bits[0]+'+'+bits[1]; // add to array3
array[i]='z+z'; // so cant rematch array position
}
}
}
array = array3;
Kind Regards
Please forgive the terse answer (and lack of testing), as I'm typing this on an iPhone.
var userArr = userString.split('|');
userArr.sort(function(a, b) {
var aArr = a.split('+'),
bArr = b.split('+'),
aLetters = aArr[0],
bLetters = bArr[0],
aNumbers = parseInt( aArr[1] ),
bNumbers = parseInt( bArr[1] );
if (aNumbers == bNumbers) {
return aLetters.localeCompare( bLetters );
}
return aNumbers - bNumbers;
/*
// Or, for reverse order:
return -(aNumbers - bNumbers);
// or if you prefer to expand your terms:
return -aNumbers + bNumbers;
*/
});
Basically we're splitting on | then doing a custom sort in which we split again on +. We convert the numbers to integers, then if they differ (e.g. 300 and 800) we compare them directly and return the result (because in that case the letters are moot). If they're the same, though (300 and 300) we compare the first parts (XXA and XXX) and return that result (assuming you want an ordinary alphabetical comparison). In this fashion the whole array is sorted.
I wasn't entirely sure what you meant by "and reversed" in your question, but hopefully this will get you started.
As you may've guessed this isn't totally optimal as we do split and parseInt on every element in every iteration, even if we already did in a previous iteration. This could be solved trivially by pre-processing the input, but with just 200 elements you probably won't see a huge performance hit.
Good luck!

Categories