On 8/14/2010 10:52 AM, Baba wrote:

for n_nuggets in range(50):
     result1 = can_buy(n_nuggets)
     result2 = can_buy(n_nuggets+1)
     result3 = can_buy(n_nuggets+2)
     result4 = can_buy(n_nuggets+3)
     result5 = can_buy(n_nuggets+4)
     result6 = can_buy(n_nuggets+5)
     if result1!=[] and result2!=[] and result3!=[] and result4!=[] and
result5!=[] and result6!=[]:
      if (n_nuggets+5)-n_nuggets==5:
         print n_nuggets-1
         break

i suppose this can be tweaked to make it shorter? For instance i
wonder if i can do the same with less variable to be defined?

[Other responders have covered a lots of the points I make below. I guess I need to be quicker!]

First, congratulations on getting to a solution! Code can very often be made shorter, although it's not always worth your while to do so. And often, shorter code is less understandable code -- which makes a big difference if you need to revisit the code later on.

Here are some things that can be done with your for-loop:

1. You don't need this "if" test, because it's always true:

      if (n_nuggets+5)-n_nuggets==5:

2. Whenever you find yourself inventing a series of variables like "result1", "result2", "result3", etc., think about using a list instead.

      results = []
      for i in range(6):
          results.append(can_buy(n_nuggets + i))

And to get really fancy, you can use a single "list comprehension" statement to do it all

     results = [can_buy(n_nuggets + i) for i in range(6)]

3. Your "if" statement tests whether all the lists are non-empty. In Python, expressions (a) and (b) are equivalent:

    (a) if result[0] != []
    (b) if result[0]

So your "if" test can be expressed as:

    if (result[0] and result[1] and result[2] and result[3]
         and result[4] and result[5])

(The parentheses are not required by "if", but they *do* enable you
to split the expression across two or more lines.) And you can use the "all" function to rescue this cumbersome statement;

    if all(results)

After all this work, the code is getting pretty short:

    for n_nuggets in range(50):
        results = [can_buy(n_nuggets + i) for i in range(6)]
        if all(results):
            print n_nuggets-1
            break

4. The variable "results" is defined in one statement, and then is used just once, in the very next statement. There's no harm in that, and I think it makes the mode easier to understand, but you can get rid of it:

    for n_nuggets in range(50):
        if all([can_buy(n_nuggets + i) for i in range(6)]):
            print n_nuggets-1
            break

But wait, there's more ... :-) So far, we've just refined the *implementation* of your algorithm. But the algorithm itself could use some work.

* When n_nuggets==0, we compute can_buy(0), can_buy(1), can_buy(2), can_buy(3), can_buy(4), and can_buy(5).

* When n_nuggets==1, we compute can_buy(1), can_buy(2), can_buy(3), can_buy(4), can_buy(5), and can_buy(6).

... and so on. We can use an algorithm in which can_buy(i) is computed just once for each value of i:

    can_buy_count = 0
    n_nuggets = 0
    while n_nuggets < 50:
        if can_buy(n_nuggets):
            can_buy_count += 1
        else:
            can_buy_count = 0

        if can_buy_count == 6:
            print n_nuggets - 6
            break
        else:
            n_nuggets += 1

And here's how you could shorten *this* code:

    ### cbc = "can buy count"
    cbc = 0
    n_nuggets = -1
    while n_nuggets < 50:
        n_nuggets += 1
        cbc = cbc+1 if can_buy(n_nuggets) else 0
        if cbc == 6:
            print n_nuggets - 6
            break

HTH,
John
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to