Find the product of the digits of a number - ocaml

I have to write a recursive function the calculates the product of the digits of a number. What I wrote down is:
let rec digits_product x = if x = 0 then 0 else let n = x mod 10 in n * digits_product (x/10)
The problem is that it always returns me 0. I am sure there is something I miss out but I can not find out. Can you help me solve the problem? The code should calculate the product of the digits of a number, for example if I enter 12345 it should return 12345 which is equal to 120.
UPDATE
I changed the code to this:
let rec digits_product x = match x with | 0 -> 0
| 1 -> 1
| 2 -> 2
| 3 -> 3
| 4 -> 4
| 5 -> 5
| 6 -> 6
| 7 -> 7
| 8 -> 8
| 9 -> 9
| _ -> (x mod 10) * digits_product (x/10)
It works right now, but I have another question: is there a more efficient way to do it?

Your code always makes a recursive call unless the parameter x is 0. Since it doesn't show signs of infinite recursion, you know that it is returning 0 at least once. This should be enough to show what is wrong.
Update
You are checking the input for 0 because the answer is obvious in that case. But there are other inputs where the answer is obvious. I.e., where you don't need to do any multiplications to get the result. Why not check for all of these? You can check for all of these values with just one test.

IMO, the syntax would look cleaner like so:
let rec produsul_cifrelor x =
match x with
| n when n < 10 -> n
| _ -> (x mod 10) * produsul_cifrelor (x/10)
Then running produsul_cifrelor 12345 will return 120.

Related

how to have multiple if statements in Haskell?

like consider the following python code,
n = 4
if n>3 :
n = 5
if n>2 :
n = 6
if n>1 :
n = 4
How to achieve this in haskell??
let n = 4
main :: IO()
main = do
if n>3 then let n = 5
if n>2 then let n = 6
if n>1 then let n = 4
Tried this but gives an error, looking for some modifications
As I commented there are some points of your program you should checkout
else must be used after if
You don't use let for top level declarations (as in let n = 4).
When you write if n>3 then let n=5 you are not changing the value of n because values are inmutables in Haskell
There are a few "idiomatic" ways you can rewrite your program
Use a chained if then else with prints. This is the closest to your code
n = 4 -- no let in top level binding
main :: IO()
main = do
if n>3 then print 5 -- do not use let n=5 because n can't be mutated
else if n>2 then print 6
else if n>1 then print 4
else print ()
Use an external function and guards. This is the most idiomatic
f :: Int -> Int
f x | x > 3 = 5
| x > 2 = 6
| x > 1 = 4
n = 4
main = do
print (f n)
As #davidflecher commented, you can use guards within a let binding
n = 4
main :: IO()
main = do
let x | n > 3 = 5
| n > 2 = 6
| n > 1 = 4
print x
Use MultyWayIf extension (This is more advance as it needs extensions to the language)
{-# LANGUAGE MultiWayIf #-}
n = 4
main :: IO()
main = do
let x = if | n > 3 -> 5
| n > 2 -> 6
| n > 1 -> 4
print x
While the example is a bit contrived, the usual way to encode an if with multiple branches is to use a case-of with () as the scrutinee as follows:
main :: IO()
main = do
case () of
_ | n > 3 -> ...
| n > 2 -> ...
| otherwise -> ...
or when part of a binding, by use of a guarded let
let x | n > 3 = ...
| n > 2 = ...
| otherwise = ...
Alternatively, this may also be encoded as guards of a helper function
f :: Int -> Int
f n | n > 3 = 5
| n > 2 = 6
| otherwise = 4
Updated to include #Iceland_jack's comment

Declaring function using function in F#

I'm trying to understand the following code to declare a function:
let string_of_int = function
| 0 -> "zero"
| 1 -> "one"
| 2 -> "two"
| _ -> "many"
which is the same as
let string_of_int2 x = match x with
|0 -> "zero"
|1 -> "one"
| 2-> "two"
_ -> "many
I understand The second way of declaring the function with is trying to match the input x with several possibilities that it could be. But I don't understand the first way to do it. What does function keyword do?
Also,
what does 'a'..'z' do in the following code?
let is_capital = function
| 'a'..'z' -> false
| 'A'..'Z' -> true
|_ -> failwith "Not a valid letter"
Why can't I have a function like this:
let examplefunc = function
|"string"-> Printf.printf "a string"
|3 -> Printf.print "an integer"
|true-> Printf.printf "a boolean"
|- -> Printf.printf "whatever"
The function keyword is a variant of fun that takes in account that the behavior of the function often directly depends on the value of the argument. For instance, if we start with the following definition of the factorial function:
For a positive integer n, n! is 1 if n = 0, and n * (n-1)! otherwise
then the natural translation to OCaml is
let factorial = function
| 0 (* if n = 0 *) -> 1
| n (* otherwise *) -> n * factorial (n-1)
like you said this strictly equivalent to
let factorial = fun n -> match n with
| 0 (* if n = 0 *) -> 1
| n (* otherwise *) -> n * factorial (n-1)
but when the argument of the function is immediately deconstructed in a pattern matching, it may be more readable to use function directly.
Concerning '0'..'9', those are range pattern that matches all characters (i.e '0'|'1'|'2'|'3'|'4'|..| '9' between the lower and upper bounds (included) of the range (following the ascii ordering of characters)
let is_digit = function '0'..'9' -> true | _ -> false
is_digit '0' (* returns true *);;
is_digit 'a' (* returns false *);;

How do I map each value from one list to another? (Haskell)

This is the code I have so far:
data Suit = Diamond | Club | Heart | Spade
deriving (Read, Enum, Eq, Bounded)
data Rank = Two | Three | Four
| Five | Six | Seven | Eight | Nine | Ten
| Jack | Queen | King | Ace
deriving (Read, Enum, Eq, Ord, Bounded)
and I am trying to map each value, either Rank or Suit to a unique prime number.
primeMapper :: Either Rank Suit -> Int
should be the final function and I want to iterate over each Suit and set it to the first four primes:
primeMapper [Diamond .. Spade] = [2,3,5,7]
and each Rank equal to the rest of the primes up until the 17th:
primeMapper [Two .. Ace] = drop 4 . take 17 $ primes
assuming I have a generating function called primes.
This code, however throws errors obviously because it generates a list from a list. How can I achieve what I am trying to do? Let me know if I can explain it better.
The ultimate goal is to have a hash table that gives unique IDs to each cards based on prime factors, and then generate prime factorization and use modulo to quickly compare poker hands.
Ultimately I solved what I am trying to do by hand as so:
primeMapper :: Either Suit Rank -> Int
primeMapper x = case x of
Left Diamond -> 2
Left Club -> 3
Left Heart -> 5
Left Spade -> 7
Right Two -> 11
Right Three -> 13
Right Four -> 17
Right Five -> 19
Right Six -> 23
Right Seven -> 29
Right Eight -> 31
Right Nine -> 37
Right Ten -> 41
Right Jack -> 43
Right Queen -> 47
Right King -> 53
Right Ace -> 59
... was there a more concise way to do this rather than write each case out by hand?
Your solution using pattern matching is best, though I would prefer
primeMapper :: Either Suit Rank -> Int
primeMapper (Left Diamond) = 2
primeMapper (Left Club) = 3
...
rather than your long case expression.
However you could also use lookup :: Eq a => a -> [(a, b)] -> Maybe b
import Data.Maybe (fromJust)
primeMapper :: Either Suit Rank -> Int
primeMapper = fromJust . flip lookup zippedPrimes
where
zippedPrimes = zip suitranks primes
suitranks = fmap Left suits ++ fmap Right ranks :: [Either Suit Rank]
suits = fromEnum minBound
ranks = fromEnum minBound
Depending on what you plan to use this for, you may not need to use primes or prime factorizations at all; you can get fast conversion to and from plain numbers just by picking one or the other of the suit or rank for a base conversion. Here I'll pick suit -- there are four suits, so take the first digit in base 4 as the suit and the remaining digits as the rank.
encode :: (Suit, Rank) -> Int
encode (s, r) = fromEnum s + 4 * fromEnum r
decode :: Int -> (Suit, Rank)
decode n = (toEnum s, toEnum r) where (r, s) = n `quotRem` 4
You can verify in ghci that this gives a unique number to each card:
> [encode (s, r) | r <- [minBound .. maxBound], s <- [minBound .. maxBound]]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51]
And that they decode appropriately:
> map decode [0..51] == [(s, r) | r <- [minBound .. maxBound], s <- [minBound .. maxBound]]
True
You can adapt some of this I hope.
no2s3s5s = \n -> take n $ scanl (\b a -> a+b) 11 $ cycle [2,4,2,4,6,2,6,4]
rnk = filter (/=49) $ no2s3s5s 14
stv = [2,3,5,7]
_deck = [ b*v | b <- stv, v <- rnk]
_Dia = take 13.drop (0*13) $ _deck
_Clb = take 13.drop (1*13) $ _deck
_Hrt = take 13.drop (2*13) $ _deck
_Spd = take 13.drop (3*13) $ _deck
_Dia
[22,26,34,38,46,58,62,74,82,86,94,106,118]
_Clb
[33,39,51,57,69,87,93,111,123,129,141,159,177]
_Hrt
[55,65,85,95,115,145,155,185,205,215,235,265,295]
_Spd
[77,91,119,133,161,203,217,259,287,301,329,371,413]
_deck
[22,26,34,38,46,58,62,74,82,86,94,106,118,33,39,51,57,69,87,93,111,123,129,141,159,177,55,65,85,95,115,145,155,185,205,215,235,265,295,77,91,119,133,161,203,217,259,287,301,329,371,413]
length _deck
52
Your multiples (_deck) are all unique.
I normally use no2s3s5s with a computed (limited) factor list and the mod function to generate a long prime list.

Out of memory error while calculating sum of multiples of 3 and 5 in Haskell

This is my code:
import Data.Bits
main = print . sum . takeWhile( < 200000) $ multSum 999
multSum m = 3 : multiples [6..m] where
multiples (p:xs)
| ((p `mod` 3 == 0) || (p `mod` 5 == 0)) = p : multiples([p..m])
| otherwise = p : xs
Error: out of memory (requested 1048576 bytes)
Where am I going wrong?
multSum isn't doing what you think it is. Try debugging it directly:
*Main> take 20 $ multSum 999
[3,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6]
multSum returns the infinite list [3,6,6,6,6...] for all arguments, thus it never exceeds 200000 and so the sum you request can't be printed.
try
mults35 m = multiples [3..m] .....
............
....| ...... = p : multiples xs
... | otherwise = multiples xs
there will be one more thing for you to add there. Try this, and you'll see.

Remove duplicates from list

I have datatype:
data SidesType = Sides Int Int Int deriving (Show)
And I need a function which get a list of SidesType and remove duplicates from it.
*Main> let a = [Sides 3 4 5,Sides 3 4 5,Sides 5 12 13,Sides 6 8 10,Sides 6 8 10,Sides 8 15 17,Sides 9 12 15,Sides 5 12 13,Sides 9 12 15,Sides 12 16 20,Sides 8 15 17,Sides 15 20 25,Sides 12 16 20,Sides 15 20 25]
*Main> removeDuplicateFromList [] a
[Sides 3 4 5,Sides 5 12 13,Sides 6 8 10,Sides 6 8 10,Sides 8 15 17,Sides 9 12 15,Sides 5 12 13,Sides 9 12 15,Sides 12 16 20,Sides 8 15 17,Sides 15 20 25,Sides 12 16 20,Sides 15 20 25]
Here is my solution:
removeElementFromList :: [SidesType] -> SidesType -> [SidesType]
removeElementFromList lst element =
let (Sides a b c) = element
in [(Sides x y z) | (Sides x y z) <- lst, (x /= a) || (y /= b)]
removeDuplicateFromList :: [SidesType] -> [SidesType] -> [SidesType]
removeDuplicateFromList inlist outlist
| (length outlist) == 0 = inlist
| otherwise =
let element = head outlist
b = tail outlist
filtered = removeElementFromList b element
in removeDuplicateFromList (inlist ++ [element]) filtered
I am just wondering if there is any other way to write this code in more haskell-way ?
As usual there is "By" function which adds flexibility:
nubBy :: (a -> a -> Bool) -> [a] -> [a]
PS Although it's O(n^2)
You're already deriving Show for your datatype. If you also derive Eq, you can use nub from module Data.List.
Use Data.List.nub
First derive the order class also:
data XYZ = XYZ .... deriving (Show, Eq, Ord)
Or write your on Eq instance:
instance Eq XYZ where
a == b = ...
Then be intelligent and use a Tree! [Computer Science Trees grow from top to bottom!][1]
import qualified Data.Map.Strict as Map
removeDuplicates ::[a] -> [a]
removeDuplicates list = map fst $ Map.toList $ Map.fromList $ map (\a -> (a,a)) list
Complexity (from right to left) for list with length N:
map of the list: O(N)
Map.fromList: O(N*log N)
Map.toList: O(log N)
map over list with list length smaller or equal to N: O(N)
They are called consecutively, this means, there are pluses between the complexities of the parts => O(2 * N + N * log N + log N) = O(N * log N)
This is way better than traversing N^2 times over the list!
See: wolframAlpha plots. I included 2*N also for comparison reasons.
2+3: http://hackage.haskell.org/package/containers-0.5.4.0/docs/Data-Map-Strict.html
[1]: Search wikipedia for Computer Science Tree