<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Implementing Maps as Lists of Key-Value-Pairs
The class ListNode implements a node of a <em style="color
Step1:  Given a key, the method find traverses the given list until it finds a node that stores the given key.  In this case, it returns the associated value.  Otherwise, None is returned.
Step2:  Given the first node of a linked list $L$, the function $L.\texttt{insert}(k, v)$ inserts the key-value pair $(k, v)$ into the list $L$.  If there is already a key value pair in $L$ that has the same key, then the old value is overwritten.  It returns a boolean that is true if a new node has been allocated.
Step3:  Given the first node of a linked list $L$, the function $L.\texttt{delete}(k)$ deletes the first key-value pair of the form $(k, v)$ from the list $L$.  If there is no such pair, the list $L$ is unchanged.  It returns a pair such that
Step4:  Given the first node of a linked list $L$, the function $L.\texttt{toString}()$ returns a string representing $L$.
Step5:  The class ListMap implements a map using a linked list of key-value pairs.  Basically, it is a wrapper for the class
ListNode.  Furthermore, an object of type ListMap is iterable.
Step6:  A MapIterator is an iterator that iterates over the elements of a linked list.  It maintains a pointer mPtr that points to the next element.
It is implemented via the function __next__.  This function either returns the next key-vale pair or, if there are no more key-value pairs left, then it raises a
StopIteration exception.
If the __iter__ method of a class $C$ returns an iterator, then we can use a 
for-loop to iterate over the elements contained in class $C$.
<ASSISTANT_TASK:>
Python Code:
class ListNode:
    def __init__(self, key, value):
        self.mKey     = key
        self.mValue   = value
        self.mNextPtr = None
Explanation: Implementing Maps as Lists of Key-Value-Pairs
The class ListNode implements a node of a <em style="color:blue">linked lists</em> of 
key-value pairs.  Every node has three member variables:
- mKey     stores the key,
- mValue   stores the value associated with this key, and
- mNextPtr stores a reference to the next node.  If there is no next node, then 
  mNextPtr is None.
Objects of class ListNode are used to represent linked lists.  
The constructor of the class ListNode creates a single node that stores the given key and its associated value.
End of explanation
def find(self, key):
    ptr = self
    while True:
        if ptr.mKey == key:
            return ptr.mValue
        if ptr.mNextPtr != None:
            ptr = ptr.mNextPtr
        else:
            return
    
ListNode.find = find
del find
Explanation: Given a key, the method find traverses the given list until it finds a node that stores the given key.  In this case, it returns the associated value.  Otherwise, None is returned.
End of explanation
def insert(self, key, value):
    while True:
        if self.mKey == key:
            self.mValue = value
            return False
        elif self.mNextPtr != None:
            self = self.mNextPtr
        else:
            self.mNextPtr = ListNode(key, value)
            return True
ListNode.insert = insert
del insert
Explanation: Given the first node of a linked list $L$, the function $L.\texttt{insert}(k, v)$ inserts the key-value pair $(k, v)$ into the list $L$.  If there is already a key value pair in $L$ that has the same key, then the old value is overwritten.  It returns a boolean that is true if a new node has been allocated.
End of explanation
def delete(self, key):
    previous = None
    ptr      = self
    while True:
        if ptr.mKey == key:
            if previous == None:
                return ptr.mNextPtr, True
            else:
                previous.mNextPtr = ptr.mNextPtr
                return self, True
        elif ptr.mNextPtr != None:
            previous = ptr
            ptr      = ptr.mNextPtr
        else:
            return self, False
ListNode.delete = delete
del delete
Explanation: Given the first node of a linked list $L$, the function $L.\texttt{delete}(k)$ deletes the first key-value pair of the form $(k, v)$ from the list $L$.  If there is no such pair, the list $L$ is unchanged.  It returns a pair such that:
- The first component of this pair is a pointer to the changed list.
  If the list becomes empty, the first component is None.
- The second component is a Boolean that is True if a node has been deleted.
End of explanation
def toString(self):
    if self.mNextPtr != None:
        return f'{self.mKey} ↦ {self.mValue}, ' + self.mNextPtr.__str__()
    else:
        return f'{self.mKey} ↦ {self.mValue}'
ListNode.__str__ = toString
del toString
Explanation: Given the first node of a linked list $L$, the function $L.\texttt{toString}()$ returns a string representing $L$.
End of explanation
class ListMap:
    def __init__(self):
        self.mPtr = None
        
    def find(self, key):
        if self.mPtr != None:
            return self.mPtr.find(key)
        
    def insert(self, key, value):
        if self.mPtr != None:
            return self.mPtr.insert(key, value)
        else:
            self.mPtr = ListNode(key, value)
            return True
            
    def delete(self, key):
        if self.mPtr != None:
            self.mPtr, flag = self.mPtr.delete(key)
            return flag
        return False
            
    def __iter__(self):
        return MapIterator(self.mPtr)
            
    def __str__(self):
        if self.mPtr != None:
            return '{' + self.mPtr.__str__() + '}'
        else:
            return '{}'
    
    def __repr__(self):
        return self.__str__()
Explanation: The class ListMap implements a map using a linked list of key-value pairs.  Basically, it is a wrapper for the class
ListNode.  Furthermore, an object of type ListMap is iterable.
End of explanation
class MapIterator:
    def __init__(self, ptr):
        self.mPtr = ptr
    
    def __next__(self):
        if self.mPtr == None:
            raise StopIteration
        key   = self.mPtr.mKey
        value = self.mPtr.mValue
        self.mPtr = self.mPtr.mNextPtr
        return key, value
def main(n = 100):
    S = ListMap()
    for i in range(2, n + 1):
        S.insert(i, True)
    for i in range(2, n // 2 + 1):
        for j in range(i, n // i + 1):
            S.delete(i * j)
    print([p for p, _ in S]) # iterates over ListMap
    print(S.find(83))
    print(S.find(99))
main()
Explanation: A MapIterator is an iterator that iterates over the elements of a linked list.  It maintains a pointer mPtr that points to the next element.
It is implemented via the function __next__.  This function either returns the next key-vale pair or, if there are no more key-value pairs left, then it raises a
StopIteration exception.
If the __iter__ method of a class $C$ returns an iterator, then we can use a 
for-loop to iterate over the elements contained in class $C$.
End of explanation
<END_TASK>