def execute_steps(self, steps): for step in steps: step = step.split() if step[0] == 'rect': axb = step[1].split('x') self.rect(Point(int(axb[0]), int(axb[1]))) elif step[0] == 'rotate': which = int(step[2].split('=')[1]) num = int(step[4]) if step[1] == 'column': self.rotate_col(which, num) elif step[1] == 'row': self.rotate_row(which, num)
def test_in_bounds(self): self.assertTrue( self.p1.in_bounds(lower_bound=Point(0, 0), upper_bound=Point(5, 5))) self.assertTrue( self.p2.in_bounds(lower_bound=Point(-1, -5), upper_bound=Point(10, 10))) self.assertFalse( self.p3.in_bounds(lower_bound=Point(-10, -10), upper_bound=Point(0, 0))) self.assertFalse( self.p4.in_bounds(lower_bound=Point(-5, -10), upper_bound=self.p4))
def a_star(start): q = PriorityQueue() q.put((0,start)) seen = set() while not q.empty(): cur = q.get()[1] if cur in seen: continue seen.add(cur) # print(cur) if cur.y == 4: return print_path(get_path(prev[cur])) g = get_g(cur) p1 = Point(cur.x,cur.y+1) prev[p1] = cur q.put((-g-get_h(p1),p1)) p2 = Point(cur.x+1,cur.y+1) prev[p2] = cur q.put((-g-get_h(p2),p2)) return None
def a_star(start, target): q = PriorityQueue() q.put((get_value(start), start)) seen = set() prev = {} while not q.empty(): cur = q.get()[1] if cur in seen: continue seen.add(cur) if cur == target: return get_g(cur, prev) p1 = cur + Point(0, 1) if p1 not in prev and 0 <= p1.x <= target.x and 0 <= p1.y <= target.y: prev[p1] = cur q.put((get_g(p1, prev) + get_h(p1, target), p1)) p2 = cur + Point(1, 0) if p2 not in prev and 0 <= p2.x <= target.x and 0 <= p2.y <= target.y: prev[p2] = cur q.put((get_g(p2, prev) + get_h(p2, target), p2)) return None
def flood_fill(fill_char:str) -> int: filled = set() wall = set() next = PriorityQueue() next.put((0,start)) while not next.empty(): tup = next.get() g = tup[0] cur = tup[1] if cur in wall or cur in filled or g > max_flood_steps: continue if grid[cur.y][cur.x] != '#': filled.add(cur) for tup in [(g+1,adj) for adj in cur.get_adjacent_points(lower_bound=Point(0,0),upper_bound=bounds)]: next.put(tup) grid[cur.y][cur.x] = fill_char else: wall.add(cur) return len(filled)
def move(self, dir): newpos = None if dir == 'U': newpos = self.pos + Point(0, 1) elif dir == 'D': newpos = self.pos + Point(0, -1) elif dir == 'R': newpos = self.pos + Point(1, 0) elif dir == 'L': newpos = self.pos + Point(-1, 0) upper_bound = Point(len(self.layout[0]), len(self.layout)) if newpos.in_bounds( lower_bound=Point(0, 0), upper_bound=upper_bound) and self.get_key_at(newpos) != '': self.pos = newpos
def dijkstra() -> int: prev = {} q = PriorityQueue() q.put((0,start.copy())) seen = set() while not q.empty(): tup = q.get() g = tup[0] cur = tup[1] if cur in seen: continue seen.add(cur) if cur == target: return len(get_path(prev,cur)) - 1 for pt in cur.get_adjacent_points(lower_bound=Point(0,0),upper_bound=bounds): if pt not in seen and grid[pt.y][pt.x] == '.': prev[pt] = cur q.put((g+1,pt)) return -1
# Written by Cameron Haddock # Written as a solution for Advent of Code 2016 # https://adventofcode.com/2016/day/13 from fishpy.geometry import Point from queue import PriorityQueue input = 1358 target = Point(31,39) start = Point(1,1) bounds = Point(50,50) max_flood_steps = 50 grid = [] def is_open_space(pt:Point) -> bool: val = pt.x*pt.x + 3*pt.x + 2*pt.x*pt.y + pt.y + pt.y*pt.y + input bin = f'{val:b}' return bin.count('1') % 2 == 0 def generate_grid(bounds:Point) -> list: grid = [] for y in range(bounds.y): row = [] for x in range(bounds.x): pt = Point(x,y) if is_open_space(pt): row.append('.') else:
def test_le(self): self.assertTrue(Point(1, 0) <= self.p1) self.assertTrue(Point(-3, 5) <= self.p4) self.assertTrue(Point(0, 1) <= self.p3) self.assertFalse(Point(6, 6) <= self.p4)
def rect(self, pt: Point): for y in range(pt.y): for x in range(pt.x): self.set_pixel(Point(x, y), True) return self
def rotate_row(self, y, steps): row = self.screen[y] row = row[-(steps % len(row)):] + row[:-(steps % len(row))] self.screen[y] = row return self def execute_steps(self, steps): for step in steps: step = step.split() if step[0] == 'rect': axb = step[1].split('x') self.rect(Point(int(axb[0]), int(axb[1]))) elif step[0] == 'rotate': which = int(step[2].split('=')[1]) num = int(step[4]) if step[1] == 'column': self.rotate_col(which, num) elif step[1] == 'row': self.rotate_row(which, num) def lit_pixels(self): return sum([sum(self.screen[y]) for y in range(self.dim.y)]) with open('2016/08/input.txt') as f: lcd = LCD(Point(50, 6)) lcd.execute_steps(f.readlines()) print( f'If the screen did work, there would be {lcd.lit_pixels()} pixels lit up' ) print(lcd)
def setUp(self): self.p1 = Point(1, 1)
# Written by Cameron Haddock # Written as a solution for Advent of Code 2015 # https://adventofcode.com/2015/day/25 from fishpy.geometry import Point def triangle(n: int): return n * (n + 1) // 2 def get_diagonal_from_coords(pt: Point) -> int: return pt.x + pt.y - 1 def cycle(iter, initial): for _ in range(1, iter): initial *= 252533 initial %= 33554393 return initial pt = Point(3083, 2978) rt = get_diagonal_from_coords(pt) print(cycle(triangle(rt - 1) + pt.x, 20151125))
from fishpy.pathfinding import Location from fishpy.pathfinding.grid import Grid class FuelCell: 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])
# Written by Cameron Haddock # Written as a solution for Advent of Code 2020 # https://adventofcode.com/2020/day/12 from fishpy.geometry import Point with open('2020/12/input.txt','r') as input_file: steps = [line.strip() for line in input_file] pos = Point(0,0) dir = Point(1,0) for step in steps: action = step[0] value = int(step[1:]) if action == 'R': while value != 0: dir = Point(dir.y,-dir.x) value -= 90 elif action == 'L': while value != 0: dir = Point(-dir.y,dir.x) value -= 90 elif action == 'F': pos += dir*value elif action == 'N': pos += Point(0,1) * value elif action == 'S': pos += Point(0,-1) * value elif action == 'E':
for pt in path: print(str(pt),'->',grid[pt.y][pt.x]) def a_star(start): q = PriorityQueue() q.put((0,start)) seen = set() while not q.empty(): cur = q.get()[1] if cur in seen: continue seen.add(cur) # print(cur) if cur.y == 4: return print_path(get_path(prev[cur])) g = get_g(cur) p1 = Point(cur.x,cur.y+1) prev[p1] = cur q.put((-g-get_h(p1),p1)) p2 = Point(cur.x+1,cur.y+1) prev[p2] = cur q.put((-g-get_h(p2),p2)) return None print(a_star(Point(0,0)))
elif self.pos.is_left_of(pos) and hash[3] in 'bcdef': adj.append(State(pos, path + 'R')) return adj def __eq__(self, other): return self.pos == other.pos def __hash__(self): return hash(self.path) @property def hash(self): return md5((input + self.path).encode()).hexdigest()[:4] start = State(Point(0, 0), '') target = State(Point(3, 3), '') d = Dijkstra(start, target, adjacency_function=State.adjacents) print(d.search()) dft = DepthFirstTraversal(start, target, adjacency_function=State.adjacents, longest_path=True) dft.execute() #Comment out return to make it work distances = [] for key in dft.distance: if key == target: distances.append(dft.distance[key]) print(max(distances))
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, layout): self.pos = Point(1, 1) self.layout = layout
def test_true_div(self): self.assertEqual(self.p1 / 2, Point(0.5, 0.5)) self.assertEqual(self.p2 / 1, Point(1, -5)) self.assertEqual(self.p3 / 4, Point(0, 0.5)) self.assertEqual(self.p4 / -1, Point(3, -5)) self.assertRaises(ZeroDivisionError, Point.__truediv__, self.p1, 0)
def reflect_point_across_line(p: Point, m, c) -> Point: u = ((1 - m**2) * p.x + 2 * m * p.y - 2 * m * c) / ((m**2) + 1) v = ((m**2 - 1) * p.y + 2 * m * p.x + 2 * c) / ((m**2) + 1) return Point(u, v)
def test_origin(self): self.assertEqual(Point.origin(1), Point(0)) self.assertEqual(Point.origin(2), Point(0, 0)) self.assertEqual(Point.origin(3), Point(0, 0, 0)) self.assertEqual(Point.origin(4), Point(0, 0, 0, 0)) self.assertEqual(Point.origin(5), Point(0, 0, 0, 0, 0)) self.assertNotEqual(Point.origin(5), Point(0, 0, 0, 0, 1)) self.assertNotEqual(Point.origin(5), Point(0, 0, 0, 0, 0, 1))
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): pt = Point(x, y) which = 0 while layers[which][pt].rep == '2': which += 1 if layers[which][pt].rep == '1': row += '@' else: row += ' ' final.append(row) final = Grid.from_list_of_strings(final) print(final)
def test_mul(self): self.assertEqual(self.p1 * 3, Point(3, 3)) self.assertEqual(self.p2 * -1, Point(-1, 5)) self.assertEqual(self.p3 * 2, Point(0, 4)) self.assertEqual(self.p4 * 0.5, Point(-1.5, 2.5))
# 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)
# https://adventofcode.com/2016/day/1 from fishpy.geometry import Point def turn_left(pt): return Point(-pt.y, pt.x) def turn_right(pt): return Point(pt.y, -pt.x) with open('2016/01/input.txt') as in_file: directions = in_file.readline().strip().split(', ') cur = Point(0, 0) seen = {cur} facing = Point(0, 1) for dir in directions: if dir[0] == 'L': facing = turn_left(facing) elif dir[0] == 'R': facing = turn_right(facing) found = False for i in range(int(dir[1:])): cur = cur + facing if cur in seen: found = True break seen.add(cur) if found:
# https://adventofcode.com/2017/day/3 from fishpy.geometry import Point, Vector from fishpy.pathfinding.grid import ExpandableGrid def is_square(n): return n**0.5 == int(n**0.5) def is_odd_square(n): return is_square(n) and int(n**0.5)%2 == 1 input = 361527 i = 1 pos = Point(0,0) step = Vector(1,0) grid = ExpandableGrid([[1]]) next_val = 1 while next_val < input: if is_odd_square(i-1): grid.expand_right(1,fill_char=0) step = Vector(0,1) if is_even_square(i-1): i += 1
def turn_right(pt): return Point(pt.y, -pt.x)
continue seen.add(cur) if cur == target: return get_g(cur, prev) p1 = cur + Point(0, 1) if p1 not in prev and p1 not in seen and 0 <= p1.x <= target.x and 0 <= p1.y <= target.y: prev[p1] = cur q.put((get_g(p1, prev) + get_h(p1, target), p1)) p2 = cur + Point(1, 0) if p2 not in prev and p2 not in seen and 0 <= p2.x <= target.x and 0 <= p2.y <= target.y: prev[p2] = cur q.put((get_g(p2, prev) + get_h(p2, target), p2)) p3 = cur + Point(0, -1) if p3 not in prev and p3 not in seen and 0 <= p3.x <= target.x and 0 <= p3.y <= target.y: prev[p3] = cur q.put((get_g(p3, prev) + get_h(p3, target), p3)) p4 = cur + Point(-1, 0) if p4 not in prev and p4 not in seen and 0 <= p4.x <= target.x and 0 <= p4.y <= target.y: prev[p4] = cur q.put((get_g(p4, prev) + get_h(p4, target), p4)) return None print(a_star(Point(0, 0), Point(len(grid[0]) - 1, len(grid) - 1)))
def turn_left(pt): return Point(-pt.y, pt.x)