Stuck SICP Exercise 1.1.7 in Javascript - javascript

I've decided to try working through the MIT SICP course, but in Javascript.
The following code outputs undefined, but it should output a fairly accurate guess of the square root of 5.
I've tested all of the smaller functions and they all work as expected, the problem must be somewhere in the recursive guessRoot() function, but I can't seem to see the problem.
var square = function(x) {
return x * x;
};
var abs = function(x) {
return x > 0 ? x : -x;
};
var goodEnough = function(g, x) {
return abs(square(g) - x) < 0.01;
};
var average = function(x, y) {
return (x + y) / 2;
};
var improve = function(g, x) {
return average(g, (x / g));
};
var guessRoot = function(guess, x) {
if (goodEnough(guess, x)) {
return guess;
} else {
guessRoot(improve(guess, x), x);
}
};
console.log(guessRoot(2.5, 5));

Looks like you're just missing a return in the recursive step.
var guessRoot = function(guess, x) {
if (goodEnough(guess, x)) {
return guess;
} else {
return guessRoot(improve(guess, x), x); // ... here
}
};
http://jsfiddle.net/mattball/TyLsL

Related

How can I find the GCD of two or more integers, javascript? No methods

I already know how to find the GCD with no methods (below), but how can I create a function that will do it with either two or more integers?
function greatest(x,y){
return x<0 || y<0 ? null : x%y===0 ? y : greatest(y, x%y);
}
console.log(greatest(64,2)); //2
console.log(greatest(88,200)); //8
//Finding the gcd of two integers using recursion
const gcd = function(x, y) {
if (!y){ //if y is zero return back x
return x;
}
return gcd(y, x % y);
}
You can use the spread syntax to group remaining arguments in an array and take the GCD one pair at a time. The LCM can be done very similarly by a similar recursion.
const gcd = function(x, y, ...z) {
if (!y && z.length > 0) {
return gcd(x, ...z);
}
if (!y) {
return x;
}
return gcd(y, x % y, ...z);
}
console.log(gcd(6, 12, 8));
console.log(gcd(9, 15, 36));
Edit: Here's LCM, as requested in the comments. Note that you need to divide multiple GCDs, you cannot group multiple GCDs together and divide.
const lcm = function(x, y, ...z) {
if (z.length == 0) {
return x * y / gcd(x, y);
}
return lcm(x * y / gcd(x, y), ...z);
}
This version uses a standard recursive binary gcd version, and then creates a gcdAll which recurs on the list of numbers supplied, bottoming out with a call to gcd:
const gcd = (a, b) =>
b == 0 ? a : gcd (b, a % b)
const gcdAll = (n, ...ns) =>
ns.length == 0 ? n : gcd (n, gcdAll (...ns))
console .log (gcdAll (1100, 495, 165)) //=> 55
I find this conceptually simple and easy to understand. But I am also intrigued by the answer from Exalted Toast, which shuffles parameters in a really useful manner.
This question needs a mix of recurstion and the spread operator (in function parameters):
//Finding the gcd of two integers using recursion
const gcd = function(x, y) {
if (!y){ //if y is zero return back x
return x;
}
return gcd(y, x % y);
}
function gcdOfMultipleNumbers(...args) {
var newArr = args.filter(a => Number.isInteger(a) && a !== 0) // remove decimals and zeros
if(newArr.length <= 0) return 0; // if no arguments remain after filtering
if(newArr.length === 1) return newArr[0]; // if one argument remains after filtering
if(newArr.length === 2) return gcd(...newArr); // if two arguments remain after filtering
// if there are more than two arguments which remain
return gcdOfMultipleNumbers(gcd(newArr.shift(), newArr.shift()), ...newArr)
}
console.log(gcd(64,2)); //2
console.log(gcd(88,200)); //8
console.log(gcdOfMultipleNumbers(64, 24, 4, 32)); // 4
console.log(gcdOfMultipleNumbers(88, 200, 44)); //4
This question reminded me of my college life. It was asked by our Professor. So, the actual math behind the scene is: gcd(a, b, c) = gcd(a, gcd(b, c))=gcd(gcd(a, b), c)... . The function you can write is here:
// the recursive function: gcd
function gcd(num1, num2) {
// base case
if (num1 === 0) {
return num2
}
return gcd(num2 % num1, num1);
}
function multiNumGCD(...args) {
let len = args.length;
let res = args[0];
for (let i = 1; i < len; i++) {
res = gcd(args[i], res);
return res;
}
}
console.log(multiNumGCD(3, 6, 7));
Hope you find it useful !!!
Here is something that worked for me
function gcd(arr) {
let numCheck = true
arr.forEach(n => {
if(isNaN(n)) numCheck = false
})
if(!numCheck) return null;
let nums = arr.map(n => parseInt(n));
if(nums.some(n => n < 1)) return null;
let lowestNum;
nums.forEach(n => {
if(lowestNum === undefined || n < lowestNum) {
lowestNum = n;
}
})
let gcd;
for(let i = 0; i <= lowestNum; i++) {
let test = nums.filter(n => !(n%i))
if(test.length !== nums.length) {null} else {
gcd = i
}
}
return gcd;
}
And to execute it, do this:
gcd([6, 9, 12]) //3
//it also works with strings
gcd(['6', '9', '12']) //3
P.S. idk for sure but by gcd you mean greatest common divisor, right?

How to write a function which can accept one or more arguments and send back addition

I have to call function in below way
sum(3)(2)
My function is:
sum(a,b) { return a + b }
Take a look at Currying concept
let sum = (a) => (b) => a + b
console.log(sum(1)(3)) // 4
you can try out this approach
function sum(x, y) {
if (y !== undefined) {
return x + y;
} else {
return function(y) { return x + y; };
}
}
To understand it better https://www.toptal.com/javascript/interview-questions

How do I Subtract two numbers without using minus operator in JavaScript? Or Using For loop

Javascript are not using Bitwise Operator ?? Here is my code javascript Code
function subtract()
{
var n1 = parseInt(document.getElementById('fvalue').value);
var n2 = parseInt(document.getElementById('svalue').value);
var x1, x2;
while(n2 != 0)
{
var brw = (~n2)&n2;
n1= n1^n2;
n2 = brw<<1;
}
document.write("Result is : " + n1);
}
Here is simple sample of adding and subtracting 2 numbers in javascript:
console.log(add(2,4));
console.log(subtract(5,4));
function add( a, b)
{
var x;
x = a^b;
while(a&b)
{
b = ((a&b)<<1);
a = x;
x = a^b;
//b=(a^b);
}
return x;
}
function subtract( x, y)
{
if (y == 0)
return x;
return subtract(x ^ y, (~x & y) << 1);
}

d3js - Create custom scale - Positive and negative logarithm

I'm currently working on a d3 project and I'm trying to display bar charts with a huge range of values, both positive and negative.
I saw online a walkaround using d3.scale.sqrt() or displaying two log scale but I was wondering if I could create my own scale.
What I have in mind is a mix between a log scale for negative values, a linear scale for values between [-e, e] and a regular log scale for positive values.
Something that might look like that: http://img15.hostingpics.net/pics/12746197ln.png
y = -log(-x) if x < -e
y = x/e if -e <= x <= e
y = log(x) if x > e
Do you think that it might be possible ?
I also created a JSFiddle to sum it up.
Thanks,
Here is one solution I found: JSFiddle
It might be a weird way, but it's working I think, if you have any pieces of advice on improvement, don't hesitate. I think I made mistakes, especially on log base and ticks.
Here is the function I created, based on d3.js itself.
(function() {
scalepnlog = {
init: function(){
return d3_scale_pnlog(d3.scale.linear().domain([ 0, 1 ]), [ 1, 10 ]);
}
}
function d3_scaleExtent(domain) {
var start = domain[0], stop = domain[domain.length - 1];
return start < stop ? [ start, stop ] : [ stop, start ];
}
var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
floor: function(x) {
return -Math.ceil(-x);
},
ceil: function(x) {
return -Math.floor(-x);
}
};
function sign(x){
return x >= 0 ? 1:-1;
}
function d3_scale_pnlog(linear, domain) {
function pnlog(x) {
return (x >= Math.E || x <= -Math.E) ? sign(x)*Math.log(Math.abs(x)) : x/Math.E;
}
function pnpow(x) {
return (x >= 1 || x <= -1 )? sign(x)*Math.pow(Math.E,Math.abs(x)) : Math.E*x;
}
function scale(x) {
return linear(pnlog(x));
}
scale.invert = function(x) {
return pnpow(linear.invert(x));
};
scale.domain = function(x) {
if (!arguments.length) return domain;
linear.domain((domain = x.map(Number)).map(pnlog));
return scale;
};
scale.nice = function() {
var niced = d3_scale_nice(domain.map(pnlog), positive ? Math : d3_scale_logNiceNegative);
linear.domain(niced);
domain = niced.map(pow);
return scale;
};
scale.ticks = function() {
var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(pnlog(u)), j = Math.ceil(pnlog(v)), n = 10 % 1 ? 2 : 10;
if (isFinite(j - i)) {
for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pnpow(i) * k);
ticks.push(pnpow(i));
for (i = 0; ticks[i] < u; i++) {}
for (j = ticks.length; ticks[j - 1] > v; j--) {}
ticks = ticks.slice(i, j);
}
return ticks;
};
scale.tickFormat = function(n, format) {
if (!arguments.length) return d3_scale_logFormat;
if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
var k = Math.max(1, 10 * n / scale.ticks().length);
return function(d) {
var i = d / pnpow(Math.round(pnlog(d)));
if (i * 10 < 10 - .5) i *= 10;
return i <= k ? format(d) : "";
};
};
scale.copy = function() {
return d3_scale_pnlog(linear.copy(), domain);
};
return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
}
})();
I don't really know what I'm doing but basically, I created pnlog and pnpow, its reciprocal, and added the different d3 functions needed until it worked.
Here they are :
function pnlog(x) {
return (x >= Math.E || x <= -Math.E) ? sign(x)*Math.log(Math.abs(x)) : x/Math.E;
}
and
function pnpow(x) {
return (x >= 1 || x <= -1 )? sign(x)*Math.pow(Math.E,Math.abs(x)) : Math.E*x;
}

Javascript return not working

I have this code:
function get_id_from_coords (x, y)
{
x = parseInt(x);
y = parseInt(y);
if (x < 0)
{
x = (x + 6) * 60;
}
else
{
x = (x + 5) * 60;
}
if (y < 0)
{
y = (y + 6) * 60;
}
else
{
y = (y + 5) * 60;
}
$('#planets').children().each(function(){
if ($(this).attr('x') == x) {
if ($(this).attr('y') == y) {
alert (parseInt($(this).attr('id')));
return parseInt($(this).attr('id'));
}
}
});
}
alert(get_id_from_coords(x, y));
However, from this code I get two popups:
First, from inside the function, I get the proper value (like 63), but then, when I alert the return value, I just get undefined.
You get undefined as you function doesn't return - the last statement is a call to each function and it's not a return statement. If you put a return, e.g.
...
return $('#planets').children().each(function(){
if ($(this).attr('x') == x) {
if ($(this).attr('y') == y) {
alert (parseInt($(this).attr('id')));
return parseInt($(this).attr('id'));
}
}
});
it will return something - in this case, based on the docs:
http://api.jquery.com/jQuery.each/
The method returns its first argument, the object that was iterated.
it will return the children of #planets.
If you want to find some value specifically using each, then you can do something like this:
...
val toRet;
$('#planets').children().each(function(){
if ($(this).attr('x') == x) {
if ($(this).attr('y') == y) {
toRet = parseInt($(this).attr('id'));
}
}
});
return toRet;

Categories

Resources