I'm a Staff Software Engineer at Cisco. I specialize in Python and Go, building functional, practical, and maintainable web systems leveraging Kubernetes and the cloud. Blog opinions are my own.
How does this look? I initially had happy memoizing previous numbers, but it seemed like it ran fast enough without it, and the memoizing cluttered things up.
Also, I didn't know about the digits method until now! :)
Looking at your solution it actually fails later in the mix. I was pretty sure you couldn't rely on the numbers not adding up to a single digit happy number (which the only other one beyond 1 is 7.)
1111111 is a happy number which will become 7 after the first iteration and 7 is a happy number. This fails your current function. Here is an updated one that would work by testing if these ever hit 4 instead of length of 1.
function isHappy(n) {
const u = n.toString().split('').reduce(((ac,cv) => ac + Math.pow(cv,2)), 0);
if (u === 1) return true;
if (u === 4) return false;
else return isHappy(u);
}
-- core function; read from bottom to topf::Int->Intf=sum-- Sum up the squares.map((^2)-- Compute squares.read-- Convert digit strings to Ints.(:[]))-- Explode number string to list of digit strings.show-- Convert input number to string-- This is a folding pattern with a tricky break condition,-- depending on the list element and the accumulator.foldP::(a->b->b)->(a->b->Bool)->b->[a]->bfoldPfpacc[]=accfoldPfpacc(x:xs)|pxacc=acc|otherwise=foldPfp(fxacc)xs-- Cut off a list's tail, once a number is repeating.-- (reverts the preserved part of the list)cut::Eqa=>[a]->[a]cut=foldP(:)elem[]-- fold by appending and checking if x is already in list-- Iterate the core function, cut the result list and check if the final-- result is 1.isHappy::Int->BoolisHappy=(==1).head.cut.iteratefmain=print$filterisHappy[1..200]
Note that Haskell function composition with the (.) operator is read from right to left (or from bottom to top, respectively). The hardest part for FP is folding with a non-trivial break condition, here.
And now that I have learned a simpler break condition for the problem, it is easier:
f::Int->Intf=sum-- Sum up the squares.map((^2)-- Compute squares.read-- Convert digits to Ints.(:[]))-- Explode number string to list of digit strings.show-- Convert input number to stringisHappy::Int->BoolisHappyn|n==4=False|n==1=True|otherwise=isHappy(fn)main=print$filterisHappy[1..200]
On the other hand, I like the possibility of my original code to see the list of intermediate results to get a feeling for the problem.
Elm solution which does not use strings. Hopefully quite understandable.
sumDigitSquaressumnum=ifnum==0then-- exit condition, processed all digitssumelseletdigit=remnum10-- get right-most digitsquare=digit*digitnewNum=num//10-- remove right-most digitinsumDigitSquares(sum+square)newNumisHappyi=if0<=i&&i<=9then-- exit condition, single digit numberi==1||i==7elseletsum=sumDigitSquares0iinisHappysum
Two recursive functions. Exit conditions are getting a number between 0 and 9. Zero is impossible to actually get from other numbers, but there if someone input 0. The only happy numbers in that range are 1 and 7. Should work with negative numbers too.
Here is a runnable solution with UI to test a range of numbers. Try it at elm-lang.org/try.
importHtmlexposing(..)importHtml.Attributesexposing(..)importHtml.Eventsexposing(..)importTaskimportResultsumDigitSquaressumnum=ifnum==0thensumelseletdigit=remnum10square=digit*digitnewNum=num//10insumDigitSquares(sum+square)newNumisHappyi=if0<=i&&i<=9theni==1||i==7elseletsum=sumDigitSquares0iinisHappysumcalculateUpToi=List.range1i|>List.filterisHappy|>CalculateCompletedi-- UItypeMsg=NumberInputString|CalculateInt|CalculateCompletedInt(ListInt)typeCalculation=NotStarted|CalculatingInt|CalculatedInt(ListInt)typealiasModel={userInput:String,validatedNumber:ResultStringInt,calculation:Calculation}init={userInput="",validatedNumber=Err"",calculation=NotStarted}![]updatemsgmodel=casemsgofNumberInputs->{model|userInput=s,validatedNumber=String.toInts}![]Calculatei->{model|calculation=Calculatingi}![Task.performcalculateUpTo(Task.succeedi)]CalculateCompletedilist->{model|calculation=Calculatedilist}![]viewmodel=div[][div[][text"Check for happy numbers up to"],div[][input[type_"text",onInputNumberInput,valuemodel.userInput][]],div[][casemodel.validatedNumberofErrerr->button[type_"button",disabledTrue][text"Calculate"]Oki->button[type_"button",onClick(Calculatei)][text"Calculate"]],casemodel.calculationofNotStarted->text""Calculatingi->div[][hr[][],text("Calculating up to "++toStringi)]Calculatedilist->div[]([hr[][],div[][text("Happy numbers up to "++toStringi)]]++List.map(\num->div[][text(toStringnum)])list)]main=Html.program{init=init,view=view,update=update,subscriptions=\_->Sub.none}
A work in two parts. First, Happy.pm, a Perl5 Module.
packageHappy;usestrict;usewarnings;useutf8;usefeatureqw{ postderef say signatures state };nowarningsqw{ experimental::postderef experimental::signatures };useCarp;useExporterqw( import );useList::Utilqw( sum0 );our@EXPORT=qw( is_happy );our%EXPORT_TAGS=('all'=>[@EXPORT],);our@EXPORT_OK=(@{$EXPORT_TAGS{'all'}});our$VERSION=0.0.1;sub is_happy( $number ) {croak'Not a number'if$number=~m{\D};croak'Not anything'if!defined$number;my%done;while($number!=0&&$number!=1){return0if$done{$number};my$output=sum0map{$_**2}splitm{},$number;$done{$number}=$output;$number=$output;}return$number;}1;
Which is called by a program.
#!/usr/bin/env perl
use strict ;
use warnings ;
use utf8 ;
use feature qw{ say } ;
use lib '/home/jacoby/lib' ;
use Happy ;
for my $i ( 0 .. 1_000_000 ) {
say $i if is_happy( $i ) ;
}
Not particularly golfy, because I like reading and understanding things.
I'm glad to see some Haskell here. :) I somehow prefer your computational approach to split the number over my quick string hack. You can easily change the base.
I have done a lot of parsing stuff in Haskell with parsec, attoparsec and readP, lately. So I instantly think of parsing when I see the problem of splitting a number into digits. The detour via strings is comfortable, because it uses the read parser. but
"Challenge" accepted to solve it computationally. :)
To import as few / basic libraries as reasonably achievable, I decided not to use the parsec library but to write a homemade digit parser.
What you do in splitNum reminds me of the quotRem function (that I found when I coded for the Challenge about Kaprekar numbers, here). quotRem just needs a swap to make for a nice digit parser in a very organic way: When dividing by 10 the integer quotient is the state of the state monad (that's still to parse) and the remainder is a parsed digit.
importControl.Monad.StateimportControl.Monad.Loops(untilM)swap::(a,b)->(b,a)swap(x,y)=(y,x)-- digit parserdigit::Integrala=>Stateaadigit=state$\s->swap$quotRems10-- eof conditioneof::Integrala=>StateaBooleof=get>>=\s->return$s==0-- parsing the digits of a number into a (reversed) list of digitsdigits::Integrala=>a->[a]digits=evalState(digit`untilM`eof)-- core functionf=sum.map(^2).digits-- iteration of f by recursion of isHappy isHappyn|n==4=False|n==1=True|otherwise=isHappy(fn)
I am a bit biased to use (faster) Ints in my prototypes, and use Integers where really needed, but I adopt your approach with Integers by at least generalizing the code to Integral types.
Although I learned to prefer folds over homemade recursion, I'm afraid the abstractness of foldP is a little bit hard to read, so perhaps I stick with the homemade recursion, this time. :)
Here's a golang implementation, optimized for speed. It takes about 200ms on my machine to find all the happy numbers from 1 to a million on my machine if you take out the prints.
sub happy($value) {
state %cache = ( 1 => True );
my $summed = [+] ($value.comb.map(*²));
return %cache{$summed} with %cache{$summed};
%cache{$summed} = False;
%cache{$summed} = happy($summed);
};
(1..200)>>.&{ happy($_)&&.say }
Here's my previously golfed version in perl6 made slightly more readable. Includes a state based cache to reduce recursion. The final line prints the happy numbers up to 200 (well up to the last befor 200)
defis_happy?(number)tmp=[]while(number>1)&&(!tmp.include?(number))tmp<<number# with ruby >=2.4 you can use number.digitsdigits=number.to_s.chars.map(&:to_i)number=digits.inject(0){|total,value|total+=value**2}endnumber==1end
We're a place where coders share, stay up-to-date and grow their careers.
Here is a nice solution in JavaScript:
Then you can play with generators for instance:
Another quick PHP one. Betting there is a more performant method but will leave that to someone else. :)
How does this look? I initially had happy memoizing previous numbers, but it seemed like it ran fast enough without it, and the memoizing cluttered things up.
Also, I didn't know about the digits method until now! :)
e: updated to work with all happy numbers
Your code in ES2016+ (and a bit less readable):
You could even shorten the
toStringby replacing it with a template string which will do an implicittoString.Looking at your solution it actually fails later in the mix. I was pretty sure you couldn't rely on the numbers not adding up to a single digit happy number (which the only other one beyond 1 is 7.)
1111111 is a happy number which will become 7 after the first iteration and 7 is a happy number. This fails your current function. Here is an updated one that would work by testing if these ever hit 4 instead of length of 1.
Hmmm, good catch :D Although the fact you found all the sad numbers end in 4 is even more interesting to me.🤔🤔
I read the wikipedia article cause I was like "wait if it's not happy wouldn't that go in to an infinite loop?" :)
Adding a solution in Haskell:
Note that Haskell function composition with the (.) operator is read from right to left (or from bottom to top, respectively). The hardest part for FP is folding with a non-trivial break condition, here.
And now that I have learned a simpler break condition for the problem, it is easier:
On the other hand, I like the possibility of my original code to see the list of intermediate results to get a feeling for the problem.
A simple Rust Solution
Elm solution which does not use strings. Hopefully quite understandable.
Two recursive functions. Exit conditions are getting a number between 0 and 9. Zero is impossible to actually get from other numbers, but there if someone input 0. The only happy numbers in that range are 1 and 7. Should work with negative numbers too.
Here is a runnable solution with UI to test a range of numbers. Try it at elm-lang.org/try.
The obvious pythonic way:
Jokes aside, here's a Python implementation using simple memoization:
Here is my C# implementation:
A work in two parts. First, Happy.pm, a Perl5 Module.
Which is called by a program.
Not particularly golfy, because I like reading and understanding things.
I'm glad to see some Haskell here. :) I somehow prefer your computational approach to split the number over my quick string hack. You can easily change the base.
I have done a lot of parsing stuff in Haskell with parsec, attoparsec and readP, lately. So I instantly think of parsing when I see the problem of splitting a number into digits. The detour via strings is comfortable,
because it uses the read parser.but"Challenge" accepted to solve it computationally. :)
To import as few / basic libraries as reasonably achievable, I decided not to use the parsec library but to write a homemade digit parser.
What you do in splitNum reminds me of the quotRem function (that I found when I coded for the Challenge about Kaprekar numbers, here). quotRem just needs a swap to make for a nice digit parser in a very organic way: When dividing by 10 the integer quotient is the state of the state monad (that's still to parse) and the remainder is a parsed digit.
I am a bit biased to use (faster) Ints in my prototypes, and use Integers where really needed, but I adopt your approach with Integers by at least generalizing the code to Integral types.
Although I learned to prefer folds over homemade recursion, I'm afraid the abstractness of foldP is a little bit hard to read, so perhaps I stick with the homemade recursion, this time. :)
Can’t resist, here’s a solution in Reason: (Try it)
Here's mine in C#. I feel like this could have been way shorter though. Oh well :p
bro log code is not good......
Thanks for letting me know.
What should I change so that my code improves?
your feedback...
your code write is good and logic is also good , but you code very long ,,,
so, listen ,try to write code small, simpal
Here's a golang implementation, optimized for speed. It takes about 200ms on my machine to find all the happy numbers from 1 to a million on my machine if you take out the prints.
Here's my previously golfed version in perl6 made slightly more readable. Includes a state based cache to reduce recursion. The final line prints the happy numbers up to 200 (well up to the last befor 200)
Golang Solution
package main import ( "fmt" "strconv" "strings" ) func isHappyNumber(num int) bool { newNum := 0 switch num { case 1: return true case 4: return false default: s := strconv.Itoa(num) digits := strings.Split(s, "") for _, i := range digits { n, _ := strconv.Atoi(i) newNum += n * n } } return isHappyNumber(newNum) } func main() { fmt.Println(isHappyNumber(94)) }F#
Here is a ruby implementation.