Problem with using sets and issubset in Python - python

I'm not clear about how my sets needs to be written. The answer I'm getting is False, which means I'm using the issubset type wrong or my sets are not written correctly.
some_cords = {(1, 2), (2, 2), (3, 2)}
line_cords = {((1, 2), (2, 2), (3, 2)), ((1, 3), (2, 3), (3, 3)), ((2, 1), (2, 2), (2, 3)),
((2, 4), (2, 3), (2, 2))}
print(some_cords.issubset(line_cords))
print(any(some_cords in k for k in line_cords))
>>False
>>False
I've tried these two methods but why they're False, I'm not sure. I've also tried writing some_cords and line_cords as tuples rather than sets, i.e.
some_cords = ((1, 2), (2, 2), (3, 2)) but I'm getting the same result. I'm running Python 3.10 in IntelliJ IDE. Thanks for any help.

As written, some_cords is a set with 3 elements, each one is a tuple: (1, 2), (2, 2) and (3, 2). On the other hand, line_cords is a set of 4 tuples, each tuple being a tuple of length 3.
Adding parenthesis around the tuples of some_cords will turn it into a set with one element similar to the ones of line_cords:
some_cords = {((1, 2), (2, 2), (3, 2))}
and the first test will return True
As for the second test (using in), some_cords is a set, and each element of line_cords is a tuple, so it will always return False. This test would be OK if some_cords was a tuple: you can achieve this removing the braces, but then you can not use issubset.

Related

unexpected EOF while parsing - how do i fix my code?

I've got
desc = ['(4,1);(1,4)', '(2,3);(3,2)', '(4,2);(2,4);(1,3);(3,1)', '(1,2);(2,1);(4,3);(3,4)']
and I want the output to be
[[(4, 1), (1, 4)], [(2, 3), (3, 2)], [(4, 2), (2, 4), (1, 3), (3, 1)], [(1, 2), (2, 1), (4, 3), (3, 4)]]
So far I've tried:
for x in range(len(desc)):
desc[x] = desc[x].split(';')
for y in range(len(desc[x])):
desc[x][y] = eval(desc[x][y])
but there is a syntax error saying 'unexpected EOF while parsing. How do I fix my code?
For the last two lines of my code I was just trying to extract the tuples from the strings containing them, is there anything else I could use except for eval()?
Unexpected EOF is caused by the indentation of the second for loop.
for x in range(len(desc)):
desc[x] = desc[x].split(';')
for y in range(len(desc[x])): # this has one tab to much
desc[x][y] = eval(desc[x][y])
This is how it should look like:
for x in range(len(desc)):
desc[x] = desc[x].split(';')
for y in range(len(desc[x])):
desc[x][y] = eval(desc[x][y])
You want to split each item of your list with the separator ';'. You need to parse your list :
for element in desc and split each element according to this separator :
temp = element.split(';'). You can then add to your output list the list [temp[0], temp[1]]
desc = ['(4,1);(1,4)', '(2,3);(3,2)', '(4,2);(2,4);(1,3);(3,1)', '(1,2);(2,1);(4,3);(3,4)']
output = []
for element in desc:
temps = element.split(";")
output.append([temps[0], temps[1]])
print(output)
# [['(4,1)', '(1,4)'], ['(2,3)', '(3,2)'], ['(4,2)', '(2,4)'], ['(1,2)', '(2,1)']]
To remove the '' you have to transform your items into actual tuples with the integers inside :
desc = ['(4,1);(1,4)', '(2,3);(3,2)', '(4,2);(2,4);(1,3);(3,1)', '(1,2);(2,1);(4,3);(3,4)']
output = []
for element in desc:
temps = element.split(";")
tuples_to_add = []
for i in temps:
tuples_to_add.append(tuple([int(i.strip('()')[0]), int(i.strip('()')[-1])]))
output.append(tuples_to_add)
print(output)
[[(4, 1), (1, 4)], [(2, 3), (3, 2)], [(4, 2), (2, 4), (1, 3), (3, 1)], [(1, 2), (2, 1), (4, 3), (3, 4)]]

Is there a difference between these two expressions in python

So, basically I just started learning python and I can't find something that proves if these two instructions do the same thing or not
I have two lists and I want to copy one into another, the thing is that I do not understood if this instruction is right
newList = [x[:] for x in List]
because newList = List does the same thing
Is there a difference between these two instructions?
Thanks!
In the first cursory look they look essentially same but there could be a difference if the List is not a list of lists [as is immediately understood by its name] ..if List is actually a tuple of tuples (supposing a naming mistake .. :-)) or something else. In such a case you are creating a list of tuples (by the first command) from what was initially something else. Other such possibilities also exist. So please see the print and type of NewList and List carefully. A subtle difference and they are not same.
You might be actually doing a type conversion if you are following the first command.
Consider the code below.
List = tuple( (x,x+1) for x in range(10))
newList = [x[:] for x in List]
The output of print and type reveal the difference instantly.
print(List)
print(newList)
type(List)
type(newList)
respective Outputs
((0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10))
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10)]
<class 'tuple'>
<class 'list'>

TypeError: unhashable type: 'list' in python chess program

I am coding a chess program and am coding check. I need the key from the opponent moves dictionary (which contains the king's position) to be used to find the coordinate of the piece placing it in check. Right now this is givng me the error:
opponentpieceposition=opponentposition.get(piece)
TypeError: unhashable type: 'list'.
Note the example below should print (1,6)
king=(5,1)
opponentmoves={'ksknight': [(8, 3), (5, 2), (6, 3)],
'ksbishop': [(3, 6), (4, 7), (5, 8), (1, 4), (1, 6), (3, 4), (4, 3), (5, 1), (6, 1)],
'king': [(6, 1), (5, 2), (4, 1)],
'queen': [(4, 5), (2, 4), (1, 3), (2, 6), (1, 7), (4, 4)],
'qsknight': [(3, 3), (1, 3)]}
opponentposition={'ksknight': (1, 3),
'ksbishop': (1, 6),
'king': (6, 1),
'queen': (4, 5),
'qsknight': (3, 3)}
if king in [z for v in opponentmoves.values() for z in v]:
piece=[key for key in opponentmoves if king in opponentmoves[key]]
opponentpieceposition=opponentposition.get(piece)
print(opponentpieceposition)
lists and objects of other mutable types cannot be used as keys in dictionaries (or elements in sets).
These containers rely on computing a hash value which is a function of the 'content' of the object at insertion time. So if the object (like mutable objects are able to) changes after insertion there will be problems.
you can instead use a tuple which is an immutable sequence.
duplicate
In your code piece is a list, it can't be dictionary key. Please follow comments in code how to overcome the issue:
if king in [z for v in opponentmoves.values() for z in v]:
piece = [key for key in opponentmoves if king in opponentmoves[key]]
print(piece) # Let's show what is piece
# result is ['ksbishop']
# so we need 1st element of the list pice
opponentpieceposition=opponentposition.get(piece[0]) # take the 1st element
print(opponentpieceposition)
Hope it helped to solve the issue.
This is what I got working.
if king in [z for v in opponent.moves.values() for z in v]:
for key in opponent.moves:
opponentpiece=opponent.moves[key]
if king in opponentpiece:
opponentposition=opponent.position[key]

Python: Print a generator expression's values when those values are itertools.product objects

I'm trying to dig into some code I found online here to better understand Python.
This is the code fragment I'm trying to get a feel for:
from itertools import chain, product
def generate_groupings(word_length, glyph_sizes=(1,2)):
cartesian_products = (
product(glyph_sizes, repeat=r)
for r in range(1, word_length + 1)
)
Here, word_length is 3.
I'm trying to evaluate the contents of the cartesian_products generator. From what I can gather after reading the answer at this SO question, generators do not iterate (and thus, do not yield a value) until they are called as part of a collection, so I've placed the generator in a list:
list(cartesian_products)
Out[6]:
[<itertools.product at 0x1025d1dc0>,
<itertools.product at 0x1025d1e10>,
<itertools.product at 0x1025d1f50>]
Obviously, I now see inside the generator, but I was hoping to get more specific information than the raw details of the itertools.product objects. Is there a way to accomplish this?
if you don't care about exhausting the generator, you can use:
list(map(list,cartesian_products))
You will get the following for word_length = 3
Out[1]:
[[(1,), (2,)],
[(1, 1), (1, 2), (2, 1), (2, 2)],
[(1, 1, 1),
(1, 1, 2),
(1, 2, 1),
(1, 2, 2),
(2, 1, 1),
(2, 1, 2),
(2, 2, 1),
(2, 2, 2)]]

Double sort with reverse

It is easy to implement a regular double sort:
pairs = [(1, 2), (2, 1), (1, 3), (2, 4), (3, 1)]
sorted(pairs,key=lambda x: (x[0],x[1]))
# out: [(1, 2), (1, 3), (2, 1), (2, 4), (3, 1)]
I am interested how to do it with the second elements in the reverse order. This can be easily implemented by grouping the pairs by the first item at first and then adding the the sorted second items together. I have implemented this both using itertools.groupby and defaultdict. Still, it remains far more complex, than the regular double sort, so i wonder, if there is a neat trick to do it in a more concise way.
double_sort(pairs)
# out: [(1, 3), (1, 2), (2, 4), (2, 1), (3, 1)]
PS! I know how to do it with numpy.argsort and would mostly like to see a standard lib approach.
This will work for numbers and similar data types
sorted(pairs, key=lambda x: (x[0], -x[1]))
This will work for all comparable types only in Python 2 :(
sorted(pairs, lambda x, y: cmp(x[0], y[0]) or cmp(y[1], x[1]))

Categories