list comprehension syntax..?

  • Thread starter Gregory Guthrie
  • Start date
G

Gregory Guthrie

Sorry for a simple question- but I don't understand how to parse this use of
a list comprehension.

The "or" clauses are odd to me.

It also seems like it is being overly clever (?) in using a lc expression as
a for loop to drive the recursion.

Thanks for any insight!
Gregory
-------------------------

# http://markbyers.com/moinmoin/moin.cgi/ShortestSudokuSolver

def solve(board):
i=board.find('0') # find next open cell
if i<0: # done if none...
print board; exit("Done")
[ m in [(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3)
or board[j] for j in range(81) ]
or solve(board[:i]+m+board[i+1:]) for m in'%d'%5**18 ]
 
D

Duncan Booth

Gregory said:
Sorry for a simple question- but I don't understand how to parse this
use of a list comprehension.

The "or" clauses are odd to me.

It also seems like it is being overly clever (?) in using a lc
expression as a for loop to drive the recursion.

You are spot on there. It is a list comprehension, but the resulting list
is just thrown away, so using a list comprehension is a complete waste of
time serving only to confuse the issue. Presumably it saved the author a
character or two.

[ exp for var in seq ]

when the result isn't used can be rewritten as:

for var in seq:
exp

and:

exp1 or exp2

when the result is thrown away is just:

if not exp1:
exp2


So:

[ m in [(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3)
or board[j] for j in range(81) ]
or solve(board[:i]+m+board[i+1:]) for m in'%d'%5**18 ]

is equivalent to:

inner = [(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3) or board[j] for j in
range(81) ]
for m in '3814697265625':
if m not in inner:
solve(board[:i]+m+board[i+1:])

(That inner list comprehension doesn't depend on m, so it doesn't need to
be reevaluated each time round the loop except, again, to save a few
characters.)

The '%d'%5**18 looks to be a silly way to iterate through all possible
digits for m even though it does some of them twice while saving one
character over writing range(1,10).

The strange expression I called 'inner' is a list containing the string
value board[j] if j is in the same row, column or block as i, or an integer
for any other cells. So 'm not in inner' is true only if the value for m is
not already used in that row column or block and is therefore a possible
candidate for that location in the board.
 
G

Gary Herron

Gregory said:
Sorry for a simple question- but I don't understand how to parse this use of
a list comprehension.

The "or" clauses are odd to me.

It also seems like it is being overly clever (?) in using a lc expression as
a for loop to drive the recursion.

Thanks for any insight!
Gregory
-------------------------

# http://markbyers.com/moinmoin/moin.cgi/ShortestSudokuSolver

def solve(board):
i=board.find('0') # find next open cell
if i<0: # done if none...
print board; exit("Done")
[ m in [(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3)
or board[j] for j in range(81) ]
or solve(board[:i]+m+board[i+1:]) for m in'%d'%5**18 ]

The "or" clause (as you call it) has nothing to do with the list
comprehension.
The syntax being used here is
[ big_expression for m in something]
*and* the big_expression contains an "or" OPERATOR, with a
complex_expression on one side and solve(...) on the other, like this
complex_expression or solve(...)
*and* the complex_expression contains a nested list comprehension like this
m in nested_lc
*and* nested_lc is
[ugly_expression for j in range(81)]
*and* ugly_expression contains another "or" OPERATOR with ...
*and* sigh...

Whoever put this expression together has made something that is
completely unreadable, mostly unmaintainable, and not noticeably more
efficient than code that is readable and maintainable.

Moreover, all the work of creating the outer list seems to be wasted
since that list is just thrown out.

This is worse than "overly clever". Loops are for looping, list
comprehension is for building lists. It is bad programming practice to
use list comprehension for looping.

Hope that helps you,
Gary Herron
 
G

Gregory Guthrie

Very helpful, thanks!!

So I see that it parses as:


m='1'
a="asdf"
b="1234"
print [((m in a) or b) for m in '%d'%1234 ]


I get it.
Thanks,
Greg


Duncan Booth said:
Gregory said:
Sorry for a simple question- but I don't understand how to parse this
use of a list comprehension.

The "or" clauses are odd to me.

It also seems like it is being overly clever (?) in using a lc
expression as a for loop to drive the recursion.

You are spot on there. It is a list comprehension, but the resulting list
is just thrown away, so using a list comprehension is a complete waste of
time serving only to confuse the issue. Presumably it saved the author a
character or two.

[ exp for var in seq ]

when the result isn't used can be rewritten as:

for var in seq:
exp

and:

exp1 or exp2

when the result is thrown away is just:

if not exp1:
exp2


So:

[ m in [(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3)
or board[j] for j in range(81) ]
or solve(board[:i]+m+board[i+1:]) for m in'%d'%5**18 ]

is equivalent to:

inner = [(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3) or board[j] for j in
range(81) ]
for m in '3814697265625':
if m not in inner:
solve(board[:i]+m+board[i+1:])

(That inner list comprehension doesn't depend on m, so it doesn't need to
be reevaluated each time round the loop except, again, to save a few
characters.)

The '%d'%5**18 looks to be a silly way to iterate through all possible
digits for m even though it does some of them twice while saving one
character over writing range(1,10).

The strange expression I called 'inner' is a list containing the string
value board[j] if j is in the same row, column or block as i, or an
integer
for any other cells. So 'm not in inner' is true only if the value for m
is
not already used in that row column or block and is therefore a possible
candidate for that location in the board.
 
C

Claudio Grondi

Gary said:
Gregory said:
Sorry for a simple question- but I don't understand how to parse this use of
a list comprehension.

The "or" clauses are odd to me.

It also seems like it is being overly clever (?) in using a lc expression as
a for loop to drive the recursion.

Thanks for any insight!
Gregory
-------------------------

# http://markbyers.com/moinmoin/moin.cgi/ShortestSudokuSolver

def solve(board):
i=board.find('0') # find next open cell
if i<0: # done if none...
print board; exit("Done")
[ m in [(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3)
or board[j] for j in range(81) ]
or solve(board[:i]+m+board[i+1:]) for m in'%d'%5**18 ]


The "or" clause (as you call it) has nothing to do with the list
comprehension.
The syntax being used here is
[ big_expression for m in something]
*and* the big_expression contains an "or" OPERATOR, with a
complex_expression on one side and solve(...) on the other, like this
complex_expression or solve(...)
*and* the complex_expression contains a nested list comprehension like this
m in nested_lc
*and* nested_lc is
[ugly_expression for j in range(81)]
*and* ugly_expression contains another "or" OPERATOR with ...
*and* sigh...

Whoever put this expression together has made something that is
completely unreadable, mostly unmaintainable, and not noticeably more
efficient than code that is readable and maintainable.

Moreover, all the work of creating the outer list seems to be wasted
since that list is just thrown out.

This is worse than "overly clever". Loops are for looping, list
comprehension is for building lists. It is bad programming practice to
use list comprehension for looping.
Isn't it an advantage considering speed of the execution?
I have just compared the speed of an explicit loop with the speed of a
list comprehension doing the same thing in another context to see it is
much better to use the latter. In board solvers speed is vital, so isn't
it a good practice to use a list comprehension for looping in this
context, anyway?

Claudio
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top