def _date_check(self, fpath): """ Checks a files modified date is equal to or within a min and max date. """ if self.date != None: search_date = datetime.fromtimestamp( self.date).strftime('%Y-%m-%d') file_date = datetime.fromtimestamp( os.path.getmtime(fpath)).strftime('%Y-%m-%d') if search_date != file_date: dprint("failed date: {}!={}".format(file_date, search_date)) return False elif self.min_date != None or self.max_date != None: file_date = os.path.getmtime(fpath) #dprint("file_date: {}".format(file_date)) if self.min_date != None: #dprint("min_date: {}".format(self.min_date)) if file_date < self.min_date: #dprint("failed min_date: {}<{}".format(str_file_date, str_min_date)) return False if self.max_date != None: #dprint("max_date: {}".format(self.max_date)) if file_date >= self.max_date: #dprint("failed max_date: {}>{}".format(file_date, str_max_date)) return False return True
def _try_parsing_date(self, string_date): """ Try's to turn a string date into a python formatted date type. Params: ---------- string_date [string] : datetime formatting string Returns: ---------- datetime """ if string_date == None: return None string_date = re.sub("\.|/|-|,|:", " ", string_date) for fmt in ('%m %d %Y', '%m %d %y', '%m %d %Y %H %M', '%m %d %y %H %M', '%d %m %Y', '%d %m %y', '%d %m %Y %H %M', '%d %m %y %H %M', '%Y %m %d', '%y %m %d', '%Y %m %d %H %M', '%y %m %d %H %M'): try: t = time.mktime( datetime.strptime(string_date, fmt).timetuple()) return t except ValueError: dprint(string_date) ThrowError(message='no valid date format found')
def run_part1(self, data: InputData) -> str: tileList = self.create_all_tiles(data.input) cornerTiles = self.get_open_side_tiles(tileList, 2) result = 1 for corner in cornerTiles: result *= corner.id helper.dprint(f"tile id: {corner.id}") return helper.validate_result('What do you get if you multiply together the IDs of the four corner tiles?', result, data.expectedAnswer)
def tag_monster(self, tile: TileData, idx: int, monsterIndexes: List[int]) -> None: helper.dprint("monster found") for i in monsterIndexes: tIdx = idx + i r = (tIdx % tile.tileSize) row = (tIdx - r) // tile.tileSize xidx = tIdx - (row * tile.tileSize) tile.tile[row][xidx] = "O"
def run_part2(self, data: InputData) -> str: result = 0 for line in data.input: total = self.evaluate2(line) result += total helper.dprint(f"{total:-6} = {line}") return helper.validate_result('What do you get if you add up the results of evaluating the homework problems using these new rules?', result, data.expectedAnswer)
def run_part1(self, data: InputData) -> str: result = 0 for line in data.input: total = self.evaluate(line) result += total helper.dprint(f"{total:-6} = {line}") return helper.validate_result('What is the sum of the resulting values?', result, data.expectedAnswer)
def _types_check(self, file_extension): """ Checks to make sure file has proper extension. Doesn't look at file structure """ if self.file_types != None: if not file_extension in self.file_types: dprint("failed file_extension: {}<{}".format( file_extension, self.file_types)) return False return True
def count_valid_images(self, messages: List[str], regex: str): regex += r'$' # Include line-end in regex to match whole line p = re.compile(regex) count = 0 for message in messages: match = p.match(message) if match: count += 1 helper.dprint(message) return count
def run_part2(self, data: InputData) -> str: tileFloor = self.build_tile_floor(data.input) day = 0 result = self.count_black_tiles([x for x in tileFloor.values()]) helper.dprint(f"Initial: {result} black tiles") while day < 100: day += 1 self.update_floor_tiles(tileFloor) result = self.count_black_tiles([x for x in tileFloor.values()]) helper.dprint(f"Day {day}: {result}") return helper.validate_result( "How many tiles will be black after 100 days?", result, data.expectedAnswer)
def _find(self, path=None): """ Returns all the files in a given path based on search criteria. Params: ----------- path [string] : path to search """ global FILES global FOLDERS global FOUND if path == None: path = self.path else: # Turn path into absolute path = os.path.abspath(path) # Traverse directory to find files for (dirpath, dirnames, filenames) in os.walk(path): dprint(dirnames) self.results[dirpath] = FileCollection() for d in dirnames: dpath = os.path.join(dirpath, d) if not dpath in self.results: self.counts.folders += 1 self.results[dpath] = FileCollection() sum = 0 for f in filenames: self.counts.files += 1 self.results[dirpath].base = dirpath fpath = os.path.join(dirpath, f) # check to see if we should keep the file keeps = self._keep_file(fpath) if keeps != False: self.counts.found += 1 fs, fd, fe = keeps self.counts.size += fs sum += fs dprint((fs, f, fd, fe)) self.results[dirpath].add_file(File( dirpath, f, fs, fd, fe)) self.results[dirpath].size = sum return self.results
def _size_check(self, file_size): """ Checks a files size to make sure: 1) it equals some "size" +/- some delta 2) it is in between some min/max size """ if self.size != None: if self.size_delta == None: ThrowError( message= 'Searching for size requires a "size_delta" as well ...') if file_size < (self.size - self.size_delta) or ( self.size + self.size_delta) < file_size: dprint("failed size: {} <> {} <> {}".format( humanfriendly.format_size(self.size - self.size_delta), file_size, humanfriendly.format_size(self.size + self.size_delta))) return False if self.min_size != None or self.max_size != None: if self.min_size != None: if file_size < self.min_size: dprint("failed min_size: {}<{}".format( file_size, self.min_size)) return False if self.max_size != None: if file_size > self.max_size: dprint("failed max_size: {}<{}".format( file_size, self.max_size)) return False return True
def run_part1(self, data: InputData) -> str: cardPublicKey = data.input[0] doorPublicKey = data.input[1] cardLoopSize = self.find_loop_size(cardPublicKey) doorLoopSize = self.find_loop_size(doorPublicKey) helper.dprint(f"card key: {cardPublicKey} loop size: {cardLoopSize}") helper.dprint(f"door key: {doorPublicKey} loop size: {doorLoopSize}") result1 = self.calculate_encryption_key(cardPublicKey, doorLoopSize) result2 = self.calculate_encryption_key(doorPublicKey, cardLoopSize) if result1 == result2: helper.dprint(" KEY MATCH") helper.dprint(f"key: {result1} - {result2}") return helper.validate_result( 'What encryption key is the handshake trying to establish?', result1, data.expectedAnswer)
def run_part2(self, data: InputData) -> str: tileList = self.create_all_tiles(data.input) sideSize = int(math.sqrt(len(tileList))) grid: List[List[TileData]] = [[None for x in range(sideSize)] for y in range(sideSize)] cornerTiles = self.get_open_side_tiles(tileList, 2) t = cornerTiles[0] grid[0][0] = t # starting corner for transformFunc in t.get_rotate_flip_actions(): bottomMatches = self.find_matching_tiles(tileList, t.get_edge_bottom()) leftMatches = self.find_matching_tiles(tileList, t.get_edge_left()) if len(bottomMatches) == 1 and len(leftMatches) == 1: break transformFunc() # bottom row for x in range(1, sideSize): edge = grid[0][x-1].get_edge_right() rtList = self.find_matching_tiles(tileList, edge) rtList.remove(grid[0][x-1]) assert(len(rtList) == 1) rt = rtList[0] for transformFunc in rt.get_rotate_flip_actions(): if rt.get_edge_left() == edge: grid[0][x] = rt break transformFunc() # each column for x in range(sideSize): for y in range(1, sideSize): edge = grid[y-1][x].get_edge_top() ntList = self.find_matching_tiles(tileList, edge) ntList.remove(grid[y-1][x]) assert(len(ntList) == 1) nt = ntList[0] for transformFunc in nt.get_rotate_flip_actions(): if nt.get_edge_bottom() == edge: grid[y][x] = nt break transformFunc() # remove all edges for y in range(sideSize): for x in range(sideSize): grid[y][x].remove_edges() # consolidate image imageList: List[str] = [] for y in range(sideSize - 1, -1, -1): #top down (each tile) for i in range(grid[0][0].tileSize): lineParts = ["".join(grid[y][x].tile[i]) for x in range(sideSize)] line = "".join(lineParts) imageList.append(line) t = TileData(0, imageList) monsterLengh = 20 spaces = " "*(t.tileSize - monsterLengh) monsterimage = f" # {spaces}# ## ## ###{spaces} # # # # # # " monsterIndexes = [i for i,c in enumerate(monsterimage) if c == '#'] monstersFound = False for transformFunc in t.get_rotate_flip_actions(): image = "".join(["".join(x) for x in t.tile]) for row in range(t.tileSize - 2): for i in range(t.tileSize - monsterLengh): start = (row * (t.tileSize)) + i if self.find_monster(image, start, monsterIndexes): monstersFound = True self.tag_monster(t, start, monsterIndexes) if monstersFound: break transformFunc() image = "\n".join(["".join(x) for x in t.tile]) helper.dprint("--- IMAGE ---") helper.dprint(image) helper.dprint("") result = 0 for row in range(t.tileSize): for x in range(t.tileSize): if t.tile[row][x] == "#": result += 1 return helper.validate_result('How many # are not part of a sea monster?', result, data.expectedAnswer)
def show_seat_map(self, seats: Table, title: str): helper.dprint(title) for y in seats: helper.dprint("".join(y)) helper.dprint("")
def play_recursive_combat(self, p1Deck: CardList, p2Deck: CardList, history: List[str]) -> Tuple[str, CardList]: game = self.nextGame self.nextGame += 1 if game == 5: helper.dprint("") helper.dprint(f"=== Game {game} ===") helper.dprint("") round = 0 winner = "" winningDeck: CardList = [] while len(p1Deck) > 0 and len(p2Deck) > 0: round += 1 if not self.add_to_history(game, p1Deck, p2Deck, history): helper.dprint( f"{Const_Player1} wins round {round} of game {game}!") return Const_Player1, p1Deck helper.dprint(f"-- Round {round} (Game {game}) --") helper.dprint(f"{Const_Player1}'s deck: " + ", ".join(str(x) for x in p1Deck)) helper.dprint(f"{Const_Player2}'s deck: " + ", ".join(str(x) for x in p2Deck)) p1Card = p1Deck.pop(0) p2Card = p2Deck.pop(0) helper.dprint(f"{Const_Player1} plays {p1Card}") helper.dprint(f"{Const_Player2} plays {p2Card}") if p1Card <= len(p1Deck) and p2Card <= len(p2Deck): helper.dprint("Playing a sub-game to determine the winner...") helper.dprint("") p1SubDeck = p1Deck[:p1Card] p2SubDeck = p2Deck[:p2Card] winner, winningDeck = self.play_recursive_combat( p1SubDeck, p2SubDeck, history) else: winner = Const_Player1 if p1Card > p2Card else Const_Player2 helper.dprint(f"{winner} wins round {round} of game {game}!") if winner == Const_Player1: p1Deck.append(p1Card) p1Deck.append(p2Card) else: p2Deck.append(p2Card) p2Deck.append(p1Card) helper.dprint("") if game == 1: helper.dprint("== Post-game results ==") helper.dprint(f"{Const_Player1}'s deck: " + ", ".join(str(x) for x in p1Deck)) helper.dprint(f"{Const_Player2}'s deck: " + ", ".join(str(x) for x in p2Deck)) else: helper.dprint(f"The winner of game {game} is {winner}!") return (Const_Player1, p1Deck) if winner == Const_Player1 else (Const_Player2, p2Deck)
def play_combat(self, p1Deck: CardList, p2Deck: CardList) -> CardList: round = 0 while len(p1Deck) > 0 and len(p2Deck) > 0: round += 1 helper.dprint(f"-- Round {round} --") helper.dprint(f"{Const_Player1}'s deck: " + ", ".join(str(x) for x in p1Deck)) helper.dprint(f"{Const_Player2}'s deck: " + ", ".join(str(x) for x in p2Deck)) p1Card = p1Deck.pop(0) p2Card = p2Deck.pop(0) helper.dprint(f"{Const_Player1} plays {p1Card}") helper.dprint(f"{Const_Player2} plays {p2Card}") if p1Card > p2Card: helper.dprint(f"{Const_Player1} wins the round!") # add_to_deck(p1Deck, p1Card, p2Card) p1Deck.append(p1Card) p1Deck.append(p2Card) else: helper.dprint(f"{Const_Player2} wins the round!") # add_to_deck(p2Deck, p2Card, p1Card) p2Deck.append(p2Card) p2Deck.append(p1Card) helper.dprint("") helper.dprint("== Post-game results ==") helper.dprint(f"{Const_Player1}'s deck: " + ", ".join(str(x) for x in p1Deck)) helper.dprint(f"{Const_Player2}'s deck: " + ", ".join(str(x) for x in p2Deck)) return p1Deck if len(p1Deck) > 0 else p2Deck