-1

Currently working on a small sudoku solver, i use the boolean

if 0 in BOARD_EASY:
  do the thing

having board as this value for testing purposes:

BOARD_EASY =[
    [7,2,5,8,1,3,6,4,9],
    [4,8,6,9,2,7,1,5,3],
    [3,1,9,6,5,4,8,7,2],
    [5,6,4,2,7,1,3,9,8],
    [8,9,1,5,3,9,4,2,7],
    [2,7,3,4,8,9,5,6,1],
    [6,3,8,7,9,5,2,1,4],
    [9,4,2,1,6,8,7,3,5],
    [0,0,7,3,4,2,9,8,6]
]

for some reasons the boolean return false, while there is still 0's in the board, am i missing something? It doesn't seems to check like the the first row of board_easy (i tried by removing the last digit for exemple)

Edit : Allowed me to finish my project, thank y'all ! (https://github.com/Lem0nRavioli/sudoku_solver)

Georgy
  • 12,464
  • 7
  • 65
  • 73
Lem0n
  • 7
  • 3

9 Answers9

4

I believe the in operator doesn't check nested values, just first level.

So it's looking through your list and it's only seeing other lists. See below.

BOARD_EASY =[
    [7,2,5,8,1,3,6,4,9], #-> list
    [4,8,6,9,2,7,1,5,3], #-> list
    [3,1,9,6,5,4,8,7,2], #-> list
    [5,6,4,2,7,1,3,9,8], #-> list
    [8,9,1,5,3,9,4,2,7], #-> list
    [2,7,3,4,8,9,5,6,1], #-> list
    [6,3,8,7,9,5,2,1,4], #-> list
    [9,4,2,1,6,8,7,3,5], #-> list
    [0,0,7,3,4,2,9,8,6]  #-> list
]

So the correct solution would be to loop through the list of lists BOARD_EASY then loop through the contents of each list as such:

for nested_list in BOARD_EASY:
  for items in nested_list:
    if 0 in items:
      print("Found!")
3

I know you already have a response for this, I wanted to share an option that minimize the iteration using any

if any(0 in elem for elem in BOARD_EASY):
    print ('0 is found in BOARD_EASY')
else:
    print ('0 is NOT found in BOARD_EASY')

The importance of any function is that it short-circuits the execution as soon as it finds the value. So it does not iterate through the full list.

Looking at your code, your if statement if 0 in BOARD_EASY: will result in if (0 == BOARD_EASY[0]) or (0 == BOARD_EASY[1]) ...... The list has many elements so the compare is not correct. You need to look for each item in the list and compare the elements in the inner list. With the code above (with any function), it does the trick.

Joe Ferndz
  • 8,417
  • 2
  • 13
  • 33
2

Per the docs for the in operator:

The operators in and not in test for membership. x in s evaluates to True if x is a member of s, and False otherwise.

0 is not a member of BOARD_EASY. The list [0,0,7,3,4,2,9,8,6] is.

So you could do something like:

any(0 in elem for elem in BOARD_EASY)
xgord
  • 4,606
  • 6
  • 30
  • 51
  • If you omit the square brackets, the expression becomes a generator, which would be better if the list is large. – jkr Oct 17 '20 at 03:19
1

BOARD_EASY is a list of lists. BOARD_EASY does not contain a 0...it contains 9 lists.

Here, look:

BOARD_EASY = [
  [7, 2, 5, 8, 1, 3, 6, 4, 9],
  [4, 8, 6, 9, 2, 7, 1, 5, 3],
  [3, 1, 9, 6, 5, 4, 8, 7, 2],
  [5, 6, 4, 2, 7, 1, 3, 9, 8],
  [8, 9, 1, 5, 3, 9, 4, 2, 7],
  [2, 7, 3, 4, 8, 9, 5, 6, 1],
  [6, 3, 8, 7, 9, 5, 2, 1, 4],
  [9, 4, 2, 1, 6, 8, 7, 3, 5],
  [0, 0, 7, 3, 4, 2, 9, 8, 6]
]

for i, x in enumerate(BOARD_EASY):
    print(i+1, x)

Result:

1 [7, 2, 5, 8, 1, 3, 6, 4, 9]
2 [4, 8, 6, 9, 2, 7, 1, 5, 3]
3 [3, 1, 9, 6, 5, 4, 8, 7, 2]
4 [5, 6, 4, 2, 7, 1, 3, 9, 8]
5 [8, 9, 1, 5, 3, 9, 4, 2, 7]
6 [2, 7, 3, 4, 8, 9, 5, 6, 1]
7 [6, 3, 8, 7, 9, 5, 2, 1, 4]
8 [9, 4, 2, 1, 6, 8, 7, 3, 5]
9 [0, 0, 7, 3, 4, 2, 9, 8, 6]

The equivalent code you're looking for checks each list in sequence:

for i, l in enumerate(BOARD_EASY):
    if 0 in l:
        print("There's a zero in row " + str(i + 1))

Result:

There's a zero in row 9
CryptoFool
  • 21,719
  • 5
  • 26
  • 44
1

You could use numpy.flatten:

BOARD_EASY = np.array(BOARD_EASY).flatten()
print("do the thing") if 0 in BOARD_EASY else False

do the thing
David Erickson
  • 16,433
  • 2
  • 19
  • 35
1

I see all answers are iterating through all elements, or copying all of the data, or implementing 3 lines of code to do it, so here is a fast and simple solution:

if 0 in itertools.chain(*BOARD_EASY):
  do the thing

What chain does is it iterates through each item in BOARD_EASY, as if it was iterating through just one list.

zvone
  • 18,045
  • 3
  • 49
  • 77
0

Nested for loops are unnecessary if you are only checking for membership of the element in one of your indices:

for count, i in enumerate(BOARD_EASY):
    if 0 in i:
        print("Found it in index", count)
adlopez15
  • 3,449
  • 2
  • 14
  • 19
0

Board_easy is a list of lists so the first element is [7,2,5...] not 7. You will need a nested for loop to iterate over each dimension

Bugbeeb
  • 2,021
  • 1
  • 9
  • 26
0

Thanks for all the answers, allowed me to understand what was going on with the 'in' operator. Ended up using a line related to the one of David Erickson:

# start of the script
BOARD_EASY = np.array(BOARD_EASY)
#
#
if 0 in np.concatenate(BOARD_EASY):
  do the thing
Lem0n
  • 7
  • 3
  • 1
    Numpy is a great tool which helps speed up some operations on large amounts of data. But if the only reason for using it is to search for something in a nested list, like here, then its usage is not justified. – zvone Oct 17 '20 at 09:28