generated from arol-polito/python-project-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
356 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
#-------------------------------------------------------------------------------------------------------------------------------- | ||
# INCLUDE | ||
#-------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
import logging | ||
|
||
from itertools import product, combinations | ||
|
||
import copy | ||
|
||
from typing import Generator, Dict, Tuple, List | ||
|
||
#-------------------------------------------------------------------------------------------------------------------------------- | ||
# RULES | ||
#-------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
""" | ||
There is a map | ||
Within the map there are low case, high case and numbers | ||
For each pair of the same symbol, two special location are generated. | ||
d = vector distance between pair of same symbols | ||
two focus # are generated at vector distance d from each of the symbols | ||
#...A...A...# | ||
#..A..A..# | ||
Focus must be within the map | ||
Calculate the focus generated by the total sum of all pairs of antennas of each symbol | ||
If multiple symbols generate a focus in the same place, that count multiple times | ||
NO! multiple focus in the same place count as 1 | ||
""" | ||
|
||
|
||
#-------------------------------------------------------------------------------------------------------------------------------- | ||
# ALGORITHM | ||
#-------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
""" | ||
PART1 | ||
I create a dictionary, where the key is the symbol (case sensitive) | ||
the dictionary is associated with a list of coordinates XY that map all the same symbols | ||
for each unique pair of those symbols, i generate a list of all the focus coordinates | ||
I save that in a dictionary of focus, with one key per symbol | ||
the solution is the total sum of all items in the focus dictionary | ||
""" | ||
|
||
class Focus: | ||
def __init__(self): | ||
""" | ||
Initialize the Focus class | ||
""" | ||
self.gn_width = -1 | ||
self.gn_height = -1 | ||
# store symbol as key, and item is a list of coordinates where that symbol appears | ||
self.gd_symbol = dict() | ||
#store coordinates, with the symbol associated with that coordinate | ||
self.gd_coordinate_symbol = dict() | ||
#for each symbol as key, store the focus as list of coordinates | ||
self.gd_focus = dict() | ||
#store coordinates, and the number of unique focus in that coordinate | ||
self.gd_coordinate_focus = dict() | ||
|
||
def load_map_from_file(self, is_filename: str) -> bool: | ||
""" | ||
From a file, load a map. | ||
For each symbol in a coordinate, add that coordinate to the dictionary as a list of coordinates with the symbol as key | ||
""" | ||
try: | ||
with open(is_filename, 'r') as file: | ||
lines = file.readlines() | ||
self.gn_height = len(lines) | ||
self.gn_width = max(len(line.strip()) for line in lines) | ||
|
||
for n_y, line in enumerate(lines): | ||
for n_x, s_symbol in enumerate(line.strip()): | ||
if s_symbol != '.': | ||
tnn_coordinate = (n_x, n_y) | ||
#fill symbol dictionary | ||
if s_symbol not in self.gd_symbol: | ||
self.gd_symbol[s_symbol] = [] | ||
self.gd_symbol[s_symbol].append( tnn_coordinate ) | ||
#fill coordinate dictionary | ||
self.gd_coordinate_symbol[tnn_coordinate] = s_symbol | ||
|
||
except Exception as e: | ||
print(f"Error loading map: {e}") | ||
return False | ||
logging.info(f"Map Size: Width: {self.gn_width} | Height: {self.gn_height}") | ||
logging.info(f"Number of frequencies (symbols): {len(self.gd_symbol)}") | ||
logging.info(f"Number of antennas: {len(self.gd_coordinate_symbol)}") | ||
logging.info(f"Symbols: {self.gd_symbol}") | ||
logging.info(f"Antennas: {self.gd_coordinate_symbol }") | ||
|
||
def show(self): | ||
logging.info(f"Map Size: Width: {self.gn_width} | Height: {self.gn_height}") | ||
s_line = "\n" | ||
for n_y in range(self.gn_height): | ||
for n_x in range(self.gn_width): | ||
tnn_coordinate = (n_x, n_y) | ||
if tnn_coordinate in self.gd_coordinate_symbol: | ||
s_line += f"{self.gd_coordinate_symbol[tnn_coordinate]}" | ||
else: | ||
s_line += "." | ||
s_line += '\n' | ||
logging.debug(s_line) | ||
|
||
def sum_vector( self, tnn_origin : Tuple[int, int], tnn_vector : Tuple[int, int] ) -> Tuple[int, int]: | ||
""" | ||
sum two XY coordinates, | ||
""" | ||
return (tnn_origin[0]+tnn_vector[0], tnn_origin[1]+tnn_vector[1]) | ||
|
||
def sub_vector( self, tnn_origin : Tuple[int, int], tnn_vector : Tuple[int, int] ) -> Tuple[int, int]: | ||
""" | ||
fsub two XY coordinates | ||
""" | ||
return (tnn_origin[0]-tnn_vector[0], tnn_origin[1]-tnn_vector[1]) | ||
|
||
def is_oob( self, tnn_origin : Tuple[int, int] ) -> bool: | ||
""" | ||
if the coordinate is out of bound, return True | ||
""" | ||
if (tnn_origin[0] < 0): | ||
return True #OOB | ||
if (tnn_origin[1] < 0): | ||
return True #OOB | ||
if (tnn_origin[0] >= self.gn_width): | ||
return True #OOB | ||
if (tnn_origin[1] >= self.gn_height): | ||
return True #OOB | ||
return False | ||
|
||
def compute_focus(self): | ||
""" | ||
for each pair of symbols | ||
create two focus in line with the symbols | ||
at the distance between the symbols | ||
""" | ||
#for each symbol | ||
for s_symbol in self.gd_symbol: | ||
#create an empty list in the focus dictionary associated with the symbol | ||
self.gd_focus[s_symbol] = list() | ||
#get the list of coordinates where that symbol appear | ||
ltnn_coordinates = self.gd_symbol[s_symbol] | ||
#for each pair of coordinates | ||
for tst_pair_of_coordinates in combinations( ltnn_coordinates, 2 ): | ||
logging.debug(f"Pair: {tst_pair_of_coordinates}") | ||
#compute distance between pair | ||
tnn_vector_distance_ab = self.sub_vector( tst_pair_of_coordinates[1], tst_pair_of_coordinates[0]) | ||
#compute coordinate of first focus | ||
tnn_focus_a = self.sub_vector( tst_pair_of_coordinates[0], tnn_vector_distance_ab ) | ||
tnn_focus_b = self.sum_vector( tst_pair_of_coordinates[1], tnn_vector_distance_ab ) | ||
logging.debug(f"Distance: {tnn_vector_distance_ab} Focus A {tnn_focus_a} OOB:{self.is_oob(tnn_focus_a)} | Focus B {tnn_focus_b} OOB:{self.is_oob(tnn_focus_b)} ") | ||
#if coordinates are within the map, add them to the focus dictionary | ||
if self.is_oob(tnn_focus_a) == False: | ||
self.gd_focus[s_symbol].append(tnn_focus_a) | ||
#add focus to the coordinate of the focus | ||
if tnn_focus_a not in self.gd_coordinate_focus: | ||
self.gd_coordinate_focus[tnn_focus_a] = 1 | ||
else: | ||
self.gd_coordinate_focus[tnn_focus_a] += 1 | ||
if self.is_oob(tnn_focus_b) == False: | ||
self.gd_focus[s_symbol].append(tnn_focus_b) | ||
#add focus to the coordinate of the focus | ||
if tnn_focus_b not in self.gd_coordinate_focus: | ||
self.gd_coordinate_focus[tnn_focus_b] = 1 | ||
else: | ||
self.gd_coordinate_focus[tnn_focus_b] += 1 | ||
logging.info(f"Number of focus for symbol {s_symbol}: {len(self.gd_focus[s_symbol])}") | ||
logging.info(f"Focus Coordinates: {self.gd_coordinate_focus}") | ||
print(f"UNIQUE FOCUS: {len(self.gd_coordinate_focus)}") | ||
|
||
#-------------------------------------------------------------------------------------------------------------------------------- | ||
# MAIN | ||
#-------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
# if interpreter has the intent of executing this file | ||
if __name__ == "__main__": | ||
logging.basicConfig( | ||
filename='day08\day_8.log', | ||
# Specify the log file name | ||
level=logging.DEBUG, | ||
# Set the level of debug to show | ||
format='[%(asctime)s] %(levelname)s %(module)s:%(lineno)d > %(message)s ', | ||
filemode='w' | ||
) | ||
logging.info("Begin") | ||
|
||
cl_focus = Focus() | ||
#cl_focus.load_map_from_file('day08\day_8_example.txt') | ||
cl_focus.load_map_from_file('day08\day_8_map.txt') | ||
cl_focus.show() | ||
cl_focus.compute_focus() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
............ | ||
........0... | ||
.....0...... | ||
.......0.... | ||
....0....... | ||
......A..... | ||
............ | ||
............ | ||
........A... | ||
.........A.. | ||
............ | ||
............ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
......#....# | ||
...#....0... | ||
....#0....#. | ||
..#....0.... | ||
....0....#.. | ||
.#....A..... | ||
...#........ | ||
#......#.... | ||
........A... | ||
.........A.. | ||
..........#. | ||
..........#. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
--- Day 8: Resonant Collinearity --- | ||
|
||
You find yourselves on the roof of a top-secret Easter Bunny installation. | ||
While The Historians do their thing, you take a look at the familiar huge antenna. | ||
Much to your surprise, it seems to have been reconfigured to emit a signal that makes people 0.1% more likely | ||
to buy Easter Bunny brand Imitation Mediocre Chocolate as a Christmas gift! Unthinkable! | ||
Scanning across the city, you find that there are actually many such antennas. | ||
Each antenna is tuned to a specific frequency indicated by a single lowercase letter, uppercase letter, or digit. | ||
You create a map (your puzzle input) of these antennas. For example: | ||
|
||
............ | ||
........0... | ||
.....0...... | ||
.......0.... | ||
....0....... | ||
......A..... | ||
............ | ||
............ | ||
........A... | ||
.........A.. | ||
............ | ||
............ | ||
|
||
The signal only applies its nefarious effect at specific antinodes based on the resonant frequencies of the antennas. | ||
In particular, an antinode occurs at any point that is perfectly in line with two antennas of the same frequency | ||
- but only when one of the antennas is twice as far away as the other. | ||
This means that for any pair of antennas with the same frequency, there are two antinodes, one on either side of them. | ||
|
||
So, for these two antennas with frequency a, they create the two antinodes marked with #: | ||
|
||
.......... | ||
...#...... | ||
.......... | ||
....a..... | ||
.......... | ||
.....a.... | ||
.......... | ||
......#... | ||
.......... | ||
.......... | ||
|
||
Adding a third antenna with the same frequency creates several more antinodes. | ||
It would ideally add four antinodes, but two are off the right side of the map, so instead it adds only two: | ||
|
||
.......... | ||
...#...... | ||
#......... | ||
....a..... | ||
........a. | ||
.....a.... | ||
..#....... | ||
......#... | ||
.......... | ||
.......... | ||
|
||
Antennas with different frequencies don't create antinodes; | ||
A and a count as different frequencies. However, antinodes can occur at locations that contain antennas. | ||
In this diagram, the lone antenna with frequency capital A creates no antinodes but has a lowercase-a-frequency antinode at its location: | ||
|
||
.......... | ||
...#...... | ||
#......... | ||
....a..... | ||
........a. | ||
.....a.... | ||
..#....... | ||
......A... | ||
.......... | ||
.......... | ||
|
||
The first example has antennas with two different frequencies, | ||
so the antinodes they create look like this, plus an antinode overlapping the topmost A-frequency antenna: | ||
|
||
......#....# | ||
...#....0... | ||
....#0....#. | ||
..#....0.... | ||
....0....#.. | ||
.#....A..... | ||
...#........ | ||
#......#.... | ||
........A... | ||
.........A.. | ||
..........#. | ||
..........#. | ||
|
||
Because the topmost A-frequency antenna overlaps with a 0-frequency antinode, | ||
there are 14 total unique locations that contain an antinode within the bounds of the map. | ||
|
||
Calculate the impact of the signal. How many unique locations within the bounds of the map contain an antinode? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
....................................8............. | ||
..................E............................... | ||
.................................g................ | ||
...........................................l...b.. | ||
..C...........s..............8..........b......... | ||
..................3..1........................b... | ||
............N....3.....................1.....b.... | ||
.....................N.....8....1..............2.. | ||
..q....................................P.......... | ||
......................N........................... | ||
...........E.................................l.... | ||
.............S.....c.............T..2v............ | ||
.........w....E........q............L.....P.....l. | ||
........w..............................a...V...... | ||
...........t..................v..V................ | ||
.....w.C............................V....4.....L.. | ||
........................................I.n..T.... | ||
.....E.5..C...8....3..q........................... | ||
...............s..0...A........W...........a....T. | ||
...............A................vPT...L..W..e.4... | ||
...........Cw..................2.....G.p.....4.... | ||
....S........q........s.............a............. | ||
S.............c......e....................V....... | ||
......5........................................... | ||
....5............................................. | ||
...........................I............g......... | ||
...............c.........A........................ | ||
.................s.............G.............etg.. | ||
.........5...L.........f...v......W............... | ||
............................0.W.....I........t.... | ||
.................................................. | ||
...................f...........Q.0................ | ||
..............1m9.f..........0........3.........F. | ||
..f...9................B.......................... | ||
...........S...........................F......e... | ||
........c.............n.....Q..................... | ||
.....N...............B............g..7....t....... | ||
..........B.........P.......G..................... | ||
..m...........................Q................... | ||
.............m.....................p...........F.. | ||
.....M..B......Q..i.....................7.4....... | ||
............M..................7.................. | ||
...........n...................................... | ||
................................p.....6.F.7....... | ||
..........M...........p.........6................. | ||
.M............i................................... | ||
..............................G................... | ||
..............li.......................6.......... | ||
.....9.....................i...6.................. | ||
.....n.............................9.............. |