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

2018/03-No Matter How You Slice It.py

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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy