solution.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. #!/usr/bin/env python3
  2. import sys
  3. from queue import PriorityQueue
  4. from dataclasses import dataclass
  5. class Bounds:
  6. width = 0
  7. height = 0
  8. @dataclass(order=True)
  9. class Pos:
  10. x: int
  11. y: int
  12. def bound(pos):
  13. return pos.x >= 0 and pos.y >= 0 and pos.x < Bounds.width and pos.y < Bounds.height
  14. def adjacent(pos):
  15. adjacents = []
  16. for i in range(-1, 2):
  17. for j in range(-1, 2):
  18. if i == j or i == -j: continue
  19. if bound(Pos(pos.x + j, pos.y + i)):
  20. adjacents.append(Pos(pos.x + j, pos.y + i))
  21. return adjacents
  22. risks = []
  23. costs = []
  24. visited = []
  25. for line in sys.stdin:
  26. risks.append([int(r) for r in line.rstrip('\n')])
  27. costs.append([sys.maxsize for r in line.rstrip('\n')])
  28. visited.append([False for r in line.rstrip('\n')])
  29. l = len(line.rstrip('\n'))
  30. if l > Bounds.width: Bounds.width = l
  31. h = len(risks)
  32. if h > Bounds.height: Bounds.height = h
  33. q = PriorityQueue()
  34. costs[0][0] = 0
  35. risks[0][0] = 0
  36. q.put((risks[0][0], Pos(0, 0)))
  37. while not q.empty():
  38. cost, pos = q.get()
  39. visited[pos.y][pos.x] = True
  40. for a in adjacent(pos):
  41. new_cost = cost + risks[a.y][a.x]
  42. if new_cost < costs[a.y][a.x]: costs[a.y][a.x] = new_cost
  43. if not visited[a.y][a.x]:
  44. q.put((new_cost, a))
  45. # results
  46. print(f'risk (cost so far)')
  47. print('\n'.join(['\t'.join([f'{c}({risks[y][x]})' for x, c in enumerate(row)]) for y, row in enumerate(costs)]))
  48. print(f'{costs[Bounds.height - 1][Bounds.width - 1]} is the lowest total risk of any path from top left (0, 0) to bottom right ({Bounds.height - 1}, {Bounds.width - 1})')