jellybean_232
jellybean_232

Reputation: 189

Haskell - Trying to create a function to find the factorial of odd numbers

fact :: Int -> Int 
fact n
    |n < 0 = 0
    |n == 0 = 1
    |n > 0 && n `mod` 2 == 1 = fact (n-1) * n
    |n > 0 && n `mod` 2 == 0 = n-1

When I enter an odd number for example: fact 5 will give 15, as it should 1 * 3 * 5 = 15. However I realized that if I do fact 7 or any other odd number, it only multiplies the first two odd numbers. How do I get the function to multiply all the odd numbers and not just the first 2. Eg. fact 7 = 35 (ie. 3 * 5). Also note, that if an even number is entered, it will work out the factorial of all the odd numbers up until and not including the even number.

Upvotes: 2

Views: 1142

Answers (2)

Aaron Roth
Aaron Roth

Reputation: 456

This reminds me of the famous Evolution of a Haskell Programmer. Paraphrasing the tenured professor's answer:

factorialOfOdds :: Integer -> Integer
factorialOfOdds n = product [1,3..n]

Upvotes: 4

daniel gratzer
daniel gratzer

Reputation: 53901

You're problem is that your case for an even number is n-1, which means that when you get to an odd number you're really just doing

n * (n - 1 - 1)

When what you want is

n * n-2 * n-4 ...

So try this instead

fact :: Integer -> Integer -- Overflows 
fact n
    |n < 0 = 0
    |n == 0 || n == 1 = 1
    |n `mod` 2 == 1 = fact (n-2) * n
    |n `mod` 2 == 0 = fact (n-1)

I also took the liberty of removing some redundant logic. Here we decrement by two if it's odd, so 5 -> 3. And in the even case we decrement by one to end up on an odd number and that recurse on that.

Upvotes: 3

Related Questions