### re: Write a script to find "Happy Numbers" VIEW POST

Elm solution which does not use strings. Hopefully quite understandable.

sumDigitSquares sum num =
if num == 0 then -- exit condition, processed all digits
sum
else
let
digit = rem num 10 -- get right-most digit
square = digit * digit
newNum = num // 10 -- remove right-most digit
in
sumDigitSquares (sum + square) newNum

isHappy i =
if 0 <= i && i <= 9 then -- exit condition, single digit number
i == 1 || i == 7
else
let sum = sumDigitSquares 0 i
in isHappy sum


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.

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Result

sumDigitSquares sum num =
if num == 0 then
sum
else
let
digit = rem num 10
square = digit * digit
newNum = num // 10
in
sumDigitSquares (sum + square) newNum

isHappy i =
if 0 <= i && i <= 9 then
i == 1 || i == 7
else
let sum = sumDigitSquares 0 i
in isHappy sum

calculateUpTo i =
List.range 1 i
|> List.filter isHappy
|> CalculateCompleted i

-- UI

type Msg =
NumberInput String
| Calculate Int
| CalculateCompleted Int (List Int)

type Calculation =
NotStarted
| Calculating Int
| Calculated Int (List Int)

type alias Model =
{ userInput : String
, validatedNumber : Result String Int
, calculation : Calculation
}

init =
{ userInput = ""
, validatedNumber = Err ""
, calculation = NotStarted
} ! []

update msg model =
case msg of
NumberInput s ->
{ model
| userInput = s
, validatedNumber = String.toInt s
} ! []

Calculate i ->
{ model | calculation = Calculating i }

CalculateCompleted i list ->
{ model | calculation = Calculated i list } ! []

view model =
div []
[ div [] [ text "Check for happy numbers up to" ]
, div [] [ input [type_ "text", onInput NumberInput, value model.userInput ] [] ]
, div []
[ case model.validatedNumber of
Err err ->
button [ type_ "button", disabled True ] [ text "Calculate" ]
Ok i ->
button [ type_ "button", onClick (Calculate i) ] [ text "Calculate" ]
]
, case model.calculation of
NotStarted ->
text ""

Calculating i ->
div [] [ hr [] [], text ("Calculating up to " ++ toString i) ]

Calculated i list ->
div []
( [ hr [] [], div [] [ text ("Happy numbers up to " ++ toString i) ] ]
++ List.map (\num -> div [] [ text (toString num) ]) list
)

]

main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = \_ -> Sub.none
}

Code of Conduct Report abuse