from dataclasses import dataclass
from typing import Iterator, Optional

@dataclass
class Node[T]:
    value: T
    next_node: Optional['Node[T]']
   

@dataclass
class LinkedList[T]:
    
    def __post_init__(self):
        self.__head: Optional[Node[T]] = None
        self.__length = 0
    
    def __eq__(self, other: 'LinkedList[T]') -> bool:
        if len(self) != len(other):
            return False
        for i in range(0, len(self)):
            if self[i] != self[i]:
                return False
        return True
        
    def __iter__(self) -> Iterator[T]:
        node = self.__head
        while node:
            yield node.value
            node = node.next_node
        
    def append(self, value: T):
        if not self.__head:
            self.__head = Node(value, None)
        else:
            node = self.__head
            while node.next_node:
                node = node.next_node
            node.next_node = Node(value, None)
        self.__length += 1
        
    def remove(self, value: T):
        if self.__head and self.__head.value == value:
            self.__head = self.__head.next_node
            self.__length -= 1
        elif self.__head:
            node = self.__head
            while node.next_node and node.next_node.value != value:
                node = node.next_node
            if node.next_node and node.next_node.value == value:
                node.next_node = node.next_node.next_node
                self.__length -= 1
                
    def __len__(self) -> int:
        return self.__length
    
    def __getitem__(self, index: int) -> T:
        if index >= len(self):
            raise IndexError
        node = self.__head
        for _ in range(0, index):
            node = node.next_node
        return node.value