class WorkingMemory:
    def __init__(self):
        self.phonological_loop = PhonologicalLoop()
        self.visuospatial_sketchpad = VisuospatialSketchpad()

    def add_phonological(self, content: str) -> None:
        """Add verbal information to phonological loop."""
        chunks = self._chunk_content(content)
        for chunk in chunks:
            self.phonological_loop.add(chunk)

    def add_visuospatial(self, content: list) -> None:
        """Add visual/spatial information to sketchpad."""
        self.visuospatial_sketchpad.add(content)

    def retrieve(self, content_type: str, by: str = 'content') -> any:
        """Retrieve information from working memory.
        
        Args:
            content_type: 'phonological' or 'visuospatial'
            by: 'content' or 'recency'
        """
        if content_type == 'phonological':
            return self.phonological_loop.retrieve(by)
        elif content_type == 'visuospatial':
            return self.visuospatial_sketchpad.retrieve(by)
        else:
            raise ValueError("Invalid content type")

    def decay(self, timestep: int) -> None:
        """Decay memory contents over time."""
        self.phonological_loop.decay(timestep)
        self visuospatial_sketchpad.decay(timestep)

    def _chunk_content(self, content: str) -> list:
        """Split verbal content into meaningful chunks."""
        # Simple chunking based on spaces (words)
        return content.split()

class PhonologicalLoop:
    def __init__(self):
        self.capacity = 4
        self.chunks = []
        self.decay_rate = 0.2

    def add(self, chunk: str) -> None:
        """Add a chunk to phonological memory."""
        if len(self.chunks) >= self.capacity:
            # Forget the oldest chunk with lowest strength
            weakest = min(enumerate(self.chunks), key=lambda x: x[1]['strength'])
            del self.chunks[weakest[0]]
        new_chunk = {'content': chunk, 'strength': 1.0}
        self.chunks.append(new_chunk)

    def retrieve(self, by: str) -> any:
        """Retrieve chunks based on content or recency."""
        if by == 'content':
            # Try to find exact match
            for chunk in self.chunks:
                if chunk['content'] == target:
                    return chunk['content']
            return None
        elif by == 'recency':
            return self.chunks[0]['content']

    def decay(self, timestep: int) -> None:
        """Decay strengths over time."""
        for chunk in self.chunks:
            chunk['strength'] = max(0, chunk['strength'] - (chunk['strength'] * self.decay_rate))

class VisuospatialSketchpad:
    def __init__(self):
        self.capacity = 3
        self.images = []
        self.decay_rate = 0.1

    def add(self, image: list) -> None:
        """Add visual information to sketchpad."""
        if len(self.images) >= self.capacity:
            # Forget the oldest image
            del self.images[0]
        self.images.append(image)

    def retrieve(self, by: str) -> any:
        """Retrieve images based on content or recency."""
        if by == 'content':
            # Simple exact match (could be more complex in real implementations)
            for img in self.images:
                if img == target:
                    return img
            return None
        elif by == 'recency':
            return self.images[0]

    def decay(self, timestep: int) -> None:
        """Decay image stability over time."""
        for i in range(len(self.images)):
            # Simple decay model (could be more complex)
            self.images[i] = self.images[i][:int(len(self.images[i]) * 0.9)]