input_1 = Vector(3, 1) input_2 = [ Vector(1, 1), Vector(3, 1), Vector(5, 1), Vector(7, 1), Vector(1, 2) ] def trees_in_line(grid: Grid, step: Vector): bounds = Point(grid.width, grid.height) pos = Point(0, 0) trees = 0 while pos.y < grid.height: pos %= bounds if not grid[pos].is_passible(): trees += 1 pos += step return trees with open('2020/03/input.txt') as f: grid = Grid.from_list_of_strings([line.strip() for line in f.readlines()]) print(f'We would encounter {trees_in_line(grid,input_1)} trees') print( f'If you multiply together the number of trees encountered on each of the listed slopes, we would encounter {prod([trees_in_line(grid,step) for step in input_2])} trees' )
# https://adventofcode.com/2021/day/15 from fishpy.geometry.lattice import LatticePoint from fishpy.geometry.vector2d import Vector2D from fishpy.pathfinding.grid import Grid from fishpy.pathfinding import Dijkstra from fishpy.pathfinding.grid.expandablegrid import ExpandableGrid from fishpy.pathfinding.location import Location with open('2021/15/input.txt') as f: lines = [[int(char) for char in line] for line in f.read().rstrip().split()] # Part 1 grid_1 = Grid.from_list_of_strings(lines) adjacency_function = lambda point: LatticePoint.get_adjacent_points( point, lower_bound=grid_1.bounds[0], upper_bound=grid_1.bounds[1]) dijkstra = Dijkstra(LatticePoint(0, 0), grid_1.size - LatticePoint(1, 1), adjacency_function=adjacency_function, heuristic_function=LatticePoint.manhattan_distance, cost_function=lambda _, new: grid_1[new].rep) print(dijkstra.search()) # Part 2 grid_2 = ExpandableGrid.blank(LatticePoint(1, 1), LatticePoint(0, 0)) grid_2_overlay = ExpandableGrid.from_list_of_strings(lines) grid_2_layout = (5, 5) for grid_x in range(grid_2_layout[0]):
continue seen.add(pt) size += 1 for adj in pt.get_adjacent_points(lower_bound=LatticePoint(0, 0), upper_bound=grid.size): q.put(grid[adj]) return size with open('2021/09/input.txt') as f: lines = [line.rstrip() for line in f] grid_body = [[int(col) for col in line] for line in lines] total_risk = 0 grid = Grid.from_list_of_strings(grid_body) # for loc in grid: # total_risk += risk_level(grid,loc) # print('The total risk level is',total_risk) # seen = set() # scores = PriorityQueue(max_=True) # for loc in grid: # loc:Location # if loc.rep == 9 or loc in seen: # continue # scores.put(basin_size(grid,loc,seen)) print( grid.flood_fill(start=Location(0, 0, Location.IMPASSABLE, rep=1), predicate_function=lambda pt: pt.rep == 9))
# https://adventofcode.com/2018/day/10 import re from typing import List from fishpy import physics from fishpy.geometry import Point, Vector from fishpy.pathfinding.grid import Grid input_file = '2018/10/input.txt' with open(input_file) as f: lights:List[physics.Object] = [] for line in f: line = re.split('<|,|>',line) pos = Point(int(line[1]),int(line[2])) vel = Vector(int(line[4]),int(line[5])) lights.append(physics.Object(pos,vel)) step = 0 for i in range(10710): for light in lights: light.step() step += 1 if step % 1000 == 0: print(step) print(step) g = Grid.blank(Point(68,16),offset=Point(184,190)).conditional_walls(lambda obj: obj in {light.position for light in lights},char='#') print(g)
# Written by Cameron Haddock # Written as a solution for Advent of Code 2016 # https://adventofcode.com/2016/day/24 from fishpy.geometry import Point from fishpy.mathematics.graphs import PathGraph from fishpy.pathfinding import Dijkstra from fishpy.pathfinding.grid import Grid with open('2016/24/input.txt') as f: grid = Grid.from_list_of_strings(f.read().strip().split('\n')) nodes = grid.char_positions([str(i) for i in range(8)]) G = PathGraph() for node in nodes: G.add_node(node) validate = lambda pt: grid[pt].is_passible() weight = lambda n1,n2: Dijkstra(nodes[n1][0],nodes[n2][0],Point.get_adjacent_points,validate,Point.manhattan_distance).search() G.add_weighted_edges_for_complete(weight) run1 = G.get_length_of_path(G.complete_travelling_salesman(start='0')) run2 = G.get_length_of_path(G.complete_travelling_salesman(start='0',end='0')) print(f'Starting from location 0, the fewest number of steps required to visit every non-0 number marked on the map at least once is {run1}') print(f'The fewest number of steps required to start at 0 and visit every non-0 number marked on the map at least once, then return to 0 is {run2}')
layer = [] for y in range(BOUNDS.y): row = [] for x in range(BOUNDS.x): if c := f.read(1): row.append(c) else: end = True break if end: break layer.append(row) if end: break layers.append( Grid.from_list_of_strings([''.join(row) for row in layer])) # Verify image not corrupted min = (-1, 10**6) for i in range(len(layers)): zeros = len(layers[i].char_positions(['0'])['0']) if zeros < min[1]: min = (i, zeros) counts = layers[min[0]].char_positions(['1', '2']) print(len(counts['1']) * len(counts['2'])) # Decode image final = [] for y in range(BOUNDS.y): row = '' for x in range(BOUNDS.x):
from fishpy.pathfinding import Dijkstra from fishpy.utility.debug import profile, timer from copy import copy class LatticeHash(LatticePoint): def __hash__(self) -> int: return self.y * 100 + self.x @staticmethod def from_point(pt: LatticePoint): return LatticeHash(pt.x, pt.y) with open('2021/23/input_2.txt') as f: grid = Grid.from_list_of_strings(f.read().splitlines()) wall_positions = grid.char_positions('# ') walls = { LatticeHash.from_point(pos) for char in wall_positions for pos in wall_positions[char] } ROOM_SIZE = grid.height - 3 class Amphipod: MOVE_COST = {'A': 1, 'B': 10, 'C': 100, 'D': 1000} BANNED_POSITIONS = { LatticeHash(3, 1), LatticeHash(5, 1), LatticeHash(7, 1), LatticeHash(9, 1)
grid_copy = g.copy() for pt in g: adj = pt.get_adjacent_points(diagonals=True, lower_bound=g._offset, upper_bound=g._offset + g.bounds) count = len([a for a in adj if g[a].rep == '#']) if g[pt].rep == '.': if count == 3: grid_copy[pt].rep = '#' else: if count not in {2, 3}: grid_copy[pt].rep = '.' g = grid_copy print('Result 1:', len([str(pt) for pt in g.char_positions('#')['#']])) g = Grid.from_list_of_strings(layout, offset=Point(-3, -3)) side = len(layout[0]) + ITERATIONS * 2 min_, max_ = -side // 2 + 1, side // 2 + 1 mat = [[[[ g[Point(x, y)].rep if z == w == 0 and Point(x, y) in g else '.' for x in range(min_, max_) ] for y in range(min_, max_)] for z in range(min_, max_)] for w in range(min_, max_)] min_bound, max_bound = PointND([0, 0, 0, 0]), PointND([20, 20, 20, 20]) bounds_function = lambda pt: min_bound <= pt < max_bound final_count = len(g.char_positions(['#'])['#']) for i in range(ITERATIONS): print(f'Count after {i} rounds is {final_count}') mat_copy = deepcopy(mat)
def __init__(self,pos:Point,grid_serial:int): self._pos = pos self._grid_serial = grid_serial self.rack_id = pos.x + 10 self.power = (pos.y * self.rack_id + grid_serial) * self.rack_id // 100 % 10 - 5 def copy(self): return FuelCell(self._pos,self._grid_serial) input = 9798 BOUNDS = Point(300,300) values = [[FuelCell(Point(x,y),input) for x in range(BOUNDS.x)] for y in range(BOUNDS.y)] # values = [[Location(x,y,Location.OPEN,rep=FuelCell(Point(x,y),input)) for x in range(BOUNDS.x)] for y in range(BOUNDS.y)] g = Grid(values) largest = (0,Point(0,0)) for x in range(BOUNDS.x-3): for y in range(BOUNDS.y-3): sg = g.subgrid(Point(x,y),Point(x+3,y+3)) value = 0 for pos in sg: value += pos.power current = (value,Point(x,y)) largest = max(largest,current) print(largest[1]) starting_size = 1 for s in range(starting_size,20):
return pos class Bot: def __init__(self,dir:str,pos:int,track_length:int): self.dir = dir self.pos = pos self.track_size = track_length def step(self): if self.dir == 'c': self.pos = (self.pos + 1) % self.track_size elif self.dir == 'ac': self.pos = (self.pos - 1) % self.track_size with open(input) as f: grid = Grid.from_list_of_strings([line.strip('\n') for line in f]) for loc in grid: if loc.rep in '^v<>': u = loc.up() in grid and grid[loc.up()].rep in '|+' d = loc.down() in grid and grid[loc.down()].rep in '|+' l = loc.left() in grid and grid[loc.left()].rep in '-+' r = loc.right() in grid and grid[loc.right()].rep in '-+' v = u and d h = l and r if v and h: loc.rep = '+' elif v: loc.rep = '|' elif h: loc.rep = '-' else:
# Written by Cameron Haddock # Written as a solution for Advent of Code 2020 # https://adventofcode.com/2020/day/11 from fishpy.geometry import Point from fishpy.pathfinding.grid import Grid with open('2020/11/input.txt', 'r') as input_file: lines = [line.strip() for line in input_file] grid1 = Grid.from_list_of_strings(lines, wall_char='') grid2 = grid1.copy() while True: copy = grid1.copy() for pt in copy: if pt.rep == '.': continue count_occupied = 0 is_empty = pt.rep == 'L' for adj in pt.get_adjacent_points(diagonals=True, lower_bound=Point(0, 0), upper_bound=grid1.bounds): if grid1[adj].rep == '#': count_occupied += 1 if is_empty and count_occupied == 0: pt.rep = '#' elif not is_empty and count_occupied >= 4: pt.rep = 'L' if grid1 == copy: break