Looping through an array and look for repeating numbers - javascript

Ok, I've spent almost two days on this problem and I give up.
What I'm trying to do is create an array of random numbers between 0-17, where each number will repeat once - so 36 numbers in total.
I wrote a function to check how many times a number occurs, if it's twice, then it returns false.
It works up until I get an undefined number, then it breaks...
Here's what I have:
var numbers = [];
function checkNumberRepeat(n,o,c){
var count = 0;
for(var i in o){
if(o[i] == n){
count ++;
}
}
if(count == c){
return false;
}else{
return n;
}
}
function makeRand(){
var rand = checkNumberRepeat(Math.floor(Math.random()*18),numbers,2);
if(rand){
return rand;
}else{
makeRand();
}
}
for(var i=0;i<36;i++){
numbers.push(makeRand());
console.log(numbers);
}
I'm pretty sure the problem is happening in my myRand() function
Any idea?
Thanks

You are missing return
return makeRand()
It has no return so returns undefined
UPDATE:
you had another mistake in your code. 0 is falsy so the if (rand) when rand is 0 returns false, hence 0 is never inserted => endless loop
makeRand shoul like this:
function makeRand() {
var rand = checkNumberRepeat(Math.floor(Math.random()*18),numbers,2);
if (rand !== false){
return rand;
} else {
return makeRand();
}
}
updated jsfiddle: http://jsfiddle.net/nayish/c9sk9suc/4/

I would take a different approach.
Create an array of [0,0,1,1,2,2,...17,17]:
var numbers = [];
for(var i = 0 ; i <= 17 ; i++) {
numbers.push(i);
numbers.push(i);
}
Iterate through the array, swapping the current element with a random element:
for(var i = 0 ; i < numbers.length ; i++) {
var rnd= Math.floor(Math.random()*numbers.length),
tmp= numbers[rnd];
numbers[rnd]= numbers[i];
numbers[i]= tmp;
}
Fiddle 1
This could easily be made into a function:
function randomize(start, stop, count) {
var numbers = [];
for(var i = start ; i <= stop ; i++) {
for(var j = 0 ; j < count ; j++) {
numbers.push(i);
}
}
for(var i = 0 ; i < numbers.length ; i++) {
var rnd= Math.floor(Math.random()*numbers.length),
tmp= numbers[rnd];
numbers[rnd]= numbers[i];
numbers[i]= tmp;
}
return numbers;
} //randomize
For your example, you would call it like this:
numbers = randomize(0, 17, 2);
Fiddle 2

Related

How do I add the number to the variable in Javascript?

I need to guess the 4-digit code by this program, but I have no idea why it doesn't work.
I tried to use two for loops to guess all of the numbers from 0 to 9 for 4 digits.
However, the program doesn't print anything.
I wonder how can I add the current value x to the variable result.
function start() {
var secretPasscode = generateRandomPasscode();
// Write your code here
var result = "";
//Loop through for the secretPasscode's length
for(var i = 0; i < secretPasscode.length; i++){
//Put numbers from 0 to 9
for(var x = 0; x < 10; x++){
result = "";
var currNum = x;
//If the current number is right, store it to the result
if(currNum == secretPasscode.charAt(i)){
result += x;
}else{
result = result;
}
}
}
return result;
println(result);
}
function isCorrect(guessCode, correctCode) {
return guessCode == correctCode;
}
// Generates a random 4 digit passcode and returns it as a String
function generateRandomPasscode() {
var randomPasscode = "";
for(var i = 0; i < 4; i++) {
var randomDigit = Randomizer.nextInt(0, 9);
randomPasscode += randomDigit;
}
return randomPasscode;
}

Return maximum length of the sequence of same items within array

I need to write a function called countZeroes, which accepts an array of only 0s and 1s.
The function should return the longest number of 1s in a row.
countZeroes([0,1,0,1,1,0,0,1]) // 2
countZeroes([1,1,1,1,0,1]) // 4
This is what I currently have.
function countZeros(arr){
total = 0
for (let i=0; i < arr.length; i++){
if (arr[i] ===1)
total += 1
}
return total
}
I'm not sure where to go from here. I know I need to compare the right index and the left index. I tried using a nested for loop which didn't work.
You need to reset total to zero when a 0 occur and keep track of the max number of repeated 1s:
function countZeros(arr){
total = 0, max = 0;
for (let i=0; i < arr.length; i++){
if (arr[i] === 1){
total += 1;
if(total>max)
max = total;
}else{
total = 0;
}
}
return max;
}
console.log(countZeros([0,1,0,1,1,0,0,1]));
console.log(countZeros([1,1,1,1,0,1]));
You can join your array and split it using 0 as separator. Resulting array of successive 1 is then sorted from shortest to longest. You can finally get the last item of array using pop():
const countZeroes = (arr) => arr.join('').split(0).sort().pop().length
console.log(countZeroes([1,0,0,1,1,1,1,0,1]))
console.log(countZeroes([0,1,0,1,1,0,0,1]))
Try this:
function countZeros(arr){
let longest = 0; // Initialize longest (0)
let total = 0; // Initialize total (0)
for (let i=0; i < arr.length; i++)
{
if( arr[i] ===1 ) // If 1, increment total
total += 1
if( total > longest ) // If the total so far is longer than longest, save it.
longest = total;
if( arr[i] !== 1 ) // If not 1, reset total; AFTER conditionally saving it.
total = 0;
}
return longest; // Return longest found
}
console.log( countZeros([0,1,0,1,1,0,0,1]) ); // 2
console.log( countZeros([1,1,1,1,0,1]) ); // 4
This will return the longest combination of 1s.
[1,1,1,1,0,1].toString().replace(/,/gi, "").split("0").sort((a, b) => b.length - a.length)[0].length
You can use foreach and counter
g={}
function countZeroes(arr){
var count;
arr.forEach((x,i)=>{
count=g[x]||1
if(x==1&&arr[i-1]==1) {g[x]=count+1}
})
g={}
return count
}
console.log(countZeroes([0,1,0,1,1,0,0,1])) // 2
console.log(countZeroes([1,1,1,1,0,1]));
console.log(countZeroes([1,1,1,1,1,1,1,0,1]));
Here is an approach with array methods.
function count_longest_sequence_of_ones(array){
return array
.reduce( count_sequential_ones, [0])
.sort()
.pop();
function count_sequential_ones(acc, number) {
if( number === 1 ) acc[acc.length-1]++;
else acc.push(0);
return acc;
}
}
console.log(count_longest_sequence_of_ones([0,1,0,1,1,0,0,1]));
console.log(count_longest_sequence_of_ones([1,1,1,1,0,1]));
PS: Looks like you got plenty of answers :). Use the one you find easiest to understand.
function countZeroes(arr) {
let max = 0;
let current = 0;
for(let i=0; i < arr.length; ++i) {
if (arr[i] == 1) {
++current;
}
else { // arr[i] == 0
if (current > max) max = current;
current = 0
}
}
if (current > max) max = current;
return max;
}

Happy numbers - recursion

I have an issue with a recursive algorithm, that solves the problem of finding the happy numbers.
Here is the code:
function TestingFunction(number){
sumNumberContainer = new Array(0);
CheckIfNumberIsHappy(number);
}
function CheckIfNumberIsHappy(number){
var sumOfTheNumbers = 0;
for (var i = 0; i < number.length; i++) {
sumOfTheNumbers += Math.pow(parseInt(number[i]), 2);
}
console.log(sumOfTheNumbers);
if(sumOfTheNumbers == 1){
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
//return true;
} else {
sumNumberContainer.push(sumOfTheNumbers);
if(sumNumberContainer.length > 1){
for (var i = 0; i < sumNumberContainer.length - 1; i++) {
for (var j = i + 1; j < sumNumberContainer.length; j++) {
if(sumNumberContainer[i] == sumNumberContainer[j]){
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
//return false;
}
}
}
}
CheckIfNumberIsHappy(sumOfTheNumbers.toString());
}
}
Algorithm is working ALMOST fine. I've tested it out by calling function with different numbers, and console was displaying correct results. The problem is that I almost can't get any value from the function. There are only few cases in which I can get any value: If the number is build out of ,,0", and ,,1", for example 1000.
Because of that, I figured out, that I have problem with returning any value when the function is calling itself again.
Now I ended up with 2 results:
Returning the
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
which is giving an infinity looped number. For example when the number is happy, the function is printing in the console number one again and again...
Returning the
//return true
or
//return false
which gives me an undefined value
I'm a little bit in check by this problem, and I'm begging you guys for help.
I would take a step back and reexamine your problem with recursion in mind. The first thing you should think about with recursion is your edge cases — when can you just return a value without recursing. For happy numbers, that's the easy case where the sum of squares === 1 and the harder case where there's a cycle. So test for those and return appropriately. Only after that do you need to recurse. It can then be pretty simple:
function sumSq(num) {
/* simple helper for sums of squares */
return num.toString().split('').reduce((a, c) => c * c + a, 0)
}
function isHappy(n, seen = []) {
/* seen array keeps track of previous values so we can detect cycle */
let ss = sumSq(n)
// two edge cases -- just return
if (ss === 1) return true
if (seen.includes(ss)) return false
// not an edge case, save the value to seen, and recurse.
seen.push(ss)
return isHappy(ss, seen)
}
console.log(isHappy(23))
console.log(isHappy(22))
console.log(isHappy(7839))
Here's a simplified approach to the problem
const digits = x =>
x < 10
? [ x ]
: [ ...digits (x / 10 >> 0), x % 10 ]
const sumSquares = xs =>
xs.reduce ((acc, x) => acc + x * x, 0)
const isHappy = (x, seen = new Set) =>
x === 1
? true
: seen.has (x)
? false
: isHappy ( sumSquares (digits (x))
, seen.add (x)
)
for (let n = 1; n < 100; n = n + 1)
if (isHappy (n))
console.log ("happy", n)
// happy 1
// happy 7
// happy 10
// ...
// happy 97
The program above could be improved by using a technique called memoization
Your code is almost correct. You just forgot to return the result of the recursive call:
function TestingFunction(number){
sumNumberContainer = new Array(0);
if (CheckIfNumberIsHappy(number))
console.log(number);
}
function CheckIfNumberIsHappy(number){
var sumOfTheNumbers = 0;
for (var i = 0; i < number.length; i++) {
sumOfTheNumbers += Math.pow(parseInt(number[i]), 2);
}
if(sumOfTheNumbers == 1){
return true;
} else {
sumNumberContainer.push(sumOfTheNumbers);
if(sumNumberContainer.length > 1){
for (var i = 0; i < sumNumberContainer.length - 1; i++) {
for (var j = i + 1; j < sumNumberContainer.length; j++) {
if(sumNumberContainer[i] == sumNumberContainer[j]){
return false;
}
}
}
}
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
}
}
for (let i=0; i<100; ++i)
TestingFunction(i.toString()); // 1 7 10 13 ... 91 94 97
I've got the solution, which was given to me in the comments, by the user: Mark_M.
I just had to use my previous
return true / return false
also I had to return the recursive statement in the function, and return the value of the CheckIfTheNumberIsHappy function, which was called in TestingFunction.
The working code:
function TestingFunction(number){
sumNumberContainer = new Array(0);
return CheckIfNumberIsHappy(number);
}
function CheckIfNumberIsHappy(number){
var sumOfTheNumbers = 0;
for (var i = 0; i < number.length; i++) {
sumOfTheNumbers += Math.pow(parseInt(number[i]), 2);
}
console.log(sumOfTheNumbers);
if(sumOfTheNumbers == 1){
return true;
} else {
sumNumberContainer.push(sumOfTheNumbers);
if(sumNumberContainer.length > 1){
for (var i = 0; i < sumNumberContainer.length - 1; i++) {
for (var j = i + 1; j < sumNumberContainer.length; j++) {
if(sumNumberContainer[i] == sumNumberContainer[j]){
return false;
}
}
}
}
return CheckIfNumberIsHappy(sumOfTheNumbers.toString());
}
}
Thanks for the great support :)

Javascript: function to describe array is skipping most of the actual function and returns undefined?

I am trying to write a single javascript function that will take in a list of numbers as arguments and will output the number of odd number, number of negative numbers, will average the numbers, and will output the median. I believe I basically have completed all of the code, but am either confusing my syntax or am incorrectly returning.
Code:
var arrayAnalyze = function(numbers){
var oddNum = []; //Array of odd numbers
var negNum = []; //Array of negative numbers
var numSum = 0; // Sum of all numbers
var avgNum = 0; //Average of all numbers
var midNum = []; //Median number
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++){
if (numbers[i] % 2 !== 0){
oddNum.push(numbers[i]);
}
}
//Return negative numbers to negNum array
for (i = 0; i < numbers.length; i++){
if (Math.abs(numbers[i]) + numbers[i] === 0){
negNum.push(numbers[i]);
}
}
//Return sum of all numbers to numSum variable
for (i = 0; i < numbers.length; i++){
numSum += i;
}
//Return average of numbers to avgNum variable
avgNum = numSum / numbers.length;
//Return median of numbers to midNum array
numbers.sort(function(a,b){return a - b;});
var evenSplit = Math.floor(numbers.length / 2);
if(numbers.length % 2){
midNum = numbers[evenSplit];
}else{
midNum = (numbers[evenSplit - 1] + numbers[evenSplit]) / 2.0; }
midNum.push();
return "Odds: " + oddNum.length, "Negatives: " + negNum.length, "Average: " + avgNum.toFixed(2), "Median: " + midNum[0];
};
console.log(arrayAnalyze(7, -3, 0, 12, 44, -5, 3));
Output:
TypeError: numbers.sort is not a function
There's a number of errors that you'd want to correct - comments inline
var arrayAnalyze = function (numbers) {
var oddNum = []; //Array of odd numbers
var negNum = []; //Array of negative numbers
var numSum = 0; // Sum of all numbers
var avgNum = 0; //Average of all numbers
var midNum = []; //Median number
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++) {
// always check the element at index, i is just the index
if (numbers[i] % 2 !== 0) {
// return exits the currently running function! (not the block)
oddNum.push(numbers[i]);
}
}
//Return negative numbers to negNum array
for (i = 0; i < numbers.length; i++) {
// exclude 0 here
if (Math.abs(numbers[i]) + numbers[i] === 0 && numbers[i]) {
negNum.push(numbers[i]);
}
}
//Return sum of all numbers to numSum variable
for (i = 0; i < numbers.length; i++) {
numSum += numbers[i];
}
//Return average of numbers to avgNum variable
avgNum = numSum / numbers.length;
//Return median of numbers to midNum array
// if you are using a function you need to invoke it to get it's value
midNum.push((function median(numbers) {
// note that this will actually sort the elements of the array you pass in in-place
numbers.sort(function (a, b) { return a - b; });
var evenSplit = Math.floor(numbers.length / 2);
if (numbers.length % 2) {
return numbers[evenSplit];
} else {
return (numbers[evenSplit - 1] + numbers[evenSplit]) / 2.0;
}
})(numbers));
// use + to concatenate the strings, otherwise it just becomes a bunch of comma separated expressions
return "Odds: " + oddNum.length + ",Negatives: " + negNum.length + ",Average: " + avgNum.toFixed(2) + ",Median: " + midNum[0];
};
// an array is passed in using square brackets
console.log(arrayAnalyze([7, -3, 0, 12, 44, -5, 3]));
when a function hits a return statement it will exit out meaning the any code beneath the return will not get executed.
In your odd number sorter you use the %/Modulus on the counter/index rather than numbers[i] to use it on each element of the numbers array parameter. This also needs fixed when you push to the appropriate results array. I have spotted this same concept being done multiple times throughout the function so I would go back and correct that as it would break a couple things.
Also to give you a tip in the right direction in terms of learning return like other users are saying, let's take a look at this part of your code:
for (i = 0; i < numbers.length; i++){
return numSum += i;
}
You do not need to return numSum as your are returning its value later at the end. Just updated the variable you initialized at the beginning by doing the following (also updated in regards to my suggestion above):
for (i = 0; i < numbers.length; i++){
numSum += numbers[i];
}
You cleary are pretty confused about how the return keyword works; I suggest you to check out some documentation here and here.
As an example, you need to change that piece of code
if (numbers % 2 !== 0){
return oddNum.push(numbers);
}else{
return false;
}
into
if (numbers % 2 !== 0){
oddNum.push(numbers);
}
All the others if structures have the same error.
I believe you have a fundamental misunderstand of what return does. MDN has a page on it: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return#Examples
return interrupts code execution, exits the innermost function and returns a value to the caller.
function myFunction() {
return "foo";
alert("This will never be reached!");
}
alert(myFunction()) // Equivalent to alert("foo").
For example, in your code:
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++){
if (i % 2 !== 0){
return oddNum.push(i); // <- code execution will stop here
}else{
return false; // <- or here, whichever is reached first.
}
}
Which means your loop will never execute for more than one iteration. So when you call
console.log(arrayAnalyze(7, -3, 0, 12, 44, -5, 3));
The first value is odd, so the function will stop at return oddNum.push(i);. And since oddNum.push(i) itself returns nothing (undefined), arrayAnalyze will return undefined too, and the log will be equivalent to
console.log(undefined);
Which is what you are seeing.
In this case the returns are completely unnecessary and the loop should read:
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++){
if (i % 2 !== 0){
oddNum.push(i); // <- now code execution is not interrupted!
}
}
And so on, through the rest of the code.
Also, at the end you declare a function called median:
//Return median of numbers to midNum array
function median(numbers) {
[...]
}
But you never invoke it (calling median(someValue)), which means the code inside it will never be executed either. I haven't checked the code for mathematical correctness, but I believe you should just remove the median declaration and leave its body inside the main arrayAnalyze function.
Your code should look like this :
var arrayAnalyze = function (numbers) {
var oddNum = []; //Array of odd numbers
var negNum = []; //Array of negative numbers
var numSum = 0; // Sum of all numbers
var avgNum = 0; //Average of all numbers
var midNum = []; //Median number
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++) {
if (i % 2 !== 0) {
oddNum.push(numbers[i]);
}
}
//Return negative numbers to negNum array
for (i = 0; i < numbers.length; i++) {
if (Math.abs(numbers[i]) + numbers[i] === 0) {
negNum.push(numbers[i]);
}
}
//Return sum of all numbers to numSum variable
for (numbers[i] = 0; numbers[i] < numbers.length; numbers[i]++) {
numSum += numbers[i];
}
//Return average of numbers to avgNum variable
avgNum = numSum / numbers.length;
//Return median of numbers to midNum array
var newArrayOfNumber = numbers;
newArrayOfNumber.sort();
var evenSplit = Math.floor(newArrayOfNumber.length / 2);
if (newArrayOfNumber.length % 2) {
midNum = newArrayOfNumber[evenSplit];
} else {
midNum = (newArrayOfNumber[evenSplit - 1] + newArrayOfNumber[evenSplit]) / 2.0;
}
return "Odds: " + oddNum.length + ", Negatives: " + negNum.length +", Average: " + avgNum.toFixed(2) +", Median: " + midNum;
};
When you call the function you should pass a array to it, so just add [] to your numbers like this : arrayAnalyze([7, -3, 0, 12, 44, -5, 3])
it should return :"Odds: 3, Negatives: 3, Average: 3.50, Median: 7.5"
When you want to add some number to a array in a for block or a if block, dont use return, just do the operation and if you want to break the for loop, use the line :
Break;
and when you want to access the number in your for loop, you should call the array and not only the i, like this : number[i]
espering that it help you
sorry for my mistakes in writting in english

How to modify this function to return string instead of int

please take a quick look at this function that I have found on the web.
function longestCommonSubstring(string1, string2){
// init max value
var longestCommonSubstring = 0;
// init 2D array with 0
var table = Array(string1.length);
for(a = 0; a <= string1.length; a++){
table[a] = Array(string2.length);
for(b = 0; b <= string2.length; b++){
table[a][b] = 0;
}
}
// fill table
for(var i = 0; i < string1.length; i++){
for(var j = 0; j < string2.length; j++){
if(string1[i]==string2[j]){
if(table[i][j] == 0){
table[i+1][j+1] = 1;
} else {
table[i+1][j+1] = table[i][j] + 1;
}
if(table[i+1][j+1] > longestCommonSubstring){
longestCommonSubstring = table[i+1][j+1];
}
} else {
table[i+1][j+1] = 0;
}
}
}
return longestCommonSubstring;
}
It returns the length of the longest common substring as an int. Now to my question, is it possible to modify this function, so that it returns the actual string instead of just returning the length of the substring, I'm quite new at programming and thought that just modifying this secetion would help if(string1[i]==string2[j]){ push(string1[i]}, but it isn't that easy, because I don't want every single character that is the same in those 2 strings to be added in that array, only those that are exactly the same.
Thanks in advance =)
Well for minimal changes to the existing function you could declare a new variable:
var theCommonString = '';
Then in the middle of the function add a line after this existing one:
longestCommonSubstring = table[i+1][j+1];
that says something like:
theCommonString = string1.substr(i + 1 - longestCommonSubstring,
longestCommonSubstring);
(That i + 1 index may be a little off, I haven't bothered working it out carefully.)
Then at the end just return your new variable instead of the existing one.
Note that if there is more than one common sub string of the same length this will return the last one.
You can just store the whole common substring in the table instead of its length:
function longestCommonSubstring(string1, string2){
// init max value
var longestCommonSubstring = "";
// init 2D array with 0
var table = Array(string1.length);
for(a = 0; a <= string1.length; a++){
table[a] = Array(string2.length);
for(b = 0; b <= string2.length; b++){
table[a][b] = 0;
}
}
// fill table
for(var i = 0; i < string1.length; i++){
for(var j = 0; j < string2.length; j++){
if(string1[i]==string2[j]){
if(table[i][j] == 0){
table[i+1][j+1] = string1[i];
} else {
table[i+1][j+1] = table[i][j] + string1[i];
}
if(table[i+1][j+1].length > longestCommonSubstring.length){
longestCommonSubstring = table[i+1][j+1];
}
} else {
table[i+1][j+1] = 0;
}
}
}
return longestCommonSubstring;
}

Categories

Resources