0

I am very new to Programming and only started learning Python 3 about 2 wks ago.

Doing an exercise that I found rather difficult, that is designed to create a function that accepts a dictionary as an argument and is supposed to determine if the dictionary represents a "valid" chessboard. Plz note the following codes only address a single aspect of the function. The part I had the greatest struggle with.

I spent quite a bit of time working on this particular project and trying to insure that both options are "valid" code so afaik there are no errors in either?

Imagine a grid (I will print the list) that is supposed to represent the squares on a chessboard. Could someone tell me which code would be deemed as more acceptable? and Why? Or if there is a simpler way I could have done this? I will only post what I feel is "relevant" to my question if more is needed plz lmk.

checks that dictionary keys are valid Chessboard Squares

# acceptable range is columns 1 - 8 rows a - h
for board_squares in dic:
    try:                                # this will accept any value as int
        if (int(board_squares[0:-1]) <= 8  # as slice up to last key char
          and board_squares[-1] <= 'h') \
          is False:
            print((Err) + ' Square outside range')
            return False
    except ValueError as e:
        print((Err) + ' Improper dictionary')
        return False       # when testing function this can be replaced with return False

Important note: In this occurrence I am referring to "board_squares" as the dictionary keys. This is the first code I came up with after a lot of effort. It slices the dictionary key and compares it to what is supposed to be represent a "valid" chessboard square. I got a bit of negative feedback on it so I went back to the drawing board and came up with this code:

def char_range(c1, c2):
    """Generates the characters from `c1` to `c2`, inclusive."""
    for c in range(ord(c1), ord(c2)+1):
        yield chr(c)
        
chessboard_squares = []
for chr1 in range(1, 9):
    for chr2 in char_range('a', 'h'):
        chessboard_squares.append(str(chr1) + chr2)
print(chessboard_squares)   # this is simply to print list so I have a visual representation
for key in dic:
    if key in list \
     is False:
        print((Err) + ' Square outside range')
        return False

Important note: In this occurrence I am referring to chessboard_squares as values in the list that the dictionary keys are compared to. This second code requires the function at the top to range over letters. I tried to insure it was very readable by using clearly defined variable labels. It creates a list of what the "valid dictionary keys should be" to represent Chessboard Squares. And lastly here is the printed list of what the valid dictionary keys "should be". Post is in the format of chessboard squares for clarity.

['1a', '1b', '1c', '1d', '1e', '1f', '1g', '1h', 
 '2a', '2b', '2c', '2d', '2e', '2f', '2g', '2h',
 '3a', '3b', '3c', '3d', '3e', '3f', '3g', '3h',
 '4a', '4b', '4c', '4d', '4e', '4f', '4g', '4h',
 '5a', '5b', '5c', '5d', '5e', '5f', '5g', '5h',
 '6a', '6b', '6c', '6d', '6e', '6f', '6g', '6h',
 '7a', '7b', '7c', '7d', '7e', '7f', '7g', '7h',
 '8a', '8b', '8c', '8d', '8e', '8f', '8g', '8h']
Armagon
  • 58
  • 10

1 Answers1

0

Since I posted this question I've learned a lot of new things and decided to answer my own question. Or if there is a simpler way I could have done this? Here is a much cleaner, and should be considered the "best", option.

    try:
         if all (
            (1 <= int(row) <= 8) and ('a' <= col <= 'h')
            for row, col in dict
          ):
            return True
    except ValueError:
        return False

First we use the all() function that takes ALL the arguments passed to it and returns True if all are True. Empty strings count as a special exception of True.

All our dictionary keys are (supposed to be) 2 character strings which are in themselves iterable, and I can use multiple assignment(aka tuple unpacking) here if I assign exactly as many characters as are in the dictionary key to variables.
In this case we assign the 1st char of the dictionary key to row and the 2nd char of the dictionary key to col(umn).
I can still use try/except ValueError because if the dictionary key isn't exactly 2 characters it will raise the same error and I am checking for specific keys.
A simple understanding short version of a list or generator "comprehension" is
doSomething for variable in iterable this is a "generator comprehension". What we end up with is:
Do something: cmp int(row) to 1 - 8 and col 'a' - 'h'
for: row(1st char of dict key), col(2nd char of dict key)
in: dictionary keys.
Because this is a "generator comprehension" it will create a set of values based off each loop iteration.
and as an example might look something like this: True, False, False, True etc.
These values will in turn be passed to all() that will consume them and return True if ALL are True else False.

here are several resources to help understand the code should anyone wish to look further:
the all function:
https://docs.python.org/3/library/functions.html#all
understanding list comprehension:
https://medium.com/swlh/list-comprehensions-in-python-3-for-beginners-8c2b18966d93
this is great in that it explains "yield" which is vital in understanding generator comprehension:
What does the "yield" keyword do?
Multiple Assignment:
https://treyhunner.com/2018/03/tuple-unpacking-improves-python-code-readability/

Armagon
  • 58
  • 10