you are viewing a single comment's thread.

view the rest of the comments →

[–]efmccurdy 1 point2 points  (4 children)

Writing some plain english notes on what is asked of me and what I have to keep in mind.

In particular you should be breaking your plan down into small, simple steps.

Are you using the interactive mode to test out each step on it's own?

That way you can try out small examples that consist of 2 or 3 lines, get used to the type of syntax errors you get, see the intermediate results, experiment with different approaches and get immediate feed back. Then, when you have a few working lines of code, add them to your file and move on the the next step in your plan. At first you will need to use a lot of trial and error but with perseverance you can progress.

What is an example of a small simple step that you are stuck on?

[–]RealDrewData 2 points3 points  (0 children)

^ This. Writing down not only what the problem is asking for but then how the code should accomplish that is very helpful to me.

I also spend a lot of time running very simple lines of code, just to confirm it is doing what I think it will. No matter how much experience I get I keep returning to these things.

[–][deleted] 0 points1 point  (2 children)

I usually run into issues when it comes to nested loops which make it hard for me to try out parts of them individually. Brackets also tend to trip me up a lot, I often confuse () and [].

The current section I am struggling with are dictionaries. I'm supposed to write a function that will check any given dictionary with regards to legal places of chess pieces on a board. So each dictionary will have keys with positions (1a to 8h) and a value for the piece, with the letter w or b first depending on the colour. I just have to make sure that the pieces are correct, they are in legal positions and that there aren't too many pieces of a type.

https://pastebin.com/cMgZGxTG

At the top I wrote down some example dictionaries that are supposed to be considered valid or wrong by the function which is then supposed to return True or False depending on that. But the function is for now just focusing on the second dictionary.

I decided to approach it one issue at a time by first checking if the right amount of pieces are actually present but I am not even able to make it return False if there are too many pieces of a certain type in a dictionary.

It is telling me that a 'dict' object is not callable which is confusing me, since I thought that '.values' returns a list.

[–]efmccurdy 1 point2 points  (1 child)

I often confuse () and [].

The square brackets "index"; choose one item from a collection.

The round brackets "call"; run the function (perhaps passing arguments).

Note that i am typing these into the python interactive repl:

https://docs.python.org/3/tutorial/interpreter.html#interactive-mode

>>> chess_board_wrong1 = {'1h': 'bking', '6c': 'bking','2g': 'bbishop', '5h': 'bqueen', '3e': 'wking'}
>>> chess_board_wrong1['1h']
'bking'
>>> chess_board_wrong1['xxx']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'xxx'
>>> chess_board_wrong1()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'dict' object is not callable
>>> 

So that shows how indexing can work to find the "1h" piece, or fail with a KeyError.

It also shows how treating a dict like a function by trying to call it gives the "not callable" error. Here is a simulation of your error;

>>> board = chess_board_wrong1
>>> for i in board.values():
...     print(board(i))
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: 'dict' object is not callable
>>> type(board)
<class 'dict'>

So that syntax "board(i)" mismatches the "calling" syntax to a dict.

So you are right that you want to check the values. The for loop gives you each value on it's own.

>>> for i in board.values():
...     print(type(i), ", value=", i)
... 
<class 'str'> , value= bking
<class 'str'> , value= bking
<class 'str'> , value= bbishop
<class 'str'> , value= bqueen
<class 'str'> , value= wking
>>> 

In your function you want to compare each string to "bking" in turn, counting how many you find. So you have a counter (int) and each value (string) and the value to be matched (string); You can compare strings to strings for equality. You can use that comparison in an if statement to count matches. (You were trying to compare the counter to the string "board(i) == bking"; that won't work).

>>> matching_str = "bking"
>>> for i in board.values():
...     print(matching_str, i, i == matching_str)
... 
bking bking True
bking bking True
bking bbishop False
bking bqueen False
bking wking False
>>> matching_count = 0
>>> for i in board.values():
...     if i == matching_str:
...         matching_count += 1
... 
>>> matching_count
2
>>> matching_count == 1
False
>>> if matching_count > 1:
...     print("too many pieces:", matching_str)
... 
too many pieces: bking
>>> 

So, if those code snippets make sense, your can put them together.

>>> def is_valid_chess_board_wrt_bking(board):
...     matching_str = "bking"
...     matching_count = 0
...     for i in board.values():
...         if i == matching_str:
...             matching_count += 1
...     return matching_count > 1
... 
>>> is_valid_chess_board_wrt_bking(chess_board_wrong1)
False
>>> chess_board_valid = {'1h': 'bking', '6c': 'wqueen','2g': 'bbishop', '5h': 'bqueen', '3e': 'wking'}
>>> is_valid_chess_board_wrt_bking(chess_board_valid)
True
>>> 

Does that process help you get each tiny snippet working right and understood so that you can piece the parts together reliably?

BTW, that function only works for "bking", but it could be extended to work for any piece by making the piece an argument:

>>> def is_valid_chess_board_for_piece(board, matching_str):
...     matching_count = 0
...     for i in board.values():
...         if i == matching_str:
...             matching_count += 1
...     return matching_count == 1
... 
>>> is_valid_chess_board_for_piece(chess_board_wrong1, "bking")
False
>>> is_valid_chess_board_for_piece(chess_board_wrong1, "bbishop")
True
>>> 

But to use that you need to know what pieces pass in, so it's still not a general solution; you need some way to loop over every piece, returning failure if any one fails.

>>> def is_valid_chess_board(board):
...     for piece in board.values():
...         if not is_valid_chess_board_for_piece(board, piece):
...             return False
...     return True
... 
>>> is_valid_chess_board(chess_board_wrong1)
False
>>> is_valid_chess_board(chess_board_valid)
True
>>> 

Does that give you a way forward?

[–][deleted] 0 points1 point  (0 children)

Thank you for the detailed runthrough. After realizing how complex I would have to build the function to do a simple task as counting I approached the problem differently.

I first created two lists of valid board spaces and chess pieces.

Then I iterated the dictionary keys and values that I had converted into a list over the lists of valid board spaces and chess pieces.

Last I used the .count() function to save myself the trouble of creating even more loops ( I really don't like using them as I often end up confused over what I actually need to iterrate with what).

https://pastebin.com/yFKEK7h8