def unitary_function(mappings: Dict[str, str]) -> np.ndarray:
        """
        Creates a unitary transformation that maps each state to the values specified in mappings.

        Some (but not all) of these transformations involve a scratch qubit, so room for one is
        always provided. That is, if given the mapping of n qubits, the calculated transformation
        will be on n + 1 qubits, where the 0th is the scratch bit and the return value
        of the function is left in the 1st.

        :param mappings: Dictionary of the mappings of f(x) on all length n bitstrings, e.g.

            >>> {'00': '0', '01': '1', '10': '1', '11': '0'}

        :return: ndarray representing specified unitary transformation.
        """
        num_qubits = int(np.log2(len(mappings)))
        bitsum = sum([int(bit) for bit in mappings.values()])

        # Only zeros were entered
        if bitsum == 0:
            return np.kron(SWAP_MATRIX, np.identity(2 ** (num_qubits - 1)))

        # Half of the entries were 0, half 1
        elif bitsum == 2 ** (num_qubits - 1):
            unitary_funct = np.zeros(shape=(2 ** num_qubits, 2 ** num_qubits))
            index_lists = [list(range(2 ** (num_qubits - 1))),
                           list(range(2 ** (num_qubits - 1), 2 ** num_qubits))]
            for j in range(2 ** num_qubits):
                bitstring = np.binary_repr(j, num_qubits)
                value = int(mappings[bitstring])
                mappings.pop(bitstring)
                i = index_lists[value].pop()
                unitary_funct[i, j] = 1
            return np.kron(np.identity(2), unitary_funct)

        # Only ones were entered
        elif bitsum == 2 ** num_qubits:
            x_gate = np.array([[0, 1], [1, 0]])
            return np.kron(SWAP_MATRIX, np.identity(2 ** (num_qubits - 1))).dot(
                np.kron(x_gate, np.identity(2 ** num_qubits)))
        else:
            raise ValueError("f(x) must be constant or balanced")
Creates a unitary transformation that maps each state to the values specified in mappings.

        Some (but not all) of these transformations involve a scratch qubit, so room for one is
        always provided. That is, if given the mapping of n qubits, the calculated transformation
        will be on n + 1 qubits, where the 0th is the scratch bit and the return value
        of the function is left in the 1st.

        :param mappings: Dictionary of the mappings of f(x) on all length n bitstrings, e.g.

            >>> {'00': '0', '01': '1', '10': '1', '11': '0'}

        :return: ndarray representing specified unitary transformation.