-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcode.py
81 lines (65 loc) · 2.71 KB
/
code.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
from pprint import pprint
from collections import Counter
def write_solution(solution, output_file_path="solution.txt"):
with open(output_file_path, "w") as output_file:
output_file.write(str(solution))
print(solution)
return solution
def read_input_lines(input_file_path="input.txt"):
with open(input_file_path, "r") as input_file:
return input_file.read().splitlines()
def split_inputs_from_first_line():
input_lines = read_input_lines()
first_line_as_str = input_lines[0]
return first_line_as_str.split(",")
# Utilities
def flatten(lst):
return [item for sublist in lst for item in sublist]
# Part 1
def other_cave(tunnel, cave):
return tunnel.replace(cave, "").replace("-", "")
def caves_connected_to(tunnels, cave):
return [other_cave(tunnel, cave) for tunnel in tunnels if cave in tunnel]
def add_cave_to_path_list(path_list, cave):
new_path_list = path_list.copy()
new_path_list.append(cave)
return new_path_list
def paths_from(tunnels, path_list, valid):
last_cave = path_list[-1]
possible_next_caves = caves_connected_to(tunnels, last_cave)
valid_next_caves = [cave for cave in possible_next_caves if valid(path_list, cave)]
return [add_cave_to_path_list(path_list, cave) for cave in valid_next_caves]
def valid_part_1(path_list, cave):
if cave == "start":
return False
elif cave.islower() and cave in path_list:
return False
else:
return True
def valid_part_2(path_list, cave):
small_caves = [cave for cave in path_list if cave.islower()]
already_visited_small_twice = [k for k, v in Counter(small_caves).items() if v > 1] != []
returning_to_small_cave = cave.islower() and cave in path_list
if cave == "start":
return False
elif already_visited_small_twice and returning_to_small_cave:
return False
else:
return True
def find_paths(tunnels, valid, paths=[["start"]], complete_paths=[], ):
if paths == []:
return complete_paths
else:
all_paths = flatten([paths_from(tunnels, path, valid) for path in paths])
new_complete_paths = complete_paths + [path for path in all_paths if path[-1] == "end"]
new_paths = [path for path in all_paths if path[-1] != "end"]
return find_paths(tunnels, valid, new_paths, new_complete_paths)
def count_distinct_paths(tunnels, valid):
return len(find_paths(tunnels, valid))
# Write solution
if __name__ == '__main__':
input_tunnels = read_input_lines()
part_1_result = count_distinct_paths(input_tunnels, valid_part_1)
part_2_result = count_distinct_paths(input_tunnels, valid_part_2)
solution = str(part_1_result) + "\n" + str(part_2_result)
write_solution(solution)