0

Write a recursive Python function called odd_factorial(x) that for input x (x >= 5) calculates 3 × 5 × 7 × . . . × x, if x is odd; or 3 × 5 × . . . × (x − 1) if x is even.

I have the recursion but I am not quite sure how to ensure x >= 5 for the first loop:

def odd_factorial(x):
    if x%2 == 1:
        if x == 3:
            return 3
        else:
            return x*odd_factorial(x-2)
    else:
        x -= 1
        if x == 3:
            return 3
        else:
            return x*odd_factorial(x-2)
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
user146068
  • 21
  • 1
  • 5
    Personally I'd keep it simple by having two functions. The first is the non-recursive entry point that both converts evens to `x-1` and checks that the input is `>=5`. It then calls the second, which is the recursive function, and is a simpler and cleaner version of the function you already have. – jlb83 Feb 15 '15 at 11:22
  • 1
    are you sure about the condition x>=5 ? – ZdaR Feb 15 '15 at 11:22
  • What should the function return if `x<5`? What is the exit condition? – Ozgur Vatansever Feb 15 '15 at 11:28
  • Remember to accept the most helpful answer to you! – J_mie6 Feb 16 '15 at 15:39

6 Answers6

1

This will be speedier and cleaner as it does not do conditioning in the actual recursion. It is still a function, albeit with another nested in.

def odd_factorial(x):
    def do_fact(x):
        if x == 3:
            return 3

        return x * do_fact(x - 2)

    if x < 5:
        raise ValueError("X must be at least 5")

    if not x % 2:
        x -= 1

    return do_fact(x)

Running:

>>> odd_factorial(5)
15
>>> odd_factorial(6)
15
>>> odd_factorial(7)
105
>>> odd_factorial(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 9, in odd_factorial
    raise ValueError("X must be at least 5")
ValueError: X must be at least 5
>>> odd_factorial(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 9, in odd_factorial
    raise ValueError("X must be at least 5")
ValueError: X must be at least 5

Another way is to return 15 for odd_factorial(5) and odd_factorial(6) directly:

def odd_factorial(x):
    if x < 5:
        raise ValueError("x must be at least 5")
    if x % 2 == 0:
        x -= 1     
    if x == 5:
        return 15
    return x * odd_factorial(x - 2)
0

add an extra check setting a flag so you catch values entered < 5 if it is the first call of the function, you can also remove the else from your code as you can only return any one line at a time:

def odd_factorial(x, flag=True):
    if x < 5 and  flag:
        return "Only numbers >= 5"
    if x % 2: # or if x & 1
        return x * odd_factorial(x - 2, False) if x != 3 else 3
    x -= 1
    return x * odd_factorial(x - 2, False)

In [32]: odd_factorial(5)
Out[32]: 15

In [33]: odd_factorial(3)
Out[33]: 'Only numbers >= 5'

In [34]: odd_factorial(7)
Out[34]: 105
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
0

Use an inner function, saves you an extra parameter:

>>> def odd_factorial(input):
     def odd_factorial_inner(x):
         if x%2 == 1:
             if x == 3:
                 return 3
             else:
                 return x*odd_factorial_inner(x-2)
         else:
             x -= 1
             if x == 3:
                 return 3
             else:
                 return x*odd_factorial_inner(x-2)
     if (input >= 5):
         return odd_factorial_inner(input)
     else:
         print "input is smaller than 5"

>>> odd_factorial(9)
945
>>> odd_factorial(4)
Input is smaller than 5.
Community
  • 1
  • 1
Ofiris
  • 6,047
  • 6
  • 35
  • 58
0

Simply complicated :)

def odd_factorial(x, signal=None):
    if x < 5 and signal==None:
        return "number should be greater than 5"
    else:
        if x%2 == 1:
            if x == 3:
                return 3
            else:
                return x*odd_factorial(x-2, signal="r")
        else:
            x -= 1
            if x == 3:
                return 3
            else:
                return x*odd_factorial(x-2, signal="r")
itzMEonTV
  • 19,851
  • 4
  • 39
  • 49
0

Why not simply change the way it is calculated:

def odd_factorial(x):
    if x%2 == 0:
        x -= 1
    if x == 5:
        return 3*5
    elif x < 5:
        raise ValueError("Input should not be < 5")
    else:
        return x*odd_factorial(x-2)

This is good because you don't repeat yourself as you did before (with the even/odd check) and you still follow the specification!

J_mie6
  • 720
  • 1
  • 9
  • 25
0

Here is a very simple recursive factorial program using just the odd numbers

#Factorial using Recursion
n = int(input("Enter the n value for Factorial:"))
def factorial(n):
if n<=1:
    return 1
else:
    return n*factorial(n-2)

print(factorial(n))
Steffi Keran Rani J
  • 3,667
  • 4
  • 34
  • 56