Skip to content

Instantly share code, notes, and snippets.

@markjenkins
Created December 8, 2016 08:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markjenkins/9e7bad92e67fc122ddfc4b321c362449 to your computer and use it in GitHub Desktop.
Save markjenkins/9e7bad92e67fc122ddfc4b321c362449 to your computer and use it in GitHub Desktop.
Solution to http://adventofcode.com/2016/day/2 using reduce and accumulate
#!/usr/bin/env python3
# Solution to http://adventofcode.com/2016/day/2 part 1
# using reduce and accumulate for awesome functional programing style points
# Mark Jenkins <mark@markjenkins.ca>
from sys import stdin
from functools import reduce
from itertools import chain, accumulate, islice
START_LOCATION = "5"
ROW_SIZE = 3
FIRST_NUM = 1
LAST_NUM = 9
def same_row(num, num_next):
# integer arithmatic, shifting over to a 0-8 scale means that
# assert(0//3 == 1//3 == 2//3)
# assert(3//3 == 4//3 == 5//3)
# assert(6//3 == 7//3 == 8//3)
if not (FIRST_NUM<=num<=LAST_NUM):
return False
else:
return (num-1)//ROW_SIZE == (num_next-1)//ROW_SIZE
def move_graph_entry(num):
return {
"U": num if num-ROW_SIZE < FIRST_NUM else num-ROW_SIZE,
"D": num if num+ROW_SIZE > LAST_NUM else num+ROW_SIZE,
"R": num if not same_row(num, num+1) else num+1,
"L": num if not same_row(num, num-1) else num-1,
}
def stringified_move_graph_entry(int_move_graph):
return { key: str(val) for key,val in int_move_graph.items() }
MOVE_GRAPH = {
str(num): stringified_move_graph_entry(move_graph_entry(num))
for num in range(FIRST_NUM, LAST_NUM+1)
}
def reduce_location_and_line_to_location(location, line):
return reduce(
lambda loc, character: MOVE_GRAPH[loc][character],
line, # sequence of characters
location)
location = START_LOCATION
# finish this the imperative way
# for line in stdin:
# location = reduce_location_and_line_to_location(location, line.strip() )
# print(location, end='')
# print()
# or, finish this with accumulate() feeding ''.join(), because we can
print( ''.join( islice( accumulate(
chain( (START_LOCATION,),
(line.strip() for line in stdin) ),
lambda loc, line: reduce_location_and_line_to_location(loc, line) ),
1, None
) # islice
) # join
) # print
#!/usr/bin/env python3
# Solution to http://adventofcode.com/2016/day/2 part 2
# Simply patch my solution to part 1 with a different MOVE_GRAPH
# Mark Jenkins <mark@markjenkins.ca>
from sys import stdin
from functools import reduce
from itertools import chain, accumulate, islice
START_LOCATION = "5"
ROW_SIZE = 3
FIRST_NUM = 1
LAST_NUM = 9
def same_row(num, num_next):
# integer arithmatic, shifting over to a 0-8 scale means that
# assert(0//3 == 1//3 == 2//3)
# assert(3//3 == 4//3 == 5//3)
# assert(6//3 == 7//3 == 8//3)
if not (FIRST_NUM<=num<=LAST_NUM):
return False
else:
return (num-1)//ROW_SIZE == (num_next-1)//ROW_SIZE
def move_graph_entry(num):
return {
"U": num if num-ROW_SIZE < FIRST_NUM else num-ROW_SIZE,
"D": num if num+ROW_SIZE > LAST_NUM else num+ROW_SIZE,
"R": num if not same_row(num, num+1) else num+1,
"L": num if not same_row(num, num-1) else num-1,
}
def stringified_move_graph_entry(int_move_graph):
return { key: str(val) for key,val in int_move_graph.items() }
MOVE_GRAPH_OLD = {
str(num): stringified_move_graph_entry(move_graph_entry(num))
for num in range(FIRST_NUM, LAST_NUM+1)
}
MOVE_GRAPH_PATCH = {
str(num): str(num+1)
for num in range(FIRST_NUM, 3+1)
}
MOVE_GRAPH_PATCH.update(
{ str(num): str(num+2)
for num in range(4,6+1)
}
)
MOVE_GRAPH_PATCH.update(
{ num: new_let
for num, new_let in zip( "789", "ABC")
}
)
MOVE_GRAPH = {
MOVE_GRAPH_PATCH[key]: {direction: MOVE_GRAPH_PATCH[destination]
for direction, destination in value.items()
}
for key, value in MOVE_GRAPH_OLD.items()
}
MOVE_GRAPH.update(
{ '1': {'U':'1', 'R':'1', 'D':'3', 'L': '1'},
'9': {'U':'9', 'R':'9', 'D':'9', 'L': '8'},
'D': {'U':'B', 'R':'D', 'D':'D', 'L': 'D'},
'5': {'U':'5', 'R':'6', 'D':'5', 'L': '5'},
} )
MOVE_GRAPH['3']['U'] = '1'
MOVE_GRAPH['8']['R'] = '9'
MOVE_GRAPH['B']['D'] = 'D'
MOVE_GRAPH['6']['L'] = '5'
def reduce_location_and_line_to_location(location, line):
return reduce(
lambda loc, character: MOVE_GRAPH[loc][character],
line, # sequence of characters
location)
location = START_LOCATION
# finish this the imperative way
# for line in stdin:
# location = reduce_location_and_line_to_location(location, line.strip() )
# print(location, end='')
# print()
# or, finish this with accumulate() feeding ''.join(), because we can
print( ''.join( islice( accumulate(
chain( (START_LOCATION,),
(line.strip() for line in stdin) ),
lambda loc, line: reduce_location_and_line_to_location(loc, line) ),
1, None
) # islice
) # join
) # print
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment