import logging | |||||
import random | |||||
import re | |||||
from enum import IntEnum | |||||
from sys import stdout | |||||
from typing import List, Tuple | |||||
# As the search for the Chief continues, a small Elf who lives on the | |||||
# station tugs on your shirt; she'd like to know if you could help her | |||||
# with her word search (your puzzle input). She only has to find one word: | |||||
# XMAS. | |||||
# This word search allows words to be horizontal, vertical, diagonal, | |||||
# written backwards, or even overlapping other words. It's a little unusual, | |||||
# though, as you don't merely need to find one instance of XMAS - you need to | |||||
# find all of them. | |||||
LOG_FILENAME = "./day04-1.log" | |||||
INPUT_FILENAME = "./input04.txt" | |||||
logger = logging.Logger(__name__) | |||||
formatter = logging.Formatter('[%(asctime)s][%(levelname)s] %(message)s') | |||||
sh = logging.StreamHandler(stdout) | |||||
sh.setLevel(logging.INFO) | |||||
sh.setFormatter(formatter) | |||||
fh = logging.FileHandler(LOG_FILENAME, mode="w", encoding="utf-8") | |||||
fh.setLevel(logging.DEBUG) | |||||
fh.setFormatter(formatter) | |||||
logger.addHandler(sh) | |||||
logger.addHandler(fh) | |||||
class LetterValues(IntEnum): | |||||
X = 1 | |||||
M = 2 | |||||
A = 4 | |||||
S = 8 | |||||
def get_word_value(word): | |||||
total = 0 | |||||
for i, letter in enumerate(word): | |||||
total += ((3**i) * LetterValues[letter]) | |||||
return total | |||||
XMAS_VALUE = get_word_value("XMAS") | |||||
SAMX_VALUE = get_word_value("SAMX") | |||||
TEST_LINES = """MMMSXXMASM | |||||
MSAMXMSMSA | |||||
AMXSXMAAMM | |||||
MSAMASMSMX | |||||
XMASAMXAMM | |||||
XXAMMXXAMA | |||||
SMSMSASXSS | |||||
SAXAMASAAA | |||||
MAMMMXMMMM | |||||
MXMXAXMASX""" | |||||
class WSGrid: | |||||
def __init__(self, lines: List[List[str]], word: str, print_intermediate_grids: bool=False): | |||||
self.grid = [list(line) for line in lines] | |||||
self.width = len(self.grid[0]) | |||||
self.height = len(self.grid) | |||||
self.final_grid = [['.' for _ in range(self.width)] for _ in range(self.height)] | |||||
self.word = word | |||||
self.words_found = 0 | |||||
self.found_positions = [] | |||||
self.print_intermediate_grids = print_intermediate_grids | |||||
self.width | |||||
def add_found_position(self: object, position: Tuple[int,int], direction: str) -> None: | |||||
self.found_positions.append((position, direction)) | |||||
logger.info(f"Found a match for {self.word} at {position} going {direction}.") | |||||
if self.print_intermediate_grids: | |||||
print("\n".join(["".join(line) for line in self.final_grid])) | |||||
def search_east(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if (self.width - x) < len(self.word): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y][x+i] for i in range(4)]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.words_found += 1 | |||||
for i, char in enumerate(self.word): | |||||
self.final_grid[y][x+i] = char | |||||
self.add_found_position(position, "east") | |||||
return found_word == self.word | |||||
def search_west(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if x+1 < len(self.word): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y][x-i] for i in range(4)]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.words_found += 1 | |||||
for i, char in enumerate(self.word): | |||||
self.final_grid[y][x-i] = char | |||||
self.add_found_position(position, "west") | |||||
return True | |||||
return False | |||||
def search_south(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if (self.height - y) < len(self.word): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y+i][x] for i in range(4)]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.words_found += 1 | |||||
for i, char in enumerate(self.word): | |||||
self.final_grid[y+i][x] = char | |||||
self.add_found_position(position, "south") | |||||
return found_word == self.word | |||||
def search_north(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if y+1 < len(self.word): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y-i][x] for i in range(4)]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.words_found += 1 | |||||
for i, char in enumerate(self.word): | |||||
self.final_grid[y-i][x] = char | |||||
self.add_found_position(position, "north") | |||||
return found_word == self.word | |||||
def search_northwest(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if y+1 < len(self.word) or x+1 < len(self.word): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y-i][x-i] for i in range(4)]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.words_found += 1 | |||||
for i, char in enumerate(self.word): | |||||
self.final_grid[y-i][x-i] = char | |||||
self.add_found_position(position, "northwest") | |||||
return found_word == self.word | |||||
def search_northeast(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if y+1 < len(self.word) or (self.width - x) < len(self.word): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y-i][x+i] for i in range(4)]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.words_found += 1 | |||||
for i, char in enumerate(self.word): | |||||
self.final_grid[y-i][x+i] = char | |||||
self.add_found_position(position, "northeast") | |||||
return found_word == self.word | |||||
def search_southwest(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if (self.height - y)+1 < len(self.word) or x+1 < len(self.word): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y+i][x-i] for i in range(4)]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.words_found += 1 | |||||
for i, char in enumerate(self.word): | |||||
self.final_grid[y+i][x-i] = char | |||||
self.add_found_position(position, "southwest") | |||||
return found_word == self.word | |||||
def search_southeast(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if (self.height - y)+1 < len(self.word) or (self.width - x) < len(self.word): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y+i][x+i] for i in range(4)]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.words_found += 1 | |||||
for i, char in enumerate(self.word): | |||||
self.final_grid[y+i][x+i] = char | |||||
self.add_found_position(position, "southeast") | |||||
return found_word == self.word | |||||
def find_word_at_position(self: object, position: Tuple[int,int]) -> int: | |||||
return sum([ | |||||
1 if self.search_north(position) else 0, | |||||
1 if self.search_south(position) else 0, | |||||
1 if self.search_east(position) else 0, | |||||
1 if self.search_west(position) else 0, | |||||
1 if self.search_northwest(position) else 0, | |||||
1 if self.search_northeast(position) else 0, | |||||
1 if self.search_southwest(position) else 0, | |||||
1 if self.search_southeast(position) else 0 | |||||
]) | |||||
def find_all_words(self: object) -> int: | |||||
for y in range(len(self.grid)): | |||||
for x in range(len(self.grid[0])): | |||||
self.words_found += self.find_word_at_position((x,y)) | |||||
return self.words_found | |||||
def main041(run_test=False, print_intermediate_grids=False, print_final_grid=False): | |||||
SEARCH_WORD = "XMAS" | |||||
if run_test: | |||||
lines = TEST_LINES.split("\n") | |||||
else: | |||||
with open("./input04.txt", "r", encoding="utf-8") as f: | |||||
lines = [l.strip() for l in f.readlines()] | |||||
finder = WSGrid(lines, SEARCH_WORD, print_intermediate_grids) | |||||
total_found = finder.find_all_words() | |||||
logger.info(f"Found {total_found} instances of {SEARCH_WORD}.") | |||||
if print_final_grid: | |||||
print("\n".join(["".join(line) for line in finder.final_grid])) | |||||
if __name__ == "__main__": | |||||
main041(run_test=False, print_intermediate_grids=False, print_final_grid=False) |
import logging | |||||
import random | |||||
import re | |||||
from enum import IntEnum | |||||
from sys import stdout | |||||
from typing import List, Tuple | |||||
# As the search for the Chief continues, a small Elf who lives on the | |||||
# station tugs on your shirt; she'd like to know if you could help her | |||||
# with her word search (your puzzle input). She only has to find one word: | |||||
# XMAS. | |||||
# This word search allows words to be horizontal, vertical, diagonal, | |||||
# written backwards, or even overlapping other words. It's a little unusual, | |||||
# though, as you don't merely need to find one instance of XMAS - you need to | |||||
# find all of them. | |||||
LOG_FILENAME = "./day04-1.log" | |||||
INPUT_FILENAME = "./input04.txt" | |||||
logger = logging.Logger(__name__) | |||||
formatter = logging.Formatter('[%(asctime)s][%(levelname)s] %(message)s') | |||||
sh = logging.StreamHandler(stdout) | |||||
sh.setLevel(logging.INFO) | |||||
sh.setFormatter(formatter) | |||||
fh = logging.FileHandler(LOG_FILENAME, mode="w", encoding="utf-8") | |||||
fh.setLevel(logging.DEBUG) | |||||
fh.setFormatter(formatter) | |||||
logger.addHandler(sh) | |||||
logger.addHandler(fh) | |||||
class LetterValues(IntEnum): | |||||
X = 1 | |||||
M = 2 | |||||
A = 4 | |||||
S = 8 | |||||
def get_word_value(word): | |||||
total = 0 | |||||
for i, letter in enumerate(word): | |||||
total += ((3**i) * LetterValues[letter]) | |||||
return total | |||||
XMAS_VALUE = get_word_value("XMAS") | |||||
SAMX_VALUE = get_word_value("SAMX") | |||||
TEST_LINES = """MMMSXXMASM | |||||
MSAMXMSMSA | |||||
AMXSXMAAMM | |||||
MSAMASMSMX | |||||
XMASAMXAMM | |||||
XXAMMXXAMA | |||||
SMSMSASXSS | |||||
SAXAMASAAA | |||||
MAMMMXMMMM | |||||
MXMXAXMASX""" | |||||
class WSGrid: | |||||
def __init__(self, lines: List[List[str]], word: str, print_intermediate_grids: bool=False): | |||||
self.grid = [list(line) for line in lines] | |||||
self.width = len(self.grid[0]) | |||||
self.height = len(self.grid) | |||||
self.final_grid = [['.' for _ in range(self.width)] for _ in range(self.height)] | |||||
self.word = word | |||||
self.word_edges = (0-(len(self.word)//2), len(self.word)//2+1) | |||||
self.words_found = 0 | |||||
self.found_positions = [] | |||||
self.print_intermediate_grids = print_intermediate_grids | |||||
self.width | |||||
def add_found_position(self: object, position: Tuple[int,int], direction: str) -> None: | |||||
self.found_positions.append((position, direction)) | |||||
logger.info(f"Found a match for {self.word} at {position} going {direction}.") | |||||
if self.print_intermediate_grids: | |||||
print("\n".join(["".join(line) for line in self.final_grid])) | |||||
def check_edges(self: object, x: int, y: int) -> bool: | |||||
# x and y can never be along the edge; they have to be at least 1 away | |||||
return not ( | |||||
x > self.width-2 | |||||
or x < 1 | |||||
or y < 1 | |||||
or y > self.height-2 | |||||
) | |||||
def search_east(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if not self.check_edges(x, y): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y][x+i] for i in range(self.word_edges[0],self.word_edges[1])]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.add_found_position(position, "east") | |||||
return found_word == self.word | |||||
def search_west(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if not self.check_edges(x, y): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y][x-i] for i in range(self.word_edges[0],self.word_edges[1])]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.add_found_position(position, "west") | |||||
return True | |||||
return False | |||||
def search_south(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if not self.check_edges(x, y): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y+i][x] for i in range(self.word_edges[0],self.word_edges[1])]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.add_found_position(position, "south") | |||||
return found_word == self.word | |||||
def search_north(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if not self.check_edges(x, y): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y-i][x] for i in range(self.word_edges[0],self.word_edges[1])]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.add_found_position(position, "north") | |||||
return found_word == self.word | |||||
def search_northwest(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if not self.check_edges(x, y): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y-i][x-i] for i in range(self.word_edges[0],self.word_edges[1])]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.add_found_position(position, "northwest") | |||||
return found_word == self.word | |||||
def search_northeast(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if not self.check_edges(x, y): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y-i][x+i] for i in range(self.word_edges[0],self.word_edges[1])]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.add_found_position(position, "northeast") | |||||
return found_word == self.word | |||||
def search_southwest(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if not self.check_edges(x, y): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y+i][x-i] for i in range(self.word_edges[0],self.word_edges[1])]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.add_found_position(position, "southwest") | |||||
return found_word == self.word | |||||
def search_southeast(self: object, position: Tuple[int,int]) -> bool: | |||||
x, y = position | |||||
if not self.check_edges(x, y): | |||||
return False | |||||
try: | |||||
found_word = "".join([self.grid[y+i][x+i] for i in range(self.word_edges[0],self.word_edges[1])]) | |||||
except IndexError: | |||||
return False | |||||
if found_word == self.word: | |||||
self.add_found_position(position, "southeast") | |||||
return found_word == self.word | |||||
def check_left(self: object, x: int, y: int, letter: str) -> bool: | |||||
return ( | |||||
self.grid[y-1][x-1] == letter | |||||
and self.grid[y+1][x-1] == letter | |||||
) | |||||
def check_top(self: object, x: int, y: int, letter: str) -> bool: | |||||
return ( | |||||
self.grid[y-1][x-1] == letter | |||||
and self.grid[y-1][x+1] == letter | |||||
) | |||||
def check_right(self: object, x: int, y: int, letter: str) -> bool: | |||||
return ( | |||||
self.grid[y-1][x+1] == letter | |||||
and self.grid[y+1][x+1] == letter | |||||
) | |||||
def check_bottom(self: object, x: int, y: int, letter: str) -> bool: | |||||
return ( | |||||
self.grid[y+1][x-1] == letter | |||||
and self.grid[y+1][x+1] == letter | |||||
) | |||||
def set_fg_mas(self: object, x: int, y: int, start_dir: str) -> bool: | |||||
def logit(): | |||||
logger.info(f"Found a match for {self.word} at {(x,y)} starting from the {start_dir}.") | |||||
match start_dir: | |||||
case "left": | |||||
self.final_grid[y][x] = "A" | |||||
self.final_grid[y-1][x-1] = "M" | |||||
self.final_grid[y+1][x-1] = "M" | |||||
self.final_grid[y-1][x+1] = "S" | |||||
self.final_grid[y+1][x+1] = "S" | |||||
logit() | |||||
case "top": | |||||
self.final_grid[y][x] = "A" | |||||
self.final_grid[y-1][x-1] = "M" | |||||
self.final_grid[y-1][x+1] = "M" | |||||
self.final_grid[y+1][x-1] = "S" | |||||
self.final_grid[y+1][x+1] = "S" | |||||
logit() | |||||
case "right": | |||||
self.final_grid[y][x] = "A" | |||||
self.final_grid[y-1][x+1] = "M" | |||||
self.final_grid[y+1][x+1] = "M" | |||||
self.final_grid[y-1][x-1] = "S" | |||||
self.final_grid[y+1][x-1] = "S" | |||||
logit() | |||||
case "bottom": | |||||
self.final_grid[y][x] = "A" | |||||
self.final_grid[y+1][x+1] = "M" | |||||
self.final_grid[y+1][x-1] = "M" | |||||
self.final_grid[y-1][x+1] = "S" | |||||
self.final_grid[y-1][x-1] = "S" | |||||
logit() | |||||
case _: | |||||
logger.warning(f"dir was not a valid value: {start_dir}") | |||||
if self.print_intermediate_grids: | |||||
print("\n".join(["".join(line) for line in self.final_grid])) | |||||
def find_word_at_position(self: object, position: Tuple[int,int]) -> int: | |||||
x, y = position | |||||
# fuck it | |||||
if self.grid[y][x] != "A": | |||||
return | |||||
if ( | |||||
self.check_left(x, y, "M") | |||||
and self.check_right(x, y, "S") | |||||
): | |||||
self.words_found += 1 | |||||
self.set_fg_mas(x, y, "left") | |||||
if ( | |||||
self.check_right(x, y, "M") | |||||
and self.check_left(x, y, "S") | |||||
): | |||||
self.words_found += 1 | |||||
self.set_fg_mas(x, y, "right") | |||||
if ( | |||||
self.check_top(x, y, "M") | |||||
and self.check_bottom(x, y, "S") | |||||
): | |||||
self.words_found += 1 | |||||
self.set_fg_mas(x, y, "top") | |||||
if ( | |||||
self.check_bottom(x, y, "M") | |||||
and self.check_top(x, y, "S") | |||||
): | |||||
self.words_found += 1 | |||||
self.set_fg_mas(x, y, "bottom") | |||||
def find_all_words(self: object) -> int: | |||||
for y in range(1,len(self.grid)-1): | |||||
for x in range(1,len(self.grid[0])-1): | |||||
self.find_word_at_position((x,y)) | |||||
return self.words_found | |||||
def main042(run_test=False, print_intermediate_grids=False, print_final_grid=False): | |||||
SEARCH_WORD = "MAS" | |||||
if run_test: | |||||
lines = TEST_LINES.split("\n") | |||||
else: | |||||
with open("./input04.txt", "r", encoding="utf-8") as f: | |||||
lines = [l.strip() for l in f.readlines()] | |||||
finder = WSGrid(lines, SEARCH_WORD, print_intermediate_grids) | |||||
total_found = finder.find_all_words() | |||||
logger.info(f"Found {total_found} instances of {SEARCH_WORD}.") | |||||
if print_final_grid: | |||||
print("\n".join(["".join(line) for line in finder.final_grid])) | |||||
if __name__ == "__main__": | |||||
main042( | |||||
run_test=False, | |||||
print_intermediate_grids=False, | |||||
print_final_grid=False | |||||
) |
# The first section specifies the page ordering rules, one per line. | |||||
# The first rule, 47|53, means that if an update includes both | |||||
# page number 47 and page number 53, then page number 47 must be | |||||
# printed at some point before page number 53. (47 doesn't necessarily | |||||
# need to be immediately before 53; other pages are allowed to be | |||||
# between them.) | |||||
# The second section specifies the page numbers of each update. | |||||
# Because most safety manuals are different, the pages needed in the | |||||
# updates are different too. The first update, 75,47,61,53,29, means | |||||
# that the update consists of page numbers 75, 47, 61, 53, and 29. | |||||
def main051(): | |||||
with open("./input05.txt", "r", encoding="utf-8") as f: | |||||
lines = [l.strip() for l in f.readlines()] | |||||
rules = [] | |||||
updates = [] | |||||
for i, line in enumerate(lines): | |||||
if "|" not in line: | |||||
first_update = i + 1 | |||||
break | |||||
rules.append([int(x) for x in line.split("|")]) | |||||
for i, line in enumerate(lines[first_update:]): | |||||
updates.append([int(x) for x in line.split(",")]) | |||||
valid_updates = [] | |||||
total_vu = 0 | |||||
for u in updates: | |||||
relevant_rules = [r for r in rules if all([x in u for x in r])] | |||||
if all([u.index(rule[0]) < u.index(rule[1]) for rule in relevant_rules]): | |||||
valid_updates.append(u) | |||||
total_vu += u[(len(u)-1)//2] | |||||
print(total_vu) | |||||
if __name__ == "__main__": | |||||
main051() |
import logging | |||||
from sys import stdout | |||||
# The first section specifies the page ordering rules, one per line. | |||||
# The first rule, 47|53, means that if an update includes both | |||||
# page number 47 and page number 53, then page number 47 must be | |||||
# printed at some point before page number 53. (47 doesn't necessarily | |||||
# need to be immediately before 53; other pages are allowed to be | |||||
# between them.) | |||||
# The second section specifies the page numbers of each update. | |||||
# Because most safety manuals are different, the pages needed in the | |||||
# updates are different too. The first update, 75,47,61,53,29, means | |||||
# that the update consists of page numbers 75, 47, 61, 53, and 29. | |||||
# For each of the incorrectly-ordered updates, use the page ordering | |||||
# rules to put the page numbers in the right order. | |||||
# Find the updates which are not in the correct order. What do you get | |||||
# if you add up the middle page numbers after correctly ordering | |||||
# just those updates? | |||||
LOG_FILENAME = "./day04-1.log" | |||||
INPUT_FILENAME = "./input04.txt" | |||||
logger = logging.Logger(__name__) | |||||
formatter = logging.Formatter('[%(asctime)s][%(levelname)s] %(message)s') | |||||
sh = logging.StreamHandler(stdout) | |||||
sh.setLevel(logging.INFO) | |||||
sh.setFormatter(formatter) | |||||
fh = logging.FileHandler(LOG_FILENAME, mode="w", encoding="utf-8") | |||||
fh.setLevel(logging.DEBUG) | |||||
fh.setFormatter(formatter) | |||||
logger.addHandler(sh) | |||||
logger.addHandler(fh) | |||||
def main052(): | |||||
with open("./input05.txt", "r", encoding="utf-8") as f: | |||||
lines = [l.strip() for l in f.readlines()] | |||||
rules = [] | |||||
updates = [] | |||||
for i, line in enumerate(lines): | |||||
if "|" not in line: | |||||
first_update = i + 1 | |||||
break | |||||
rules.append([int(x) for x in line.split("|")]) | |||||
for i, line in enumerate(lines[first_update:]): | |||||
updates.append([int(x) for x in line.split(",")]) | |||||
valid_updates = [] | |||||
invalid_updates = [] | |||||
new_invalid_updates = [] | |||||
total_vu = 0 | |||||
total_iu = 0 | |||||
for u in updates: | |||||
relevant_rules = [r for r in rules if all([x in u for x in r])] | |||||
all_valid = all([u.index(rule[0]) < u.index(rule[1]) for rule in relevant_rules]) | |||||
if all_valid: | |||||
valid_updates.append(u) | |||||
total_vu += u[(len(u)-1)//2] | |||||
else: | |||||
invalid_updates.append(u) | |||||
logger.info(f"Applying rules to {u}...") | |||||
while not all_valid: | |||||
logger.info(f"{u} still doesn't meet all the rules.") | |||||
for rule in relevant_rules: | |||||
i1 = u.index(rule[0]) | |||||
i2 = u.index(rule[1]) | |||||
if i1 > i2: | |||||
u[i1] = rule[1] | |||||
u[i2] = rule[0] | |||||
logger.info(f"Swapping {rule[0]} and {rule[1]}, u is now {u}.") | |||||
all_valid = all([u.index(rule[0]) < u.index(rule[1]) for rule in relevant_rules]) | |||||
new_invalid_updates.append(u) | |||||
middle_val = u[(len(u)-1)//2] | |||||
logger.info(f"Adding {middle_val} to {total_iu} to get {total_iu + middle_val}.") | |||||
total_iu += middle_val | |||||
print(total_vu) | |||||
logger.info(f"Total of invalid update centers is {total_iu}.") | |||||
if __name__ == "__main__": | |||||
main052() |