nodeArray = [ 3, 3, 7, 6, 6, 7, 15, 10, 10, 14, 13, 13, 14, 15, 23, 18, 18, 22, 21, 21, 22, 23, 0 ];
nodes = [];
links = [];
function left(i) {
return 2*i + 1;
}
function right(i) {
return 2*i + 2;
}
function parent(i) {
console.log("Parent =" + (i-1)/2);
return (i-1)/2;
}
var index = 0;
do{
if (index === 0) {
var node = {
'value': nodeArray[index],
'child1_index': left(index),
'child1_value': nodeArray[left(index)],
'child2_index': right(index),
'child2_value': nodeArray[right(index)],
'parent_index' : 'null',
'parent_value' : 'null'
};
} else {
var node = {
'value': nodeArray[index],
'child1_index': left(index),
'child1_value': nodeArray[left(index)],
'child2_index': right(index),
'child2_value': nodeArray[right(index)],
'parent_index' :parent(index),
'parent_value' : nodeArray[parent(index)],
'index' : index
};
}
nodes.push(node);
index++;
} while (index != nodeArray.length)
console.log(nodes);
I have written the above code for future turning it into a binary tree with d3.js library, unfortunately all my parent node values (which are apparently given by any nodes (index -1 )/ 2. give numbers like 5.5 etc being half the index or something. which obviously wont work. Some nodes give full integers then some do not.
example console output for one of my node objects. which looks right
Node1:
parent_index:0
parent_value:3
example of other node objects. which dont look right are
Node2:
parent_index:0.5
parent_value:undefined
Here is a jsfiddle if anyone's interested
http://jsfiddle.net/mryfw095/5/
I think you just want your parent function to round down.
function parent(i) {
console.log("Parent =" + Math.floor((i-1)/2));
return Math.floor((i-1)/2);
}
Related
I have a problem with Project Euler challenge 5. The challenge is based on finding the smallest positive number that is divisible by all the numbers from 1 to 20. This is my code:
let i = 1;
function myFunction (num) {
return i % num == 0
}
while (true) {
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
if (arr.every(myFunction)) {
console.log(i)
break;
} else {
i++
continue;
}
}
The code up to number 16 works fine (720720), but once I add another number to the array, in order (16, 17, 18, ...) it doesn't work anymore. I don't know why, I'm very new to programming. If you could instruct me.
The answer above takes way to long, like he said, quite a few seconds.
This code is longer but takes less than a second to come up with the result.
const divisibleByAllToN = (n) => {
const twoToN = Array(n - 1)
.fill(2)
.map((item, index) => item + index);
let numbersToBeMultiplied = twoToN.filter((item) => {
for (var i = 2; i < item; i++) if (item % i === 0) return false;
return item > 1;
});
numbersToBeMultiplied = numbersToBeMultiplied.map((item) => {
let value = item;
while (value * item <= n) {
value = value * item;
}
return value;
});
return numbersToBeMultiplied.reduce((acc, val) => acc * val);
};
divisibleByAllToN(20);
solved :
you need to return a condition in myFunction in order for array.every to work properly :
let i = 1;
function myFunction (num) {
var result = i / num
return parseInt(result) === result // condition HERE to check if result is an int
}
while (true) {
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
if (arr.every(myFunction)) {
console.log(i)
break;
} else {
i++
continue;
}
}
doing this we get (after about 20 seconds) the right result : 232792560
Given the array (list) of integers below, I am looking to extract each integer and if three or more integers ascend consecutively, I want to replace the middle integers with a "-" to represent a range. And then lastly return values as a string.
For example, the first 7 integers from list: -6, -3, -2, -1, 0, 1, 3
Would become '-6,-3-1,3'
Because there is more than three consecutive integers from -3 to 1.
Ultimately, solution(list) should return the following string: "-6,-3-1,3-5,7-11,14,15,17-20"
In its present form it returns the following string: "-6,-3,-2,-1,0,1,3,4,5,7,8,9,10,11,14,15,17,18,19,20"
Which is simply the array converted into a string.
var list = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20];
solution(list);
function solution(list) {
final = [];
range = [];
while (list.length > 0) {
take = list.splice(0,1);
range.push(take);
n = 1;
while (take+n === list[0]) {
a = list.splice(0,1);
range.push(a);
n++;
}
if (range.length >= 3) {
min = Math.min(range).toString();
max = Math.max(range).toString();
final.push(min + "-" + max);
range.length = 0;
} else if (range.length === 2) {
final.push(range[0].toString());
final.push(range[1].toString());
range.length = 0;
} else if (range.length === 1) {
final.push(range[0].toString());
range.length = 0;
}
}
return final.join(",");
}
However, I was able to get the desired result successfully in Ruby:
list = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
def solution(list)
final = []
range = []
while (list.length > 0) do
take = list.shift
range << take
n = 1
while (take+n == list[0]) do
a = list.slice!(0)
range << a
n +=1
end
if (range.length >= 3)
final << (range.min.to_s + "-" + range.max.to_s)
range = []
elsif (range.length == 2)
final << range[0]
final << range[1]
range = []
elsif (range.length == 1)
final << range[0].to_s
range = []
end
end
return final.join(",")
end
My approach in Ruby is almost identical that of my JavaScript. So, if I was wondering if someone could:
1) Explain why this approach works with Ruby, but not Javascript. Please feel free to inform me even if it is a simple syntax error on my part.
2) How I could possibly go about extracting the integers and returning the correct ranges in JavaScript?
Your help is greatly appreciated! Thanks!
Here's a better ruby solution:
list = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
stringified = list.chunk_while{|a, b| a == b - 1}.map do |seq|
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the core of the solution
if seq.length > 2 # long enough sequence
"#{seq.first}-#{seq.last}"
else
seq
end
end.join(', ')
stringified # => "-6, -3-1, 3-5, 7-11, 14, 15, 17-20"
This should also be a hint for your javascript implementation. Separate concerns as much as possible. Chunking, stringifying, turning a sequence into a range-like string: these all should be separate pieces of code. If they're not all tangled together, they're much easier to reason about.
In Javascript, you could use a three pass approach, first for getting the grouped ranges, then get the ranges in an array and later join the whole array.
var array = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20],
result = array
.reduce(function (r, a) {
var last = r[r.length - 1];
if (last && last[1] + 1 === a) {
last[1] = a;
} else {
r.push([a, a]);
}
return r;
}, [])
.reduce(function (r, a) {
return r.concat(a[0] === a[1] ? a[0] : a[1] - a[0] < 2 ? a : a.join('-'));
}, [])
.join();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Splice returns an array, you have to take the first item from returned array
take = list.splice(0,1)[0];
Also note that shift (take = list.shift()) is a better candidate for this operation.
Math.min doesn't accept arrays, you can use a workaround with apply/call
Math.min.apply(null,range);
In ES6 this can be done as Math.min(...range) using spread syntax
It is better to clear an array by assigning to a new array.
range = [];
I obviously prefer the functional and declarative method by #ninasholz This is just to explain why my code didn't work
var list = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20];
console.log(solution(list));
function solution(list) {
final = [];
range = [];
while (list.length > 0) {
//splice returns array take first item
take = list.splice(0,1)[0];
range.push(take);
n = 1;
while (take + n === list[0]) {
a = list.splice(0,1)[0];
range.push(a);
n++;
}
console.log(range);
if (range.length >= 3) {
//Math.min doesnt accept arrays
min = Math.min.apply(null,range);
max = Math.max.apply(null,range);
final.push(min + "-" + max);
range = [];
} else if (range.length === 2) {
final.push(range[0]);
final.push(range[1]);
range = [];
} else if (range.length === 1) {
final.push(range[0]);
range = [];
}
}
return final.join(",");
}
I am trying to find a number by using the input to search in the array.
Got any idea why this does not work?
Every time i run the code i only get the message:
"Number does not exist"
var arr = [18, 21, 34, 42, 65, 63, 39, 13, 15, 24, -1, 14, 15];
var number = document.getElementById("find").value;
var svar = "";
function exists(){
for(i=0; i < arr.length; i++){
if(parseInt(arr[i]) == parseInt(number)){
svar++;
document.getElementById("existsArray").innerHTML = tall + "Number exists";
} else {
document.getElementById("existsArray").innerHTML = tall + "Number does not exist";
}
}
}
<p id="existsArray"></p>
<input placeholder="what number would you like to find?" id="find" type="number">
<button type="button" onclick="exists()">Finn tallet</button>
I replaced your for loop with indexOf
If you still want to use the loop you should break when you find the matching number
var arr = [18, 21, 34, 42, 65, 63, 39, 13, 15, 24, -1, 14, 15];
var svar = 0;
function exists() {
var number = +document.getElementById("find").value;
if (arr.indexOf(number) !== -1) {
svar++;
document.getElementById("existsArray").innerHTML = "Number exists";
} else {
document.getElementById("existsArray").innerHTML = "Number does not exist";
}
}
<input type="number" id="find" />
<button onclick="exists();">Does it exist ?</button>
<p id="existsArray"></p>
If you want to get the number of occurrence you should use this :
var occurrences = arr.filter(function (num) {return num === number;}).length
So your problem is that you don't exit the loop when you find the matching number. As a result, unless the number you are looking for is the very last number in your array, it will keep looping and the else clause will execute.
function exist() {
var number = parseInt(document.getElementById("find").value,10);
for(i=0; i < arr.length; i++){
if (exists === arr[i]) {
// number exists
break; // <-- this is important another alternative would be to just
// return at this point if the function doesn't do anything else
}
else {
// this number doesn't match, so we'll keep searching
}
}
}
Of course, this is much easier if you just use the built in functions Array.prototype.find or Array.prototype.indexOf
You can also use a filter to keep only values in the array wich match with input :
var arr = [18, 21, 34, 42, 65, 63, 39, 13, 15, 24, -1, 14, 15];
var input = "65";
var result = arr.filter(item => item === parseInt(input));
if (result.length === 0) console.log("number doesn't exist");
else console.log("number exists");
I've made some modifications to your code up front to help isolate your test case. If you look at this rework of your existing code, you'll see you get a message for each of your array elements, ending with "Number does not exist", which was your original problem. This is because that's the last message, overwriting your previous positive results.
var number = "42";
//var svar = "";
var svar = 0;//changing this from a string to a number. Can't ++ a string.
var myArray = [18, 21, 34, 42, 65, 63, 39, 13, 15, 24, -1, 14, 15];
/*
* #param {String} num - Passing the value that I'm looking for, rather than
* trying to pull it from elsewhere. This makes this much easier to test later.
* #param {Array} arr - Array of integers to search
*/
function exists(num, arr) {
for(i=0; i < arr.length; i++){
//if(parseInt(arr[i]) == parseInt(number)){
//No need to use parseInt here on the array. It's already a Number.
if(arr[i] == parseInt(number)){
svar++;/* I don't see any reason to be incrementing this. Perhaps it's elsewhere
in your implementation? */
//Using console.log() instead of elements not included in your code sample
console.log("Number exists");
} else {
//This keeps overwriting the above, except in a case where
//the last number would be a match!
console.error("Number does not exist");
}
}
}
exists(number, myArray);
If you want this to work as intended, you can either can eliminate your "Number does not exist" else branch, which will cause the positive message to remain, and you can leave your default text as "Number does not exist", or you simplify it, using what I'd recommend:
var number = "42",
number2 = "101",
myArray = [18, 21, 34, 42, 65, 63, 39, 13, 15, 24, -1, 14, 15];
var existsSimple = function (num, arr) {
return myArray.filter(function (itemNum) {return itemNum === parseInt(num);}).length > 0;
};
console.log('Number exists: ' + existsSimple(number, myArray));//true
console.log('Number exists: ' + existsSimple(number2, myArray));//false
I'm a beginner in javascript, so bear with me if this question is too simple. I'm trying to simplify this function
var calculateTotal =function(nodeData){
var totalSelectedUnit0 = 0;
var totalSelectedUnit1 = 0;
var totalSelectedUnit2 = 0;
for(x=$scope.selectFrom; x<$scope.selectTo; x++){
totalSelectedUnit0 += nodeData.items[0].usage.categories[x].current;
totalSelectedUnit1 += nodeData.items[1].usage.categories[x].current;
totalSelectedUnit2 += nodeData.items[2].usage.categories[x].current;
}
console.log(totalSelectedUnit0);
console.log(totalSelectedUnit1);
console.log(totalSelectedUnit2);
};
calculateTotal(node);
And this is how I attempted to refactor the code
var calculateTotal =function(nodeData){
var totalSelectedUnit=[];
for(i=0; i<nodeData.items.length; i++){
for(x=$scope.selectFrom; x<$scope.selectTo; x++){
totalSelectedUnit[i] += nodeData.items[i].usage.categories[x].current;
}
}
console.log(totalSelectedUnit);
};
There are couple of things I'm trying to achieve here. The calculation should ignore null or Nan values. Also I would like to use the map and reduce to achieve this calculation.
The first problem I could see is the result array is not initialized, so the result will be NaN as you are adding an undefined value to a number.
var calculateTotal = function(nodeData) {
var totalSelectedUnit = nodeData.items.map(function(item) { //create a result value for each item in the items array
return item.usage.categories.slice($scope.selectFrom, $scope.selectTo).reduce(function(v1, v2) { //sum up values between the from and to index
return v1 + (v2 || 0); //ignore the falsy values
}, 0);
})
console.log(totalSelectedUnit);
};
var $scope = {
selectFrom: 0,
selectTo: 4
};
var nodeData = {
items: [{
usage: {
categories: [2, 3, 4, 5, 6, 7, 8, 9, 1]
}
}, {
usage: {
categories: [12, 13, 14, 15, 16, 17, 18, 19, 10]
}
}, {
usage: {
categories: [22, 23, 24, 25, 26, 27, 28, 29, 20]
}
}]
};
calculateTotal(nodeData);
Consider this example:
var a = {
"Check" : function doThis(value, index, ar) {
if(value >= 10) {
document.write(value + ", ");
}
else {
document.write("The array element is less than 10, ");
}
}
}
var arr = [12, 20, 2, 3, 15];
document.write(arr.forEach(a.Check));
Which results in:
12, 20, The array element is less than 10,
The array element is less than 10, 15, undefined
I don't understand why there is an extra element in the array which is undefined. Does it have something to do with defining the callback function in an object?
replace:
document.write(arr.forEach(a.Check));
with:
arr.forEach(a.Check);
With document.write(arr.forEach(a.Check)); you are printing what the arr.forEach() call returns (undefined)