```python
pip install cirq
```

    Requirement already satisfied: cirq in /usr/local/lib/python3.7/dist-packages (0.13.1)
    Requirement already satisfied: cirq-rigetti==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-pasqal==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-aqt==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-ionq==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-core==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-web==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: cirq-google==0.13.1 in /usr/local/lib/python3.7/dist-packages (from cirq) (0.13.1)
    Requirement already satisfied: requests~=2.18 in /usr/local/lib/python3.7/dist-packages (from cirq-aqt==0.13.1->cirq) (2.23.0)
    Requirement already satisfied: sympy in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (1.7.1)
    Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (3.10.0.2)
    Requirement already satisfied: matplotlib~=3.0 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (3.2.2)
    Requirement already satisfied: sortedcontainers~=2.0 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (2.4.0)
    Requirement already satisfied: duet~=0.2.0 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (0.2.3)
    Requirement already satisfied: networkx~=2.4 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (2.6.3)
    Requirement already satisfied: tqdm in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (4.62.3)
    Requirement already satisfied: pandas in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (1.3.5)
    Requirement already satisfied: scipy in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (1.7.3)
    Requirement already satisfied: numpy~=1.16 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.13.1->cirq) (1.21.5)
    Requirement already satisfied: google-api-core[grpc]<2.0.0dev,>=1.14.0 in /usr/local/lib/python3.7/dist-packages (from cirq-google==0.13.1->cirq) (1.26.3)
    Requirement already satisfied: protobuf>=3.13.0 in /usr/local/lib/python3.7/dist-packages (from cirq-google==0.13.1->cirq) (3.17.3)
    Requirement already satisfied: pyjwt~=1.7.1 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.7.1)
    Requirement already satisfied: pyquil~=3.0.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (3.0.1)
    Requirement already satisfied: h11~=0.9.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.9.0)
    Requirement already satisfied: retrying~=1.3.3 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.3.3)
    Requirement already satisfied: pydantic~=1.8.2 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.8.2)
    Requirement already satisfied: qcs-api-client~=0.8.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.8.0)
    Requirement already satisfied: certifi~=2021.5.30 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (2021.5.30)
    Requirement already satisfied: sniffio~=1.2.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.2.0)
    Requirement already satisfied: toml~=0.10.2 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.10.2)
    Requirement already satisfied: httpcore~=0.11.1 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.11.1)
    Requirement already satisfied: idna~=2.10 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (2.10)
    Requirement already satisfied: six~=1.16.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.16.0)
    Requirement already satisfied: rfc3339~=6.2 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (6.2)
    Requirement already satisfied: python-dateutil~=2.8.1 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (2.8.2)
    Requirement already satisfied: httpx~=0.15.5 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.15.5)
    Requirement already satisfied: iso8601~=0.1.14 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (0.1.16)
    Requirement already satisfied: attrs~=20.3.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (20.3.0)
    Requirement already satisfied: rfc3986~=1.5.0 in /usr/local/lib/python3.7/dist-packages (from cirq-rigetti==0.13.1->cirq) (1.5.0)
    Requirement already satisfied: google-auth<2.0dev,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (1.35.0)
    Requirement already satisfied: pytz in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (2018.9)
    Requirement already satisfied: packaging>=14.3 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (21.3)
    Requirement already satisfied: googleapis-common-protos<2.0dev,>=1.6.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (1.54.0)
    Requirement already satisfied: setuptools>=40.3.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (57.4.0)
    Requirement already satisfied: grpcio<2.0dev,>=1.29.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (1.43.0)
    Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.7/dist-packages (from google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (0.2.8)
    Requirement already satisfied: cachetools<5.0,>=2.0.0 in /usr/local/lib/python3.7/dist-packages (from google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (4.2.4)
    Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/lib/python3.7/dist-packages (from google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (4.8)
    Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.13.1->cirq) (0.11.0)
    Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.13.1->cirq) (3.0.7)
    Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.13.1->cirq) (1.3.2)
    Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /usr/local/lib/python3.7/dist-packages (from pyasn1-modules>=0.2.1->google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.13.1->cirq) (0.4.8)
    Requirement already satisfied: lark<0.12.0,>=0.11.1 in /usr/local/lib/python3.7/dist-packages (from pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.11.3)
    Requirement already satisfied: rpcq<4.0.0,>=3.6.0 in /usr/local/lib/python3.7/dist-packages (from pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (3.9.2)
    Requirement already satisfied: retry<0.10.0,>=0.9.2 in /usr/local/lib/python3.7/dist-packages (from pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.9.2)
    Requirement already satisfied: importlib-metadata<4.0.0,>=3.7.3 in /usr/local/lib/python3.7/dist-packages (from pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (3.10.1)
    Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata<4.0.0,>=3.7.3->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (3.7.0)
    Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests~=2.18->cirq-aqt==0.13.1->cirq) (1.24.3)
    Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests~=2.18->cirq-aqt==0.13.1->cirq) (3.0.4)
    Requirement already satisfied: py<2.0.0,>=1.4.26 in /usr/local/lib/python3.7/dist-packages (from retry<0.10.0,>=0.9.2->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (1.11.0)
    Requirement already satisfied: decorator>=3.4.2 in /usr/local/lib/python3.7/dist-packages (from retry<0.10.0,>=0.9.2->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (4.4.2)
    Requirement already satisfied: msgpack<1.0,>=0.6 in /usr/local/lib/python3.7/dist-packages (from rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.6.2)
    Requirement already satisfied: python-rapidjson in /usr/local/lib/python3.7/dist-packages (from rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (1.5)
    Requirement already satisfied: pyzmq>=17 in /usr/local/lib/python3.7/dist-packages (from rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (22.3.0)
    Requirement already satisfied: ruamel.yaml in /usr/local/lib/python3.7/dist-packages (from rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.17.21)
    Requirement already satisfied: ruamel.yaml.clib>=0.2.6 in /usr/local/lib/python3.7/dist-packages (from ruamel.yaml->rpcq<4.0.0,>=3.6.0->pyquil~=3.0.0->cirq-rigetti==0.13.1->cirq) (0.2.6)
    Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy->cirq-core==0.13.1->cirq) (1.2.1)

```python
# import required libraries
import random
import time
import cirq
from cirq import H, X, CNOT, measure
import matplotlib.pyplot as plt

def main(n,decide):
    # Choose qubits to use.
    q = cirq.LineQubit.range(n+1)

    # Pick a secret n-bit function and create a circuit to query the oracle.
    secret_function = [random.randint(0, 1) for _ in range(n)]

    # Create a balanced or constant oracle depending on the deciding bit.
    oracle = make_oracle(q,n,secret_function,decide)
    print(f"Secret function:\nf(x) = <{', '.join(str(e) for e in secret_function)}>")

    # Embed the oracle into a quantum circuit querying it.
    circuit = make_deutsch_circuit(q,n, oracle)
    print('Circuit:')
    print(circuit)

    # Simulate the circuit
#    simulator = cirq.Simulator()
#    result = simulator.run(circuit)
    run_simulation(circuit,1024)

# Custom function used to respresent a a set of bits in string format
def bitstring(bits):
    return ''.join(str(int(b)) for b in bits)
def run_simulation(c,run_count):
  simulator = cirq.Simulator()
  result = simulator.run(c, repetitions=run_count)
  frequencies = result.histogram(key='result', fold_func=bitstring)
  print(f'Sampled results:\n{frequencies}')

  # Check if we actually found the secret value.
  most_common_bitstring = frequencies.most_common(1)[0][0]

def make_oracle(q,n, secret_function,decide):
    """Gates implementing the secret function f(x)."""

    # If deciding bit is 0, implement a balanced function, in this case it is a CNOT of each input bits with a predefined control bit in X basis, that hold the value 1
    if decide == 0:
      print()
      print("Should be a balanced function!")
      print()
      for i,j in enumerate(secret_function):

        if j == 1:
          yield cirq.X(q[i])

      for i in q[:n]:
        yield CNOT(i,q[n])

      for i,j in enumerate(secret_function):

        if j == 1:
          yield cirq.X(q[i])

    # If the deciding bit is 1, we implement a balanced function
    else:
      print()
      print("Should be a constant function!")
      print()

def make_deutsch_circuit(q,n,oracle):
    c = cirq.Circuit()

    # Initialize input qubits
    c.append( cirq.H.on_each(q[:n]))
    # Initialize output qubits
    c.append(cirq.X(q[n]) )
    c.append(cirq.H(q[n]) )

    # Query oracle
    c.append(oracle)

    # Measure in H basis
    c.append(cirq.H.on_each(q[:n]))
    c.append(cirq.measure(*q[:n], key="result"))
    return c

```

```python
# Running the algorithm by altering the circuit for varied values of n, where n represents number of qubits &
# Capturing time taken for the algorithm to run for each value of n for a balanced function

t=[]
decide = 0
for i in range(1,21):

    st=time.time()
    main(i,decide)
    end=time.time()
    t.append(end-st)

```

    Secret function:
    f(x) = <0>

    Should be a balanced function!

    Circuit:
    0: ───H───────@───H───M('result')───
                  │
    1: ───X───H───X─────────────────────
    Sampled results:
    Counter({'1': 1024})
    Secret function:
    f(x) = <1, 0>

    Should be a balanced function!

    Circuit:
    0: ───H───X───@───X───H───M('result')───
                  │           │
    1: ───H───────┼───@───H───M─────────────
                  │   │
    2: ───X───H───X───X─────────────────────
    Sampled results:
    Counter({'11': 1024})
    Secret function:
    f(x) = <0, 0, 1>

    Should be a balanced function!

    Circuit:
    0: ───H───────@───H───────────────M('result')───
                  │                   │
    1: ───H───────┼───@───H───────────M─────────────
                  │   │               │
    2: ───H───X───┼───┼───@───X───H───M─────────────
                  │   │   │
    3: ───X───H───X───X───X─────────────────────────
    Sampled results:
    Counter({'111': 1024})
    Secret function:
    f(x) = <0, 0, 1, 0>

    Should be a balanced function!

    Circuit:
    0: ───H───────@───H───────────────M('result')───
                  │                   │
    1: ───H───────┼───@───H───────────M─────────────
                  │   │               │
    2: ───H───X───┼───┼───@───X───H───M─────────────
                  │   │   │           │
    3: ───H───────┼───┼───┼───@───H───M─────────────
                  │   │   │   │
    4: ───X───H───X───X───X───X─────────────────────
    Sampled results:
    Counter({'1111': 1024})
    Secret function:
    f(x) = <1, 0, 1, 1, 1>

    Should be a balanced function!

    Circuit:
    0: ───H───X───@───X───H───────────────────M('result')───
                  │                           │
    1: ───H───────┼───@───H───────────────────M─────────────
                  │   │                       │
    2: ───H───X───┼───┼───@───X───H───────────M─────────────
                  │   │   │                   │
    3: ───H───X───┼───┼───┼───@───X───H───────M─────────────
                  │   │   │   │               │
    4: ───H───X───┼───┼───┼───┼───@───X───H───M─────────────
                  │   │   │   │   │
    5: ───X───H───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'11111': 1024})
    Secret function:
    f(x) = <0, 0, 1, 0, 1, 1>

    Should be a balanced function!

    Circuit:
    0: ───H───────@───H───────────────────────────M('result')───
                  │                               │
    1: ───H───────┼───@───H───────────────────────M─────────────
                  │   │                           │
    2: ───H───X───┼───┼───@───X───H───────────────M─────────────
                  │   │   │                       │
    3: ───H───────┼───┼───┼───@───H───────────────M─────────────
                  │   │   │   │                   │
    4: ───H───X───┼───┼───┼───┼───@───X───H───────M─────────────
                  │   │   │   │   │               │
    5: ───H───X───┼───┼───┼───┼───┼───@───X───H───M─────────────
                  │   │   │   │   │   │
    6: ───X───H───X───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'111111': 1024})
    Secret function:
    f(x) = <0, 0, 1, 1, 0, 0, 1>

    Should be a balanced function!

    Circuit:
    0: ───H───────@───H───────────────────────────────M('result')───
                  │                                   │
    1: ───H───────┼───@───H───────────────────────────M─────────────
                  │   │                               │
    2: ───H───X───┼───┼───@───X───H───────────────────M─────────────
                  │   │   │                           │
    3: ───H───X───┼───┼───┼───@───X───H───────────────M─────────────
                  │   │   │   │                       │
    4: ───H───────┼───┼───┼───┼───@───H───────────────M─────────────
                  │   │   │   │   │                   │
    5: ───H───────┼───┼───┼───┼───┼───@───H───────────M─────────────
                  │   │   │   │   │   │               │
    6: ───H───X───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                  │   │   │   │   │   │   │
    7: ───X───H───X───X───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'1111111': 1024})
    Secret function:
    f(x) = <0, 0, 0, 1, 0, 1, 0, 0>

    Should be a balanced function!

    Circuit:
    0: ───H───────@───H───────────────────────────────M('result')───
                  │                                   │
    1: ───H───────┼───@───H───────────────────────────M─────────────
                  │   │                               │
    2: ───H───────┼───┼───@───H───────────────────────M─────────────
                  │   │   │                           │
    3: ───H───X───┼───┼───┼───@───X───H───────────────M─────────────
                  │   │   │   │                       │
    4: ───H───────┼───┼───┼───┼───@───H───────────────M─────────────
                  │   │   │   │   │                   │
    5: ───H───X───┼───┼───┼───┼───┼───@───X───H───────M─────────────
                  │   │   │   │   │   │               │
    6: ───H───────┼───┼───┼───┼───┼───┼───@───H───────M─────────────
                  │   │   │   │   │   │   │           │
    7: ───H───────┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                  │   │   │   │   │   │   │   │
    8: ───X───H───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'11111111': 1024})
    Secret function:
    f(x) = <1, 1, 0, 0, 0, 1, 1, 1, 1>

    Should be a balanced function!

    Circuit:
    0: ───H───X───@───X───H───────────────────────────────────M('result')───
                  │                                           │
    1: ───H───X───┼───@───X───H───────────────────────────────M─────────────
                  │   │                                       │
    2: ───H───────┼───┼───@───H───────────────────────────────M─────────────
                  │   │   │                                   │
    3: ───H───────┼───┼───┼───@───H───────────────────────────M─────────────
                  │   │   │   │                               │
    4: ───H───────┼───┼───┼───┼───@───H───────────────────────M─────────────
                  │   │   │   │   │                           │
    5: ───H───X───┼───┼───┼───┼───┼───@───X───H───────────────M─────────────
                  │   │   │   │   │   │                       │
    6: ───H───X───┼───┼───┼───┼───┼───┼───@───X───H───────────M─────────────
                  │   │   │   │   │   │   │                   │
    7: ───H───X───┼───┼───┼───┼───┼───┼───┼───@───X───H───────M─────────────
                  │   │   │   │   │   │   │   │               │
    8: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                  │   │   │   │   │   │   │   │   │
    9: ───X───H───X───X───X───X───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'111111111': 1024})
    Secret function:
    f(x) = <1, 1, 0, 1, 0, 1, 1, 1, 1, 0>

    Should be a balanced function!

    Circuit:
    0: ────H───X───@───X───H───────────────────────────────────M('result')───
                   │                                           │
    1: ────H───X───┼───@───X───H───────────────────────────────M─────────────
                   │   │                                       │
    2: ────H───────┼───┼───@───H───────────────────────────────M─────────────
                   │   │   │                                   │
    3: ────H───X───┼───┼───┼───@───X───H───────────────────────M─────────────
                   │   │   │   │                               │
    4: ────H───────┼───┼───┼───┼───@───H───────────────────────M─────────────
                   │   │   │   │   │                           │
    5: ────H───X───┼───┼───┼───┼───┼───@───X───H───────────────M─────────────
                   │   │   │   │   │   │                       │
    6: ────H───X───┼───┼───┼───┼───┼───┼───@───X───H───────────M─────────────
                   │   │   │   │   │   │   │                   │
    7: ────H───X───┼───┼───┼───┼───┼───┼───┼───@───X───H───────M─────────────
                   │   │   │   │   │   │   │   │               │
    8: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │           │
    9: ────H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │
    10: ───X───H───X───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'1111111111': 1024})
    Secret function:
    f(x) = <0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0>

    Should be a balanced function!

    Circuit:
    0: ────H───────@───H───────────────────────────────────────────M('result')───
                   │                                               │
    1: ────H───X───┼───@───X───H───────────────────────────────────M─────────────
                   │   │                                           │
    2: ────H───────┼───┼───@───H───────────────────────────────────M─────────────
                   │   │   │                                       │
    3: ────H───X───┼───┼───┼───@───X───H───────────────────────────M─────────────
                   │   │   │   │                                   │
    4: ────H───────┼───┼───┼───┼───@───H───────────────────────────M─────────────
                   │   │   │   │   │                               │
    5: ────H───X───┼───┼───┼───┼───┼───@───X───H───────────────────M─────────────
                   │   │   │   │   │   │                           │
    6: ────H───X───┼───┼───┼───┼───┼───┼───@───X───H───────────────M─────────────
                   │   │   │   │   │   │   │                       │
    7: ────H───────┼───┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │   │   │   │   │                   │
    8: ────H───────┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │               │
    9: ────H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────M─────────────
                   │   │   │   │   │   │   │   │   │   │           │
    10: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │
    11: ───X───H───X───X───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'11111111111': 1024})
    Secret function:
    f(x) = <0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1>

    Should be a balanced function!

    Circuit:
    0: ────H───────@───H───────────────────────────────────────────────────M('result')───
                   │                                                       │
    1: ────H───────┼───@───H───────────────────────────────────────────────M─────────────
                   │   │                                                   │
    2: ────H───────┼───┼───@───H───────────────────────────────────────────M─────────────
                   │   │   │                                               │
    3: ────H───X───┼───┼───┼───@───X───H───────────────────────────────────M─────────────
                   │   │   │   │                                           │
    4: ────H───X───┼───┼───┼───┼───@───X───H───────────────────────────────M─────────────
                   │   │   │   │   │                                       │
    5: ────H───X───┼───┼───┼───┼───┼───@───X───H───────────────────────────M─────────────
                   │   │   │   │   │   │                                   │
    6: ────H───────┼───┼───┼───┼───┼───┼───@───H───────────────────────────M─────────────
                   │   │   │   │   │   │   │                               │
    7: ────H───X───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────M─────────────
                   │   │   │   │   │   │   │   │                           │
    8: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │                       │
    9: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │   │                   │
    10: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │               │
    11: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │
    12: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'111111111111': 1024})
    Secret function:
    f(x) = <1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0>

    Should be a balanced function!

    Circuit:
    0: ────H───X───@───X───H───────────────────────────────────────────────M('result')───
                   │                                                       │
    1: ────H───────┼───@───H───────────────────────────────────────────────M─────────────
                   │   │                                                   │
    2: ────H───X───┼───┼───@───X───H───────────────────────────────────────M─────────────
                   │   │   │                                               │
    3: ────H───────┼───┼───┼───@───H───────────────────────────────────────M─────────────
                   │   │   │   │                                           │
    4: ────H───X───┼───┼───┼───┼───@───X───H───────────────────────────────M─────────────
                   │   │   │   │   │                                       │
    5: ────H───X───┼───┼───┼───┼───┼───@───X───H───────────────────────────M─────────────
                   │   │   │   │   │   │                                   │
    6: ────H───────┼───┼───┼───┼───┼───┼───@───H───────────────────────────M─────────────
                   │   │   │   │   │   │   │                               │
    7: ────H───X───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────M─────────────
                   │   │   │   │   │   │   │   │                           │
    8: ────H───────┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────M─────────────
                   │   │   │   │   │   │   │   │   │                       │
    9: ────H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │                   │
    10: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │               │
    11: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │           │
    12: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │
    13: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'1111111111111': 1024})
    Secret function:
    f(x) = <0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1>

    Should be a balanced function!

    Circuit:
    0: ────H───────@───H───────────────────────────────────────────────────────────M('result')───
                   │                                                               │
    1: ────H───X───┼───@───X───H───────────────────────────────────────────────────M─────────────
                   │   │                                                           │
    2: ────H───────┼───┼───@───H───────────────────────────────────────────────────M─────────────
                   │   │   │                                                       │
    3: ────H───────┼───┼───┼───@───H───────────────────────────────────────────────M─────────────
                   │   │   │   │                                                   │
    4: ────H───X───┼───┼───┼───┼───@───X───H───────────────────────────────────────M─────────────
                   │   │   │   │   │                                               │
    5: ────H───X───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────M─────────────
                   │   │   │   │   │   │                                           │
    6: ────H───X───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────M─────────────
                   │   │   │   │   │   │   │                                       │
    7: ────H───────┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │                                   │
    8: ────H───────┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │                               │
    9: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │                           │
    10: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │                       │
    11: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │                   │
    12: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │               │
    13: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │
    14: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'11111111111111': 1024})
    Secret function:
    f(x) = <0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1>

    Should be a balanced function!

    Circuit:
    0: ────H───────@───H───────────────────────────────────────────────────────────────M('result')───
                   │                                                                   │
    1: ────H───X───┼───@───X───H───────────────────────────────────────────────────────M─────────────
                   │   │                                                               │
    2: ────H───────┼───┼───@───H───────────────────────────────────────────────────────M─────────────
                   │   │   │                                                           │
    3: ────H───────┼───┼───┼───@───H───────────────────────────────────────────────────M─────────────
                   │   │   │   │                                                       │
    4: ────H───────┼───┼───┼───┼───@───H───────────────────────────────────────────────M─────────────
                   │   │   │   │   │                                                   │
    5: ────H───────┼───┼───┼───┼───┼───@───H───────────────────────────────────────────M─────────────
                   │   │   │   │   │   │                                               │
    6: ────H───X───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────M─────────────
                   │   │   │   │   │   │   │                                           │
    7: ────H───X───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │                                       │
    8: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │                                   │
    9: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │                               │
    10: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │                           │
    11: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │                       │
    12: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │                   │
    13: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │               │
    14: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │
    15: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'111111111111111': 1024})
    Secret function:
    f(x) = <0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1>

    Should be a balanced function!

    Circuit:
    0: ────H───────@───H───────────────────────────────────────────────────────────────────M('result')───
                   │                                                                       │
    1: ────H───────┼───@───H───────────────────────────────────────────────────────────────M─────────────
                   │   │                                                                   │
    2: ────H───X───┼───┼───@───X───H───────────────────────────────────────────────────────M─────────────
                   │   │   │                                                               │
    3: ────H───────┼───┼───┼───@───H───────────────────────────────────────────────────────M─────────────
                   │   │   │   │                                                           │
    4: ────H───────┼───┼───┼───┼───@───H───────────────────────────────────────────────────M─────────────
                   │   │   │   │   │                                                       │
    5: ────H───X───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────────────M─────────────
                   │   │   │   │   │   │                                                   │
    6: ────H───────┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │                                               │
    7: ────H───X───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │                                           │
    8: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │                                       │
    9: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │                                   │
    10: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │                               │
    11: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │                           │
    12: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │                       │
    13: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │                   │
    14: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │               │
    15: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │
    16: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'1111111111111111': 1024})
    Secret function:
    f(x) = <1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0>

    Should be a balanced function!

    Circuit:
    0: ────H───X───@───X───H───────────────────────────────────────────────────────────────M('result')───
                   │                                                                       │
    1: ────H───────┼───@───H───────────────────────────────────────────────────────────────M─────────────
                   │   │                                                                   │
    2: ────H───X───┼───┼───@───X───H───────────────────────────────────────────────────────M─────────────
                   │   │   │                                                               │
    3: ────H───────┼───┼───┼───@───H───────────────────────────────────────────────────────M─────────────
                   │   │   │   │                                                           │
    4: ────H───X───┼───┼───┼───┼───@───X───H───────────────────────────────────────────────M─────────────
                   │   │   │   │   │                                                       │
    5: ────H───────┼───┼───┼───┼───┼───@───H───────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │                                                   │
    6: ────H───X───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │                                               │
    7: ────H───────┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │                                           │
    8: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │                                       │
    9: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │                                   │
    10: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │                               │
    11: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │                           │
    12: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │                       │
    13: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │                   │
    14: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │               │
    15: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │           │
    16: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │
    17: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'11111111111111111': 1024})
    Secret function:
    f(x) = <1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0>

    Should be a balanced function!

    Circuit:
    0: ────H───X───@───X───H───────────────────────────────────────────────────────────────────M('result')───
                   │                                                                           │
    1: ────H───X───┼───@───X───H───────────────────────────────────────────────────────────────M─────────────
                   │   │                                                                       │
    2: ────H───X───┼───┼───@───X───H───────────────────────────────────────────────────────────M─────────────
                   │   │   │                                                                   │
    3: ────H───X───┼───┼───┼───@───X───H───────────────────────────────────────────────────────M─────────────
                   │   │   │   │                                                               │
    4: ────H───X───┼───┼───┼───┼───@───X───H───────────────────────────────────────────────────M─────────────
                   │   │   │   │   │                                                           │
    5: ────H───X───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │                                                       │
    6: ────H───────┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │                                                   │
    7: ────H───────┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │                                               │
    8: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │                                           │
    9: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │                                       │
    10: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │                                   │
    11: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │                               │
    12: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │                           │
    13: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │                       │
    14: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │                   │
    15: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │               │
    16: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │           │
    17: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │
    18: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────
    Sampled results:
    Counter({'111111111111111111': 1024})
    Secret function:
    f(x) = <1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1>

    Should be a balanced function!

    Circuit:
    0: ────H───X───@───X───H───────────────────────────────────────────────────────────────────────────M('result')───
                   │                                                                                │
    1: ────H───X───┼───@───X───H───────────────────────────────────────────────────────────────────────M─────────────
                   │   │                                                                               │
    2: ────H───────┼───┼───@───H───────────────────────────────────────────────────────────────────────M─────────────
                   │   │   │                                                                           │
    3: ────H───X───┼───┼───┼───@───X───H───────────────────────────────────────────────────────────────M─────────────
                   │   │   │   │                                                                       │
    4: ────H───X───┼───┼───┼───┼───@───X───H───────────────────────────────────────────────────────────M─────────────
                   │   │   │   │   │                                                                   │
    5: ────H───────┼───┼───┼───┼───┼───@───H───────────────────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │                                                               │
    6: ────H───────┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │                                                           │
    7: ────H───X───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │                                                       │
    8: ────H───────┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │                                                   │
    9: ────H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │                                               │
    10: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │                                           │
    11: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │                                       │
    12: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │                                   │
    13: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │                               │
    14: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │                           │
    15: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │                       │
    16: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │                   │
    17: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │               │
    18: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │
    19: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'1111111111111111111': 1024})
    Secret function:
    f(x) = <0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1>

    Should be a balanced function!

    Circuit:
    0: ────H───────@───H───────────────────────────────────────────────────────────────────────────────────M('result')───
                   │                                                                                │
    1: ────H───X───┼───@───X───H───────────────────────────────────────────────────────────────────────────M─────────────
                   │   │                                                                                │
    2: ────H───────┼───┼───@───H───────────────────────────────────────────────────────────────────────────M─────────────
                   │   │   │                                                                               │
    3: ────H───X───┼───┼───┼───@───X───H───────────────────────────────────────────────────────────────────M─────────────
                   │   │   │   │                                                                           │
    4: ────H───────┼───┼───┼───┼───@───H───────────────────────────────────────────────────────────────────M─────────────
                   │   │   │   │   │                                                                       │
    5: ────H───X───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │                                                                   │
    6: ────H───────┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │                                                               │
    7: ────H───X───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │                                                           │
    8: ────H───────┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │                                                       │
    9: ────H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │                                                   │
    10: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │                                               │
    11: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │                                           │
    12: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │                                       │
    13: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │                                   │
    14: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │                               │
    15: ───H───────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───H───────────────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │                           │
    16: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │                       │
    17: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │                   │
    18: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───────M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │               │
    19: ───H───X───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───@───X───H───M─────────────
                   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │
    20: ───X───H───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X───X─────────────────────────
    Sampled results:
    Counter({'11111111111111111111': 1024})

```python
# Plotting the time taken by the algorithm against the number of qubits in the circuit to analyze scalability of the algorithm

plt.scatter(list(range(1,21)), t)
plt.xlabel('Qubits')
plt.ylabel('Time (in seconds)')
plt.title(" Time vs Qubits ")
plt.show()

```

```python
# Running the algorithm by altering the circuit for varied values of n, where n represents number of qubits &
# Capturing time taken for the algorithm to run for each value of n for a balanced function

t=[]
decide = 1
for i in range(1,21):

    st=time.time()
    main(i,decide)
    end=time.time()
    t.append(end-st)

```

    Secret function:
    f(x) = <0>

    Should be a constant function!

    Circuit:
    0: ───H───H───M('result')───

    1: ───X───H─────────────────
    Sampled results:
    Counter({'0': 1024})
    Secret function:
    f(x) = <0, 1>

    Should be a constant function!

    Circuit:
    0: ───H───H───M('result')───
                  │
    1: ───H───H───M─────────────

    2: ───X───H─────────────────
    Sampled results:
    Counter({'00': 1024})
    Secret function:
    f(x) = <0, 1, 0>

    Should be a constant function!

    Circuit:
    0: ───H───H───M('result')───
                  │
    1: ───H───H───M─────────────
                  │
    2: ───H───H───M─────────────

    3: ───X───H─────────────────
    Sampled results:
    Counter({'000': 1024})
    Secret function:
    f(x) = <0, 0, 0, 1>

    Should be a constant function!

    Circuit:
    0: ───H───H───M('result')───
                  │
    1: ───H───H───M─────────────
                  │
    2: ───H───H───M─────────────
                  │
    3: ───H───H───M─────────────

    4: ───X───H─────────────────
    Sampled results:
    Counter({'0000': 1024})
    Secret function:
    f(x) = <0, 1, 0, 1, 1>

    Should be a constant function!

    Circuit:
    0: ───H───H───M('result')───
                  │
    1: ───H───H───M─────────────
                  │
    2: ───H───H───M─────────────
                  │
    3: ───H───H───M─────────────
                  │
    4: ───H───H───M─────────────

    5: ───X───H─────────────────
    Sampled results:
    Counter({'00000': 1024})
    Secret function:
    f(x) = <1, 1, 1, 1, 1, 0>

    Should be a constant function!

    Circuit:
    0: ───H───H───M('result')───
                  │
    1: ───H───H───M─────────────
                  │
    2: ───H───H───M─────────────
                  │
    3: ───H───H───M─────────────
                  │
    4: ───H───H───M─────────────
                  │
    5: ───H───H───M─────────────

    6: ───X───H─────────────────
    Sampled results:
    Counter({'000000': 1024})
    Secret function:
    f(x) = <1, 1, 1, 1, 1, 0, 1>

    Should be a constant function!

    Circuit:
    0: ───H───H───M('result')───
                  │
    1: ───H───H───M─────────────
                  │
    2: ───H───H───M─────────────
                  │
    3: ───H───H───M─────────────
                  │
    4: ───H───H───M─────────────
                  │
    5: ───H───H───M─────────────
                  │
    6: ───H───H───M─────────────

    7: ───X───H─────────────────
    Sampled results:
    Counter({'0000000': 1024})
    Secret function:
    f(x) = <0, 1, 1, 0, 0, 1, 1, 0>

    Should be a constant function!

    Circuit:
    0: ───H───H───M('result')───
                  │
    1: ───H───H───M─────────────
                  │
    2: ───H───H───M─────────────
                  │
    3: ───H───H───M─────────────
                  │
    4: ───H───H───M─────────────
                  │
    5: ───H───H───M─────────────
                  │
    6: ───H───H───M─────────────
                  │
    7: ───H───H───M─────────────

    8: ───X───H─────────────────
    Sampled results:
    Counter({'00000000': 1024})
    Secret function:
    f(x) = <0, 1, 1, 1, 0, 0, 1, 1, 1>

    Should be a constant function!

    Circuit:
    0: ───H───H───M('result')───
                  │
    1: ───H───H───M─────────────
                  │
    2: ───H───H───M─────────────
                  │
    3: ───H───H───M─────────────
                  │
    4: ───H───H───M─────────────
                  │
    5: ───H───H───M─────────────
                  │
    6: ───H───H───M─────────────
                  │
    7: ───H───H───M─────────────
                  │
    8: ───H───H───M─────────────

    9: ───X───H─────────────────
    Sampled results:
    Counter({'000000000': 1024})
    Secret function:
    f(x) = <1, 0, 1, 0, 0, 1, 0, 1, 1, 1>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────

    10: ───X───H─────────────────
    Sampled results:
    Counter({'0000000000': 1024})
    Secret function:
    f(x) = <0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────

    11: ───X───H─────────────────
    Sampled results:
    Counter({'00000000000': 1024})
    Secret function:
    f(x) = <0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────
                   │
    11: ───H───H───M─────────────

    12: ───X───H─────────────────
    Sampled results:
    Counter({'000000000000': 1024})
    Secret function:
    f(x) = <0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────
                   │
    11: ───H───H───M─────────────
                   │
    12: ───H───H───M─────────────

    13: ───X───H─────────────────
    Sampled results:
    Counter({'0000000000000': 1024})
    Secret function:
    f(x) = <0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────
                   │
    11: ───H───H───M─────────────
                   │
    12: ───H───H───M─────────────
                   │
    13: ───H───H───M─────────────

    14: ───X───H─────────────────
    Sampled results:
    Counter({'00000000000000': 1024})
    Secret function:
    f(x) = <0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────
                   │
    11: ───H───H───M─────────────
                   │
    12: ───H───H───M─────────────
                   │
    13: ───H───H───M─────────────
                   │
    14: ───H───H───M─────────────

    15: ───X───H─────────────────
    Sampled results:
    Counter({'000000000000000': 1024})
    Secret function:
    f(x) = <1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────
                   │
    11: ───H───H───M─────────────
                   │
    12: ───H───H───M─────────────
                   │
    13: ───H───H───M─────────────
                   │
    14: ───H───H───M─────────────
                   │
    15: ───H───H───M─────────────

    16: ───X───H─────────────────
    Sampled results:
    Counter({'0000000000000000': 1024})
    Secret function:
    f(x) = <1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────
                   │
    11: ───H───H───M─────────────
                   │
    12: ───H───H───M─────────────
                   │
    13: ───H───H───M─────────────
                   │
    14: ───H───H───M─────────────
                   │
    15: ───H───H───M─────────────
                   │
    16: ───H───H───M─────────────

    17: ───X───H─────────────────
    Sampled results:
    Counter({'00000000000000000': 1024})
    Secret function:
    f(x) = <0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────
                   │
    11: ───H───H───M─────────────
                   │
    12: ───H───H───M─────────────
                   │
    13: ───H───H───M─────────────
                   │
    14: ───H───H───M─────────────
                   │
    15: ───H───H───M─────────────
                   │
    16: ───H───H───M─────────────
                   │
    17: ───H───H───M─────────────

    18: ───X───H─────────────────
    Sampled results:
    Counter({'000000000000000000': 1024})
    Secret function:
    f(x) = <1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────
                   │
    11: ───H───H───M─────────────
                   │
    12: ───H───H───M─────────────
                   │
    13: ───H───H───M─────────────
                   │
    14: ───H───H───M─────────────
                   │
    15: ───H───H───M─────────────
                   │
    16: ───H───H───M─────────────
                   │
    17: ───H───H───M─────────────
                   │
    18: ───H───H───M─────────────

    19: ───X───H─────────────────
    Sampled results:
    Counter({'0000000000000000000': 1024})
    Secret function:
    f(x) = <1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0>

    Should be a constant function!

    Circuit:
    0: ────H───H───M('result')───
                   │
    1: ────H───H───M─────────────
                   │
    2: ────H───H───M─────────────
                   │
    3: ────H───H───M─────────────
                   │
    4: ────H───H───M─────────────
                   │
    5: ────H───H───M─────────────
                   │
    6: ────H───H───M─────────────
                   │
    7: ────H───H───M─────────────
                   │
    8: ────H───H───M─────────────
                   │
    9: ────H───H───M─────────────
                   │
    10: ───H───H───M─────────────
                   │
    11: ───H───H───M─────────────
                   │
    12: ───H───H───M─────────────
                   │
    13: ───H───H───M─────────────
                   │
    14: ───H───H───M─────────────
                   │
    15: ───H───H───M─────────────
                   │
    16: ───H───H───M─────────────
                   │
    17: ───H───H───M─────────────
                   │
    18: ───H───H───M─────────────
                   │
    19: ───H───H───M─────────────

    20: ───X───H─────────────────
    Sampled results:
    Counter({'00000000000000000000': 1024})

```python
# Plotting the time taken by the algorithm against the number of qubits in the circuit to analyze scalability of the algorithm

plt.scatter(list(range(1,21)), t)
plt.xlabel('Qubits')
plt.ylabel('Time (in seconds)')
plt.title(" Time vs Qubits ")
plt.show()

```

```python

```


# Data Visualization for Exploration

This notebook details data visualization for exploring a dataset. The goal is to understand more about the data as a human, not to make beautiful graphs, communicate, or feature engineering input into models.

```python
import pandas as pd
import numpy as np
import scipy.stats as st

#ggplot equivalent: plotnine
from plotnine import *

#scales package equivalent: mizani
from mizani.breaks import *
from mizani.formatters import *

#widgets
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets

#utility
import utils
def clean_comma(x): return float(str(x).replace(',',''))
```

```python
'''
Snippet for plotnine with thai font by @korakot
https://gist.github.com/korakot/01d181229b21411b0a20784e0ca20d3d
'''
import matplotlib
# !wget https://github.com/Phonbopit/sarabun-webfont/raw/master/fonts/thsarabunnew-webfont.ttf -q
# !cp thsarabunnew-webfont.ttf /usr/share/fonts/truetype/
matplotlib.font_manager._rebuild()
matplotlib.rc('font', family='TH Sarabun New')
theme_set(theme_minimal(11, 'TH Sarabun New'));
```

```python
df = pd.read_csv('data/taladrod.csv')
df['sales_price'] = df.sales_price.map(clean_comma)
df['market_price'] = df.market_price.map(clean_comma)
df.head()
```

      id
      brand
      series
      model
      gen
      year
      color
      gear
      gas
      sales_price
      original_price
      market_price
      description
      contact_location
      subscribers
      scraped_date
      removed_date

      0
      2210000
      HONDA
      JAZZ
      1.5 i-VTEC SV (AS)
      ปี08-13
      2014.0
      สีขาว
      เกียร์ออโต้
      NaN
      488000.0
      NaN
      NaN
      เครดิตดีออกรถ10,000จบครับ\nรับประกันเครื่องเกี...
      กรุงเทพฯ
      1047.0
      2019-05-22
      NaN

      1
      2210001
      TOYOTA
      ESTIMA
      2.4 G HYBRID
      ปี10-ปัจจุบัน
      2013.0
      สีขาว
      เกียร์ออโต้
      NaN
      1677000.0
      NaN
      3050000.0
      TOPสุด Estima Aeras Hybrid รถเข้าเซอร์วิส TOYO...
      กรุงเทพฯ
      182.0
      2019-05-22
      NaN

      2
      2210009
      HONDA
      JAZZ
      1.5 i-VTEC V (AS)
      ปี08-13
      2008.0
      สีน้ำเงิน
      เกียร์ออโต้
      NaN
      338000.0
      NaN
      NaN
      เครดิดีออกรถ10,000จบครับ\nรับประกันเครื่องเกีย...
      กรุงเทพฯ
      1047.0
      2019-05-22
      NaN

      3
      2210012
      FORD
      RANGER
      2.2 WILDTRAK DBL CAB HI-RIDER
      DOUBLECAB
      2016.0
      สีขาว
      เกียร์ออโต้
      NaN
      689000.0
      NaN
      849000.0
      รับรองสภาพ ไม่มีชน มือเดียว พาช่างมาตรวจสภาพรถ...
      กรุงเทพฯ
      760.0
      2019-05-22
      NaN

      4
      2210016
      TOYOTA
      SOLUNA
      VIOS 1.5 E (ABS+AB)
      VIOS ปี13-ปัจจุบัน
      2015.0
      สีบรอนซ์เงิน
      เกียร์ออโต้
      NaN
      359000.0
      NaN
      649000.0
      ไมล์แท้ 99,xxx TOYOTA SOLUNA VIOS 1.5E\nTOYOTA...
      กรุงเทพฯ
      699.0
      2019-05-22
      NaN

## Warming Up: Missing Values

We use grammar of graphics implementation `ggplot` (ported to Python as `plotnine`) to explore the `taladrod` dataset. Grammar of graphics is an especially useful tool since we do not know exactly what kind of plots we want to see and want to be able to add them up as we go.

Source: [A Comprehensive Guide to the Grammar of Graphics for Effective Visualization of Multi-dimensional Data](https://towardsdatascience.com/a-comprehensive-guide-to-the-grammar-of-graphics-for-effective-visualization-of-multi-dimensional-1f92b4ed4149)

```python
missing = utils.check_missing(df)
missing['over90'] = missing.per_missing.map(lambda x: True if x>0.9 else False)
missing.head()
```

      col_name
      per_missing
      rnk
      over90

      0
      original_price
      0.991380
      00_original_price
      True

      1
      gas
      0.936525
      01_gas
      True

      2
      removed_date
      0.886728
      02_removed_date
      False

      3
      market_price
      0.561658
      03_market_price
      False

      4
      subscribers
      0.000641
      04_subscribers
      False

```python
g = (ggplot(missing,aes(x='rnk',y='per_missing',fill='over90')) + #base plot
     geom_col() + #type of plot
     geom_text(aes(x='rnk',y='per_missing+0.1',label='round(100*per_missing,2)')) +#annotate
     scale_y_continuous(labels=percent_format()) + #y-axis tick
     theme_minimal() + coord_flip()#theme and flipping plot
    )
g
```

```python
#drop columns with too many missing values
df.drop(missing[missing.over90==True].col_name,1,inplace=True)
df.head()
```

      id
      brand
      series
      model
      gen
      year
      color
      gear
      sales_price
      market_price
      description
      contact_location
      subscribers
      scraped_date
      removed_date

      0
      2210000
      HONDA
      JAZZ
      1.5 i-VTEC SV (AS)
      ปี08-13
      2014.0
      สีขาว
      เกียร์ออโต้
      488000.0
      NaN
      เครดิตดีออกรถ10,000จบครับ\nรับประกันเครื่องเกี...
      กรุงเทพฯ
      1047.0
      2019-05-22
      NaN

      1
      2210001
      TOYOTA
      ESTIMA
      2.4 G HYBRID
      ปี10-ปัจจุบัน
      2013.0
      สีขาว
      เกียร์ออโต้
      1677000.0
      3050000.0
      TOPสุด Estima Aeras Hybrid รถเข้าเซอร์วิส TOYO...
      กรุงเทพฯ
      182.0
      2019-05-22
      NaN

      2
      2210009
      HONDA
      JAZZ
      1.5 i-VTEC V (AS)
      ปี08-13
      2008.0
      สีน้ำเงิน
      เกียร์ออโต้
      338000.0
      NaN
      เครดิดีออกรถ10,000จบครับ\nรับประกันเครื่องเกีย...
      กรุงเทพฯ
      1047.0
      2019-05-22
      NaN

      3
      2210012
      FORD
      RANGER
      2.2 WILDTRAK DBL CAB HI-RIDER
      DOUBLECAB
      2016.0
      สีขาว
      เกียร์ออโต้
      689000.0
      849000.0
      รับรองสภาพ ไม่มีชน มือเดียว พาช่างมาตรวจสภาพรถ...
      กรุงเทพฯ
      760.0
      2019-05-22
      NaN

      4
      2210016
      TOYOTA
      SOLUNA
      VIOS 1.5 E (ABS+AB)
      VIOS ปี13-ปัจจุบัน
      2015.0
      สีบรอนซ์เงิน
      เกียร์ออโต้
      359000.0
      649000.0
      ไมล์แท้ 99,xxx TOYOTA SOLUNA VIOS 1.5E\nTOYOTA...
      กรุงเทพฯ
      699.0
      2019-05-22
      NaN

## Categorical Variables

We want to know primarily two things about our categorical variables:
1. How each variable is distributed
2. How each variable relate to the dependent variable
    * 2.1 when dependent variable is numerical
    * 2.2 when dependent variable is categorical

```python
cat_vars = ['brand','series','gen','color','gear','contact_location']
cat_df = df[cat_vars].copy()
cat_df.head()
```

      brand
      series
      gen
      color
      gear
      contact_location

      0
      HONDA
      JAZZ
      ปี08-13
      สีขาว
      เกียร์ออโต้
      กรุงเทพฯ

      1
      TOYOTA
      ESTIMA
      ปี10-ปัจจุบัน
      สีขาว
      เกียร์ออโต้
      กรุงเทพฯ

      2
      HONDA
      JAZZ
      ปี08-13
      สีน้ำเงิน
      เกียร์ออโต้
      กรุงเทพฯ

      3
      FORD
      RANGER
      DOUBLECAB
      สีขาว
      เกียร์ออโต้
      กรุงเทพฯ

      4
      TOYOTA
      SOLUNA
      VIOS ปี13-ปัจจุบัน
      สีบรอนซ์เงิน
      เกียร์ออโต้
      กรุงเทพฯ

To simplify the data cleaning step, we "otherify" values that appear less than 3% of the time in all categorical columns.

```python
#otherify popular values; you can (should?) also have a mapping dict
for col in cat_vars: cat_df = utils.otherify(cat_df,col,th=0.03)
```

### Value Distribution

Even without plotting them out, we can see the value distribution in each variable using `ipywidgets`.

```python
interact(utils.value_dist, df =fixed(cat_df),
         col = widgets.Dropdown(options=list(cat_df.columns),value='brand'))
```

    interactive(children=(Dropdown(description='col', options=('brand', 'series', 'gen', 'color', 'gear', 'contact…

    <function utils.value_dist(df, col)>

**Exercise** Implement `cat_plot` function that plots value distribution for each categorical variable.

```python
def cat_plot(df,col):
    return utils.cat_plot(df,col)
#input dataframe and column
#output histogram plot of value distribution

interact(cat_plot, df=fixed(cat_df),
         col = widgets.Dropdown(options=list(cat_df.columns),value='brand'))
```

    interactive(children=(Dropdown(description='col', options=('brand', 'series', 'gen', 'color', 'gear', 'contact…

    <function __main__.cat_plot(df, col)>

```python
#excluding others
def cat_plot_noothers(df,col):
    x = df.copy()
    x = x[x[col]!='others']
    return utils.cat_plot(x,col) + utils.thai_text(8)

interact(cat_plot_noothers, df=fixed(cat_df),
         col = widgets.Dropdown(options=list(cat_df.columns),value='gen'))
```

    interactive(children=(Dropdown(description='col', index=2, options=('brand', 'series', 'gen', 'color', 'gear',…

    <function __main__.cat_plot_noothers(df, col)>

### Numerical and Categorical Variables

```python
#relationship between dependent variable and categorical variable
cat_df['sales_price'] = utils.boxcox(df['sales_price'])
cat_df.head()
```

      brand
      series
      gen
      color
      gear
      contact_location
      sales_price

      0
      HONDA
      others
      ปี08-13
      สีขาว
      เกียร์ออโต้
      กรุงเทพฯ
      13.056226

      1
      TOYOTA
      others
      others
      สีขาว
      เกียร์ออโต้
      กรุงเทพฯ
      14.320520

      2
      HONDA
      others
      ปี08-13
      others
      เกียร์ออโต้
      กรุงเทพฯ
      12.669810

      3
      FORD
      others
      others
      สีขาว
      เกียร์ออโต้
      กรุงเทพฯ
      13.413541

      4
      TOYOTA
      SOLUNA
      others
      สีบรอนซ์เงิน
      เกียร์ออโต้
      กรุงเทพฯ
      12.733758

```python
#relationship between sales price and color
cat_df.groupby('color').sales_price.describe()
```

      count
      mean
      std
      min
      25%
      50%
      75%
      max

      color

      others
      1756.0
      12.568359
      1.019319
      0.000000
      12.072547
      12.542548
      13.028055
      16.905644

      สีขาว
      4207.0
      13.085453
      0.940839
      0.000000
      12.672950
      13.005832
      13.498058
      16.438729

      สีดำ
      2848.0
      13.071142
      0.913027
      0.000000
      12.594734
      13.014780
      13.535466
      16.111071

      สีน้ำตาล
      607.0
      12.660002
      0.814474
      8.853808
      12.144203
      12.782689
      13.140205
      15.635210

      สีบรอนซ์เงิน
      1879.0
      12.760100
      0.923268
      0.000000
      12.421188
      12.779876
      13.151924
      15.854130

      สีเทา
      2740.0
      12.786451
      0.957211
      0.000000
      12.421188
      12.818555
      13.188621
      17.822480

**Exercise** Implement `numcat_plot` function that plots the relationship between a dependent numerical variable and an independent categorical as displayed above. Useful geoms are `geom_boxplot`, `geom_violin` and `geom_jitter`. Optionally remove outliers before plotting.

```python
def numcat_plot(df,num,cat, no_outliers=True, geom=geom_boxplot()):
    return utils.numcat_plot(df,num,cat, no_outliers, geom)
#plot the summary above
```

```python
interact(numcat_plot,
         df=fixed(cat_df),
         num=fixed('sales_price'),
         no_outliers = widgets.Checkbox(value=True),
         geom=fixed(geom_boxplot()), #geom_violin, geom_jitter
         cat= widgets.Dropdown(options=list(cat_df.columns)[:-1],value='gen'))
```

    interactive(children=(Dropdown(description='cat', index=2, options=('brand', 'series', 'gen', 'color', 'gear',…

    <function __main__.numcat_plot(df, num, cat, no_outliers=True, geom=<plotnine.geoms.geom_boxplot.geom_boxplot object at 0x7fa9a455f358>)>

```python
interact(numcat_plot,
         df=fixed(cat_df),
         num=fixed('sales_price'),
         no_outliers = widgets.Checkbox(value=True),
         geom=fixed(geom_violin()), #geom_violin, geom_jitter
         cat= widgets.Dropdown(options=list(cat_df.columns)[:-1],value='series'))
```

    interactive(children=(Dropdown(description='cat', index=1, options=('brand', 'series', 'gen', 'color', 'gear',…

    <function __main__.numcat_plot(df, num, cat, no_outliers=True, geom=<plotnine.geoms.geom_boxplot.geom_boxplot object at 0x7fa9a455f358>)>

Sometimes we want to see the numerical distribution filled with categories. This is especially useful plotting the results of a binary classification.

```python
def numdist_plot(df, num,cat, geom=geom_density(alpha=0.5), no_outliers=True):
    return utils.numdist_plot(df, num, cat, geom, no_outliers)

#either
#density: geom_density(alpha=0.5)
#histogram: geom_histogram(binwidth=0.5, position='identity',alpha=0.5)
#position: identity or dodge
numdist_plot(cat_df,'sales_price','gear')
```

```python
numdist_plot(cat_df,'sales_price','gear',
             geom=geom_histogram(binwidth=0.5, position='dodge',alpha=0.5))
```

### Categorical and Categorical Variables

**Exercise** We can cross-tabulate categorical variables to see their relationship by using `facet_wrap`; for instance, if our dependent variable is `gear` and indpendent variable of interest is `color`.

```python
def catcat_plot(df, cat_dep, cat_ind):
    return utils.catcat_plot(df,cat_dep,cat_ind)
```

```python
interact(catcat_plot,
         df=fixed(cat_df),
         cat_dep=widgets.Dropdown(options=list(cat_df.columns)[:-1],value='gear'),
         cat_ind= widgets.Dropdown(options=list(cat_df.columns)[:-1],value='color'))
```

    interactive(children=(Dropdown(description='cat_dep', index=4, options=('brand', 'series', 'gen', 'color', 'ge…

    <function __main__.catcat_plot(df, cat_dep, cat_ind)>

### Multiple Ways of Relationships

You can use `facet_grid` to display multiple ways of relationships; but keep in mind that this is probably what your model is doing anyways so it might not be most human-readable plot to explore.

```python
#getting fancy; not necessarily the best idea
new_df = utils.remove_outliers(cat_df,'sales_price')
g = (ggplot(new_df, aes(x='gen',y='sales_price')) +
     geom_boxplot() + theme_minimal() +
     facet_grid('contact_location~color') +
     theme(axis_text_x = element_text(angle = 90, hjust = 1))
    ) + utils.thai_text(8)
g
```

## Numerical Variables

We want to know two things about numerical variables:
1. Their distributions
2. Their relationships with one another; possibly this involves transforming variables to make them less skewed aka more difficult to see variations

```python
import datetime
now = datetime.datetime.now()
df['nb_year'] = now.year - df['year']
num_vars = ['nb_year','sales_price','market_price','subscribers']
num_df = df[num_vars].dropna() #this is why you need to deal with missing values BEFORE exploration
num_df.describe()
```

      nb_year
      sales_price
      market_price
      subscribers

      count
      6150.000000
      6.150000e+03
      6.150000e+03
      6150.000000

      mean
      4.512195
      7.120724e+05
      1.333557e+06
      525.634959

      std
      2.026358
      7.745356e+05
      1.288468e+06
      386.841217

      min
      0.000000
      1.000000e+00
      3.690000e+05
      1.000000

      25%
      3.000000
      3.390010e+05
      6.490000e+05
      191.250000

      50%
      5.000000
      4.790010e+05
      8.770000e+05
      423.000000

      75%
      6.000000
      7.590010e+05
      1.445000e+06
      772.000000

      max
      8.000000
      1.297000e+07
      1.645000e+07
      1469.000000

`seaborn` has an excellent `pairplot` implementation which not only shows the distribution of values but also their relathionships. It seems like we can get what we want easily; however, as we can see `sales_price` and `market_price` are a little skewed, making it more difficult to see their relationships with other more spread out variables.

```python
import seaborn as sns
sns.pairplot(num_df) #non-normal data is a problem!
```

In a lot of cases, a variable with normally distributed values have more variations and easier for us to see their relationships with other variables. We will try to transform our skewed variables to more "normal" ones to see if that helps.

**Q-Q plot** compares two probability distributions by plotting their quantiles against each other. We can use this to determine the normality of a variable by plotting the sample quantiles (from the data we have) against its theoretical quantiles (where the quantiles would be if the variable is normally distributed).

```python
interact(utils.qq_plot, df=fixed(num_df),
         col=widgets.Dropdown(options=list(num_df.columns)))
```

    interactive(children=(Dropdown(description='col', options=('nb_year', 'sales_price', 'market_price', 'subscrib…

    <function utils.qq_plot(df, col)>

**Box-Cox transformation** is a statistical technique used to make data look like more normally distributed.

\begin{align}
g_\lambda(y) = \left\{
\begin{array}{lr}\displaystyle\frac{y^\lambda - 1}{\lambda} &  \lambda \neq 0\\
        & \\
       \log(y) &  \lambda = 0
     \end{array}
   \right.
\end{align}

**Exercise** Implement `boxcox` transformation according to the equation above.

```python
def boxcox(ser,lamb=0):
    pass
#input a column from pandas dataframe
#output transformed column
```

One way of choosing the hyperparameter $\lambda$ is to look at the Q-Q plot and choose transformation which makes the slope closest to 1.

```python
#see transformation results
def what_lamb(df,col,lamb):
    sample_df = df.copy()
    former_g = utils.qq_plot(sample_df,col)
    sample_df[col] = utils.boxcox(sample_df[col],lamb)
    print(utils.qq_plot(sample_df,col),former_g)

interact(what_lamb, df=fixed(num_df),
         col=widgets.Dropdown(options=list(num_df.columns),value='sales_price'),
         lamb=widgets.FloatSlider(min=-3,max=3,step=0.5,value=0)
         )
```

    interactive(children=(Dropdown(description='col', index=1, options=('nb_year', 'sales_price', 'market_price', …

    <function __main__.what_lamb(df, col, lamb)>

This can also be automated by plotting a slope for each arbitary $\lambda$; for instance from -3 to 3.

```python
lamb_df = utils.boxcox_lamb_df(num_df.subscribers)
interact(utils.boxcox_plot, df=fixed(num_df),
         col=widgets.Dropdown(options=list(num_df.columns),value='sales_price'),
         ls=fixed([i/10 for i in range(-30,31,5)])
         )
```

    interactive(children=(Dropdown(description='col', index=1, options=('nb_year', 'sales_price', 'market_price', …

    <function utils.boxcox_plot(df, col, ls=[-3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0])>

```python
#transform sales and market prices
for col in ['sales_price','market_price']:
    num_df['new_'+col] = utils.boxcox(num_df[col], utils.boxcox_lamb(num_df[col]))
```

You can see that post transformation, we can see the (lack of) relationships between variables clearer.

```python
sns.pairplot(num_df[['nb_year','new_sales_price','new_market_price','subscribers']]) #a little better!
```

For our example, we have only four numerical variables; but imagine when you have ten or more. You may want to plot their distributions separately from relationships.

```python
num_m = num_df.melt()
num_m.head()
```

      variable
      value

      0
      nb_year
      6.0

      1
      nb_year
      3.0

      2
      nb_year
      4.0

      3
      nb_year
      4.0

      4
      nb_year
      7.0

**Exercise** Implement `value_dist_plot` to plot value distribution of all variables.

```python
def value_dist_plot(df,bins=30):
    return utils.value_dist_plot(df,bins)
#input dataframe with only numerical variables
#output distribution plot for each variable
value_dist_plot(num_df)
```

Likewise in case there are too many pairs of relationships, you might plot the relationships pair-by-pair with `ipywidget` and `seaborn`'s `jointplot` function.

```python
interact(utils.jointplot, df=fixed(num_df),
         col_x= widgets.Dropdown(options=list(num_df.columns),value='sales_price'),
         col_y=widgets.Dropdown(options=list(num_df.columns),value='market_price'),
         kind=widgets.Dropdown(options=['scatter','resid','reg','hex','kde','point'],value='scatter'))
```

    interactive(children=(Dropdown(description='col_x', index=1, options=('nb_year', 'sales_price', 'market_price'…

    <function utils.jointplot(df, col_x, col_y, no_outliers=True, kind='reg')>

As you might have noticed, we have not used any statistical concept to describe the relationship, and that is by design. We can also see correlation table with a simple `pandas` function:

```python
#correlation plot if you must; but it's just ONE number for the relationship
num_df.corr(method='pearson').style.background_gradient(cmap='coolwarm')
```

        	        nb_year	        sales_price	        market_price	        subscribers	        new_sales_price	        new_market_price

                        nb_year
                        1
                        -0.220633
                        -0.00786656
                        0.163404
                        -0.275434
                        -0.0152819

                        sales_price
                        -0.220633
                        1
                        0.862739
                        -0.07795
                        0.955499
                        0.819534

                        market_price
                        -0.00786656
                        0.862739
                        1
                        -0.063786
                        0.858924
                        0.948289

                        subscribers
                        0.163404
                        -0.07795
                        -0.063786
                        1
                        -0.0165204
                        0.039791

                        new_sales_price
                        -0.275434
                        0.955499
                        0.858924
                        -0.0165204
                        1
                        0.882803

                        new_market_price
                        -0.0152819
                        0.819534
                        0.948289
                        0.039791
                        0.882803
                        1

```python
def pearson_corr(x,y):
    sub_x = x - x.mean()
    sub_y = y - y.mean()
    return (sub_x * sub_y).sum() / np.sqrt((sub_x**2).sum() * (sub_y**2).sum())

#spearman and kendall: pearson with rank variables
pearson_corr(df.nb_year,df.sales_price)
```

    -0.23316757399518453

However, the famous Anscombe plots show us that it is always better to look at distribution rather than a summary number.

Source: [A Comprehensive Guide to the Grammar of Graphics for Effective Visualization of Multi-dimensional Data](https://towardsdatascience.com/a-comprehensive-guide-to-the-grammar-of-graphics-for-effective-visualization-of-multi-dimensional-1f92b4ed4149)

```python

```