input: Write a function to solve the Towers of Hanoi game by recursively moving disks from the source rod to the target rod using a spare rod. The function should print the moves and update the rods' state accordingly. If there's only one disk to move, it should simply print the move from source to target. The function should handle the base case of no disks to move by doing nothing. 
  
  assert hanoi(8, [(i, "A") for i in range(1, 9)], [], []): 
  "Moving disk 1 from A to B"
  "Moving disk 2 from A to C"
  ...
  "Moving disk 8 from A to C"
output: def hanoi(n, source, target, spare):
      if n == 0:
          return
      hanoi(n-1, source, spare, target)
      disk, src_rod = source.pop(0)
      target.insert(0, (disk, src_rod))
      print(f"Moving disk {disk} from {src_rod} to {target[0][1]}")
      hanoi(n-1, spare, target, source)