09_diskfrag.py 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. #!/usr/bin/env python3
  2. import sys
  3. def parse(digits):
  4. files = []
  5. free = []
  6. is_file = True
  7. pos = 0
  8. for size in map(int, digits):
  9. if is_file:
  10. files.append((len(files), pos, size))
  11. else:
  12. free.append((pos, size))
  13. pos += size
  14. is_file = not is_file
  15. return files, free
  16. def move_blocks(free, files):
  17. fid = len(files) - 1
  18. for i, (free_pos, free_size) in enumerate(free):
  19. while free_size:
  20. _, pos, size = files[fid]
  21. if pos < free_pos:
  22. return checksum(files)
  23. moved = min(size, free_size)
  24. files.append((fid, free_pos, moved))
  25. files[fid] = fid, pos, size - moved
  26. free_pos += moved
  27. free_size -= moved
  28. fid -= moved == size
  29. def move_files(free, files):
  30. for fid, pos, size in reversed(files):
  31. for i, (free_pos, free_size) in enumerate(free):
  32. if free_pos > pos:
  33. break
  34. if free_size >= size:
  35. files[fid] = fid, free_pos, size
  36. free[i] = free_pos + size, free_size - size
  37. break
  38. return checksum(files)
  39. def checksum(files):
  40. return sum((pos + i) * fid for fid, pos, size in files for i in range(size))
  41. files, free = parse(sys.stdin.read().rstrip())
  42. print(move_blocks(free, list(files)))
  43. print(move_files(free, files))