# Path: lcs/Perception.py
# class Perception(collections.abc.Sequence):
#     """
#     Represents current state of the environment at given time instance.
#     By default each environment attribute is represented as `str` type.
#     """
# 
#     __slots__ = ['_items', 'oktypes']
# 
#     def __init__(self, observation, oktypes=(str,)):
#         assert all(type(e) in oktypes for e in observation)
#         self._items = tuple(observation)
# 
#     @classmethod
#     def empty(cls):
#         return cls([], oktypes=(None,))
# 
#     def __hash__(self):
#         return hash(self._items)
# 
#     def __getitem__(self, i):
#         return self._items[i]
# 
#     def __len__(self) -> int:
#         return len(self._items)
# 
#     def __repr__(self):
#         return ' '.join(map(str, self))
# 
#     def __eq__(self, other):
#         return all(p0 == p1 for p0, p1 in zip(self, other))
# 
# Path: lcs/agents/macs/macs.py
# class Effect(ImmutableSequence):
#     WILDCARD = '?'  # don't know symbol - matches any value
# 
#     @staticmethod
#     def generate(p: Perception) -> Generator[Effect]:
#         blank = [Effect.WILDCARD for _ in p]
#         for i, F in enumerate(p):
#             w = blank[:]
#             w[i] = F
#             yield Effect(w)
# 
#     def __lt__(self, other: Effect):
#         return self._items < other._items
# 
#     def conflicts(self, other: Effect) -> bool:
#         """Other classifier has different value for the same attribute"""
#         for si, oi in zip(self, other):
#             if si != self.WILDCARD and oi != self.WILDCARD and si != oi:
#                 return True
# 
#         return False
# 
#     def does_match(self, p: Perception) -> bool:
#         return all(ei == pi for ei, pi in zip(self, p) if ei != self.WILDCARD)
# 
#     def subsumes(self, other) -> bool:
#         raise NotImplementedError('MACS has no subsume operator')


import pytest
from lcs import Perception
from lcs.agents.macs.macs import Effect
    @pytest.mark.parametrize('_e1, _e2, _res', [
        ('????', '????', False),
        ('??1?', '??1?', False),
        ('??1?', '??2?', True),
        ('2?1?', '2?1?', False),
        ('2?1?', '2?2?', True),
        ('2???', '??2?', False),
    ])
    def test_should_detect_conflicts(self, _e1, _e2, _res):
        assert Effect(_e1).conflicts(Effect(_e2)) == _res
        assert Effect(_e2).conflicts(Effect(_e1)) == _res

    @pytest.mark.parametrize('_p1, _res', [
        ('1010', ['1???', '?0??', '??1?', '???0'])
    ])
    def test_should_generate(self, _p1, _res):
        # given
        p = Perception(_p1)

        # when
        effects = Effect.generate(p)
        effects = list(map(str, effects))

        assert len(effects) == len(_res)
        assert sorted(effects) == sorted(_res)

    def test_should_sort(self):
        # given
        e1 = Effect('???1')
        e2 = Effect('?2?1')

# Path: lcs/Perception.py
# class Perception(collections.abc.Sequence):
#     """
#     Represents current state of the environment at given time instance.
#     By default each environment attribute is represented as `str` type.
#     """
# 
#     __slots__ = ['_items', 'oktypes']
# 
#     def __init__(self, observation, oktypes=(str,)):
#         assert all(type(e) in oktypes for e in observation)
#         self._items = tuple(observation)
# 
#     @classmethod
#     def empty(cls):
#         return cls([], oktypes=(None,))
# 
#     def __hash__(self):
#         return hash(self._items)
# 
#     def __getitem__(self, i):
#         return self._items[i]
# 
#     def __len__(self) -> int:
#         return len(self._items)
# 
#     def __repr__(self):
#         return ' '.join(map(str, self))
# 
#     def __eq__(self, other):
#         return all(p0 == p1 for p0, p1 in zip(self, other))
# 
# Path: lcs/agents/macs/macs.py
# class Effect(ImmutableSequence):
#     WILDCARD = '?'  # don't know symbol - matches any value
# 
#     @staticmethod
#     def generate(p: Perception) -> Generator[Effect]:
#         blank = [Effect.WILDCARD for _ in p]
#         for i, F in enumerate(p):
#             w = blank[:]
#             w[i] = F
#             yield Effect(w)
# 
#     def __lt__(self, other: Effect):
#         return self._items < other._items
# 
#     def conflicts(self, other: Effect) -> bool:
#         """Other classifier has different value for the same attribute"""
#         for si, oi in zip(self, other):
#             if si != self.WILDCARD and oi != self.WILDCARD and si != oi:
#                 return True
# 
#         return False
# 
#     def does_match(self, p: Perception) -> bool:
#         return all(ei == pi for ei, pi in zip(self, p) if ei != self.WILDCARD)
# 
#     def subsumes(self, other) -> bool:
#         raise NotImplementedError('MACS has no subsume operator')


# Path: tests/lcs/agents/macs/test_Effect.py
import pytest
from lcs import Perception
from lcs.agents.macs.macs import Effect

    @pytest.mark.parametrize('_e1, _e2, _res', [
        ('????', '????', False),
        ('??1?', '??1?', False),
        ('??1?', '??2?', True),
        ('2?1?', '2?1?', False),
        ('2?1?', '2?2?', True),
        ('2???', '??2?', False),
    ])
    def test_should_detect_conflicts(self, _e1, _e2, _res):
        assert Effect(_e1).conflicts(Effect(_e2)) == _res
        assert Effect(_e2).conflicts(Effect(_e1)) == _res

    @pytest.mark.parametrize('_p1, _res', [
        ('1010', ['1???', '?0??', '??1?', '???0'])
    ])
    def test_should_generate(self, _p1, _res):
        # given
        p = Perception(_p1)

        # when
        effects = Effect.generate(p)
        effects = list(map(str, effects))

        assert len(effects) == len(_res)
        assert sorted(effects) == sorted(_res)

    def test_should_sort(self):
        # given
        e1 = Effect('???1')
        e2 = Effect('?2?1')

        e3 = Effect('???1')