**Background**   
You most probably know, that the *kilo* used by IT-People differs from the
*kilo* used by the rest of the world. Whereas *kilo* in kB is (mostly) intrepreted as 1024 Bytes (especially by operating systems) the non-IT *kilo* denotes the factor 1000 (as in "1 kg is 1000g"). The same goes for the prefixes mega, giga, tera, peta and so on.
To avoid misunderstandings (like your hardware shop selling you a 1E+12 Byte harddisk as 1 TB, whereas  your Windows states that it has only 932 GB, because the shop uses factor 1000 whereas operating systems use factor 1024 by default) the  International Electrotechnical Commission has proposed to use **kibibyte** for 1024 Byte.The according unit symbol would be **KiB**. Other Prefixes would be respectivly:   

```
1 MiB = 1024 KiB   
1 GiB = 1024 MiB   
1 TiB = 1024 GiB     
```

**Task**   
Your task is to write a conversion function between the kB and the KiB-Units. The function receives as parameter a memory size including a unit and converts into the corresponding unit of the other system:


```
memorysizeConversion ( "10 KiB") -> "10.24 kB"   
memorysizeConversion ( "1 kB") -> "0.977 KiB"   
memorysizeConversion ( "10 TB") -> "9.095 TiB"   
memorysizeConversion ( "4.1 GiB") -> "4.402 GB"   
```

**Hints**
- the parameter always contains a (fractioned) number, a whitespace and a valid unit
- units are case sensitive, valid units are **kB MB GB TB KiB MiB GiB TiB**
- result must be rounded to 3 decimals (round half up,no trailing zeros) see examples above

**Resources**
If you want to read more on ...ibi-Units:  
https://en.wikipedia.org/wiki/Kibibyte

Difficulty: introductory

Starter code:

def memorysize_conversion(memorysize):
	

Solutions:
def memorysize_conversion(memorysize):
    [value, unit] = memorysize.split(" ")
    kibis = ["KiB", "MiB", "GiB", "TiB"]
    kilos = ["kB", "MB", "GB", "TB"]
    if unit in kibis:
        return (str(round(float(value)*pow(1.024, kibis.index(unit)+1), 3))+" "+kilos[kibis.index(unit)])
    else:
        return (str(round(float(value)/pow(1.024, kilos.index(unit)+1), 3))+" "+kibis[kilos.index(unit)])

CONV = {'KiB': 'kB', 'MiB': 'MB', 'GiB': 'GB', 'TiB': 'TB',
        'kB': 'KiB', 'MB': 'MiB', 'GB': 'GiB', 'TB': 'TiB'}

def memorysize_conversion(size):
    val, unit = size.split()
    val = float(val)
    p = 'KMGT'.index(unit[0].upper()) + 1
    
    r = 1.024 if 'i' in unit else 1 / 1.024
    
    return '%s %s' % (round(val * r ** p, 3), CONV[unit])

def memorysize_conversion(size):
    x, unit = size.upper().split()
    x, (u, *i, _) = float(x), unit
    op = float.__mul__ if i else float.__truediv__
    p, conv = "_KMGT".index(u), f"{u}{'' if i else 'i'}B"
    return f"{round(op(x, 1.024**p), 3)} {conv}".replace("KB", "kB")

v1, v2 = 1000/1024, 1024/1000

D1 = {"kB":v1, "MB":v1**2, "GB":v1**3, "TB":v1**4,
      "KiB":v2, "MiB":v2**2, "GiB":v2**3, "TiB":v2**4}
      
D2 = {"kB":"KiB", "MB":"MiB", "GB":"GiB", "TB":"TiB",
      "KiB":"kB", "MiB":"MB", "GiB":"GB", "TiB":"TB"}

def memorysize_conversion(memorysize):
    x, y = memorysize.split()
    return f"{round(float(x) * D1[y], 3)} {D2[y]}"

from decimal import Decimal, ROUND_HALF_UP

units = 'KMGT'
q = Decimal('0.001')

def memorysize_conversion(memorysize):
    n, unit = memorysize.split()
    n = Decimal(n)
    i = units.find(unit[0].upper()) + 1
    if unit[1] == 'i':
        n *= 1024 ** i
        n /= 1000 ** i
        new_unit = ['kB', 'MB', 'GB', 'TB'][i-1]
    else:
        n *= 1000 ** i
        n /= 1024 ** i
        new_unit = ['KiB', 'MiB', 'GiB', 'TiB'][i-1]
    new_value = format(n.quantize(n, rounding=ROUND_HALF_UP), '.3f').rstrip('0.')
    return f'{new_value} {new_unit}'

kibi = ['KiB', 'MiB', 'GiB', 'TiB']
si = ['kB', 'MB', 'GB', 'TB']

def memorysize_conversion(size):
    val, unit = size.split()
    n = 'KMGT'.index(unit[0].upper())
    
    if unit in kibi:
        return '%s %s' % (round(float(val) * 1.024 ** (n+1), 3), si[n])
    else:
        return '%s %s' % (round(float(val) / 1.024 ** (n+1), 3), kibi[n])

d = {'KiB':1.024,'kB':0.9765625,'GiB':1.073741824,'GB':0.93132257461548,'MiB':1.048576,'MB':0.95367431640625,'TiB':1.099511627776,'TB':0.90949470177293}
to = {'KiB':' kB','GiB':' GB','MiB':' MB','TiB':' TB','TB':' TiB','GB':' GiB','MB':' MiB','kB':' KiB'}
memorysize_conversion=lambda m:str(round(float(m.split()[0]) * d[m.split()[1]],3)) + to[m.split()[1]]

d={'k':1,'m':2,'g':3,'t':4}
def memorysize_conversion(memorysize):
    n,u=memorysize.split(' ')
    n=float(n)
    x=d[u[0].lower()]
    if u[1]=='i':
        n=round(n*(1.024**x),3)
        return '{} {}{}'.format(n,u[0],u[2]).replace('K','k')
    else:
        n=round(n/(1.024**x),3)
        return '{} {}i{}'.format(n,u[0].upper(),u[1])

DCT_TO_IB = { unit: 1.024**p for unit,p in zip('KMGT',range(1,5)) }

def memorysize_conversion(s):
    toB = s[-2]=='i'
    v,u  = s.split()
    unit = (u[0]!='K' and u[0] or 'k')+u[-1] if toB else  u[0].upper()+"i"+u[-1]
    out  = float(v) * DCT_TO_IB[u[0].upper()]**(toB or -1)
    out  = f'{ out :.3f}'.rstrip('0')
    return f'{out} {unit}'

def memorysize_conversion(s):
    a, b = s.split()
    n, m, i = (1024, 1000, "") if "i" in b else (1000, 1024, "i")
    p = " KMGT".index(b[0].upper())
    return f"{round(float(a) * n**p / m**p, 3)} {'k' if b[0] == 'K' else b[0].upper()}{i}B"