Last active
December 7, 2016 07:05
-
-
Save markjenkins/b2b4a9251cb3e14224bd3214e1a377df to your computer and use it in GitHub Desktop.
solution to https://adventofcode.com/2016/day/1 part 2, uses reduce(), nearly functional
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# solution to https://adventofcode.com/2016/day/1 part 2 | |
# in a functional style with python 3.3+ enhanced accumulate() and dropwhile() | |
# Mark Jenkins <mark@markjenkins.ca> | |
from itertools import accumulate, dropwhile, chain | |
MOVEMENTS = ((0,1), (1,0), (0,-1), (-1,0)) | |
DIRECTION_CHANGES = {"R": 1, "L": -1} | |
def next_pos(state, token): | |
displacement, direction = state | |
change_dir = DIRECTION_CHANGES[token[0]] | |
change_magnitude = int(token[1:]) | |
new_direction = (direction + change_dir) % len(MOVEMENTS) | |
move = (change_magnitude*MOVEMENTS[new_direction][0], | |
change_magnitude*MOVEMENTS[new_direction][1] ) | |
new_displacement = (displacement[0] + move[0], displacement[1] + move[1]) | |
locations_visited = frozenset( | |
(displacement[0] + i*MOVEMENTS[new_direction][0], | |
displacement[1] + i*MOVEMENTS[new_direction][1]) | |
for i in range(1, change_magnitude+1) | |
) | |
return new_displacement, new_direction, locations_visited | |
def next_pos_with_history(state, token): | |
(displacement, direction, | |
last_locations_visited, old_locations_visited) = state | |
combined_locations_visited = old_locations_visited.union( | |
last_locations_visited) | |
new_displacement, new_direction, new_locations_visited = \ | |
next_pos((displacement, direction),token) | |
return (new_displacement, new_direction, | |
new_locations_visited, combined_locations_visited) | |
initial_state = ((0, 0), 0, frozenset(), frozenset()) | |
history_accumulation = accumulate( | |
chain( (initial_state,), input().split(", ") ), | |
next_pos_with_history | |
) # accumulate | |
def no_repeat_of_history(state): | |
(displacement, direction, | |
last_locations_visited, old_locations_visited) = state | |
return not any( new_loc in old_locations_visited | |
for new_loc in last_locations_visited) | |
# find the first repeat of history | |
success=next(dropwhile(no_repeat_of_history, history_accumulation), None) | |
if success == None: | |
print("no repeat of location found") | |
else: | |
assert( not no_repeat_of_history(success) ) | |
(displacement, direction, | |
last_locations_visited, old_locations_visited) = success | |
repeat_location = next( | |
dropwhile( lambda new_loc: new_loc not in old_locations_visited, | |
last_locations_visited ) # dropwhile | |
) # next | |
print( abs(repeat_location[0]) + abs(repeat_location[1]) ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment