Why does this code only work in certain JS executors? - javascript

This code takes an integer and returns the amount of 1s that are present.
function countOnes(i) {
let str = i.toString();
let ones = 0;
for(let x = 0; x < i.length; x++) {
if(str.charAt(x) === '1') ones++;
}
return ones;
}
console.log(countOnes(111000));
But it only appears to work in certain executors of JavaScript. If I enter this code into p5.js or Mozilla MDN, I will receive the desired output of 3.
But if I use the console in my browser and some other websites emulating that, 0 will be returned with every given value.
Why is this the case?

you cant loop on i.length, i its still a 'Number' type,
you should loop on "str.length" instead.
you better give more meaningful names... i should be num,
str should be numStr, ones should be counter.
try this:
function countOnes(num) {
var counter = 0;
var numsArray = Array.from((num + ''))
numsArray.forEach(num => {
return (num == 1)? counter++ : ''
})
return counter
}
console.log(countOnes(1110010)); // 4

Related

how to loop through two indexes in javascript

why it's giving me the first index and i need the ouput below which is "StOp mAkInG SpOnGeBoB MeMeS!"
function spongeMeme(sentence) {
let x = sentence.split("");
for(let i = 0; i < sentence.length;i+=2){
return x[i].toUpperCase()
}
}
console.log(spongeMeme("stop Making spongebob Memes!")) // S
// output : StOp mAkInG SpOnGeBoB MeMeS!"
You're returning just the first letter of what is stored inside of x.
Try to debug it and see what is going on.
The way I'd do it is like so:
function spongeMeme(sentence) {
return sentence.split("")
.map((s, i) => (i % 2 != 0 ? s.toUpperCase() : s))
.join("");
}
console.log(spongeMeme("stop Making spongebob Memes!"));
Try this:
function spongeMeme(sentence) {
let x = sentence.split("");
let newSentence = '';
for(let i = 0; i < sentence.length;i++){
// If the letter is even
if(i % 2 ==0) {
newSentence += x[i].toUpperCase();
}
// If the letter is odd
else {
newSentence += x[i].toLowerCase();
}
}
return newSentence
}
console.log(spongeMeme("stop Making spongebob Memes!"))
First of all you can only return once per function, so you have to create a variable and store all the new letter inside, and, at the end, return this variable.
You're immediately returning on the first iteration of your for loop, hence the reason you're only getting back a single letter.
Let's start by fixing your existing code:
function spongeMeme(sentence) {
let x = sentence.split("");
for(let i = 0; i < sentence.length; i+=2) {
// You can't return here. Update the value instead.
return x[i].toUpperCase()
}
// Join your sentence back together before returning.
return x.join("");
}
console.log(spongeMeme("stop Making spongebob Memes!"))
That'll work, but we can clean it up. How? By making it more declarative with map.
function spongeMeme(sentence) {
return sentence
.split('') // convert sentence to an array
.map((char, i) => { // update every other value
return (i % 2 === 0) ? char.toUpperCase() : char.toLowerCase();
})
.join(''); // convert back to a string
}
You can also do that:
const spongeMeme = (()=>
{
const UpperLower = [ (l)=>l.toUpperCase(), (l)=>l.toLowerCase() ]
return (sentence) =>
{
let i = -1, s = ''
for (l of sentence) s += UpperLower[i=++i&1](l)
return s
}
})()
console.log(spongeMeme("stop Making spongebob Memes!"))
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}
OR
function spongeMemez(sentence)
{
let t = false, s = ''
for (l of sentence) s += (t=!t) ? l.toUpperCase() : l.toLowerCase()
return s
}
but I think this version is slower, because using an index should be faster than a ternary expression

Code Wars Persistent Bugger issue with if-statement not running for-loop

https://www.codewars.com/kata/persistent-bugger/train/javascript
I'm working on the JavaScript Code Wars Persistent Bugger problem. As seen in the code, my if-statement appears to completely ignore the for-loop within it.
Anything logged within the for-loop does not show, and anything logged outside the for-loop remained the same as if the for-loop wasn't there. I've tried researching the use of for-loops inside if-statements as well as existing solutions for this Code Wars problem, but did not see my issue being replicated. From my understanding, the if-statement should run through everything within it from top to bottom.
const persistence = (num) => {
if (typeof(num) === 'number') {
let count = 0
let mult = num
let newMult = 1
let stop = false
while (stop === false){
if (mult >= 10) {
for (let i = 0; i < mult.length; i++) {
newMult = newMult * mult[i]
// // doesn't log anything. code isn't running through for loop?
// console.log(newMult)
}
// // logs initial num of 999
// console.log(mult)
// // logs initial newMult of 1
// console.log(newMult)
count++
mult = newMult
newMult = 1
}
else {
stop = true
}
}
return count
}
}
// logs 1, should be 4
console.log(persistence(999))
I think I have the logic correct, but maybe there's some fundamental issue I'm missing in regards to how if-statements and for-loops work. I noticed there are much simpler ways to solve this problem, but if I could receive feedback on why my specific code doesn't work, and how I could tweak it to make it work, that would be greatly appreciated.
You are iterating to the length of num on the for loop. As num is type number ,it has no length.
You need to iterate over a string version of mult (let's call it multStr) in order to access its numeric-indexed properties as digits. (Otherwise, it won't have a length, and accessing its numeric properties wouldn't give anything in return.)
You can also significantly clean up the code by returning early instead of having such nested blocks:
const persistence = (num) => {
if (typeof num !== 'number') {
return;
}
let count = 0
let mult = num
while (true) {
if (mult < 10) {
return count;
}
const multStr = String(mult); // <--------------------------
let newMult = 1
for (let i = 0; i < multStr.length; i++) { // <--------------------------
newMult = newMult * multStr[i] // <--------------------------
}
mult = newMult;
count++
}
}
console.log(persistence(999))
You could also consider using reduce to calculate the newMult instead:
const persistence = (num) => {
if (typeof num !== 'number') {
return;
}
let count = 0
let mult = num
while (true) {
if (mult < 10) {
return count;
}
mult = [...String(mult)].reduce((a, b) => a * b, 1);
count++
}
}
console.log(persistence(999))

NodeJS require with asynch functions when synch is wanted

I have the following code
var utils = require(`${__dirname}/../../utils/utils.js`);
...
let object = utils.parse(input);
if (object === undefined){
let helper = utils.recognize(input);
msg.channel.sendMessage("\"" + input + "\" not recognized. Did you mean \"" + helper[0] + "\"?");
object = utils.parse(helper[0]);
}
//code related to object
console.log(object.strLength);
where "parse" tries to match the input to an object in a database, and "recognize" tries to find the best match if the input is spelled incorrectly (Levenshtein) (along with additional info such as how close the match was).
Currently the issue is that the code is ran asynchronously; "object.strLength" returns an undefined before utils.recognize() returns a value. If I copy/paste the recognize() and parse() functions into the file, then the code is run synchronously and I do not run into any issues. However I would rather keep those functions in a separate file as I reuse them in other files.
Is there a way to specify that the functions in utils must be synch? I know that there are libraries that convert asynch into synch but I prefer to use as few libraries as I can help it. I tried to have the recognize functions return a Promise but it ended up as a jumbled mess
edit: here's parse. I did not think it was necessary to answer this question so I did not include it initially:
var db = require(`${__dirname}/../data/database.js`);
...
var parse = (input) => {
let output = db[output];
if (output === null) {
Object.keys(db).forEach((item) => {
if (db[item].num === parseInt(input) || (db[item].color + db[item].type === input)){
output = db[item];
return false;
}
});
}
return output;
}
I solved the issue, thanks everyone. Here's what was wrong, it was with recognize(). It was my mistake to not show the code for it initially.
Original recognize:
var recognize = (item) => {
//iterate through our databases and get a best fit
let bestItem = null;
let bestScore = 99999; //arbitrary large number
//let bestType = null;
//found algorithm online by milot-mirdita
var levenshtein = function(a, b) {
if (a.length == 0) { return b.length; }
if (b.length == 0) { return a.length; }
// swap to save some memory O(min(a,b)) instead of O(a)
if(a.length > b.length) {
let tmp = a;
a = b;
b = tmp;
}
let row = [];
for(let i = 0; i <= a.length; i++) {
row[i] = i;
}
for (let i = 1; i <= b.length; i++) {
let prev = i;
for (let j = 1; j <= a.length; j++) {
let val;
if (b.charAt(i-1) == a.charAt(j-1)) {
val = row[j-1]; // match
} else {
val = Math.min(row[j-1] + 1, // substitution
prev + 1, // insertion
row[j] + 1); // deletion
}
row[j - 1] = prev;
prev = val;
}
row[a.length] = prev;
}
return row[a.length];
}
//putting this here would make the code work
//console.log("hi");
Object.keys(db).forEach((key) => {
if (levenshtein(item, key) < bestScore) {
bestItem = key;
bestScore = levenshtein(item, key);
}
});
return [bestItem, bestScore];
}
My solution was to move the levenshtein function outside of the recognize function, so if I wanted to I can call levenshtein from another function
#user949300 and #Robert Moskal, I changed the forEach loop into a let...in loop. There is no functional difference (as far as I can tell) but the code does look cleaner.
#Thomas, I fixed the let output = db[output]; issue, oops.
Again, thanks for all of your help, I appreciate it. And happy New Year too

JS crashes sometimes with Timer scramble

My Javascript timer is for people with a rubiks cube with generates a scramble (nevermind all this, but just to tell you I'm generating after each solve a new scramble will be generated) and my scrambles do actually have a while (true) statement. So that does crash my script, but it 95/100 times stops just before the script crashes but I don't wanna have any times.
Let me explain a bit more detailed about the problem.
Problem: javascript crashes because my script takes too long to generate a scramble.
Below you have 3 functions I use.
This function generates a scramble with the Fisher-Yates shuffle.
Timer.prototype.generateScramble = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
This function validates the input e.g. I receive an array as the following:
Here I only have to check the first character. That's why I use the seconds [ ] notation. I don't want people get an F with an F2 e.g.
var scr = ["F","R","U","B","L","D","F2","R2","U2","B2","L2","D2","F'","R'","U'","B'","L'","D'"]
Timer.prototype.validateScramble2 = function(array) {
var last = array.length-1;
for (var i = 0; i < array.length-1; i++) {
if (array[i][0] == array[i+1][0]) {
return false;
}
}
for (var i = 0; i < array.length-2; i++) {
if (array[i][0] == array[i+2][0]) {
return false;
}
}
if (array[0][0] == [last][0]) {
return false;
}
return true;
};
The above functions are just waiting to be called. Well in the function below I use them.
Timer.prototype.updateScramble2 = function(scrambleArr, len, type) {
var self = this;
var scramble = '', j, updatedArr = [];
while (updatedArr.length < len) {
j = (Math.floor(Math.random() * scrambleArr.length));
updatedArr.push(scrambleArr[j]);
}
while (!self.validateScramble2(updatedArr)) {
updatedArr = self.generateScramble(updatedArr);
}
for (var i = 0; i < updatedArr.length; i++) {
scramble += updatedArr[i] + ' ';
}
scrambleDiv.innerHTML = scramble;
};
I assume you guys understand it but let me explain it briefly.
The first while-loop adds a random value from the given array(scrambleArr) into a new array called updatedArr.
The next while-loop calls the validateScramble2() function if there isn't in an array F next to an F2.
The for-loop adds them into a new variable added with a whitespace and then later we show the scramble in the div: scrambleDiv.innerHTML = scramble;
What do I need know after all this information?
Well I wanna know why my updateScramble2() functions lets my browser crash every time and what I do wrong and how I should do it.
I'm not entirely sure I understand the question, but from the way your code looks, I think you have an infinite loop going on. It appears as if validateScramble2 always returns false which causes your second loop in updateScramble2 to perpetually run.
I suggest you insert a breakpoint in your code and inspect the values. You could also insert debugger; statements in your code, works the same way. Open dev tools prior to doing these.
A suggestion is instead of using loops, use a timer. This breaks up your loop into asynchronous iterations rather than synchronous. This allows the browser breathing space for other operations. Here's an example of a forEachAsync:
function forEachAsync(array, callback){
var i = 0;
var timer = setInterval(function(){
callback.call(null, array[i]);
if(++i >= array.length) clearInterval(timer);
}, 0);
}
forEachAsync([1,2,4], function(item){
console.log(item);
});
You can take this further and use Promises instead of callbacks.

Find variable value

I have some inputs in my app: <_input code/> + <_input code/> = <_input code/>.
Let's imagine first input name is a, appropriately second and third inputs' names are b and c. I filled my inputs:
7 + x = 12
Is there any way to calculate x value?
What do I want from my script:
It finds variable in inputs' values.
It checks all fields of my form filled properly.
It finds variable in inputs' values.
From given information script calculates value of variable.
How many inputs will be doesn't matter. I just want to find value of x. Is there any library to do this?
function calculcateA(b,c){
return c-b;
}
if(inputA === 'x'){
alert(calculateA(inputB,inputC));
}
And so on... there is nothing wrong with this functions, but I want to automate this proccess like WolframAplha.
The best thing for you, I guess would be to find some library for solving equations. If you are in need to solve bigger sets of equations then maybe something related to linear algebra.
Can't really tell you an exact solution so you will have to search for yourself.
Here is some code that should solve the problem.
function calculate() {
var varIndex = -1;
//Ensure that at least two three arguements are passed
if (arguments.length < 3) {
throw "You need at least three parameters to make an equation";
}
//Make sure that there is only one variable
for (var i = 0; i < arguments.length; i++) {
if (isNaN(arguments[i])) {
if (varIndex != -1) {
throw "You can't have two variables";
return;
}
varIndex = i;
}
}
//If variable has been found
if (varIndex != -1) {
var answer = 0;
//If variable is at the last position, add all constants
if (varIndex == types.length - 1) {
for (var j = 0; j < arguments.length - 1; j++) {
answer = answer + j;
}
} else {
//Otherwise Deduct all values from the last
answer = arguments[arguments.length - 1];
for (var k = 0; k < arguments.length - 1; k++) {
if (k == varIndex) { continue; }
answer = answer - j;
}
}
//Return Result
return { variable: arguments[varIndex], answer: answer };
}
else {
throw "You need at least one variable";
return;
}
}
You would use the above as follows:
var a = document.querySelector("input[name=a]");
var b = document.querySelector("input[name=b]");
var c = document.querySelector("input[name=c]");
var calcBtn = document.getElementById("calculate");
calcBtn.addEventListener("click", function () {
try {
var result = calculate(a.value, b.value, c.value);
console.log("The value of " + result.variable + " is " + result.answer);
} catch (e) {
console.log(e);
}
});

Categories