0

How can I execute the following code in a more efficient way in python? The input flags are binary valued. The output depends on all possible permutations of the flag.

def f1():

    return 1

def f2():

    return 2

def f3():

    return 3    


def g(p1, p2, p3):

    if p1 ==  1 & p2 == 0 & p3 == 0:
        f1()

    elif: p1 == 0 & p2 == 1 & p3 == 0:
        f2()

    elif: p1 == 0 & p2 == 0 & p3 == 1:
        f3()

    elif: p1 == 1 & p2 == 1 & p3 == 1:
        f1()
        f2()

and so on.

idjaw
  • 25,487
  • 7
  • 64
  • 83
P. A.
  • 53
  • 5

2 Answers2

3

You can combine the three bits into a single number and then test the value of that number like this:

def g(p1, p2, p3):

   v = (p1 << 2) + (p2 << 1) + p3

    if v == 4: # 100
        f1()
    elif v == 2: # 010
        f2()
    elif v == 1: # 001
        f3()
    elif v == 7: # 111
        f1()
        f2()
Dan D.
  • 73,243
  • 15
  • 104
  • 123
  • 1
    I'd personally use `0b100`/`0b010`/etc. as the constant to make it slightly more obvious, but yeah, I just posted (and then deleted) this exact answer 15 seconds after you. – ShadowRanger Nov 03 '16 at 03:26
1

If you want to use the arguments (p1, p2, p3) as flags, you could always pack those arguments as a list using *args (see this, this and this) and put your functions in a list (yep, Python lets you do that) and get something like:

def f1():
    return 1

def f2():
    return 2

def f3():
    return 3 

def g(*ps):
    functions = [f1, f2, f3]
    for i, p in enumerate(ps):
        if p == 1:  # Could do just `if p:` (0 evaluates to False, anything else to True)
            print(functions[i])()  # Notice the () to actually call the function 

if __name__ == "__main__":
    print("Run 1 0 0")
    g(1, 0, 0)
    print("Run 1 1 0")
    g(1, 1, 0)
    print("Run 0 1 0")
    g(0, 1, 0)
    print("Run 1 1 1")
    g(1, 1, 1)

As per ShadowRanger's comment to this answer, you could even shorten the code a bit more. For instance, using zip:

def g(*ps):
    functions = [f1, f2, f3]
    for function, p in zip(functions, ps):
        if p:
            print(function())

Or using itertools.compress (you'll need to import itertools at the top of your file):

def g(*ps):
    functions = [f1, f2, f3]
    for function in itertools.compress(functions, ps):
        print(function())
Community
  • 1
  • 1
Savir
  • 17,568
  • 15
  • 82
  • 136
  • 2
    Why use `enumerate` when you could just do `for func, p in zip(functions, ps):` and avoid indexing? For that matter, you could simplify even further with `itertools`: `for func in itertools.compress(functions, ps): func()`, avoiding any tests at all (`compress` will return the function corresponding to each truthy `p`). – ShadowRanger Nov 03 '16 at 03:56
  • Very true! As a matter of fact, I didn't even know the `itertools.compress`!! (TIL) **:-)** I did think about the zip... I was trying to deviate as little as I could from the initial code? But you're right: the OP asked for a more efficient way, and those are. – Savir Nov 03 '16 at 04:10
  • 1
    I'm gonna go find one of your answers and upvote it!! **:-D** – Savir Nov 03 '16 at 04:13