-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPuzzle-14.py
153 lines (127 loc) · 3.91 KB
/
Puzzle-14.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import numpy as np
from copy import deepcopy
test = """O....#....
O.OO#....#
.....##...
OO.#O....O
.O.....O#.
O.#..O.#.#
..O..#O..O
.......O..
#....###..
#OO..#....
"""
def transpose(l_str: list[str]) -> list[str]:
"""
transpose a list of list of str
"""
return [list(x) for x in zip(*l_str)]
def transpose_back(l_str: list[str]) -> list[str]:
"""
The transpose operation over the other axis
"""
#first transpose the reversed list
l_transpose_rev = [list(x) for x in
zip(*[list(reversed(l)) for l in l_str])]
# Then reverse it again
l_transpose_rev_rev = [list(reversed(x)) for x in l_transpose_rev]
return l_transpose_rev_rev
def slide_on_map_north(l_str: list[str]) -> list[str]:
"""
list[str] -> list[str]
reads a map and slides the "O" to the north
"""
l_transpose = transpose(l_str)
l_trans_slide = [slide_line(x) for x in l_transpose]
return transpose(l_trans_slide)
def slide_on_map_west(l_str: list[str]) -> list[str]:
"""
list[str] -> list[str]
reads a map and slides the "O" to the west
"""
return [slide_line(x) for x in l_str]
def slide_on_map_south(l_str: list[str]) -> list[str]:
"""
reads a map and slides the "O" to the south
"""
#then reverse it again
l_transpose_back = transpose_back(l_str)
l_transback_slide = [slide_line(x) for x in l_transpose_back]
return transpose_back(l_transback_slide)
def slide_on_map_east(l_str: list[str]) -> list[str]:
"""
now sliding to the east
"""
l_reversed = [list(reversed(x)) for x in l_str]
l_rev_slide = [slide_line(x) for x in l_reversed]
return [list(reversed(x)) for x in l_rev_slide]
def slide_cycle(l_str: list[str]) -> list[str]:
"""
performs one slide cycle
"""
l_cycle = slide_on_map_north(l_str)
l_cycle = slide_on_map_west(l_cycle)
l_cycle = slide_on_map_south(l_cycle)
return slide_on_map_east(l_cycle)
def determine_cycle_period(l_str: list[str]) -> list[list[str]]:
"""
from a map, performs cycles of slides until we got back to the
same configuration
"""
l_str_cycles = [[list(x) for x in l_str]]
found_period = False
cycle = 0
while not found_period:
l_new_cycle = slide_cycle(l_str_cycles[-1])
found_period = l_new_cycle in l_str_cycles
l_str_cycles += [l_new_cycle]
cycle += 1
print ("Cycle", cycle)
loop = [i for i,x in enumerate(l_str_cycles) if x == l_str_cycles[-1]]
print("Found period at cycle", cycle)
print("Positions that are looping:", loop[0], "and", loop[1])
return l_str_cycles
def score_slide_map(l_str:list[list[str]]) -> int:
"""
scores the slided map
"""
nO = [sum([c == "O" for c in row]) for row in l_str]
revnO = list(reversed(nO))
return sum([(i+1)* revnO[i] for i in range(len(revnO))])
def slide_line(l_chars: list[str]) -> list[str]:
"""
list[str] -> list[str]
goes from left to right in a string and slides the
"0" characters to the left up to :
- the last "O"
- the last "#"
"""
l_out = []
l_dots = []
for c in l_chars:
if c == "O":
l_out.append(c)
if c == ".":
l_dots.append(c)
if c == "#":
l_out = l_out + l_dots + [c]
l_dots = []
l_out = l_out + l_dots
return(l_out)
str_test = [x for x in test.split("\n") if len(x) >0]
test_slided = slide_on_map_north(str_test)
test_score = score_slide_map(test_slided)
filename = "./input_day14.txt"
fin = open(filename, "r")
textfull = fin.read()
fin.close()
str_full = [x for x in textfull.split("\n") if len(x) >0]
full_slided = slide_on_map_north(str_full)
full_score = score_slide_map(full_slided)
ncycles = 1000000000
toto = determine_cycle_period(str_test)
#Found period at cycle 97
#Positions that are looping: 88 and 97
(ncycles - 88) % 9 #3
88 + 3 # 91
score_slide_map(toto[91])