var userNumber = parseInt(prompt("What number would you like to have factored?"));
var factoring = function(n) {
var m = n;
var o = n;
for(i = 2; i < n/2; i++) {
if (m % i === 0 && o % i === 0) {
var p = 0;
while (n % i === 0) {
n = n / i;
p++;
}
n = m;
o = o / i;
if (p > 1) {
console.log(i + "^" + p);
}
else {
console.log(i);
}
}
else {}
}
};
factoring(userNumber);
When I feed the above code an input that's large and relatively very composite, it gives wrong answers. 900, for example gives:
2^2
3^2
5^2
6^2
The first three rows are accurate, but the 6^2 is just a repeat of the 2 and the 3. How do I make the 6^2 not show, as well as solving other similar problems like the extra 25 given when you input 1000?
P.S. I am aware that this code takes more work than is necessary, but I would still rather make it work more or less as is than replace it with some other method entirely.
You are resetting n to its original value by doing n=m;. This is the reason, why you get non-prime factors. Also, you don't need o. Also, you need to run your outer loop till m/2 + 1, not just till m/2. See the corrected version below.
var userNumber = parseInt(prompt("What number would you like to have factored?"));
var factoring = function(n) {
var m = n;
var o = n;
for(i = 2; i < m/2 + 1; i++) {
if (n % i === 0) {
var p = 0;
while (n % i === 0) {
n = n / i;
p++;
}
if (p > 1) {
console.log(i + "^" + p);
}
else {
console.log(i);
}
}
else {}
}
};
factoring(userNumber);
Related
I've been trying to solve this kata on codewars.
I've got an algorithm, but it's apparently too slow to pass the test. It can create sequence of 2450 numbers in just under 1.6 seconds. I don't need the solution but the hint or something to help me to make my algorithm faster.
function ulamSequence(u0, u1, n) {
// create an array with first two elements in it
const seq = [u0, u1];
// create a loop that checks if next number is valid and if it is, push it in seq
num: for (let i = u1 + 1; seq.length < n; i++) {
let sumCount = 0;
for (let k = 0; k < seq.length - 1; k++) {
if (seq.indexOf(i - seq[k]) > k && ++sumCount === 2) { continue num; }
}
sumCount === 1 ? seq.push(i) : "";
}
return seq;
}
Here's an idea: have an array sums so that sums[N] keeps the number of possible summations for N. For example, for U(1,2) sums[3] will be 1 and sums[5] will be 2 (1+4, 2+3). On each step, locate the minimal N so that N > last item and sums[N] == 1. Add N to the result, then sum it with all previous items and update sums accordingly.
function ulam(u0, u1, len) {
let seq = [u0, u1]
let sums = []
let last = u1
sums[u0 + u1] = 1
while (seq.length < len) {
last += 1
while (sums[last] !== 1) {
last += 1
}
for (let n of seq) {
let s = n + last
sums[s] = (sums[s] || 0) + 1
}
seq.push(last)
}
return seq
}
console.time()
ulam(1, 2, 2450)
console.timeEnd()
function ulamSequence(u0, u1, n) {
const seq = [u0, u1];
const set = new Set(seq);
for (let i = u1 + 2; seq.length < n; i++) {
let sumCount = 0;
for (let k = 0; k < seq.length - 1; k++) {
if (set.has(i - seq[k])) {
sumCount++;
if (sumCount === 2) {
continue;
}
}
}
if (sumCount === 1) {
seq.push(i);
set.add(i);
}
}
return seq;
}
Why is my code to generate a fibonacci sequence not working? Fibonacci sequence would go like this: [0,1,1,2,3,5,8,13,21,34] when n=10 and so on if greater, where the last two numbers are added to give the next number. I tried this using a while loop as I initially tried using a for loop but I couldn't determine a change to put in the (). I don't think there are any problems in the first 8 lines of the code as I tried them before and they worked so problem is after but I can't figure it out...thanks in advance!
var seq = [];
function fibonacciGenerator(n) {
if (n === 1) {
seq.push(0);
} else if (n === 2) {
seq.push(0, 1);
} else if (n > 2) {
seq.push(0, 1);
while(len < n) {
var len = seq.length;
seq.push(seq[len] + seq[len - 1]);
}
}
return seq;
}
console.log(fibonacciGenerator(10));
Edit: This is the code that works for n=1 and n=2 hence I'm convinced that the problem is in the while loop but I can't figure it out. :
var seq = [];
function fibonacciGenerator(n) {
if (n === 1) {
seq.push(0);
} else if (n === 2) {
seq.push(0, 1);
}
return seq;
}
console.log(fibonacciGenerator(2));
Now my console is printing [0,1]
Edit:
Ok guys I fixed the code myself and now it works if anyone wants to know how to use while loop for fib seq here it is:
var seq = [];
function fibonacciGenerator(n) {
if (n === 1) {
seq.push(0);
} else if (n === 2) {
seq.push(0, 1);
} else if (n > 2) {
seq.push(0, 1);
var len = seq.length;
while (len < n) {
seq.push(seq[len-1] + seq[len - 2]);
len++;
}
}
return seq;
}
console.log(fibonacciGenerator(10));
Here is a proper fibonacci module:
function fibonacciGenerator(n){
var fib = []; // Initialize array!
fib[0] = 0;
fib[1] = 1;
for (var i = 2; i < n; i++) {
// Next fibonacci number = previous + one before previous
// Translated to JavaScript:
fib[i] = fib[i - 2] + fib[i - 1];
}
return fib;
}
console.log(fibonacciGenerator(10))
Hope it will help!
Edit as pinted out my function was doing adding 1 extra line. Fixed by replaceing for (var i = 2; i <= n; i++) { with for (var i = 2; i < n; i++) {
Ok guys I fixed the code myself and now it works if anyone wants to know how to use while loop for fib seq here it is:
var seq = [];
function fibonacciGenerator(n) {
if (n === 1) {
seq.push(0);
} else if (n === 2) {
seq.push(0, 1);
} else if (n > 2) {
seq.push(0, 1);
var len = seq.length;
while (len < n) {
seq.push(seq[len-1] + seq[len - 2]);
len++;
}
}
return seq;
}
console.log(fibonacciGenerator(10));
I made a simple function in js that took one argument n, and factored it down to primes. However, when n is a product of duplicates of primes, it does not add the duplicates to the array of factors. For example the number 28. 28 is equal to 2*2*7 = 2^2 * 7. If I run my function factor(n) with n = 28, I want to get the following result: [2,2,7]. Instead, I get [2,7]. Can someone help me fix this??? Here's the function in js:
function factor(n) {
var factors = []
for (var i = 2; i < n; i++) {
if (divisible(n,i)) {
if (isPrime(i)) {
factors.push(i)
}
factor(i)
}
}
console.log(factors)
}
THANKS!
const primeFactors = N => {
const smallestFactor = n => {
if (n % 2 === 0) return 2;
for (let k = 3; k * k <= n; k+= 2) if (n % k === 0) return k;
return n;
}
let factors = [];
let val = N;
while (val !== 1) {
let factor = smallestFactor(val);
factors.push(factor);
val /= factor;
}
return factors;
}
console.log(primeFactors(28));
I am working on this kata https://www.codewars.com/kata/count-9-s-from-1-to-n/train/javascript
and i have written this code for it, but its not working. This question is similar to this one Count the number of occurrences of 0's in integers from 1 to N
but it is different because searching for 9's is practically very different to searching for 0's.
think part of the problem with this code is that it takes too long to run...
any advice appreciated!
function has9(n) {
var nine = [];
var ninearr = n.toString().split('');
for (var j = 0; j < ninearr.length; j++) {
if (ninearr[j] == '9') {
nine.push(ninearr[j]);
}
}
return nine.length;
}
function number9(n) {
var arr = [];
var arrnew = [];
for (var i = 0; i <= n; i++) {
arr.push(i);
}
for (var l = 0; l < arr.length; l++) {
arrnew.push(has9(l));
}
var sum = arrnew.reduce((a, b) => a + b, 0);
return sum;
}
Why not a regex based solution? (Too slow as well?)
const count9s = num => num.toString().match(/9/g).length
console.log(count9s(19716541879)) // 2
console.log(count9s(919191919191919)) // 8
console.log(count9s(999)) // 3
console.log(count9s(999999)) // 6
I have taken the above hint and completely re written the code, which I now feel should work, and it does for most inputs, but codewars is saying it fails on some of them. any ideas why?
function nines(n){
if(n>=100){
var q= Math.floor(n/100);
var nq= q * 20;
var r = (n%100);
var s = Math.floor(r/9);
if (r<=90){
return s + nq;
}
if (r == 99){
return 20 + nq;
}
if (90 < r < 100 && r!= 99){
var t = (r-90);
return nq + s + t;
}
}
if (n<100){
if (n<=90){
var a = Math.floor(n/9);
return a ;
}
if (n == 99){
return 20
}
if (90 < n < 100 && n!= 99){
var c = (n-90);
return 10 + c;
}
}
}
=== UPDATE ===
I just solved your kata using
function number9Helper(num) {
var pow = Math.floor(Math.log10(num));
var round = Math.pow(10, pow);
var times = Math.floor(num / round);
var rest = Math.abs(num - (round * times));
var res = pow * (round==10 ? 1 : round / 10) * times;
if (num.toString()[0] == '9') res += rest;
if (rest < 9) return res;
else return res + number9Helper(rest);
}
function number9(num) {
var res = number9Helper(num);
res = res + (num.toString().split('9').length-1);
return res;
}
== Function below works but is slow ===
So, could something like this work for you:
for (var nines=0, i=1; i<=n; i++) nines += i.toString().split('9').length-1;
Basically, there are many way to achieve what you need, in the end it all depends how do you want to approach it.
You can test it with
function nines(n) {
for (var nines=0, i=1; i<=n; i++) nines += i.toString().split('9').length-1;
return nines;
}
function number9(n) {
if (n < 8) {
return 0
};
if (n === 9) {
return 1
};
if (n > 10) {
let str = ''
for (let i = 9; i <= n; i++) {
str += String(i)
}
return str.match(/[9]/g).length
}
}
So I have a random javascript array of names...
[#larry,#nicholas,#notch] etc.
They all start with the # symbol. I'd like to sort them by the Levenshtein Distance so that the the ones at the top of the list are closest to the search term. At the moment, I have some javascript that uses jQuery's .grep() on it using javascript .match() method around the entered search term on key press:
(code edited since first publish)
limitArr = $.grep(imTheCallback, function(n){
return n.match(searchy.toLowerCase())
});
modArr = limitArr.sort(levenshtein(searchy.toLowerCase(), 50))
if (modArr[0].substr(0, 1) == '#') {
if (atRes.childred('div').length < 6) {
modArr.forEach(function(i){
atRes.append('<div class="oneResult">' + i + '</div>');
});
}
} else if (modArr[0].substr(0, 1) == '#') {
if (tagRes.children('div').length < 6) {
modArr.forEach(function(i){
tagRes.append('<div class="oneResult">' + i + '</div>');
});
}
}
$('.oneResult:first-child').addClass('active');
$('.oneResult').click(function(){
window.location.href = 'http://hashtag.ly/' + $(this).html();
});
It also has some if statements detecting if the array contains hashtags (#) or mentions (#). Ignore that. The imTheCallback is the array of names, either hashtags or mentions, then modArr is the array sorted. Then the .atResults and .tagResults elements are the elements that it appends each time in the array to, this forms a list of names based on the entered search terms.
I also have the Levenshtein Distance algorithm:
var levenshtein = function(min, split) {
// Levenshtein Algorithm Revisited - WebReflection
try {
split = !("0")[0]
} catch(i) {
split = true
};
return function(a, b) {
if (a == b)
return 0;
if (!a.length || !b.length)
return b.length || a.length;
if (split) {
a = a.split("");
b = b.split("")
};
var len1 = a.length + 1,
len2 = b.length + 1,
I = 0,
i = 0,
d = [[0]],
c, j, J;
while (++i < len2)
d[0][i] = i;
i = 0;
while (++i < len1) {
J = j = 0;
c = a[I];
d[i] = [i];
while(++j < len2) {
d[i][j] = min(d[I][j] + 1, d[i][J] + 1, d[I][J] + (c != b[J]));
++J;
};
++I;
};
return d[len1 - 1][len2 - 1];
}
}(Math.min, false);
How can I work with algorithm (or a similar one) into my current code to sort it without bad performance?
UPDATE:
So I'm now using James Westgate's Lev Dist function. Works WAYYYY fast. So performance is solved, the issue now is using it with source...
modArr = limitArr.sort(function(a, b){
levDist(a, searchy)
levDist(b, searchy)
});
My problem now is general understanding on using the .sort() method. Help is appreciated, thanks.
Thanks!
I wrote an inline spell checker a few years ago and implemented a Levenshtein algorithm - since it was inline and for IE8 I did quite a lot of performance optimisation.
var levDist = function(s, t) {
var d = []; //2d matrix
// Step 1
var n = s.length;
var m = t.length;
if (n == 0) return m;
if (m == 0) return n;
//Create an array of arrays in javascript (a descending loop is quicker)
for (var i = n; i >= 0; i--) d[i] = [];
// Step 2
for (var i = n; i >= 0; i--) d[i][0] = i;
for (var j = m; j >= 0; j--) d[0][j] = j;
// Step 3
for (var i = 1; i <= n; i++) {
var s_i = s.charAt(i - 1);
// Step 4
for (var j = 1; j <= m; j++) {
//Check the jagged ld total so far
if (i == j && d[i][j] > 4) return n;
var t_j = t.charAt(j - 1);
var cost = (s_i == t_j) ? 0 : 1; // Step 5
//Calculate the minimum
var mi = d[i - 1][j] + 1;
var b = d[i][j - 1] + 1;
var c = d[i - 1][j - 1] + cost;
if (b < mi) mi = b;
if (c < mi) mi = c;
d[i][j] = mi; // Step 6
//Damerau transposition
if (i > 1 && j > 1 && s_i == t.charAt(j - 2) && s.charAt(i - 2) == t_j) {
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
}
}
}
// Step 7
return d[n][m];
}
I came to this solution:
var levenshtein = (function() {
var row2 = [];
return function(s1, s2) {
if (s1 === s2) {
return 0;
} else {
var s1_len = s1.length, s2_len = s2.length;
if (s1_len && s2_len) {
var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
while (i1 < s1_len)
row[i1] = ++i1;
while (i2 < s2_len) {
c2 = s2.charCodeAt(i2);
a = i2;
++i2;
b = i2;
for (i1 = 0; i1 < s1_len; ++i1) {
c = a + (s1.charCodeAt(i1) === c2 ? 0 : 1);
a = row[i1];
b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
row[i1] = b;
}
}
return b;
} else {
return s1_len + s2_len;
}
}
};
})();
See also http://jsperf.com/levenshtein-distance/12
Most speed was gained by eliminating some array usages.
Updated: http://jsperf.com/levenshtein-distance/5
The new Revision annihilates all other benchmarks. I was specifically chasing Chromium/Firefox performance as I don't have an IE8/9/10 test environment, but the optimisations made should apply in general to most browsers.
Levenshtein Distance
The matrix to perform Levenshtein Distance can be reused again and again. This was an obvious target for optimisation (but be careful, this now imposes a limit on string length (unless you were to resize the matrix dynamically)).
The only option for optimisation not pursued in jsPerf Revision 5 is memoisation. Depending on your use of Levenshtein Distance, this could help drastically but was omitted due to its implementation specific nature.
// Cache the matrix. Note this implementation is limited to
// strings of 64 char or less. This could be altered to update
// dynamically, or a larger value could be used.
var matrix = [];
for (var i = 0; i < 64; i++) {
matrix[i] = [i];
matrix[i].length = 64;
}
for (var i = 0; i < 64; i++) {
matrix[0][i] = i;
}
// Functional implementation of Levenshtein Distance.
String.levenshteinDistance = function(__this, that, limit) {
var thisLength = __this.length, thatLength = that.length;
if (Math.abs(thisLength - thatLength) > (limit || 32)) return limit || 32;
if (thisLength === 0) return thatLength;
if (thatLength === 0) return thisLength;
// Calculate matrix.
var this_i, that_j, cost, min, t;
for (i = 1; i <= thisLength; ++i) {
this_i = __this[i-1];
for (j = 1; j <= thatLength; ++j) {
// Check the jagged ld total so far
if (i === j && matrix[i][j] > 4) return thisLength;
that_j = that[j-1];
cost = (this_i === that_j) ? 0 : 1; // Chars already match, no ++op to count.
// Calculate the minimum (much faster than Math.min(...)).
min = matrix[i - 1][j ] + 1; // Deletion.
if ((t = matrix[i ][j - 1] + 1 ) < min) min = t; // Insertion.
if ((t = matrix[i - 1][j - 1] + cost) < min) min = t; // Substitution.
matrix[i][j] = min; // Update matrix.
}
}
return matrix[thisLength][thatLength];
};
Damerau-Levenshtein Distance
jsperf.com/damerau-levenshtein-distance
Damerau-Levenshtein Distance is a small modification to Levenshtein Distance to include transpositions. There is very little to optimise.
// Damerau transposition.
if (i > 1 && j > 1 && this_i === that[j-2] && this[i-2] === that_j
&& (t = matrix[i-2][j-2]+cost) < matrix[i][j]) matrix[i][j] = t;
Sorting Algorithm
The second part of this answer is to choose an appropriate sort function. I will upload optimised sort functions to http://jsperf.com/sort soon.
I implemented a very performant implementation of levenshtein distance calculation if you still need this.
function levenshtein(s, t) {
if (s === t) {
return 0;
}
var n = s.length, m = t.length;
if (n === 0 || m === 0) {
return n + m;
}
var x = 0, y, a, b, c, d, g, h, k;
var p = new Array(n);
for (y = 0; y < n;) {
p[y] = ++y;
}
for (; (x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x;
b = x + 1;
d = x + 2;
g = x + 3;
h = x + 4;
for (y = 0; y < n; y++) {
k = s.charCodeAt(y);
a = p[y];
if (a < c || b < c) {
c = (a > b ? b + 1 : a + 1);
}
else {
if (e1 !== k) {
c++;
}
}
if (c < b || d < b) {
b = (c > d ? d + 1 : c + 1);
}
else {
if (e2 !== k) {
b++;
}
}
if (b < d || g < d) {
d = (b > g ? g + 1 : b + 1);
}
else {
if (e3 !== k) {
d++;
}
}
if (d < g || h < g) {
g = (d > h ? h + 1 : d + 1);
}
else {
if (e4 !== k) {
g++;
}
}
p[y] = h = g;
g = d;
d = b;
b = c;
c = a;
}
}
for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) {
d = (a > d ? d + 1 : a + 1);
}
else {
if (e !== s.charCodeAt(y)) {
d = c + 1;
}
else {
d = c;
}
}
p[y] = d;
c = a;
}
h = d;
}
return h;
}
It was my answer to a similar SO question
Fastest general purpose Levenshtein Javascript implementation
Update
A improved version of the above is now on github/npm see
https://github.com/gustf/js-levenshtein
The obvious way of doing this is to map each string to a (distance, string) pair, then sort this list, then drop the distances again. This way you ensure the levenstein distance only has to be computed once. Maybe merge duplicates first, too.
I would definitely suggest using a better Levenshtein method like the one in #James Westgate's answer.
That said, DOM manipulations are often a great expense. You can certainly improve your jQuery usage.
Your loops are rather small in the example above, but concatenating the generated html for each oneResult into a single string and doing one append at the end of the loop will be much more efficient.
Your selectors are slow. $('.oneResult') will search all elements in the DOM and test their className in older IE browsers. You may want to consider something like atRes.find('.oneResult') to scope the search.
In the case of adding the click handlers, we may want to do one better avoid setting handlers on every keyup. You could leverage event delegation by setting a single handler on atRest for all results in the same block you are setting the keyup handler:
atRest.on('click', '.oneResult', function(){
window.location.href = 'http://hashtag.ly/' + $(this).html();
});
See http://api.jquery.com/on/ for more info.
I just wrote an new revision: http://jsperf.com/levenshtein-algorithms/16
function levenshtein(a, b) {
if (a === b) return 0;
var aLen = a.length;
var bLen = b.length;
if (0 === aLen) return bLen;
if (0 === bLen) return aLen;
var len = aLen + 1;
var v0 = new Array(len);
var v1 = new Array(len);
var i = 0;
var j = 0;
var c2, min, tmp;
while (i < len) v0[i] = i++;
while (j < bLen) {
c2 = b.charAt(j++);
v1[0] = j;
i = 0;
while (i < aLen) {
min = v0[i] - (a.charAt(i) === c2 ? 1 : 0);
if (v1[i] < min) min = v1[i];
if (v0[++i] < min) min = v0[i];
v1[i] = min + 1;
}
tmp = v0;
v0 = v1;
v1 = tmp;
}
return v0[aLen];
}
This revision is faster than the other ones. Works even on IE =)