black, and part 2 day 8
This commit is contained in:
parent
0c856bcc7e
commit
cf1d693033
@ -3,6 +3,7 @@ import shared
|
|||||||
import itertools
|
import itertools
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part1(rows):
|
def part1(rows):
|
||||||
pass
|
pass
|
||||||
@ -19,7 +20,7 @@ def main():
|
|||||||
part1(rows)
|
part1(rows)
|
||||||
print("🕒", elapsed())
|
print("🕒", elapsed())
|
||||||
|
|
||||||
rows = [row for row in shared.load_rows(1,True)]
|
rows = [row for row in shared.load_rows(1, True)]
|
||||||
with shared.elapsed_timer() as elapsed:
|
with shared.elapsed_timer() as elapsed:
|
||||||
part2(rows)
|
part2(rows)
|
||||||
print("🕒", elapsed())
|
print("🕒", elapsed())
|
||||||
|
@ -7,37 +7,37 @@ NUMS = {
|
|||||||
"one": 1,
|
"one": 1,
|
||||||
"two": 2,
|
"two": 2,
|
||||||
"six": 6,
|
"six": 6,
|
||||||
|
|
||||||
"four": 4,
|
"four": 4,
|
||||||
"five": 5,
|
"five": 5,
|
||||||
"nine": 9,
|
"nine": 9,
|
||||||
|
|
||||||
"seven": 7,
|
"seven": 7,
|
||||||
"eight": 8,
|
"eight": 8,
|
||||||
"three": 3,
|
"three": 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part1(rows):
|
def part1(rows):
|
||||||
total = 0
|
total = 0
|
||||||
for row in rows:
|
for row in rows:
|
||||||
numbers = ''.join(filter(str.isdigit, row))
|
numbers = "".join(filter(str.isdigit, row))
|
||||||
total += get_total(numbers)
|
total += get_total(numbers)
|
||||||
print(total)
|
print(total)
|
||||||
|
|
||||||
|
|
||||||
def get_total(numbers):
|
def get_total(numbers):
|
||||||
tens, ones= int(numbers[0]),int(numbers[-1])
|
tens, ones = int(numbers[0]), int(numbers[-1])
|
||||||
return (tens * 10) + ones
|
return (tens * 10) + ones
|
||||||
|
|
||||||
|
|
||||||
def loop_row(row):
|
def loop_row(row):
|
||||||
digits = []
|
digits = []
|
||||||
for idx, _ in enumerate(row):
|
for idx, _ in enumerate(row):
|
||||||
if str.isdigit(row[idx]):
|
if str.isdigit(row[idx]):
|
||||||
digits.append(row[idx])
|
digits.append(row[idx])
|
||||||
continue
|
continue
|
||||||
for x in [3,4,5]:
|
for x in [3, 4, 5]:
|
||||||
next = row[idx:idx+x]
|
next = row[idx : idx + x]
|
||||||
if next in NUMS.keys():
|
if next in NUMS.keys():
|
||||||
digits.append(str(NUMS[next]))
|
digits.append(str(NUMS[next]))
|
||||||
break
|
break
|
||||||
@ -52,6 +52,7 @@ def part2(rows):
|
|||||||
total += get_total(nums)
|
total += get_total(nums)
|
||||||
print(total)
|
print(total)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
rows = [row for row in shared.load_rows(1)]
|
rows = [row for row in shared.load_rows(1)]
|
||||||
with shared.elapsed_timer() as elapsed:
|
with shared.elapsed_timer() as elapsed:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import shared
|
import shared
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
def split_games(row):
|
def split_games(row):
|
||||||
game, draws = row.split(":")
|
game, draws = row.split(":")
|
||||||
game = int(game.split(" ")[-1])
|
game = int(game.split(" ")[-1])
|
||||||
@ -10,14 +11,16 @@ def split_games(row):
|
|||||||
cube = cube.split()
|
cube = cube.split()
|
||||||
count, color = cube
|
count, color = cube
|
||||||
colors[color].append(int(count))
|
colors[color].append(int(count))
|
||||||
return game,colors
|
return game, colors
|
||||||
|
|
||||||
|
|
||||||
MAXES = {
|
MAXES = {
|
||||||
"red": 12,
|
"red": 12,
|
||||||
"green":13,
|
"green": 13,
|
||||||
"blue": 14,
|
"blue": 14,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part1(rows):
|
def part1(rows):
|
||||||
applicable = []
|
applicable = []
|
||||||
@ -39,14 +42,11 @@ def part2(rows):
|
|||||||
total = 0
|
total = 0
|
||||||
for row in rows:
|
for row in rows:
|
||||||
_, colors = split_games(row)
|
_, colors = split_games(row)
|
||||||
power=1
|
power = 1
|
||||||
for vals in colors.values():
|
for vals in colors.values():
|
||||||
power *= max(vals)
|
power *= max(vals)
|
||||||
total += power
|
total += power
|
||||||
print(total)
|
print(total)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -5,43 +5,49 @@ import functools
|
|||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
SYMBOLS="*%@#+-/$=&"
|
SYMBOLS = "*%@#+-/$=&"
|
||||||
|
|
||||||
|
|
||||||
def get_all_numbers_and_starting_coords(mat):
|
def get_all_numbers_and_starting_coords(mat):
|
||||||
"""
|
"""
|
||||||
for a coordinate, walks right until it encounters a non digit,
|
for a coordinate, walks right until it encounters a non digit,
|
||||||
when it does, it adds that number string to a collection,
|
when it does, it adds that number string to a collection,
|
||||||
and starts over, walking right until it continues to next row
|
and starts over, walking right until it continues to next row
|
||||||
"""
|
"""
|
||||||
nums = []
|
nums = []
|
||||||
for y, row in enumerate(mat):
|
for y, row in enumerate(mat):
|
||||||
x = 0
|
x = 0
|
||||||
while x < len(row):
|
while x < len(row):
|
||||||
num = matrix.number_starting_at(mat, x,y)
|
num = matrix.number_starting_at(mat, x, y)
|
||||||
if num is None:
|
if num is None:
|
||||||
x += 1
|
x += 1
|
||||||
continue
|
continue
|
||||||
nums.append(((x,y), num))
|
nums.append(((x, y), num))
|
||||||
x += len(num)
|
x += len(num)
|
||||||
return nums
|
return nums
|
||||||
|
|
||||||
|
|
||||||
def get_row_coords(x1, y, length):
|
def get_row_coords(x1, y, length):
|
||||||
"""
|
"""
|
||||||
for a given x,y point, it just creates the rest of the x/y coords to the right of this coord for a run
|
for a given x,y point, it just creates the rest of the x/y coords to the right of this coord for a run
|
||||||
"""
|
"""
|
||||||
coords = []
|
coords = []
|
||||||
for x in range(x1, x1+length):
|
for x in range(x1, x1 + length):
|
||||||
coords.append((x,y))
|
coords.append((x, y))
|
||||||
return coords
|
return coords
|
||||||
|
|
||||||
|
|
||||||
def process_number(mx, coords, num):
|
def process_number(mx, coords, num):
|
||||||
line_coords = get_row_coords(*coords, len(num))
|
line_coords = get_row_coords(*coords, len(num))
|
||||||
for coord in line_coords:
|
for coord in line_coords:
|
||||||
any_symbols = [(cs, v) for cs,v in matrix.get_neighbor_coords(mx, *coord) if v in SYMBOLS]
|
any_symbols = [
|
||||||
|
(cs, v) for cs, v in matrix.get_neighbor_coords(mx, *coord) if v in SYMBOLS
|
||||||
|
]
|
||||||
if any_symbols:
|
if any_symbols:
|
||||||
return True, any_symbols[0]
|
return True, any_symbols[0]
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part1(mat):
|
def part1(mat):
|
||||||
choose = []
|
choose = []
|
||||||
@ -66,8 +72,8 @@ def part2(mat):
|
|||||||
for coords, num in nums:
|
for coords, num in nums:
|
||||||
valid, sc = process_number(mat, coords, num)
|
valid, sc = process_number(mat, coords, num)
|
||||||
if valid:
|
if valid:
|
||||||
symbols[(sc[0]['r'],sc[0]['c'])].append(num)
|
symbols[(sc[0]["r"], sc[0]["c"])].append(num)
|
||||||
|
|
||||||
total = 0
|
total = 0
|
||||||
for splat in splats:
|
for splat in splats:
|
||||||
neighbors = symbols[splat]
|
neighbors = symbols[splat]
|
||||||
@ -78,7 +84,6 @@ def part2(mat):
|
|||||||
print(total)
|
print(total)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
mat = shared.load_file_char_matrix(shared.get_fname(3))
|
mat = shared.load_file_char_matrix(shared.get_fname(3))
|
||||||
with shared.elapsed_timer() as elapsed:
|
with shared.elapsed_timer() as elapsed:
|
||||||
|
@ -4,6 +4,7 @@ from pprint import pprint
|
|||||||
|
|
||||||
pattern = r"Card\s+(\d+): ([\d\s]+) \| ([\d\s]+)"
|
pattern = r"Card\s+(\d+): ([\d\s]+) \| ([\d\s]+)"
|
||||||
|
|
||||||
|
|
||||||
def load_cards(rows):
|
def load_cards(rows):
|
||||||
cards = {}
|
cards = {}
|
||||||
for row in rows:
|
for row in rows:
|
||||||
@ -18,37 +19,38 @@ def load_cards(rows):
|
|||||||
have=have,
|
have=have,
|
||||||
have_count=len(have),
|
have_count=len(have),
|
||||||
points=0,
|
points=0,
|
||||||
refs=0
|
refs=0,
|
||||||
)
|
)
|
||||||
if have:
|
if have:
|
||||||
points = 1
|
points = 1
|
||||||
for _ in range(len(have)-1):
|
for _ in range(len(have) - 1):
|
||||||
points *= 2
|
points *= 2
|
||||||
cards[card_number]['points'] = points
|
cards[card_number]["points"] = points
|
||||||
return cards
|
return cards
|
||||||
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part1(cards):
|
def part1(cards):
|
||||||
print(sum(card['points'] for _, card in cards.items()))
|
print(sum(card["points"] for _, card in cards.items()))
|
||||||
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part2(cards):
|
def part2(cards):
|
||||||
card_ids = list(range(len(cards)+1))
|
card_ids = list(range(len(cards) + 1))
|
||||||
for card_id, card in cards.items():
|
for card_id, card in cards.items():
|
||||||
nn = [x+1+card_id for x in range(card['have_count'])]
|
nn = [x + 1 + card_id for x in range(card["have_count"])]
|
||||||
if not nn:
|
if not nn:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# One point for initially having the card
|
# One point for initially having the card
|
||||||
for idx in nn:
|
for idx in nn:
|
||||||
cards[idx]['refs'] += 1
|
cards[idx]["refs"] += 1
|
||||||
# X more points for how many times this card is referenced
|
# X more points for how many times this card is referenced
|
||||||
for _ in range(card['refs']):
|
for _ in range(card["refs"]):
|
||||||
for idx in nn:
|
for idx in nn:
|
||||||
cards[idx]['refs'] += 1
|
cards[idx]["refs"] += 1
|
||||||
# Sum the ref counts, and then add the total cards in
|
# Sum the ref counts, and then add the total cards in
|
||||||
print(sum(card['refs'] for _, card in cards.items()) +len(cards))
|
print(sum(card["refs"] for _, card in cards.items()) + len(cards))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -2,11 +2,12 @@ import shared
|
|||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Mapping:
|
class Mapping:
|
||||||
dst: int
|
dst: int
|
||||||
src: int
|
src: int
|
||||||
ran: int # RANGE
|
ran: int # RANGE
|
||||||
|
|
||||||
|
|
||||||
maps_parts = [
|
maps_parts = [
|
||||||
@ -19,21 +20,24 @@ maps_parts = [
|
|||||||
"humidity-to-location",
|
"humidity-to-location",
|
||||||
]
|
]
|
||||||
|
|
||||||
group = lambda l,s: list(zip(*(iter(l),) * s))
|
group = lambda l, s: list(zip(*(iter(l),) * s))
|
||||||
|
|
||||||
|
|
||||||
def line_ints(s):
|
def line_ints(s):
|
||||||
return [int(x) for x in s.split() if s]
|
return [int(x) for x in s.split() if s]
|
||||||
|
|
||||||
|
|
||||||
def parse_line(line):
|
def parse_line(line):
|
||||||
return Mapping(*line)
|
return Mapping(*line)
|
||||||
|
|
||||||
|
|
||||||
class Mapper:
|
class Mapper:
|
||||||
def __init__(self, rows):
|
def __init__(self, rows):
|
||||||
self.parse(rows)
|
self.parse(rows)
|
||||||
|
|
||||||
def parse(self, rows):
|
def parse(self, rows):
|
||||||
seeds = rows.pop(0)
|
seeds = rows.pop(0)
|
||||||
rows.pop(0) # Discard empty to start at a clean slate
|
rows.pop(0) # Discard empty to start at a clean slate
|
||||||
seeds = line_ints(seeds.split(":")[1])
|
seeds = line_ints(seeds.split(":")[1])
|
||||||
maps = {}
|
maps = {}
|
||||||
current_map = None
|
current_map = None
|
||||||
@ -52,22 +56,23 @@ class Mapper:
|
|||||||
possibilities = self.maps[step]
|
possibilities = self.maps[step]
|
||||||
for p in possibilities:
|
for p in possibilities:
|
||||||
if source < p.src:
|
if source < p.src:
|
||||||
#print(f"\t{source} less than {p.src}")
|
# print(f"\t{source} less than {p.src}")
|
||||||
continue
|
continue
|
||||||
if source > p.src+ p.ran:
|
if source > p.src + p.ran:
|
||||||
#print(f"\t{source} greater than {p.src}+{p.ran}={p.src+p.ran}")
|
# print(f"\t{source} greater than {p.src}+{p.ran}={p.src+p.ran}")
|
||||||
continue
|
continue
|
||||||
#print(f"\t{source} in range")
|
# print(f"\t{source} in range")
|
||||||
#print(f"\t{source} is {p.dst + (source - p.src)}")
|
# print(f"\t{source} is {p.dst + (source - p.src)}")
|
||||||
return p.dst + (source - p.src)
|
return p.dst + (source - p.src)
|
||||||
break
|
break
|
||||||
return source
|
return source
|
||||||
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part1(rows):
|
def part1(rows):
|
||||||
mapper = Mapper(rows[:])
|
mapper = Mapper(rows[:])
|
||||||
locations = []
|
locations = []
|
||||||
|
|
||||||
for seed in mapper.seeds:
|
for seed in mapper.seeds:
|
||||||
next = seed
|
next = seed
|
||||||
for part in maps_parts:
|
for part in maps_parts:
|
||||||
@ -78,16 +83,14 @@ def part1(rows):
|
|||||||
print(min(locations))
|
print(min(locations))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part2(rows):
|
def part2(rows):
|
||||||
mapper = Mapper(rows[:])
|
mapper = Mapper(rows[:])
|
||||||
locations = []
|
locations = []
|
||||||
seeds = group(mapper.seeds, 2)
|
seeds = group(mapper.seeds, 2)
|
||||||
|
|
||||||
|
|
||||||
for seed_group in seeds:
|
for seed_group in seeds:
|
||||||
for seed in range(seed_group[0], seed_group[0]+seed_group[1]):
|
for seed in range(seed_group[0], seed_group[0] + seed_group[1]):
|
||||||
next = seed
|
next = seed
|
||||||
for part in maps_parts:
|
for part in maps_parts:
|
||||||
_part = next
|
_part = next
|
||||||
@ -96,7 +99,6 @@ def part2(rows):
|
|||||||
print(min(locations))
|
print(min(locations))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
rows = [row for row in shared.load_rows(5)]
|
rows = [row for row in shared.load_rows(5)]
|
||||||
with shared.elapsed_timer() as elapsed:
|
with shared.elapsed_timer() as elapsed:
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import matrix
|
import matrix
|
||||||
import shared
|
import shared
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from functools import reduce # Valid in Python 2.6+, required in Python 3
|
from functools import reduce # Valid in Python 2.6+, required in Python 3
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Game:
|
class Game:
|
||||||
duration: int
|
duration: int
|
||||||
highscore: int
|
highscore: int
|
||||||
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part1(rows):
|
def part1(rows):
|
||||||
times = [int(r) for r in rows[0].split(":")[1].split(" ") if r]
|
times = [int(r) for r in rows[0].split(":")[1].split(" ") if r]
|
||||||
@ -32,18 +32,21 @@ def part2(rows):
|
|||||||
ways.append(calculate(game))
|
ways.append(calculate(game))
|
||||||
print(reduce(operator.mul, ways, 1))
|
print(reduce(operator.mul, ways, 1))
|
||||||
|
|
||||||
|
|
||||||
def search(game, _range):
|
def search(game, _range):
|
||||||
for held in _range:
|
for held in _range:
|
||||||
remaining = game.duration - held
|
remaining = game.duration - held
|
||||||
score = held * remaining
|
score = held * remaining
|
||||||
if score > game.highscore:
|
if score > game.highscore:
|
||||||
return held
|
return held
|
||||||
|
|
||||||
|
|
||||||
def calculate(game):
|
def calculate(game):
|
||||||
starting_win = search(game, range(game.duration+1))
|
starting_win = search(game, range(game.duration + 1))
|
||||||
ending_win = search(game, reversed(range(game.duration+1)))
|
ending_win = search(game, reversed(range(game.duration + 1)))
|
||||||
print(game, starting_win, ending_win)
|
print(game, starting_win, ending_win)
|
||||||
return ending_win+1-starting_win
|
return ending_win + 1 - starting_win
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
rows = [row for row in shared.load_rows(6)]
|
rows = [row for row in shared.load_rows(6)]
|
||||||
@ -51,7 +54,7 @@ def main():
|
|||||||
part1(rows)
|
part1(rows)
|
||||||
print("🕒", elapsed())
|
print("🕒", elapsed())
|
||||||
|
|
||||||
rows = [row for row in shared.load_rows(6,True)]
|
rows = [row for row in shared.load_rows(6, True)]
|
||||||
with shared.elapsed_timer() as elapsed:
|
with shared.elapsed_timer() as elapsed:
|
||||||
part2(rows)
|
part2(rows)
|
||||||
print("🕒", elapsed())
|
print("🕒", elapsed())
|
||||||
|
@ -5,9 +5,9 @@ from collections import defaultdict
|
|||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
#STRENGTHS = list(reversed("A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, 2".split(", ")))
|
# STRENGTHS = list(reversed("A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, 2".split(", ")))
|
||||||
STRENGTHS = "A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, 2".split(", ")
|
STRENGTHS = "A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, 2".split(", ")
|
||||||
STRENGTHS_TO_WEIGHT = {k:idx for idx, k in enumerate(STRENGTHS)}
|
STRENGTHS_TO_WEIGHT = {k: idx for idx, k in enumerate(STRENGTHS)}
|
||||||
|
|
||||||
STRENGTH_HANDS = [
|
STRENGTH_HANDS = [
|
||||||
"Five of a Kind",
|
"Five of a Kind",
|
||||||
@ -19,20 +19,20 @@ STRENGTH_HANDS = [
|
|||||||
"High Card",
|
"High Card",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def determine_hand(cards):
|
def determine_hand(cards):
|
||||||
card_set = set(cards)
|
card_set = set(cards)
|
||||||
if len(card_set) == 1:
|
if len(card_set) == 1:
|
||||||
return "Five of a Kind"
|
return "Five of a Kind"
|
||||||
|
|
||||||
|
|
||||||
same_cards = sorted([cards.count(a) for a in card_set])
|
same_cards = sorted([cards.count(a) for a in card_set])
|
||||||
if len(same_cards) == 2:
|
if len(same_cards) == 2:
|
||||||
if max(same_cards) == 4:
|
if max(same_cards) == 4:
|
||||||
return "Four of a Kind"
|
return "Four of a Kind"
|
||||||
elif max(same_cards) == 3:
|
elif max(same_cards) == 3:
|
||||||
return "Full House"
|
return "Full House"
|
||||||
elif len(same_cards) == 3:
|
elif len(same_cards) == 3:
|
||||||
if max(same_cards) == 3:
|
if max(same_cards) == 3:
|
||||||
return "Three of a Kind"
|
return "Three of a Kind"
|
||||||
else:
|
else:
|
||||||
return "Two Pair"
|
return "Two Pair"
|
||||||
@ -40,6 +40,7 @@ def determine_hand(cards):
|
|||||||
return "One Pair"
|
return "One Pair"
|
||||||
return "High Card"
|
return "High Card"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Hand:
|
class Hand:
|
||||||
cards: str
|
cards: str
|
||||||
@ -72,8 +73,8 @@ def part1(rows):
|
|||||||
in_order.extend(hands[kind])
|
in_order.extend(hands[kind])
|
||||||
total = 0
|
total = 0
|
||||||
for rank, card in enumerate(in_order):
|
for rank, card in enumerate(in_order):
|
||||||
total += (rank+1)*card.bid
|
total += (rank + 1) * card.bid
|
||||||
|
|
||||||
print(total)
|
print(total)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,85 +1,55 @@
|
|||||||
import shared
|
import shared
|
||||||
from scanf import scanf
|
from scanf import scanf
|
||||||
|
from pprint import pprint
|
||||||
|
from math import lcm
|
||||||
|
|
||||||
|
|
||||||
def check(d):
|
def setup(rows):
|
||||||
return all(x[-1] == "Z" for x in d.values())
|
|
||||||
|
|
||||||
# @shared.profile
|
|
||||||
def part2(rows):
|
|
||||||
MAP = {}
|
MAP = {}
|
||||||
instructions = rows.pop(0)
|
instructions = rows.pop(0)
|
||||||
rows.pop(0)
|
rows.pop(0)
|
||||||
instructions = instructions.replace("L", "0")
|
instructions = instructions.replace("L", "0")
|
||||||
instructions = instructions.replace("R", "1")
|
instructions = instructions.replace("R", "1")
|
||||||
instructions = [int(x) for x in instructions]
|
instructions = [int(x) for x in instructions]
|
||||||
print(instructions)
|
|
||||||
|
|
||||||
for row in rows:
|
for row in rows:
|
||||||
entry, left, right = scanf("%s = (%s, %s)", row)
|
entry, left, right = scanf("%s = (%s, %s)", row)
|
||||||
MAP[entry] = [left,right]
|
MAP[entry] = [left, right]
|
||||||
|
return MAP, instructions
|
||||||
|
|
||||||
starting_entries = []
|
|
||||||
ending_entries = []
|
|
||||||
for key in MAP.keys():
|
|
||||||
if key[-1] == "A":
|
|
||||||
starting_entries.append(key)
|
|
||||||
if key[-1] == "Z":
|
|
||||||
ending_entries.append(key)
|
|
||||||
|
|
||||||
|
|
||||||
endpoints = {k: k for k in starting_entries}
|
|
||||||
print(endpoints)
|
|
||||||
print(check(endpoints))
|
|
||||||
print(starting_entries)
|
|
||||||
print()
|
|
||||||
count = 0
|
|
||||||
while True:
|
|
||||||
print(count, endpoints, check(endpoints))
|
|
||||||
for start in starting_entries:
|
|
||||||
v = endpoints[start]
|
|
||||||
idx = count % len(instructions)
|
|
||||||
l_r = instructions[idx]
|
|
||||||
_next = MAP[v][l_r]
|
|
||||||
endpoints[start] = _next
|
|
||||||
count += 1
|
|
||||||
if check(endpoints):
|
|
||||||
break
|
|
||||||
print(count)
|
|
||||||
|
|
||||||
# @shared.profile
|
# @shared.profile
|
||||||
def part1(rows):
|
def part1(rows):
|
||||||
MAP = {}
|
_map, _instructions = setup(rows)
|
||||||
instructions = rows.pop(0)
|
count, _ = find("AAA", _instructions, _map)
|
||||||
rows.pop(0)
|
print(count)
|
||||||
instructions = instructions.replace("L", "0")
|
|
||||||
instructions = instructions.replace("R", "1")
|
|
||||||
instructions = [int(x) for x in instructions]
|
|
||||||
|
|
||||||
for row in rows:
|
|
||||||
entry, left, right = scanf("%s = (%s, %s)", row)
|
|
||||||
MAP[entry] = [left,right]
|
|
||||||
|
|
||||||
|
# @shared.profile
|
||||||
|
def part2(rows):
|
||||||
|
_map, _instructions = setup(rows)
|
||||||
|
starting_points = [k for k in _map.keys() if k[-1] == "A"]
|
||||||
|
ending_points = [k for k in _map.keys() if k[-1] == "Z"]
|
||||||
|
ends = []
|
||||||
|
for s in starting_points:
|
||||||
|
count, end = find(s, _instructions, _map, None)
|
||||||
|
ends.append(count)
|
||||||
|
print(lcm(*ends))
|
||||||
|
|
||||||
|
|
||||||
|
def find(start, instructions, MAP, target="ZZZ"):
|
||||||
count = 0
|
count = 0
|
||||||
current = "AAA"
|
current = start
|
||||||
target = "ZZZ"
|
|
||||||
steps = []
|
|
||||||
while True:
|
while True:
|
||||||
steps.append(current)
|
|
||||||
idx = count % len(instructions)
|
idx = count % len(instructions)
|
||||||
l_r = instructions[idx]
|
l_r = instructions[idx]
|
||||||
current = MAP[current][l_r]
|
current = MAP[current][l_r]
|
||||||
count += 1
|
count += 1
|
||||||
if current == target:
|
if target is None:
|
||||||
steps.append(target)
|
if current.endswith("Z"):
|
||||||
break
|
return count, current
|
||||||
|
elif current == target:
|
||||||
print(steps)
|
return count, current
|
||||||
print(count)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -67,7 +67,7 @@ def number_starting_at(mx, x, y):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
current += d
|
current += d
|
||||||
next = number_starting_at(mx, x+1, y)
|
next = number_starting_at(mx, x + 1, y)
|
||||||
if next is None:
|
if next is None:
|
||||||
return current
|
return current
|
||||||
return current + next
|
return current + next
|
||||||
@ -340,22 +340,22 @@ def highlight(matrix, red=[], green=[], blue=[], blink_green=[]):
|
|||||||
print a matrix of anything, Falsy values turns to `.` for clarity
|
print a matrix of anything, Falsy values turns to `.` for clarity
|
||||||
"""
|
"""
|
||||||
mx = deepcopy(matrix)
|
mx = deepcopy(matrix)
|
||||||
for (y, x) in red:
|
for y, x in red:
|
||||||
if (y, x) in blue or (y, x) in green or (y, x) in blink_green:
|
if (y, x) in blue or (y, x) in green or (y, x) in blink_green:
|
||||||
continue
|
continue
|
||||||
new = f"{colors.RED}{mx[y][x]}{colors.ENDC}"
|
new = f"{colors.RED}{mx[y][x]}{colors.ENDC}"
|
||||||
mx[y][x] = new
|
mx[y][x] = new
|
||||||
for (y, x) in green:
|
for y, x in green:
|
||||||
if (y, x) in blue or (y, x) in blink_green:
|
if (y, x) in blue or (y, x) in blink_green:
|
||||||
continue
|
continue
|
||||||
new = f"{colors.GREEN}{mx[y][x]}{colors.ENDC}"
|
new = f"{colors.GREEN}{mx[y][x]}{colors.ENDC}"
|
||||||
mx[y][x] = new
|
mx[y][x] = new
|
||||||
for (y, x) in blue:
|
for y, x in blue:
|
||||||
if (y, x) in blink_green:
|
if (y, x) in blink_green:
|
||||||
continue
|
continue
|
||||||
new = f"{colors.BLUE}{mx[y][x]}{colors.ENDC}"
|
new = f"{colors.BLUE}{mx[y][x]}{colors.ENDC}"
|
||||||
mx[y][x] = new
|
mx[y][x] = new
|
||||||
for (y, x) in blink_green:
|
for y, x in blink_green:
|
||||||
new = f"{colors.BLINK}{colors.GREEN}{mx[y][x]}{colors.ENDC}"
|
new = f"{colors.BLINK}{colors.GREEN}{mx[y][x]}{colors.ENDC}"
|
||||||
mx[y][x] = new
|
mx[y][x] = new
|
||||||
print(ppmx(mx, pad=False, space=True, zero="0"))
|
print(ppmx(mx, pad=False, space=True, zero="0"))
|
||||||
@ -364,29 +364,29 @@ def highlight(matrix, red=[], green=[], blue=[], blink_green=[]):
|
|||||||
def draw_shape_at(mx, row, col, shape=None, value=1):
|
def draw_shape_at(mx, row, col, shape=None, value=1):
|
||||||
if shape is None:
|
if shape is None:
|
||||||
raise Exception("Please provide a list of coordinate offsets from Y,X to draw")
|
raise Exception("Please provide a list of coordinate offsets from Y,X to draw")
|
||||||
for y,x in shape:
|
for y, x in shape:
|
||||||
mx[row+y][col+x] = value
|
mx[row + y][col + x] = value
|
||||||
|
|
||||||
|
|
||||||
def collision_at(mx, row, col, shape=None):
|
def collision_at(mx, row, col, shape=None):
|
||||||
if shape is None:
|
if shape is None:
|
||||||
raise Exception("Please provide a list of coordinate offsets from Y,X to draw")
|
raise Exception("Please provide a list of coordinate offsets from Y,X to draw")
|
||||||
for y,x in shape:
|
for y, x in shape:
|
||||||
if mx[row+y][col+x] != 0:
|
if mx[row + y][col + x] != 0:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def out_of_bounds(mx, row, col, shape=None):
|
def out_of_bounds(mx, row, col, shape=None):
|
||||||
|
|
||||||
if shape is None:
|
if shape is None:
|
||||||
raise Exception("Please provide a list of coordinate offsets from Y,X to draw")
|
raise Exception("Please provide a list of coordinate offsets from Y,X to draw")
|
||||||
height, width = get_size(mx)
|
height, width = get_size(mx)
|
||||||
for y,x in shape:
|
for y, x in shape:
|
||||||
if row+y > height-1:
|
if row + y > height - 1:
|
||||||
return True
|
return True
|
||||||
if col+x >= width:
|
if col + x >= width:
|
||||||
return True
|
return True
|
||||||
if col+x < 0:
|
if col + x < 0:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -396,47 +396,44 @@ def spiral_generator(width, height):
|
|||||||
l = 0
|
l = 0
|
||||||
m = height
|
m = height
|
||||||
n = width
|
n = width
|
||||||
|
|
||||||
''' k - starting row index
|
""" k - starting row index
|
||||||
m - ending row index
|
m - ending row index
|
||||||
l - starting column index
|
l - starting column index
|
||||||
n - ending column index
|
n - ending column index
|
||||||
i - iterator '''
|
i - iterator """
|
||||||
|
|
||||||
while (k < m and l < n):
|
while k < m and l < n:
|
||||||
|
|
||||||
# Print the first row from
|
# Print the first row from
|
||||||
# the remaining rows
|
# the remaining rows
|
||||||
for i in range(l, n):
|
for i in range(l, n):
|
||||||
yield (i,k)
|
yield (i, k)
|
||||||
#print(a[k][i], end=" ")
|
# print(a[k][i], end=" ")
|
||||||
|
|
||||||
k += 1
|
k += 1
|
||||||
|
|
||||||
# Print the last column from
|
# Print the last column from
|
||||||
# the remaining columns
|
# the remaining columns
|
||||||
for i in range(k, m):
|
for i in range(k, m):
|
||||||
yield (n-1,i)
|
yield (n - 1, i)
|
||||||
#print(a[i][n - 1], end=" ")
|
# print(a[i][n - 1], end=" ")
|
||||||
|
|
||||||
n -= 1
|
n -= 1
|
||||||
|
|
||||||
# Print the last row from
|
# Print the last row from
|
||||||
# the remaining rows
|
# the remaining rows
|
||||||
if (k < m):
|
if k < m:
|
||||||
|
|
||||||
for i in range(n - 1, (l - 1), -1):
|
for i in range(n - 1, (l - 1), -1):
|
||||||
#print(a[m - 1][i], end=" ")
|
# print(a[m - 1][i], end=" ")
|
||||||
yield (i, m-1)
|
yield (i, m - 1)
|
||||||
|
|
||||||
m -= 1
|
m -= 1
|
||||||
|
|
||||||
# Print the first column from
|
# Print the first column from
|
||||||
# the remaining columns
|
# the remaining columns
|
||||||
if (l < n):
|
if l < n:
|
||||||
for i in range(m - 1, k - 1, -1):
|
for i in range(m - 1, k - 1, -1):
|
||||||
#print(a[i][l], end=" ")
|
# print(a[i][l], end=" ")
|
||||||
yield (l,i)
|
yield (l, i)
|
||||||
|
|
||||||
l += 1
|
|
||||||
|
|
||||||
|
l += 1
|
||||||
|
@ -31,12 +31,12 @@ def minmax(l):
|
|||||||
|
|
||||||
|
|
||||||
def load_rows(day, part2=False):
|
def load_rows(day, part2=False):
|
||||||
return [row for row in load(day,part2)]
|
return [row for row in load(day, part2)]
|
||||||
|
|
||||||
|
|
||||||
def load(day, part2=False):
|
def load(day, part2=False):
|
||||||
if part2:
|
if part2:
|
||||||
path = Path(get_fname(day)+".part2")
|
path = Path(get_fname(day) + ".part2")
|
||||||
try:
|
try:
|
||||||
return path.read_text().rstrip().split("\n")
|
return path.read_text().rstrip().split("\n")
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
@ -111,58 +111,59 @@ def elapsed_timer():
|
|||||||
elapser = lambda: end - start
|
elapser = lambda: end - start
|
||||||
|
|
||||||
|
|
||||||
|
def render_cubes(maxX, maxY, maxZ, my_cubes):
|
||||||
|
|
||||||
def render_cubes(maxX,maxY,maxZ, my_cubes):
|
|
||||||
from mpl_toolkits.mplot3d import Axes3D
|
from mpl_toolkits.mplot3d import Axes3D
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
|
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
|
||||||
|
|
||||||
def cuboid_data(o, size=(1,1,1)):
|
def cuboid_data(o, size=(1, 1, 1)):
|
||||||
X = [[[0, 1, 0], [0, 0, 0], [1, 0, 0], [1, 1, 0]],
|
X = [
|
||||||
[[0, 0, 0], [0, 0, 1], [1, 0, 1], [1, 0, 0]],
|
[[0, 1, 0], [0, 0, 0], [1, 0, 0], [1, 1, 0]],
|
||||||
[[1, 0, 1], [1, 0, 0], [1, 1, 0], [1, 1, 1]],
|
[[0, 0, 0], [0, 0, 1], [1, 0, 1], [1, 0, 0]],
|
||||||
[[0, 0, 1], [0, 0, 0], [0, 1, 0], [0, 1, 1]],
|
[[1, 0, 1], [1, 0, 0], [1, 1, 0], [1, 1, 1]],
|
||||||
[[0, 1, 0], [0, 1, 1], [1, 1, 1], [1, 1, 0]],
|
[[0, 0, 1], [0, 0, 0], [0, 1, 0], [0, 1, 1]],
|
||||||
[[0, 1, 1], [0, 0, 1], [1, 0, 1], [1, 1, 1]]]
|
[[0, 1, 0], [0, 1, 1], [1, 1, 1], [1, 1, 0]],
|
||||||
|
[[0, 1, 1], [0, 0, 1], [1, 0, 1], [1, 1, 1]],
|
||||||
|
]
|
||||||
X = np.array(X).astype(float)
|
X = np.array(X).astype(float)
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
X[:,:,i] *= size[i]
|
X[:, :, i] *= size[i]
|
||||||
X += np.array(o)
|
X += np.array(o)
|
||||||
return X
|
return X
|
||||||
|
|
||||||
def plotCubeAt(positions,sizes=None,colors=None, **kwargs):
|
def plotCubeAt(positions, sizes=None, colors=None, **kwargs):
|
||||||
if not isinstance(colors,(list,np.ndarray)): colors=["C0"]*len(positions)
|
if not isinstance(colors, (list, np.ndarray)):
|
||||||
if not isinstance(sizes,(list,np.ndarray)): sizes=[(1,1,1)]*len(positions)
|
colors = ["C0"] * len(positions)
|
||||||
|
if not isinstance(sizes, (list, np.ndarray)):
|
||||||
|
sizes = [(1, 1, 1)] * len(positions)
|
||||||
g = []
|
g = []
|
||||||
for p,s,c in zip(positions,sizes,colors):
|
for p, s, c in zip(positions, sizes, colors):
|
||||||
g.append( cuboid_data(p, size=s) )
|
g.append(cuboid_data(p, size=s))
|
||||||
return Poly3DCollection(np.concatenate(g),
|
return Poly3DCollection(
|
||||||
facecolors=np.repeat(colors,6, axis=0), **kwargs)
|
np.concatenate(g), facecolors=np.repeat(colors, 6, axis=0), **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
N1 = maxX
|
N1 = maxX
|
||||||
N2 = maxY
|
N2 = maxY
|
||||||
N3 = maxZ
|
N3 = maxZ
|
||||||
ma = np.random.choice([0,1], size=(N1,N2,N3), p=[0.99, 0.01])
|
ma = np.random.choice([0, 1], size=(N1, N2, N3), p=[0.99, 0.01])
|
||||||
x,y,z = np.indices((N1,N2,N3))-.5
|
x, y, z = np.indices((N1, N2, N3)) - 0.5
|
||||||
#positions = np.c_[x[ma==1],y[ma==1],z[ma==1]]
|
# positions = np.c_[x[ma==1],y[ma==1],z[ma==1]]
|
||||||
positions = np.c_[my_cubes]
|
positions = np.c_[my_cubes]
|
||||||
colors= np.random.rand(len(positions),3)
|
colors = np.random.rand(len(positions), 3)
|
||||||
|
|
||||||
fig = plt.figure()
|
fig = plt.figure()
|
||||||
ax = fig.add_subplot(projection='3d')
|
ax = fig.add_subplot(projection="3d")
|
||||||
ax.set_aspect('equal')
|
ax.set_aspect("equal")
|
||||||
|
|
||||||
pc = plotCubeAt(positions, colors=colors,edgecolor="k")
|
pc = plotCubeAt(positions, colors=colors, edgecolor="k")
|
||||||
ax.add_collection3d(pc)
|
ax.add_collection3d(pc)
|
||||||
|
|
||||||
ax.set_xlim([0,maxX])
|
ax.set_xlim([0, maxX])
|
||||||
ax.set_ylim([0,maxY])
|
ax.set_ylim([0, maxY])
|
||||||
ax.set_zlim([0,maxZ])
|
ax.set_zlim([0, maxZ])
|
||||||
#plotMatrix(ax, ma)
|
# plotMatrix(ax, ma)
|
||||||
#ax.voxels(ma, edgecolor="k")
|
# ax.voxels(ma, edgecolor="k")
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user