I solved the Hexadecimal problem in Clojure.
As usual I extracted some helpers and played with partial and the thread last macro (->>) to try to make the solution more readable:
You can nitpick my solution here and/or see all the exercises I've done so far in this repository.
Cool to see you code, thanks!
ReplyDeleteTo be a bit picky - I am not sure if it is correct to return 0 if the string is not valid hex? Zero is also a number.
Below is my Haskell solution to this, solving it with the maybe-monad. Not sure what the canonical clojure way would be? Throwing an error, maybe?
Cheers,
Petter
--
import Data.Char
import Data.Functor
import Control.Applicative
toDig :: Char -> Maybe Int
toDig c
| c >= 'a' && c <= 'f' = Just ((ord c) - 87)
| c >= '0' && c <= '9' = Just ((ord c) - 48)
| otherwise = Nothing
toNumList :: [Char] -> [Maybe Int]
toNumList = map (toDig . toLower)
toNumRec :: [Maybe Int] -> Int -> Maybe Int -> Maybe Int
toNumRec [] i acc = acc
toNumRec (f:rest) i acc
| f == Nothing = f
| otherwise = let acc' = (+) <$> acc <*> (pure (*(16^i)) <*> f)
in toNumRec rest (i+1) acc'
toDec str = toNumRec (reverse (toNumList str)) 0 (Just 0)
Thanks Petter.
ReplyDeleteNice solution the Haskell one!
I also found weird to return a zero in case of an invalid hex string.
I did it jut to make the Exercism given tests pass, this one in particular:
(deftest hex-to-int-invalid-hex
(is (= 0 (hexadecimal/hex-to-int "carrot"))))
I'm not sure which is the canonical Clojure way. I'm still a beginner. I guess I'd throw an IllegalArgumentException.
Best regards,
Manuel
Hi again Manuel
ReplyDeleteMaybe the solution is as simpe as returning 'nil - in case you test would pass if you test this value?
Here is a slightly shorter haskell version:
import Data.Char
import Data.Functor
import Control.Applicative
toDig :: Char -> Maybe Int
toDig c
| elem c ['a'..'f'] = Just ((ord c) - 87)
| elem c ['0'..'9'] = Just ((ord c) - 48)
| otherwise = Nothing
toNumList :: [Char] -> [Maybe Int]
toNumList = map (toDig . toLower)
toNumRec :: [Maybe Int] -> Int -> Maybe Int -> Maybe Int
toNumRec [] i acc = acc
toNumRec (f:rest) i acc =
let acc' = liftA2 (\acc f -> ((16^i)*f) + acc) acc f
in toNumRec rest (i+1) acc'
toDec str = toNumRec (reverse (toNumList str)) 0 (Just 0)
Hi Petter
ReplyDeleteYes, nil would be probably much better than an exception.
Best regards,
Manuel