Take the following IPv4 address: `128.32.10.1`

This address has 4 octets where each octet is a single byte (or 8 bits).

* 1st octet `128` has the binary representation: `10000000`
* 2nd octet `32` has the binary representation: `00100000`
* 3rd octet `10` has the binary representation: `00001010`
* 4th octet `1` has the binary representation: `00000001`

So `128.32.10.1` == `10000000.00100000.00001010.00000001`

Because the above IP address has 32 bits, we can represent it as the unsigned 32 bit number: `2149583361`

Complete the function that takes an unsigned 32 bit number and returns a string representation of its IPv4 address.

## Examples
```
2149583361 ==> "128.32.10.1"
32         ==> "0.0.0.32"
0          ==> "0.0.0.0"
```

Difficulty: introductory

Starter code:

def int32_to_ip(int32):
	

Solutions:
from ipaddress import IPv4Address

def int32_to_ip(int32):
    return str(IPv4Address(int32))

def int32_to_ip(int32):
    return '{}.{}.{}.{}'.format(*int32.to_bytes(4, 'big'))

from ipaddress import ip_address

def int32_to_ip(int32):
    return str(ip_address(int32))

def int32_to_ip(i):
    return '.'.join([str(x) for x in [i >> 24 & 0xFF, 
                                      i >> 16 & 0xFF,
                                      i >> 8 & 0xFF,
                                      i & 0xFF]])

import ipaddress
def int32_to_ip(int32):
    return str(ipaddress.IPv4Address(int32))


def int32_to_ip(int32):
    """
    The solution involves bitwise AND of int32 and a mask that we can shift around.
    Say we have the number 17194 (0b0100001100101010). This can be divided into 2
    bytes: 01000011 and 00101010.
    We can AND this with a byte that is filled with 1s - 255 (0b11111111), shifted
    left by a certain amount of bytes to get the digits in that byte:
    01000011 00101010 # 17194
    11111111 00000000 # 255 << 8
    01000011 00000000 # 17194 & 255 << 8
    However, we need to shift this value *back* to get a number within (0,255)
    inclusive, as required, so shift right by the same amount.
    """
    first = (int32 & (255 << 24)) >> 24
    second = (int32 & (255 << 16)) >> 16
    third = (int32 & (255 << 8)) >> 8
    fourth = int32 & 255
    return f"{first}.{second}.{third}.{fourth}"

# convert binary
def convert_bin(arr):
  summa = 0
  for x,y in enumerate(arr[::-1]):
    summa = summa + 2**x * int(y)
  return summa
  
  
def int32_to_ip(int32):

  n = ""

  while int32 > 0:
    y = str(int32 % 2)
    n = y + n
    int32 = int(int32 / 2)


  if len(n) != 32: # make 32 bit
    while len(n) != 32:
      n = '0' + n

  a = n[:8] # first 8
  b = n[8:16] # secound 8
  c = n[16 : 24] # third 8
  d = n[24 : 32] # fourth 8

  return(str(convert_bin(a))+'.'+str(convert_bin(b))+'.'+str(convert_bin(c))+'.'+str(convert_bin(d)))

def int32_to_ip(int32):
    # your code here
    
    octets = []
    octets.append(str( (int32 & 0xFF000000) >> 24))
    octets.append(str( (int32 & 0x00FF0000) >> 16))
    octets.append(str(  (int32 & 0x0000FF00) >> 8))
    octets.append(str(int32 & 0x000000FF))
    return '.'.join(octets)

def int32_to_ip(int32):
  return '.'.join([str(int(bin(int32)[2:].zfill(32)[i:i+8], 2)) for i in range(0, 32, 8)])

from re import sub
def int32_to_ip(int32):
  return sub(r'(\d{8})', lambda x: str(int(x.group(), 2))+'.' , '{0:32b}'.format(int32).replace(' ', '0'))[:-1]