Sergio
Sergio

Reputation: 37

Hash states to be able to compare them

I have these two states that represent the same state, but with changed order, with Python:

state1 = [ [1,5,6], [8,2,1] ]
state2 = [ [8,2,1], [1,5,6] ]

How can I hash these two states to be able to compare them? (state1 == state2)

Upvotes: 1

Views: 97

Answers (3)

Elicon
Elicon

Reputation: 219

the easiest:

sorted(state1) == sorted(state2)

It may be more correct to convert to set, But then the list inside the list needs to be converted to a tuple:

state1 = [ [1,5,6], [8,2,1] ]
state2 = [ [8,2,1], [1,5,6] ]

s1 = set(tuple(i) for i in state1)
s2 = set(tuple(i) for i in state2)

s1 == s2

Upvotes: 1

wim
wim

Reputation: 363133

I would do it like this:

>>> from collections import Counter
>>> def my_hash(state):
...     counter = Counter(map(tuple, state))
...     items = frozenset(counter.items())
...     return hash(items)
... 
>>> my_hash(state1) == my_hash(state2)
True

Upvotes: 1

wjandrea
wjandrea

Reputation: 33107

Just to be able to compare them, you don't need to hash them. For example, sets support unordered comparisons. You just need to make the sublists hashable first, which you can do by converting them to tuples:

def state_comparable(state: list[list[int]]) -> set[tuple[int]]:
    return {tuple(sub) for sub in state}
>>> state_comparable(state1) == state_comparable(state2)
True

But if you do need to hash them, you can simply swap set for frozenset:

def state_hash(state: list[list[int]]) -> int:
    return hash(frozenset(tuple(sub) for sub in state))
>>> state_hash(state1) == state_hash(state2)
True

Note: These solutions assume the sublists are always unique. Otherwise, see wim's answer for how to use a Counter.

Upvotes: 0

Related Questions