Guest User

Untitled

a guest
Dec 13th, 2018
47
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ########################################################################
  2. #
  3. # Iterate the carts through one tick.
  4. #
  5. # Do this by looping through the length of the carts/tracks strings,
  6. # processing each cart found (where `carts[index] in '<>^v'`).
  7. #
  8. # Use the generator trick to assign a dictionary to `directions` with
  9. # the following key-value pairs:
  10. # ```
  11. # {
  12. # '<': ( -1, 'v', '<', '^'),
  13. # '>': ( 1, '^', '>', 'v'),
  14. # '^': (-width, '<', '^', '>'),
  15. # 'v': ( width, '>', 'v', '<'),
  16. # collision_marker: (0,)
  17. # '\\': { '^': '<', 'v': '>', '>': 'v', '<': '^' },
  18. # '/': { '^': '>', 'v': '<', '>': '^', '<': 'v' },
  19. # }
  20. # ```
  21. # Each cart direction contains the `(offset, left, straight, right)`
  22. # tuple for that direction: the `offset` to add to the current index
  23. # for the cart's next location, and the cart direction if it turns left,
  24. # straight, or right.
  25. # The collision marker (`X` by default) is represented by a 0 offset -
  26. # the cart doesn't # move.
  27. # In addition, the _track_ symbols `/` and `\\` are represented with a
  28. # mapping of current direction to new direction,
  29. #
  30. # Acucmulate over each index which holds a cart:
  31. #
  32. # use the generator trick to assign `cart` to `carts[index]`,
  33. # `next_turn` to `next_turns[index]`,
  34. # `cart_turn` to `directions[cart]`,
  35. # and `next_index` to `index + cart_turn[0]`.
  36. #
  37. # Use the generator trick to assign `new_cart` and `new_next_turn`
  38. # based on `carts[next_index]` and `tracks[next_index]`:
  39. # If `cart` is the collision marker _or_ `carts[next_index]` is not a space:
  40. # `new_cart` is the collision marker and
  41. # `new_next_turn` is ` `.
  42. # Else if `tracks[next_index]` is a `+`:
  43. # `new_cart` is `cart_turn[int(next_turn)]` and
  44. # `new_next_turn` is `str(int(next_turn) % 3 + 1)`.
  45. # Else if it's in `directions:
  46. # `new_cart` is `directions[tracks[next_index]][cart]` and
  47. # `new_next_turn` is `next_turn`.
  48. # Otherwise (the cart isn't turning):
  49. # `new_cart` is `cart` and `new_next_turn` is `next_turn`.
  50. #
  51. # If `next_index` is the same as `index`, return the current state
  52. # unchanged.
  53. # Otherwise, return the `carts` string with `carts[next_index]`
  54. # replaced by `new_cart` and `carts[index]` replaced by a space, and
  55. # return the `next_turns` string with `next_turns[next_index]`
  56. # replaced by `new_next_turn` and `next_turns[index] replaced by a
  57. # space.
  58. # (This is slightly complicated by having to do two different
  59. # replacement expressions based on if `next_index` comes before
  60. # or after `index`)
  61.  
  62. cart_tick = lambda current_state, collision_marker = 'X': (
  63. # use generator trick to bind `directions`
  64. # for the scope of the rest of the function
  65. (
  66.  
  67. # Acucmulate over each index which holds a cart:
  68.  
  69. reduce(
  70.  
  71. lambda current_state, index: (
  72. # use generator trick to bind values to names
  73. # for the scope of the expression
  74. (
  75.  
  76. # If `next_index` is the same as `index`, return the current state
  77. # unchanged.
  78.  
  79. (tracks, carts, next_turns, width, height)
  80. if next_index == index
  81. else
  82.  
  83. # Otherwise, return the `carts` string with `carts[next_index]`
  84. # replaced by `new_cart` and `carts[index]` replaced by a space, and
  85. # return the `next_turns` string with `next_turns[next_index]`
  86. # replaced by `new_next_turn` and `next_turns[index] replaced by a
  87. # space.
  88. # (This is slightly complicated by having to do two different
  89. # replacement expressions based on if `next_index` comes before
  90. # or after `index`)
  91.  
  92. (
  93. tracks,
  94. (
  95. carts[:next_index]
  96. + new_cart
  97. + carts[next_index + 1:index]
  98. + ' '
  99. + carts[index + 1:]
  100. )
  101. if next_index < index
  102. else (
  103. carts[:index]
  104. + ' '
  105. + carts[index + 1:next_index]
  106. + new_cart
  107. + carts[next_index + 1:]
  108. )
  109. ,
  110. (
  111. next_turns[:next_index]
  112. + new_next_turn
  113. + next_turns[next_index + 1:index]
  114. + ' '
  115. + next_turns[index + 1:]
  116. )
  117. if next_index < index
  118. else (
  119. next_turns[:index]
  120. + ' '
  121. + next_turns[index + 1:next_index]
  122. + new_next_turn
  123. + next_turns[next_index + 1:]
  124. )
  125. ,
  126. width,
  127. height
  128. )
  129.  
  130. # use the generator trick to assign `cart` to `carts[index]`,
  131. # `next_turn` to `next_turns[index]`,
  132. # `cart_turn` to `directions[cart]`,
  133. # and `next_index` to `index + cart_turn[0]`.
  134.  
  135. for (tracks, carts, next_turns, width, height) in [current_state]
  136. for cart in [carts[index]]
  137. for next_turn in [next_turns[index]]
  138. for cart_turn in [directions[cart]]
  139. for next_index in [index + cart_turn[0]]
  140.  
  141. # Use the generator trick to assign `new_cart` and `new_next_turn`
  142. # based on `carts[next_index]` and `tracks[next_index]`:
  143. # If `cart` is the collision marker _or_ `carts[next_index]` is not a space:
  144. # `new_cart` is the collision marker and
  145. # `new_next_turn` is ` `.
  146. # Else if `tracks[next_index]` is a `+`:
  147. # `new_cart` is `cart_turn[int(next_turn)]` and
  148. # `new_next_turn` is `str(int(next_turn) % 3 + 1)`.
  149. # Else if it's in `directions:
  150. # `new_cart` is `directions[tracks[next_index]][cart]` and
  151. # `new_next_turn` is `next_turn`.
  152. # Otherwise (the cart isn't turning):
  153. # `new_cart` is `cart` and `new_next_turn` is `next_turn`.
  154.  
  155. for new_cart in [
  156. collision_marker
  157. if cart == collision_marker or carts[next_index] != ' '
  158. else
  159. cart_turn[int(next_turn)]
  160. if tracks[next_index] == '+'
  161. else
  162. directions[tracks[next_index]][cart]
  163. if tracks[next_index] in directions
  164. else
  165. cart
  166. ]
  167. for new_next_turn in [
  168. ' '
  169. if cart == collision_marker or carts[next_index] != ' '
  170. else
  171. str(int(next_turn) % 3 + 1)
  172. if tracks[next_index] == '+'
  173. else
  174. next_turn
  175. ]
  176.  
  177. ).next()
  178. )
  179.  
  180. ,
  181.  
  182. itertools.chain(
  183. (current_state,),
  184. itertools.ifilter(
  185. lambda index: (
  186. current_state[1][index] in '<>^v'
  187. )
  188. ,
  189. xrange(len(current_state[0]))
  190. )
  191. )
  192.  
  193. )
  194.  
  195. # Use the generator trick to assign a dictionary to `directions` with
  196. # the following key-value pairs:
  197.  
  198. for directions in [
  199. {
  200. '<': ( -1, 'v', '<', '^'),
  201. '>': ( 1, '^', '>', 'v'),
  202. '^': (-current_state[3], '<', '^', '>'),
  203. 'v': ( current_state[3], '>', 'v', '<'),
  204. collision_marker: (0,),
  205. '\\': { '^': '<', 'v': '>', '>': 'v', '<': '^' },
  206. '/': { '^': '>', 'v': '<', '>': '^', '<': 'v' },
  207. }
  208. ]
  209.  
  210. ).next()
  211. )
RAW Paste Data