Unicode Transformation Format – 8-bit
As the name suggests UTF-8 was designed to encode data in a stream of bytes.

It works by splitting the bits up in multiples of eight. This is achieved by inserting headers to mark in how many bytes the bits were split. If the bits need to be split in two, the header `110` is added as prefix leaving five bits of the byte for the rest of the data. Followed by a continuation byte.

A continuation byte always start with `10` leaving six bits for data.
For a three-way split: the header `1110` is added with two continuation bytes and for four: `11110` with three continuation bytes. The number of ones at the start of the first byte denotes the number of bytes the data was split in.
# Task
Your task is to write two functions:
1. `to_utf8_binary`: which encodes a string to a bitstring using UTF-8 encoding.
2. `from_utf8_binary`: which does the reverse.

- Layout of UTF-8 byte sequences:
```
# BYTES  FIRST CODE POINT  LAST CODE POINT    BYTE 1      BYTE 2      BYTE 3      BYTE 4
    1                   0              127    0xxxxxxx  
    2                 128             2047    110xxxxx    10xxxxxx
    3                2048            65535    1110xxxx    10xxxxxx    10xxxxxx  
    4               65536          1114111    11110xxx    10xxxxxx    10xxxxxx    10xxxxxx
```

# Examples
```
ENCODE
 A  -> 1000001         -> 01000001
 八 -> 101000101101011 -> 1110-0101 10-000101 10-101011
 
DECODE
 110-00010 10-100111                     -> 10100111          -> §
 11110-000 10-010000 10-001010 10-001100 -> 10000001010001100 -> 𐊌
```
* Spaces and hyphens just for clarity
- https://en.wikipedia.org/wiki/UTF-8#Encoding

```python

USER_FILENAME = "<user_code>"
import sys, json, builtins
import math, heapq, bisect, itertools, functools, collections, statistics, fractions, decimal, operator, array, random, re, string, os, pathlib
try:
    import resource as _res
except Exception:
    _res = None
from collections import Counter, defaultdict, deque, OrderedDict
from functools import lru_cache, reduce
from itertools import accumulate, permutations, combinations, product
from math import gcd, ceil, floor, sqrt
from decimal import Decimal
try:
    from typing import *
except Exception:
    pass
try:
    sys.setrecursionlimit(1_000_000)
except Exception:
    pass
try:
    import site as _site
    try:
        _sys_sites = _site.getsitepackages() if hasattr(_site, "getsitepackages") else []
        for _p in _sys_sites:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
    try:
        _usp = _site.getusersitepackages()
        if isinstance(_usp, str):
            _usp = [_usp]
        for _p in _usp:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
except Exception:
    pass

def _disabled_input(*args, **kwargs):
    raise RuntimeError("input() is disabled in callable mode")
builtins.input = _disabled_input

ns = {"__name__": "__judge__"}  # prevent if __name__ == "__main__" blocks
for _k, _v in list(globals().items()):
    if not _k.startswith("_"):
        ns[_k] = _v
_CODE = "def to_utf8_binary(string):\n    \n    stList = list(string)\n    bincodes = [toBin(c) for c in stList ]\n    return ''.join(bincodes)\ndef toBin(string) :      \n    print((ord(string)))\n    a =  bin(ord(string))[2:]\n    if(ord(string) <= 127) :\n        padded = a.zfill(8)\n        return (padded)\n    elif ord(string) <= 2047 : \n         padded = a.zfill(11)\n         return '110' +  padded[:5] + '10' + padded[5:]\n    elif ord(string) <= 65535 : \n        padded = a.zfill(16)\n        part1 = '1110' + padded[:4]\n        remaining = padded[4:]\n        part2 = '10' + remaining[:6]\n        remaining = remaining[6:]\n        part3 = '10' + remaining\n        return part1 + part2 + part3\n    elif ord(string) <= 1114111 :\n        print(a)\n        padded = a.zfill(21)\n        part1 = '11110' + padded[:3]\n        print(part1)\n        remaining = padded[3:]\n        part2 = '10' + remaining[:6]\n        print(part2)\n        remaining = remaining[6:]\n        part3 = '10' + remaining[:6]\n        remaining = remaining[6:]\n        part4 = '10' + remaining[:6]\n        return part1 + part2 + part3+part4\n\n\ndef splitEveryN(n, li):\n    return [li[i:i+n] for i in range(0, len(li), n)]\n\ndef getLenInByte(part):\n    print(part)\n    if part[0] == '0' : \n        return 1\n    elif part[:3] == '110' : \n        print('two bytes')\n        return 2\n    elif part[:4] == '1110' : \n        return 3\n    elif part[:5] == '11110'  : #4 byte\n        return 4\n\ndef from_utf8_binary(bitstring):\n    li = splitEveryN(8, bitstring)\n    i = 0\n    result=[]\n    while(i < len(li)) :\n        bytelen = getLenInByte(li[i])\n        nextbin = li[i : i+bytelen]\n        joined = ''.join(nextbin)\n        \n        frombin = fromBin(joined)\n        result +=  frombin #li[i] is a string\n        i +=  bytelen\n    return ''.join(result)\n\n\ndef fromBin(bitstring):\n    if len(bitstring) <= 8 : \n        return chr(int(bitstring,2))\n    elif len(bitstring) <= 16 : \n        part1 = bitstring[3:8]\n        part2 = bitstring[10:16]\n        bi = part1+part2\n        return chr(int(bi,2))\n    elif len(bitstring) <=24 : \n        part1 = bitstring[4:8]\n        part2 = bitstring[10:16]\n        part3 = bitstring[18:]\n        return chr(int(part1+part2+part3, 2))\n    elif len(bitstring) <= 32 : \n        part1 = bitstring[5:8]\n        part2 = bitstring[10:16]\n        part3 = bitstring[18:24]\n        part4 = bitstring[26:]\n        return chr(int(part1 + part2+ part3+part4, 2))\n    return ''\n\n\n\n        \n"
_co = compile(_CODE, USER_FILENAME, "exec")
exec(_co, ns, ns)

_target = None
_fn_name = 'to_utf8_binary'
if _fn_name:
    if "Solution" in ns:
        try:
            _obj = ns["Solution"]()
            if hasattr(_obj, _fn_name):
                _target = getattr(_obj, _fn_name)
        except Exception:
            _target = None
    if _target is None and _fn_name in ns and callable(ns[_fn_name]):
        _target = ns[_fn_name]
# Fallback: if there's exactly one user-defined function, use it
if _target is None:
    _cands = [v for k, v in ns.items() if callable(v) and getattr(v, "__module__", "") in ("__judge__", "__main__")]
    _user_funcs = [c for c in _cands if getattr(c, "__name__", "").startswith("_") is False]
    if len(_user_funcs) == 1:
        _target = _user_funcs[0]
if _target is None:
    raise RuntimeError(f"Could not resolve callable '{_fn_name}'")

_raw = sys.stdin.read().strip()
if _raw:
    _parsed = json.loads(_raw)
    if isinstance(_parsed, dict):
        _kwargs = _parsed.get("kwargs", {})
        _args = _parsed.get("args", [])
    else:
        _args, _kwargs = _parsed, {}
else:
    _args, _kwargs = [], {}
if not isinstance(_args, (list, tuple)):
    _args = [_args]
_res = _target(*_args, **_kwargs)
try:
    sys.stdout.write(repr(_res) + "\n")
except Exception:
    pass

```

Measured memory_bytes: 6928