Romeo lingers near the Capulet house to talk with Juliet when she appears in her window. The pair declare their love for one another and intend to marry the next day. With the help of Juliet's Nurse, the lovers arrange to marry when Juliet goes for confession at the cell of Friar Laurence. There, they are secretly married (talk about a short engagement).
Right before they get married, Romeo forgets what he originally planned to say in his vows! He quickly excuses himself to use the chamber pot to come up with something clever and meaningful. Romeo suddenly remembers that before Juliet was in love with him, she was in love with math! He has this vague memory of her saying something about how much she loves numbers that are happy?
Write a function that determines if a number is considered "happy". Per Juliet's description, a happy number is a positive integer that if the sum each individual digit is squared, the result will eventually become 1. Any other number that repeats into an endless cycle is not considered happy and should return false. Complicated, right? Juliet must really love math...
// Input: 19
happyNum(19); // should return true
// Explanation
/*
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1 and therefore happy
*/
// Input: 12
happyNum(12); // should return false
// Explanation
/*
1^2 + 2^2 = 5
5^2 = 25
2^2 + 5^2 = 29
2^2 + 9^2 = 85
8^2 + 5^2 = 89 <--
8^2 + 9^2 = 145
1^2 + 4^2 + 5^2 = 42
4^2 + 2^2 = 20
2^2 + 0^2 = 4
4^2 = 16
1^2 + 6^2 = 37
3^2 + 7^2 = 58
5^2 + 8^2 = 89 // REPEAT and therefore not happy :(
*/
1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, 94, 97, 100, 103, 109, 129, 130, 133, 139, 167, 176, 188, 190, 192, 193, 203, 208, 219, 226, 230, 236, 239, 262, 263, 280, 291, 293, 301, 302, 310, 313, 319, 320, 326, 329, 331, 338, 356, 362, 365, 367, 368, 376, 379, 383, 386, 391, 392, 397, 404, 409, 440, 446, 464, 469, 478, 487, 490, 496, 536, 556, 563, 565, 566, 608, 617, 622, 623, 632, 635, 637, 638, 644, 649, 653, 655, 656, 665, 671, 673, 680, 683, 694, 700, 709, 716, 736, 739, 748, 761, 763, 784, 790, 793, 802, 806, 818, 820, 833, 836, 847, 860, 863, 874, 881, 888, 899, 901, 904, 907, 910, 912, 913, 921, 923, 931, 932, 937, 940, 946, 964, 970, 973, 989, 998, 1000
There should be some sort of loop/recursion happening so that we can keep checking the sum of the squares of the digits for each number. When we do this, there are two cases that could occur:
- The sum of the squares eventually gets to 1 - return true
- The sequence of sums of the squares starts looping, never reaching 1 - return false
We can check for the first case somewhat easily. But what about the second? We don't want to be trapped in an infinite loop! How can we check if we've been here before? How can we check if we've been here before? How can we check if we've been here before?
That's right, we can store previously found sums of squares in some kind of data structure! Since we are only storing the number and don't need a key-value pair, we could use something like a Set. Depending on your approach, you can fold this into your function parameters (in a recursive solution) or declare it and use it within the function itself (iterative solution).
// helper function
function digitSum (n) {
// divides digits into an array. Returns sum of the squares of each digit
return n.toString().split('').map(digit => +digit).reduce((acc, cur) => acc += Math.pow(cur, 2), 0)
}
function isHappy (n) {
let sum = digitSum(n)
const nSet = new Set()
nSet.add(n)
while (sum != 1 && !nSet.has(sum)) {
nSet.add(sum)
const newSum = digitSum(sum)
sum = newSum;
}
if (sum === 1) return true;
if (nSet.has(sum)) return false;
}
function isHappy (n, nSet = new Set()) {
// when recursing, if we have already gotten to this number, we are in an endless cycle - return false :(
if (nSet.has(n)) return false;
// get all digits
const digitsArr = n.toString().split('').map(digit => +digit)
// find sum of squares of digits
const digitSum = digitsArr.reduce((acc, cur) => acc += Math.pow(cur, 2), 0)
// if all squares equal to 1, number is happy!
if (digitSum === 1) return true;
else {
nSet.add(n);
return isHappy(digitSum, nSet)
}
};
"But soft, what light through yonder window breaks? It is the east, and Juliet is the sun. 932, 7, 899, 19, 86. 847? 226, 13, 301, 313, 28, 478, 736!"