/src/mine.py

https://bitbucket.org/dtim/icfpc2012
Python | 186 lines | 145 code | 26 blank | 15 comment | 48 complexity | 80e6cfe6b84b1306e6ce79690cd45283 MD5 | raw file
  1. # coding=utf-8
  2. import sys
  3. import copy
  4. from cell import *
  5. # cell objects
  6. EMPTY_CELL = EmptyCell()
  7. WALL_CELL = WallCell()
  8. ROCK_CELL = RockCell()
  9. EARTH_CELL = EarthCell()
  10. GOLD_CELL = GoldCell()
  11. ROBOT_CELL = RobotCell()
  12. def decode_cell(c):
  13. if c == 'R':
  14. return ROBOT_CELL
  15. if c == '@':
  16. return WALL_CELL # really it's a higher order lambda
  17. if c == 'W':
  18. return WALL_CELL # really it's a Wadler's Beard
  19. if c == '#':
  20. return WALL_CELL
  21. if c == '*':
  22. return ROCK_CELL
  23. if c == '.':
  24. return EARTH_CELL
  25. if c == '!':
  26. return EARTH_CELL # really it's a Hutton's Razor
  27. if c == '\\':
  28. return GOLD_CELL
  29. if c == 'O':
  30. return LiftCell(True)
  31. if c == 'L':
  32. return LiftCell(False)
  33. if c in "ABCDEFGHI":
  34. return TeleportCell(c)
  35. if c in "123456789":
  36. return TargetCell(c)
  37. return EMPTY_CELL
  38. class Mine:
  39. def __init__(self):
  40. self.rows = []
  41. self.height = 0
  42. self.width = 0
  43. self.water = 0
  44. self.flooding = 0
  45. self.waterproof = 10
  46. self.robot_position = None
  47. self.gold = 0
  48. self.teleports = {}
  49. def clone(self):
  50. return copy.deepcopy(self)
  51. def update(self, otherMine):
  52. self.rows = otherMine.rows
  53. def xy_to_rc(self, xy):
  54. return (self.height - xy[1], xy[0] - 1)
  55. def rc_to_xy(self, rc):
  56. return (rc[1] + 1, self.height - rc[0])
  57. def __getitem__(self, xy):
  58. return self.at(xy)
  59. def __setitem__(self, xy, value):
  60. (r, c) = self.xy_to_rc(xy)
  61. if r < 0 or r >= self.height or c < 0 or c >= self.width:
  62. raise Exception("Invalid coordinates")
  63. self.rows[r][c] = value
  64. def at(self, xy):
  65. (r, c) = self.xy_to_rc(xy)
  66. if r < 0 or r >= self.height or c < 0 or c >= self.width:
  67. return WALL_CELL
  68. if c >= len(self.rows[r]):
  69. return EMPTY_CELL
  70. return self.rows[r][c]
  71. def dump(self):
  72. from cStringIO import StringIO
  73. file_str = StringIO()
  74. for row in self.rows:
  75. for cell in row:
  76. file_str.write(cell.show())
  77. file_str.write("\n")
  78. file_str.write("\n")
  79. if self.water > 0 or self.flooding > 0 or self.waterproof != 10:
  80. file_str.write("Water %d\n" % self.water)
  81. file_str.write("Flooding %d\n" % self.flooding)
  82. file_str.write("Waterproof %d\n" % self.waterproof)
  83. if self.teleports:
  84. for ts in self.teleports.keys():
  85. file_str.write("Trampoline %(s)s targets %(t)s\n" % \
  86. {"s" : ts, "t" : self.teleports[ts]})
  87. return file_str.getvalue()
  88. def update_positions(self, teleports):
  89. sources = {}
  90. targets = {}
  91. x = 1
  92. y = self.height
  93. for row in self.rows:
  94. for cell in row:
  95. cell_type = cell.type()
  96. if cell_type == Cell.GOLD:
  97. self.gold += 1
  98. elif cell_type == Cell.ROBOT:
  99. self.robot_position = (x, y)
  100. elif cell_type == Cell.TELEPORT:
  101. cell.position = (x, y)
  102. sources[cell.label] = cell
  103. elif cell_type == Cell.TARGET:
  104. cell.position = (x, y)
  105. targets[cell.label] = cell
  106. x += 1
  107. x = 1
  108. y = y - 1
  109. for tp in teleports.keys():
  110. source = sources[tp]
  111. target = targets[teleports[tp]]
  112. source.set_target(target)
  113. target.add_source(source)
  114. def parse(self, lines):
  115. teleports = {}
  116. reading_mine = True
  117. for line in lines:
  118. line = line.rstrip()
  119. if reading_mine:
  120. if line != "":
  121. self.rows.append([decode_cell(c) for c in line])
  122. self.height = self.height + 1
  123. columns = len(line)
  124. if columns > self.width:
  125. self.width = columns
  126. else:
  127. reading_mine = False
  128. else:
  129. if line == "":
  130. continue
  131. words = line.split()
  132. if words[0] == "Water":
  133. self.water = int(words[1])
  134. elif words[0] == "Flooding":
  135. self.flooding = int(words[1])
  136. elif words[0] == "Waterproof":
  137. self.waterproof = int(words[1])
  138. elif words[0] == "Trampoline":
  139. teleports[words[1]] = words[3]
  140. self.update_positions(teleports)
  141. self.teleports = teleports
  142. print(self.teleports)
  143. if __name__ == "__main__":
  144. import fileinput
  145. mine = Mine()
  146. mine.parse(fileinput.input())
  147. print(mine.dump())
  148. #~ for y in range(1, mine.height + 1):
  149. #~ for x in range(1, mine.width + 1):
  150. #~ sys.stdout.write(mine[x, mine.height + 1 - y].show())
  151. #~ sys.stdout.write('\n')
  152. #~
  153. #~ if mine.has_teleports():
  154. #~ for t in mine.teleports.viewvalues():
  155. #~ print("teleport " + t.label + " to " + t.target.label)
  156. #~
  157. #~ print(mine.lifts.keys())
  158. #~ print(mine.golds.keys())
  159. #~ print(mine.rocks.keys())
  160. #~ print(mine.robot_position)