Side effects on input! Removes unreachable states from a
    DFA and returns the pruned DFA.

    It is possible to remove from a DFA A all unreachable states
    from the initial state without altering the language.
    The reachable DFA :math:`A_R` corresponding to A is defined as:

    :math:`A_R = (Σ, S_R , s_0 , ρ|S_R , F ∩ S_R )`

    where

    • :math:`S_R` set of reachable state from the initial one
    • :math:`ρ|S_R` is the restriction on :math:`S_R × Σ` of ρ.

    :param dict dfa: input DFA.
    :return: *(dict)* representing the pruned DFA.

def dfa_reachable(dfa: dict) -> dict:
    """ Side effects on input! Removes unreachable states from a
    DFA and returns the pruned DFA.

    It is possible to remove from a DFA A all unreachable states
    from the initial state without altering the language.
    The reachable DFA :math:`A_R` corresponding to A is defined as:

    :math:`A_R = (Σ, S_R , s_0 , ρ|S_R , F ∩ S_R )`

    where

    • :math:`S_R` set of reachable state from the initial one
    • :math:`ρ|S_R` is the restriction on :math:`S_R × Σ` of ρ.

    :param dict dfa: input DFA.
    :return: *(dict)* representing the pruned DFA.
    """
    reachable_states = set()  # set of reachable states from root
    boundary = set()
    reachable_states.add(dfa['initial_state'])
    boundary.add(dfa['initial_state'])

    while boundary:
        s = boundary.pop()
        for a in dfa['alphabet']:
            if (s, a) in dfa['transitions']:
                if dfa['transitions'][s, a] not in reachable_states:
                    reachable_states.add(dfa['transitions'][s, a])
                    boundary.add(dfa['transitions'][s, a])
    dfa['states'] = reachable_states
    dfa['accepting_states'] = \
        dfa['accepting_states'].intersection(dfa['states'])

    transitions = dfa[
        'transitions'].copy()  # TODO why copy? because for doesn't cycle
    # mutable set....
    for t in transitions:
        if t[0] not in dfa['states']:
            dfa['transitions'].pop(t)
        elif dfa['transitions'][t] not in dfa['states']:
            dfa['transitions'].pop(t)

    return dfa