Each string in an array is a number, for example array1 = ["1296", "12", "27"];
For each string above, if possible to divide by 6 evenly without remainders, I want to do so at least once, then if the result is still longer than 2 characters, repeat. Then replace the string in the same position, such that the array would become ["36", "2", "27"];
so far, my code partly works.
w=0;
function divideBySix(){
if ((array1[w] / 6) == (Math.floor(array1[w] / 6))) {
var temp = array1[w] / 6;
array1[w] = temp.toString();
if (array1[w].length < 3) {
w++;
}
divideBySix();
}
The function successfully divides the first string by 6 once, and then calls itself again and again until the result is within 2 chars long. At that point, it should continue calling itself, and do the same to the next string of the array. But it doesn't do the next string. I don't know why it stops after finishing the first string. So the array looks like this ["36", "12", "27"]; Also, w successfully gets incremented. So I know its getting at least that far...
The function you give has unbalanced { }. When I add one at the end and run it, I get the result you say you want — ["36", "2", "27"]. There must be something else wrong, or you have not copied the code correctly.
In order to understand the operation, I added this to the beginning of divideBySix:
console.log(w, array1.toString());
i think you could just go with the modulo operator, if this is what you wanted to achieve
if(array1[w] % 6 == 0) doSomething()
and to solve your current problem you could introduce a second function ; for me it works with :
function divideBySix(array){
for(var i = 0; i < array.length; i++){
array[i] = divideNumber(array[i], 0);
}
}
function divideNumber(nr, ct){
if((ct < 1 || nr > 99) && nr%6 == 0 ) return divideNumber(nr/6, ct+1);
else return nr;
}
var array1 = ["1296", "12", "27"];
divideBySix(array1);
alert(array1);
When I test the code, that's what it does:
http://jsfiddle.net/Guffa/x4fNP/
Related
I've been learning Javascript via FCC for 6 weeks now, and decided to spend a week learning, and playing around with methods to get really close and comfortable with using them in loops, and with statements. Just playing around with strings, I was trying to replace the string "I like milk", with "I like silk". My code accomplishes this, and I understand it, but I decided to add an || operator, and the outcome bewilders me. If i say if(x[i]=== 'm' || x[i] === 'I', it doesn't replace 'I', but replaces 'm' If i leave it the way it is in my original code, it produces the string 'I lise milk', even though 'k' was never mentioned. What is going on?
let x = 'Hello I like milk';
let y = '';
for(let i = 0; i < x.length; i++) {
if(x[i] === 'm' || 'I') {
y = x.replace(x[i], 's' )
}
}
console.log(y)
ok, there are a couple of gotchas that make your code interesting
x[i] === 'm' || 'I' is always true, because 'I' is truthy - if that's not clear, you can test this with if ('I') { console.log('Merry Christmas') }
your loop produces a new string with one replacement every loop, i.e. it produces the same result as no loop and
y = x.replace(x[x.length - 1], 's')
the replace will replace the first matching character - the last character in your string is k, so the replace will change the first matching k to s
so, the result of your code is
'Hello I lise milk'
Hope that helps clear things up!
btw, the easiest way to replace all ms and Is with an s:
console.log(x.replace(/[mI]/g, 's'))
So you basically are running into an issue with the way your code is flowing.
Let's start with issue one: Why is the m being overwritten but not the y?
So basically you have var x and y that you are updating throughout your loop.
The way your code works is basically: If the letter equals m or I replace it with an s.
The problem you are going to have here however is you never store the value that has since been updated. So when it loops again it is taking the default value of x (which hasn't actually been updated) and is writing it to y. This is going to overwrite the value each time.
We can demo this by simply logging inside of the loop.
let x = 'Hello I like milk';
let y = '';
for(let i = 0; i < x.length; i++) {
if(x[i] === 'm' || x[i] === 'I') {
y = x.replace(x[i], 's' )
console.log(y)
}
}
So if you run the above, you will see two lines being outputted.
Hello s like milk
Hello I like milk
The m is the only one being printed however because the log is after the final update.
So the next issue: Why is replacing that k?
As another commented posted, "I" is always going to be truthy. Truthy basically means the value isn't null, undefined, 0 etc. "I" has a value which means it will always be true.
So is the K being replaced? Well if we run that code, the final letter being checked and replaced is a k. .replace only replaces (by default) the first instance of that letter it comes across. In your case, that K is the first K that is seen.
So to fix it, don't check on "I" check: x[i] === "I"
EDIT: To answer your question about why the last letter matters
So the last letter matters here because you have what basically equates to:
if("I"){}
So that above snippet, contrary to what you may think actually means if this has a value, which because I is a valid character, will always report true. So for your loop, everything is actually being checked, regardless of the character because I is always going to be true.
Here is an easy way to check it:
Lets say I have an array of integers from 1 to 10. I have (pseudo code):
if array value < 10 OR I
Print that value
With the way you are currently thinking, you would expect it to stop printing if the values are less than 10 right? Nope! Once again because I is always truthy and we are saying OR the value I (true) so we are going to always get a print!
Code example:
var x = [0, 1, 2, 3, 4 , 50, 60, 70, 80];
for(var i = 0; i < x.length; i++){
if(x[i] < 10 || "I") {
console.log(x[i]);
}
}
See? Everything prints out! Even though half of the values are over 10 they are still printing out. Why? Because "I" is always true! Now let's edit that a bit to make it a bit more strict in checking:
let x = [0, 1, 2, 3, 4 , 50, 60, 70, 80];
for(var i = 0; i < x.length; i++){
if(x[i] < 10 || x[i] === "I") {
console.log(x[i]);
}
}
See? Much better :)
Greetings Stack Overflow!
First off, this is my first question!
I am trying to solve the selfDividingNumbers algorithm and I ran into this interesting problem. This function is supposed to take a range of numbers to check if they are self dividing.
Self Dividing example:
128 is a self-dividing number because
128 % 1 == 0, 128 % 2 == 0, and 128 % 8 == 0.
My attempt with Javascript.
/*
selfDividingNumbers( 1, 22 );
*/
var selfDividingNumbers = function(left, right) {
var output = [];
while(left <= right){
// convert number into an array of strings, size 1
var leftString = left.toString().split();
// initialize digit iterator
var currentDigit = leftString[0];
for(var i = 0; i < leftString.length; i++){
currentDigit = parseInt(leftString[i])
console.log( left % currentDigit );
}
// increment lower bound
left++;
}
return output
};
When comparing the current lower bound to the current digit of the lower bound, left % currentDigit it always produces zero! I figure this is probably a type error but I am unsure of why and would love for someone to point out why!
Would also like to see any other ideas to avoid this problem!
I figured this was a good chance to get a better handle on Javascript considering I am clueless as to why my program is producing this output. Any help would be appreciated! :)
Thanks Stack Overflow!
Calling split() isn't buying you anything. Remove it and you'll get the results you expect. You still have to write the code to populate output though.
The answer by #Joseph may fix your current code, but I think there is a potentially easier way to go about doing this. Consider the following script:
var start = 128;
var num = start;
var sd = true;
while (num > 0) {
var last = num % 10;
if (start % last != 0) {
sd = false;
break;
}
num = Math.floor(num / 10);
}
if (sd) {
print("Is self dividing");
}
else {
print("Is NOT self dividing");
}
Demo
To test each digit in the number for its ability to cleanly divide the original number, you can simply use a loop. In each iteration, check num % 10 to get the current digit, and then divide the number by ten. If we never see a digit which can not divide evenly, then the number is not self dividing, otherwise it is.
So the string split method takes the string and returns an array of string parts. The method expects a parameter, however, the dividing element. If no dividing element is provided, the method will return only one part, the string itself. In your case, what you probably intended was to split the string into individual characters, which would mean the divider would be the empty string:
var leftString = left.toString().split('');
Since you are already familiar with console.log, note that you could also use it to debug your program. If you are confused about the output of left % currentDigit, one thing you could try is logging the variables just before the call,
console.log(typeof left, left, typeof currentDigit, currentDigit)
which might give you ideas about where to look next.
I'm totally not a Math whiz kid here, but have put together a function with the great help of StackOverflow (and a lot of trial and error) that generates a random serial number from a Formula, group of Letters/Numbers, and array (so as to not duplicate values).
So, my current formula is as follows:
$.extend({
generateSerial: function(formula, chrs, checks) {
var formula = formula && formula != "" ? formula : 'XXX-XXX-XXX-XXX-XXX', // Default Formula to use, should change to what's most commonly used!
chrs = chrs && chrs != "" ? chrs : "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", // Default characters to randomize, if not defined!
len = (formula.match(/X/g) || []).length,
indices = [],
rand;
// Get all "-" char indexes
for(var i=0; i < formula.length; i++) {
if (formula[i] === "-") indices.push(i);
}
do {
rand = Array(len).join().split(',').map(function() {
return chrs.charAt(Math.floor(Math.random() * chrs.length));
}).join('');
// Rebuild string!
if (indices && indices.length > 0)
{
for(var x=0; x < indices.length; x++)
rand = rand.insert(indices[x], '-');
}
} while (checks && $.inArray(rand, checks) !== -1);
return rand;
}
});
Ok, so, what I need to be able to do is to find total possible values and make sure that it is possible to generate a unique serial number before actually doing so.
For example:
var num = $.generateSerial('XX', 'AB', new Array('AB', 'BA', 'AA', 'BB'));
This will cause the code to do an infinite loop, since there are no more possibilties here, other than the ones being excluded from the extension. So this will cause browser to crash. What I need to be able to do here is to be able to get the number of possible unique values here and if it is greater than 0, continue, otherwise, don't continue, maybe an alert for an error would be fine.
Also, keep in mind, could also do this in a loop so as to not repeat serials already generated:
var currSerials = [];
for (var x = 0; x < 5; x++)
{
var output = $.generateSerial('XXX-XXX-XXX', '0123456789', currSerials);
currSerials.push(output);
}
But the important thing here, is how to get total possible unique values from within the generateSerial function itself? We have the length, characters, and exclusions array also in here (checks). This would seem more like a math question, and I'm not expert in Math. Could use some help here.
Thanks guys :)
Here is a jsFiddle of it working nicely because there are more possible choices than 16: http://jsfiddle.net/qpw66bwb/1/
And here is a jsFiddle of the problem I am facing: Just click the "Generate Serials" button to see the problem (it continuously loops, never finishes), it wants to create 16 serials, but 16 possible choices are not even possible with 2 characters and only using A and B characters: http://jsfiddle.net/qpw66bwb/2/
I need to catch the loop here and exit out of it, if it is not able to generate a random number somehow. But how?
The number of possible serials is len * chrs.length, assuming all the characters in chrs are different. The serial contains len characters to fill in randomly, and chrs.length is the number of possible characters in each position of that.
I'm starting to learn javascript and I basically needed a countup that adds an x value to a number(which is 0) every 1 second. I adapted a few codes I found on the web and came up with this:
var d=0;
var delay=1000;
var y=750;
function countup() {
document.getElementById('burgers').firstChild.nodeValue=y+d;
d+=y;
setTimeout(function(){countup()},delay);
}
if(window.addEventListener){
window.addEventListener('load',countup,false);
}
else {
if(window.attachEvent){
window.attachEvent('onload',countup);
}
}
There's probably residual code there but it works as intended.
Now my next step was to divide the resultant string every 3 digits using a "," - basically 1050503 would become 1,050,503.
This is what I found and adapted from my research:
"number".match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
I just can't find a way to incorporate this code into the other. What should I use to replace the "number" part of this code?
The answer might be obvious but I've tried everything I knew without sucess.
Thanks in advance!
To use your match statement, you need to convert your number to a String.
Let's say you have 1234567.
var a = 1234567;
a = a + ""; //converts to string
alert(a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(","));
If you wish, you can wrap this into a function:
function baz(a) {
a = a + "";
return a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
}
Usage is baz(1234); and will return a string for y our.
While I do commend you for using a pattern matching algorithm, this would probably be easier to, practically speaking, implement using a basic string parsing function, as it doesn't look anywhere as intimidating from just looking at the match statement.
function foo(bar) {
charbar = (""+bar).split(""); //convert to a String
output = "";
for(x = 0; x < charbar.length; x++) { //work backwards from end of string
i = charbar.length - 1 - x; //our index
output = charbar[i] + output; //pre-pend the character to the output
if(x%3 == 2 && i > 0) { //every 3rd, we stick in a comma, except if it is not the leftmost digit
output = ',' + output;
}
}
return output;
}
Usage is basically foo(1234); which yields 1,234.
I'm trying to build a function that adds up all the numbers within a string... for example, 'dlsjf3diw62' would end up being 65.
I tried to be clever and put together a recursive function:
function NumberAddition(str) {
var numbers='1234567890';
var check=[];
str=str.split[''];
function recursive(str,check) {
if (str.length==0)
return check;
else if (numbers.indexOf(str[0])>=0)
{
for (i=0;i<str.length;i++){
if (numbers.indexOf(str[i])<0)
check.push(str.slice(0,i));
str=str.slice(i);
return recursive(str,check);
}
}
else
str.shift();
return recursive(str,check);
}
You'll see that I'm trying to get my numbers returned as an array in the array named check. Unfortunately, I have a maximum call stack size exceeded, and I'm not sure why! The recursion does have a base case!! It ends once str no longer has any contents. Why wouldn't this work? Is there something I'm missing?
-Will
You can achieve the same thing with a far easier solution, using regular expressions, as follows:
var str = 'dlsjf3diw62';
var check = str.match(/\d+/g); // this pattern matches all instances of 1 or more digits
Then, to sum the numbers, you can do this:
var checkSum = 0;
for (var i = 0; i < check.length; i++) {
checkSum += parseInt(check[i]);
}
Or, slightly more compact:
var checkSum = check.reduce(function(sum, num){ return sum + parseInt(num) }, 0);
The reason your recursion doesn't work is the case where you do enter the for loop, because you've found a digit, but the digits continue to the end of the string. If that happens, the return inside the for loop never happens, and the loop ends. After that, the .shift() does not happen, because it's in that else branch, so you return re-process the same string.
You shouldn't solve this particular problem that way, but the code makes a good example of the anti-pattern of having return statements inside if bodies followed by else. Your code would be clearer (and would work) if it looked like this:
function recursive(str, check) {
if (str.length == 0)
return check;
if (numbers.indexOf(str[0]) >= 0) {
// Find the end of the string of digits, or
// the end of the whole thing
for (var i = 0; i < str.length && numbers.indexOf(str[i]) >= 0; i++);
check.push(str.slice(0, i));
str = str.slice(i);
return recursive(str, check);
}
// A non-digit character
str.shift();
return recursive(str, check);
}
In that version, there are no else clauses, because the two if clauses always involve a return. The for loop is changed to simply find the right value of "i" for the subsequent slicing.
edit — one thing this doesn't fix is the fact that you're pushing arrays into your "check" list. That is, the substring "62" would be pushed as the array ["6", "2"]. That's not a huge problem; it's solved with the addition of a .join() in the right place.