class Node:
  def __init__(self, name):
    self.name = name
    self.address = None
    self.neighbors = []

  def add_neighbors(self, *neighbors):
    self.neighbors += neighbors

  def assign_addresses(self, lowest_free_address):
    if self.address == None:
      self.address = lowest_free_address
      print('node', self.name, '<- address', self.address)
      lowest_free_address += 1
      for nb in self.neighbors:
        lowest_free_address = nb.assign_addresses(lowest_free_address)
    return lowest_free_address

#     __    __
#  __/D \__/I \__
# /A \__/G \__/L \
# \__/E \__/J \__/
# /B \__/H \__/M \
# \__/F \__/K \__/
# /C \__/  \__/N \
# \__/        \__/

A = Node('A')
B = Node('B')
C = Node('C')
D = Node('D')
E = Node('E')
F = Node('F')
G = Node('G')
H = Node('H')
I = Node('I')
J = Node('J')
K = Node('K')
L = Node('L')
M = Node('M')
N = Node('N')

A.add_neighbors(B, E, D)
B.add_neighbors(C, F, E, A)
C.add_neighbors(F, B)
D.add_neighbors(A, E, G)
E.add_neighbors(F, H, G, D, A, B)
F.add_neighbors(H, E, B, C)
G.add_neighbors(D, E, H, J, I)
H.add_neighbors(K, J, G, E, F)
I.add_neighbors(G, J, L)
J.add_neighbors(K, M, L, I, G, H)
K.add_neighbors(N, M, J, H)
L.add_neighbors(I, J, M)
M.add_neighbors(L, J, K, N)
N.add_neighbors(M, K)

n = E.assign_addresses(0)
print(n, ' addresses assigend')
