Skip to content

Commit 6d33d35

Browse files
committed
Added days 2018-03, 2018-04
1 parent 688e701 commit 6d33d35

File tree

3 files changed

+341
-0
lines changed

3 files changed

+341
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# -------------------------------- Input data -------------------------------- #
2+
import os, drawing
3+
4+
test_data = {}
5+
6+
test = 1
7+
test_data[test] = {"input": """#1 @ 1,3: 4x4
8+
#2 @ 3,1: 4x4
9+
#3 @ 5,5: 2x2""",
10+
"expected": ['Unknown', 'Unknown'],
11+
}
12+
13+
test = 'real'
14+
input_file = os.path.join(os.path.dirname(__file__), 'Inputs', os.path.basename(__file__).replace('.py', '.txt'))
15+
test_data[test] = {"input": open(input_file, "r+").read().strip(),
16+
"expected": ['110546', '819'],
17+
}
18+
19+
# -------------------------------- Control program execution -------------------------------- #
20+
21+
case_to_test = 'real'
22+
part_to_test = 2
23+
verbose_level = 1
24+
25+
# -------------------------------- Initialize some variables -------------------------------- #
26+
27+
puzzle_input = test_data[case_to_test]['input']
28+
puzzle_expected_result = test_data[case_to_test]['expected'][part_to_test-1]
29+
puzzle_actual_result = 'Unknown'
30+
31+
32+
# -------------------------------- Actual code execution -------------------------------- #
33+
34+
if part_to_test == 1:
35+
fabric = {}
36+
for string in puzzle_input.split('\n'):
37+
if string == '':
38+
continue
39+
_, _, start, size = string.split(' ')
40+
cut_x, cut_y = int(start.split(',')[0]), int(start.split(',')[1][:-1])
41+
size_x, size_y = int(size.split('x')[0]), int(size.split('x')[1])
42+
43+
fabric.update({(x, y): fabric.get((x, y), 0) + 1
44+
for x in range (cut_x, cut_x + size_x)
45+
for y in range (cut_y, cut_y + size_y)})
46+
47+
puzzle_actual_result = len([fabric[coord] for coord in fabric if fabric[coord] > 1])
48+
49+
50+
51+
else:
52+
fabric = {}
53+
cuts = []
54+
for string in puzzle_input.split('\n'):
55+
if string == '':
56+
continue
57+
_, _, start, size = string.split(' ')
58+
cut_x, cut_y = int(start.split(',')[0]), int(start.split(',')[1][:-1])
59+
size_x, size_y = int(size.split('x')[0]), int(size.split('x')[1])
60+
61+
cuts.append((cut_x, cut_y, size_x, size_y))
62+
63+
fabric.update({(x, y): fabric[(x, y)] + 1 if (x, y) in fabric else 1
64+
for x in range (cut_x, cut_x + size_x)
65+
for y in range (cut_y, cut_y + size_y)})
66+
67+
cut_id = 0
68+
for cut in cuts:
69+
cut_id += 1
70+
if all(fabric[(x, y)] == 1
71+
for x in range (cut[0], cut[0] + cut[2])
72+
for y in range (cut[1], cut[1] + cut[3])):
73+
puzzle_actual_result = cut_id
74+
break
75+
76+
77+
78+
# -------------------------------- Outputs / results -------------------------------- #
79+
80+
if verbose_level >= 3:
81+
print ('Input : ' + puzzle_input)
82+
print ('Expected result : ' + str(puzzle_expected_result))
83+
print ('Actual result : ' + str(puzzle_actual_result))
84+
85+
86+
87+

2018/04-Repose Record.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# -------------------------------- Input data -------------------------------- #
2+
import os, parse, numpy as np
3+
4+
test_data = {}
5+
6+
test = 1
7+
test_data[test] = {"input": """[1518-11-01 00:00] Guard #10 begins shift
8+
[1518-11-01 00:05] falls asleep
9+
[1518-11-01 00:25] wakes up
10+
[1518-11-01 00:30] falls asleep
11+
[1518-11-01 00:55] wakes up
12+
[1518-11-01 23:58] Guard #99 begins shift
13+
[1518-11-02 00:40] falls asleep
14+
[1518-11-02 00:50] wakes up
15+
[1518-11-03 00:05] Guard #10 begins shift
16+
[1518-11-03 00:24] falls asleep
17+
[1518-11-03 00:29] wakes up
18+
[1518-11-04 00:02] Guard #99 begins shift
19+
[1518-11-04 00:36] falls asleep
20+
[1518-11-04 00:46] wakes up
21+
[1518-11-05 00:03] Guard #99 begins shift
22+
[1518-11-05 00:45] falls asleep
23+
[1518-11-05 00:55] wakes up""",
24+
"expected": ['240', 'Unknown'],
25+
}
26+
27+
test = 'real'
28+
input_file = os.path.join(os.path.dirname(__file__), 'Inputs', os.path.basename(__file__).replace('.py', '.txt'))
29+
test_data[test] = {"input": open(input_file, "r+").read().strip(),
30+
"expected": ['30630', '136571'],
31+
}
32+
33+
# -------------------------------- Control program execution -------------------------------- #
34+
35+
case_to_test = 1
36+
part_to_test = 1
37+
verbose_level = 1
38+
39+
# -------------------------------- Initialize some variables -------------------------------- #
40+
41+
puzzle_input = test_data[case_to_test]['input']
42+
puzzle_expected_result = test_data[case_to_test]['expected'][part_to_test-1]
43+
puzzle_actual_result = 'Unknown'
44+
45+
46+
# -------------------------------- Actual code execution -------------------------------- #
47+
48+
parse_format1 = '''[{date:ti}] Guard #{guard:d} begins shift'''
49+
parse_format2 = '''[{date:ti}] falls asleep'''
50+
parse_format3 = '''[{date:ti}] wakes up'''
51+
all_notes = sorted(puzzle_input.split('\n'))
52+
53+
sleep_pattern = {}
54+
for string in all_notes:
55+
r = parse.parse(parse_format1, string)
56+
if r is not None:
57+
guard = r['guard']
58+
if guard not in sleep_pattern:
59+
sleep_pattern[guard] = np.zeros(60)
60+
continue
61+
62+
r = parse.parse(parse_format2, string)
63+
if r is not None:
64+
asleep = r['date'].minute if r['date'].hour == 0 else 0
65+
continue
66+
67+
r = parse.parse(parse_format3, string)
68+
if r is not None:
69+
sleep_pattern[guard][asleep:r['date'].minute] += 1
70+
continue
71+
72+
if part_to_test == 1:
73+
sleep_duration = {x:sum(sleep_pattern[x]) for x in sleep_pattern}
74+
75+
most_sleepy = [x for x,v in sleep_duration.items() if v == max(sleep_duration.values())][0]
76+
77+
puzzle_actual_result = most_sleepy * np.argpartition(-sleep_pattern[most_sleepy], 1)[0]
78+
79+
80+
else:
81+
most_slept = 0
82+
most_slept_guard = 0
83+
most_slept_minute = 0
84+
for guard in sleep_pattern:
85+
if most_slept < max(sleep_pattern[guard]):
86+
most_slept = max(sleep_pattern[guard])
87+
most_slept_guard = guard
88+
most_slept_minute = np.argpartition(-sleep_pattern[guard], 1)[0]
89+
90+
puzzle_actual_result = most_slept_guard * most_slept_minute
91+
92+
93+
94+
95+
96+
# -------------------------------- Outputs / results -------------------------------- #
97+
98+
if verbose_level >= 3:
99+
print ('Input : ' + puzzle_input)
100+
print ('Expected result : ' + str(puzzle_expected_result))
101+
print ('Actual result : ' + str(puzzle_actual_result))
102+
103+
104+
105+

2018/drawing.py

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import math, os
2+
3+
4+
def text_to_grid (text):
5+
"""
6+
Converts a text to a set of coordinates
7+
8+
The text is expected to be separated by newline characters
9+
Each character will have its coordinates as keys
10+
11+
:param string text: The text to convert
12+
:return: The converted grid, its height and width
13+
"""
14+
grid = {}
15+
lines = text.splitlines()
16+
height = len(lines)
17+
width = 0
18+
for y in range(len(lines)):
19+
width = max(width, len(lines[y]))
20+
for x in range(len(lines[y])):
21+
grid[(x, y)] = lines[y][x]
22+
23+
return grid
24+
25+
def grid_to_text (grid, blank_character = ' '):
26+
"""
27+
Converts the grid to a text format
28+
29+
:param dict grid: The grid to convert, in format (x, y): value
30+
:param string blank_character: What to use for cells with unknown value
31+
:return: The grid in text format
32+
"""
33+
34+
text = ''
35+
36+
grid_x, grid_y = zip(*grid.keys())
37+
38+
for y in range (min(grid_y), max(grid_y)+1):
39+
for x in range (min(grid_x), max(grid_x)+1):
40+
if (x, y) in grid:
41+
text += str(grid[(x, y)])
42+
else:
43+
text += blank_character
44+
text += os.linesep
45+
text = text[:-len(os.linesep)]
46+
47+
return text
48+
49+
def split_in_parts (grid, width, height):
50+
"""
51+
Splits a grid in parts of width*height size
52+
53+
:param dict grid: The grid to convert, in format (x, y): value
54+
:param integer width: The width of parts to use
55+
:param integer height: The height of parts to use
56+
:return: The different parts
57+
"""
58+
59+
if not isinstance(width, int) or not isinstance(height, int):
60+
return False
61+
if width <= 0 or height <= 0:
62+
return False
63+
64+
grid_x, grid_y = zip(*grid.keys())
65+
grid_width = max(grid_x) - min(grid_x) + 1
66+
grid_height = max(grid_y) - min(grid_y) + 1
67+
68+
parts = []
69+
70+
for part_y in range(math.ceil(grid_height / height)):
71+
for part_x in range (math.ceil(grid_width / width)):
72+
parts.append({(x, y):grid[(x, y)] \
73+
for x in range(part_x*width, min((part_x + 1)*width, grid_width)) \
74+
for y in range(part_y*height, min((part_y + 1)*height, grid_height))})
75+
76+
return parts
77+
78+
def merge_parts (parts, width, height):
79+
"""
80+
Merges different parts in a single grid
81+
82+
:param dict parts: The parts to merge, in format (x, y): value
83+
:return: The merged grid
84+
"""
85+
86+
grid = {}
87+
88+
part_x, part_y = zip(*parts[0].keys())
89+
part_width = max(part_x) - min(part_x) + 1
90+
part_height = max(part_y) - min(part_y) + 1
91+
92+
part_nr = 0
93+
for part_y in range(height):
94+
for part_x in range(width):
95+
grid.update({(x + part_x*part_width, y + part_y*part_height): parts[part_nr][(x, y)] for (x, y) in parts[part_nr]})
96+
part_nr += 1
97+
98+
return grid
99+
100+
def rotate (grid, rotations = (0, 90, 180, 270)):
101+
"""
102+
Rotates a grid and returns the result
103+
104+
:param dict grid: The grid to rotate, in format (x, y): value
105+
:param tuple rotations: Which angles to use for rotation
106+
:return: The parts in text format
107+
"""
108+
109+
rotated_grid = []
110+
111+
grid_x, grid_y = zip(*grid.keys())
112+
width = max(grid_x) - min(grid_x) + 1
113+
height = max(grid_y) - min(grid_y) + 1
114+
115+
for angle in rotations:
116+
if angle == 0:
117+
rotated_grid.append(grid)
118+
elif angle == 90:
119+
rotated_grid.append({(height-y, x): grid[(x, y)] for (x, y) in grid})
120+
elif angle == 180:
121+
rotated_grid.append({(width-x, height-y): grid[(x, y)] for (x, y) in grid})
122+
elif angle == 270:
123+
rotated_grid.append({(y, width-x): grid[(x, y)] for (x, y) in grid})
124+
125+
return rotated_grid
126+
127+
def flip (grid, flips = ('V', 'H')):
128+
"""
129+
Flips a grid and returns the result
130+
131+
:param dict grid: The grid to rotate, in format (x, y): value
132+
:param tuple flips: Which flips (horizontal, vertical) to use for flip
133+
:return: The parts in text format
134+
"""
135+
136+
flipped_grid = []
137+
138+
grid_x, grid_y = zip(*grid.keys())
139+
width = max(grid_x) - min(grid_x) + 1
140+
height = max(grid_y) - min(grid_y) + 1
141+
142+
for flip in flips:
143+
if flip == 'H':
144+
flipped_grid.append({(x, height-y): grid[(x, y)] for (x, y) in grid})
145+
elif flip == 'V':
146+
flipped_grid.append({(width-x, y): grid[(x, y)] for (x, y) in grid})
147+
148+
return flipped_grid
149+

0 commit comments

Comments
 (0)