My solution to Project Euler #8 not working anymore - javascript

so , I solved a problem online where I found the Largest product of any 5 consecutive numbers In a 1000-digit number :
var bignumber = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
var bigarray = bignumber.split("");
var prod = [];
var buy = 1;
var z = 4;
for (var i = 0; i < bigarray.length; i+=z) {
mult = bigarray[i];
for (var x = 1; x <= z; x++) {
mult *= bigarray[i+x];
}
prod.push(mult);
}
prod.sort(function(a, b){return b-a});
document.write(prod[0]);
where z can be the number of the consecutive digits i want minus 1 ,, and the solution was 40824 wich is correct I think solution
Later I found that this problem belonged to Project Euler here , but instead It's 13 consecutive digits , so when I tried to change z = 12 , it gave me an Incorrect solution ,, why ?

Your mistake is in line for (var i = 0; i < bigarray.length; i+=z) {:
Change the loop condition to i < bigarray.length - z. Reason: Since the inner for loop advances up to z indices, the outer loop has to guarantee that there are at least z elements remining from index i.
Change the loop increment to i+=1. Reason: Consider finding the largest product of two consecutive digits in input "1221". 1*2 = 2 and 2*1 = 2 is what your algorithm computes. The solution however is 2*2 = 4 which can only be found when considering every input digit as a possible starting point.
Once you made these changes, you could start optimizing your algorithm. For example, you can kind of re-use the mult value from the previous iteration.

You may do as follows;
function getMaxProductConseq(s,n){
return Math.max(...s.split("")
.map((_,i,a) => a.slice(i,i+n))
.slice(0,s.length-n+1)
.map(sa => sa.reduce((p,c) => +p * +c)));
}
var bignumber = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
console.log(getMaxProductConseq(bignumber,13));

Related

Why am I getting one empty array item in every other array like a pattern? (JavaScript)

UPDATE AT THE BOTTOM OF THE POST!
This is the first part of a program that will eventually make SVG star polygons.
Only star polygons that can be made in one go, I.e. like a Pentagram, NOT like a Hexagram that can only be made with at least 2 shapes I.e. 2 inverted and overlapping triangles.
I'm almost finished with this. Everything seems to be working well and I'm getting the out put I want except there's an empty array item in every other array produced for some reason.
In this part
I'm printing to the console (for testing) an object with items named with numbers that represent the number of points / sides of a regular polygon. Within each item is an array with the lower half of all the non factoring numbers of that item (number) I.e. an array of numbers that when the number (item name) is divided by them, it will return a fraction.
E.g. Object
starPolygons{'5': 2, '7': 3, 2, '8': 3, '9': 4, 2, …}
(Representation of: Pentagon: Heptagon: Octagon: Nonagon: …)
What "qty_test" functions does
The points variable (= 8 for example) is sent to a function (qty_test) which is used to find the number of divisors I need to test and inside it is divided by 2. If the result is a fraction, it will return the result rounded back, and if its even, it will return the result - 1.
//8 has more divisors to cycle through -so its a better example!
//In the real program, it will be 5.
let points = 8;
let starPolygons = {};
E.g. qty_test
point (=8) ()=> n /= 2 (=4)
if n - n(rounded-back) = 0?
true returns (n -1) and false returns n(rounded-back)
function qty_test(n) {
n /= 2;
let divisorQTY = n - Math.floor(n) !== 0;
return divisorQTY ? Math.floor(n) : (n - 1);
};
What divisor_test functions does
This function uses the number returned from the previous function (n) to set a for loop that tests every cycle if n is not a factor of the value of the points variable. I.e. points divided by n returns a fraction and if it returns true, meaning a fraction was produced n`s value is indexed in an array and decreaces by 1 (--n).
E.g. divisor_test
n(=8) / 2 = 4 << 2 will be ignored.
n(=8) / 3 = 2.666... << 3 will be collected
function divisor_test(n) {
let nonFactors = [];
n = qty_test(n);
for (let index = 0; index <= n; index++) {
let quotient = (points / n) - Math.floor(points / n) !== 0;
quotient ? nonFactors[index] = n-- : --n;
};
return nonFactors;
};
The program cycles through 5 - 360 and indexes an object with numbers (5-360) and array list of their lower half non factor numbers.
while (points <= 360) {
nonFactors = divisor_test(points);
let testArray = nonFactors.length;
if (testArray) starPolygons[String(points)] = nonFactors;
points++;
};
console.log(starPolygons);
AS YOU CAN SEE IN THIS IMAGE. THE PATTERN OF EMPTY ARRAY INDEXES / ITEMS
UPDATE: I NOTICED THE PATTERN OF ARRAYS WITH THE EMPTY SLOTS HAS AN INTERESTING QUALITY TO IT. This is so cool and so confusing as to what causes this...
During the Iteration you are forcing the array to add an empty item.
So, the empty object appears when the array has only two items in it and you are trying to nonFactors[3] = n--;
and thats what causes the issue.
So a more simplified version of the for loop with the solution will be
for (let index = 0; index <= n; index++) {
let quotient = (points / n) - Math.floor(points / n) !== 0;
if(quotient){
if(index > nonFactors.length){
nonFactors[index - 1] = n--
}else{
nonFactors[index] = n--
}
}else{
n = n -1;
}
};
I solved my problem
There's an answer here that already explains what causes the problem and also gives a working solution by Nadav Hury (upvote his answer. I bet his answer generally works better in more situations)! So I will just post my own version of a solution.
for (let index = 0; n >= 2; index++) {
let quotient = (points / n) - Math.floor(points / n) !== 0;
if (quotient) nonFactors[index] = n--;
else --n, --index;
};
The culprit is that in the line with checking the quotient
quotient ? nonFactors[index] = n-- : --n;
you added setting the value only for the case when it is present that is equal to true but you didn't add to the case when it is false correct solution is:
quotient ? nonFactors[index] = n-- : nonFactors[index] = --n;.

Time Complexity of HackerRank Diagonal Difference

Can anyone help me identify the time complexity of the following code?
Background: this is a HackerRank algorithm problem where the editorial section lists the solution with a time complexity of O(n^2) but I think its O(n).
I believe its O(n) because we're only using one loop to traverse the 2 dimensional array and are not using nested loops and only looping over the array once.
Am I correct or am I missing something?
Solution
//arr is a 2 dimensional array containing an equal number of rows and columns
function diagonalDifference(arr) {
let diff = 0;
const length = arr.length - 1;
for (let i = 0; i < arr.length; i++) {
diff += arr[i][i] - arr[i][length - i];
}
return Math.abs(diff);
}
Problem
Given a square matrix (AKA 2D Array), calculate the absolute difference between the sums of its diagonals.
For example, the square matrix arr is shown below:
1 2 3
4 5 6
9 8 9
The left-to-right diagonal = 1 + 5 + 9 = 15. The right to left diagonal = 3 + 5 + 9 = 17. Their absolute difference is |15 - 17| = 2.
Am I correct or am I missing something?
You are right, but I think their categorization of O(n^2) may be due to the interpretation wherein n refers to the n of the input (i.e. the side-length of the matrix). In this case, the number of elements in the matrix itself is exactly n^2, and thus any solution (since any solution must read in all n^2 inputs) is Ω(n^2) (where Ω roughly means "at least").
Your categorization of the solution as O(n) is correct if we say that n refers to the size of the whole input matrix.
The time complexity of the code is O(n) where is the length of the matrix. As you have correctly said the loop is running only once and that too equals the number of rows/ columns viz the length of the matrix. there are no nested loops. So the time complexity is definitely, O(n) for all the cases best, worst, avg.
My solution:
function diagonalDifference(arr) {
let leftDiagSum = 0;
let rightDiagSum = 0;
for (let i = 0; i < arr.length; i++) {
leftDiagSum += arr[i][i];
rightDiagSum += arr[i][arr[i].length - (i + 1)];
}
let sum = Math.abs(leftDiagSum - rightDiagSum);
return sum;
}
You can try this also:
`
function diagonalDifference(arr) {
let firstDiagonalSum = arr[0][0] + arr[1][1] + arr[2][2];
let secondDiagonalSum = arr[0][2] + arr[1][1] + arr[2][0];
let result = (secondDiagonalSum) - (firstDiagonalSum);
return result;
}`
in python :
def diagonalDifference(arr):
d1 = 0
d2 = 0
n = len(arr)
for i in range(0, n):
for j in range(0, n):
if (i == j):
d1 += arr[i][j]
if (i == n - j - 1):
d2 += arr[i][j]
return abs(d1 - d2)

Codefights: Correct solution but system does not accept it

Experienced codefighters, i have just started using Codefight website to learn Javascript. I have solved their task but system does not accept it. The task is to sum all integers (inidividual digit) in a number. For example sumDigit(111) = 3. What is wrong with my code? Please help me.
Code
function digitSum(n) {
var emptyArray = [];
var total = 0;
var number = n.toString();
var res = number.split("");
for (var i=0; i<res.length; i++) {
var numberInd = Number(res[i]);
emptyArray.push(numberInd);
}
var finalSum = emptyArray.reduce(add,total);
function add(a,b) {
return a + b;
}
console.log(finalSum);
//console.log(emptyArray);
//console.log(res);
}
Here's a faster trick for summing the individual digits of a number using only arithmetic:
var digitSum = function(n) {
var sum = 0;
while (n > 0) {
sum += n % 10;
n = Math.floor(n / 10);
}
return sum;
};
n % 10 is the remainder when you divide n by 10. Effectively, this retrieves the ones-digit of a number. Math.floor(n / 10) is the integer division of n by 10. You can think of it as chopping off the ones-digit of a number. That means that this code adds the ones digit to sum, chops off the ones digit (moving the tens digit down to where the ones-digit was) and repeats this process until the number is equal to zero (i.e. there are no digits left).
The reason why this is more efficient than your method is that it doesn't require converting the integer to a string, which is a potentially costly operation. Since CodeFights is mainly a test of algorithmic ability, they are most likely looking for the more algorithmic answer, which is the one I explained above.

Finding the nth item in a repeating list of fixed items

I have to determine the mathematical formula to calculate a particular repeating position in a series of numbers. The list of numbers repeats ad infinitum and I need to find the number every n numbers in this list. So I want to find the *n*th item in a list of repeating y numbers.
For example, if my list has 7 digits (y=7) and I need every 5th item (n=5), how do I find that item?
The list would be like this (which I've grouped in fives for ease of viewing):
12345 67123 45671 23456 71234 56712 34567
I need to find in the first grouping number 5, then in the second grouping number 3, then 1 from the third group, then 6, then 4, then 2, then 7.
This needs to work for any number for y and n. I usually use a modulus for finding *n*th items, but only when the list keeps increasing in number and not resetting.
I'm trying to do this in Javascript or JQuery as it's a browser based problem, but I'm not very mathematical so I'm struggling to solve it.
Thanks!
Edit: I'm looking for a mathematical solution to this ideally but I'll explain a little more about the problem, but it may just add confusion. I have a list of items in a carousel arrangement. In my example there are 7 unique items (it could be any number), but the list in real terms is actually five times that size (nothing to do with the groups of 5 above) with four sets of duplicates that I create.
To give the illusion of scrolling to infinity, the list position is reset on the 'last' page (there are two pages in this example as items 1-7 span across the 5 item wide viewport). Those groups above represent pages as there are 5 items per page in my example. The duplicates provide the padding necessary to fill in any blank spaces that may occur when moving to the next page of items (page 2 for instance starts with 6 and 7 but then would be empty if it weren't for the duplicated 1,2 and 3). When the page goes past the last page (so if we try to go to page 3) then I reposition them further back in the list to page one, but offset so it looks like they are still going forwards forever.
This is why I can't use an array index and why it would be useful to have a mathematical solution. I realise there are carousels out there that do similar tasks to what I'm trying to achieve, but I have to use the one I've got!
Just loop every 5 characters, like so:
var data = "12345671234567123456712345671234567";
var results = [];
for(var i = 4; i < data.length; i += 5){
results.push(data[i]);
}
//results = [5, 3, 1, 6, 4, 2, 7]
If you want to use a variable x = 5; then your for loop would look like this:
for(var i = x - 1; i < data.length; i += x){...
There is no need to know y
If your input sequence doesn't terminate, then outputting every nth item will eventually produce its own repeating sequence. The period (length) of this repetition will be the lowest common multiple of the period of the input sequence (y) and the step size used for outputting its items (x).
If you want to output only the first repetition, then something like this should do the trick (untested):
var sequence = "1234567";
var x = 5;
var y = sequence.length;
var count = lcm(x, y);
var offset = 4;
var output = [];
for (var i = 0; i < count; i += x)
{
j = (offset + i) % y;
output.push(sequence[j]);
}
You should be able to find an algorithm for computing the LCM of two integers fairly easily.
A purely mathematical definition? Err..
T(n) = T(n-1) + K For all n > 0.
T(1) = K // If user wants the first element in the series, you return the Kth element.
T(0) = 0 // If the user want's a non-existent element, they get 0.
Where K denotes the interval.
n denotes the desired term.
T() denotes the function that generates the list.
Lets assume we want every Kth element.
T(1) = T(0) + K = K
T(2) = T(1) + K = 2K
T(3) = T(2) + K = 3K
T(n) = nk. // This looks like a promising equation. Let's prove it:
So n is any n > 1. The next step in the equation is n+1, so we need to prove that
T(n + 1) = k(n + 1).
So let's have a go.
T(n+1) = T(N+1-1) + K.
T(n+1) = T(n) + K
Assume that T(n) = nk.
T(n+1) = nk + k
T(n+1) = k(n + 1).
And there is your proof, by induction, that T(n) = nk.
That is about as mathematical as you're gonna get on SO.
Nice simple recurrence relation that describes it quite well there.
After your edit I make another solution;)
var n = 5, y = 7;
for (var i = 1; i<=y; i++) {
var offset = ( i*y - (i-1)*n ) % y;
var result = 0;
if (offset === n) {
result = y;
} else {
result = (n - offset) > 0 ? n - offset : offset;
}
console.log(result);
}
[5, 3, 1, 6, 4, 2, 7] in output.
JSFIDDLE: http://jsfiddle.net/mcrLQ/4/
function get(x, A, B) {
var r = (x * A) % B;
return r ? r : B;
}
var A = 5;
var B = 7;
var C = [];
for (var x = 1; x <= B; ++x) {
C.push(get(x, A, B));
}
console.log(C);
Result: [5, 3, 1, 6, 4, 2, 7]
http://jsfiddle.net/xRFTD/
var data = "12345 67123 45671 23456 71234 56712 34567";
var x = 5;
var y = 7;
var results = [];
var i = x - 1; // enumeration in string starts from zero
while ( i <= data.length){
results.push(data[i]);
i = i + x + 1;// +1 for spaces ignoring
}

Need help making an approximation of Euler's constant

It's very close but just one number off. If you can change anything here to make it better it'd be appreciated. I'm comparing my number with Math.E to see if I'm close.
var e = (function() {
var factorial = function(n) {
var a = 1;
for (var i = 1; i <= n; i++) {
a = a * i;
}
return a;
};
for (var k = 0, b = []; k < 18; k++) {
b.push(b.length ? b[k - 1] + 1 / factorial(k) : 1 / factorial(k));
}
return b[b.length - 1];
})();
document.write(e);document.write('<br />'+ Math.E);​
My number: 2.7182818284590455
Math.E: 2.718281828459045
Work from higher numbers to lower numbers to minimize cancellation:
var e = 1;
for(var k = 17; k > 0; --k) {
e = 1 + e/k;
}
return e;
Evaluating the Taylor polynomial by Horner's rule even avoids the factorial and allows you to use more terms (won't make a difference beyond 17, though).
As far as I can see your number is the same as Math.E and even has a better precision.
2.7182818284590455
2.718281828459045
What is the problem after all?
With javascript, you cannot calculate e this way due to the level of precision of javascript computations. See http://www.javascripter.net/faq/accuracy.htm for more info.
To demonstrate this problem please take a look at the following fiddle which calculates e with n starting at 50000000, incrementing n by 1 every 10 milliseconds:
http://jsfiddle.net/q8xRs/1/
I like using integer values to approximate real ones.
Possible approximations of e in order of increasing accuracy are:
11/4
87/32
23225/8544
3442297523731/1266350489376
That last one is fairly accurate, equating to:
2.7182818284590452213260834432
which doesn't diverge from wikipedia's value till the 18th:
2.71828182845904523536028747135266249775724709369995
So there's that, if you're interested.

Categories