Beispiel #1
0
def part_one():
	target_weight = sum(data) // 3
	largest = max(data)
	for x in range(largest )
	print(target_weight)
	return


def part_two():
	return


if __name__ == '__main__':
	run_with_timer(part_one)  #
	run_with_timer(part_two)  #
Beispiel #2
0
    dist = float('inf') if is_min else float('-inf')
    curr_dist = 0
    for next_city in city_map[start_city]:
        if next_city not in visited_cities:
            curr_dist = city_map[start_city][next_city] + traverse_map(
                city_map, next_city, visited_cities.copy(), is_min)
            if (is_min and curr_dist < dist) or (not is_min
                                                 and curr_dist > dist):
                dist = curr_dist
    return dist if curr_dist > 0 else 0


def part_one():
    city_map = build_city_graph()
    return min(
        traverse_map(city_map, start_city, [], True)
        for start_city in city_map)


def part_two():
    city_map = build_city_graph()
    return max(
        traverse_map(city_map, start_city, [], False)
        for start_city in city_map)


if __name__ == '__main__':
    run_with_timer(part_one)  # 251 -- took 208 ms
    run_with_timer(part_two)  # 898 -- took 197 ms
Beispiel #3
0
	for _ in range(num_phases):
		result[-1] = input_signal[-1]
		for j in range(len(input_signal) - 2, len(input_signal) // 2, -1):
			result[j] = (input_signal[j] + result[j + 1]) % 10
		input_signal = list(result)
		result = [0] * len(input_signal)
	return int(''.join(str(x) for x in input_signal[offset:offset + 8]))


def calculate_output_value(input_signal, row_num):
	if row_num >= len(input_signal) // 2:
		return abs(sum(int(x) for x in input_signal[row_num - len(input_signal):])) % 10
	else:
		i = row_num
		total = 0
		multiplier = 1
		while i < len(input_signal):
			for j in range(row_num + 1):
				if i + j < len(input_signal):
					total += input_signal[i + j] * multiplier
				else:
					break
			i += 2 * (row_num + 1)
			multiplier *= -1
		return abs(total) % 10


if __name__ == '__main__':
	run_with_timer(part_one)  # 58100105
	run_with_timer(part_two)  # 41781287
Beispiel #4
0
def part_one():
    molecule, molmap = get_data_as_molecule_map()
    return replacement_step(molecule, molmap)


def f(start, target, molmap, depth):
    if len(start) > len(target):
        return None
    elif start == target:
        return depth

    curr_min = 999999999
    for i in range(len(start)):
        for j in molmap[start[i]]:
            next_val = f(start[:i] + j + start[i + 1:], target, molmap,
                         depth + 1)
            if next_val:
                curr_min = min(curr_min, next_val)
    return curr_min


def part_two():
    molecule = get_elems(data[-1])
    molmap = get_data_as_molecule_map()


if __name__ == '__main__':
    run_with_timer(part_one)  # 509 -- took 0 ms
    run_with_timer(part_two)  #
Beispiel #5
0
		for y_init in range(yrange, -yrange, -1):
			y = 0
			x = 0
			curr_x_velocity = x_init
			curr_y_velocity = y_init
			while y >= region["ye"] and x <= region["xe"]:
				if curr_x_velocity == 0 and x < region["xs"]:
					break
				x += curr_x_velocity
				y += curr_y_velocity
				if region["xs"] <= x <= region["xe"] and region["ys"] >= y >= region["ye"]:
					valid_coords.append({"x": x_init, "y": y_init})
					break
				curr_y_velocity -= 1
				curr_x_velocity -= 1 if curr_x_velocity > 0 else 0
	return valid_coords


def part_one():
	maxy = int(abs(region["ye"]))-1
	return maxy * (maxy + 1) // 2


def part_two():
	return len(get_valid_initial_velocities())


if __name__ == '__main__':
	run_with_timer(part_one)  # 12561 -- took 0 ms
	run_with_timer(part_two)  # 3785 -- took 90 ms
Beispiel #6
0
card_public_key, door_public_key = [
    int(x.strip()) for x in open("input.txt").readlines()
]


def transform_val(val, subject_number):
    return (val * subject_number) % 20201227


def part_one():
    subject_number = 7
    door_loop_size = 0
    val = 1
    while val != door_public_key:
        val = transform_val(val, subject_number)
        door_loop_size += 1

    val = 1
    for _ in range(door_loop_size):
        val = transform_val(val, card_public_key)
    return val


def part_two():
    return 0


if __name__ == '__main__':
    run_with_timer(part_one)  # 18329280 -- took 4313 ms
    run_with_timer(part_two)  # 0 -- took 0 ms
Beispiel #7
0
        start = [int(x) for x in vent[0].split(',')]
        end = [int(x) for x in vent[1].split(',')]

        if start[0] == end[0]:
            for x in range(min(start[1], end[1]), max(start[1], end[1]) + 1):
                floor_map[start[0]][x] += 1
        elif start[1] == end[1]:
            for x in range(min(start[0], end[0]), max(start[0], end[0]) + 1):
                floor_map[x][start[1]] += 1
        elif include_diagonals:
            xdir = -1 if start[0] > end[0] else 1
            ydir = -1 if start[1] > end[1] else 1
            for x in range(abs(start[0] - end[0]) + 1):
                floor_map[start[0] + (xdir * x)][start[1] + (ydir * x)] += 1
    return floor_map


def part_one():
    floor_map = mark_vents(False)
    return sum(1 for x in floor_map for y in x if y > 1)


def part_two():
    floor_map = mark_vents(True)
    return sum(1 for x in floor_map for y in x if y > 1)


if __name__ == '__main__':
    run_with_timer(part_one)  # 7468 -- took 57 ms
    run_with_timer(part_two)  # 22364 -- took 76 ms
Beispiel #8
0
    curr_count = 0
    new_str = ''
    for x in input_val:
        if int(x) != last_num:
            if curr_count > 0:
                new_str += str(curr_count) + str(last_num)
            last_num = int(x)
            curr_count = 0
        curr_count += 1
    new_str += str(curr_count) + str(last_num)
    return new_str


def part_one():
    new_val = data
    for x in range(40):
        new_val = look_and_say(new_val)
    return len(new_val)


def part_two():
    new_val = data
    for x in range(50):
        new_val = look_and_say(new_val)
    return len(new_val)


if __name__ == '__main__':
    run_with_timer(part_one)  # 492982 -- took 1248 ms
    run_with_timer(part_two)  # 6989950 -- took 22484 ms
Beispiel #9
0
        "die": 1,
        "turn": 1,
        "p1": {
            "num": 1,
            "score": 0,
            "pos": data[0]
        },
        "p2": {
            "num": 2,
            "score": 0,
            "pos": data[1]
        }
    }
    while state["p1"]["score"] < 1000 and state["p2"]["score"] < 1000:
        make_move(state, deterministic_die)
    return min(state["p1"]["score"], state["p2"]["score"]) * (
        (state["turn"] - 1) * 3)


def part_two():
    # state = {"die": 1, "turn": 1, "p1": {"num": 1, "score": 0, "pos": data[0]}, "p2": {"num": 2, "score": 0, "pos": data[1]}}
    # while state["p1"]["score"] < 1000 and state["p2"]["score"] < 1000:
    # 	make_move(state, deterministic_die)
    # return min(state["p1"]["score"], state["p2"]["score"]) * ((state["turn"]-1)*3)
    return


if __name__ == '__main__':
    run_with_timer(part_one)  # 512442 -- took 0 ms
    run_with_timer(part_two)  #
Beispiel #10
0
def get_next_pass(initial):
	pw = increment(initial)
	is_valid = check_pw(pw)
	while not is_valid:
		if 'i' in pw:
			pw = short_cut(pw, 'i')
		elif 'l' in pw:
			pw = short_cut(pw, 'l')
		elif 'o' in pw:
			pw = short_cut(pw, 'o')
		else:
			pw = increment(pw)

		is_valid = check_pw(pw)
	return pw


def part_one():
	return get_next_pass(data)


def part_two():
	initial = get_next_pass(data)
	return get_next_pass(initial)


if __name__ == '__main__':
	run_with_timer(part_one)  # hepxxyzz -- took 2388 ms
	run_with_timer(part_two)  # heqaabcc -- took 8270 ms
Beispiel #11
0
    flashed_points.add(p)
    for neighbor in p.get_neighbors():
        neighbor.set_value(neighbor.get_value() + 1)
        if neighbor.get_value() > 9 and neighbor not in flashed_points:
            increment_and_flash_neighbors(neighbor, flashed_points)


def part_one():
    m = Grid(values=data)
    m.set_neighbors_for_all(True)
    return sum(take_step(m) for _ in range(1, 101))


def part_two():
    m = Grid(values=data)
    m.set_neighbors_for_all(True)

    i = 0
    while not sum(
            1 for row in range(m.get_height())
            if len(list(filter(lambda x: x.get_value() != 0, m.get_row(
                row)))) != 0) == 0:
        take_step(m)
        i += 1
    return i


if __name__ == '__main__':
    run_with_timer(part_one)  # 1675 -- took 46 ms
    run_with_timer(part_two)  # 515 -- took 206 ms
Beispiel #12
0
			return rem_str, v_total, sum(literals)
		elif type_id == 1:
			return rem_str, v_total, math.prod(literals)
		elif type_id == 2:
			return rem_str, v_total, min(literals)
		elif type_id == 3:
			return rem_str, v_total, max(literals)
		elif type_id == 5:
			return rem_str, v_total, 1 if literals[0] > literals[1] else 0
		elif type_id == 6:
			return rem_str, v_total, 1 if literals[0] < literals[1] else 0
		elif type_id == 7:
			return rem_str, v_total, 1 if literals[0] == literals[1] else 0


def convert_hex_to_bin_str(hex_str):
	return "".join(bin(int(x, 16))[2:].zfill(4) for x in list(hex_str))


def part_one():
	return parse_packet(convert_hex_to_bin_str(data))[1]


def part_two():
	return parse_packet(convert_hex_to_bin_str(data))[2]


if __name__ == '__main__':
	run_with_timer(part_one)  # 852 -- took 1 ms
	run_with_timer(part_two)  # 19348959966392 -- took 0 ms
Beispiel #13
0
        for prop in ticker.keys():
            if prop in sue.keys() and ticker[prop] != sue[prop]:
                match_found = False
        if match_found:
            return sues.index(sue) + 1
    return


def part_two():
    sues = get_sues_list()
    for sue in sues:
        match_found = True
        for prop in ticker.keys():
            if prop in sue.keys():
                if prop in ('cats', 'trees'):
                    if ticker[prop] >= sue[prop]:
                        match_found = False
                elif prop in ('pomeranians', 'goldfish'):
                    if ticker[prop] <= sue[prop]:
                        match_found = False
                elif ticker[prop] != sue[prop]:
                    match_found = False
        if match_found:
            return sues.index(sue) + 1
    return


if __name__ == '__main__':
    run_with_timer(part_one)  # 40 -- took 2 ms
    run_with_timer(part_two)  # 241 -- took 1 ms
Beispiel #14
0
def part_one():
	bag_map = get_bag_map()

	changed = True
	initial_bag_set = set()
	initial_bag_set.add('shiny gold')
	while changed:
		changed = False
		initial_size = len(initial_bag_set)
		for k, v in bag_map.items():
			for bag in bag_map[k].keys():
				if bag in initial_bag_set:
					initial_bag_set.add(k)
					if len(initial_bag_set) > initial_size:
						changed = True
	initial_bag_set.remove('shiny gold')
	return len(initial_bag_set)


def count_bags(bag_map, bag):
	return 1 + sum(v * count_bags(bag_map, k) for k, v in bag_map[bag].items())


def part_two():
	return count_bags(get_bag_map(), 'shiny gold') - 1


if __name__ == '__main__':
	run_with_timer(part_one)  # 185 -- took 2 ms
	run_with_timer(part_two)  # 89084 -- took 2 ms
Beispiel #15
0
        points_to_switch = []
        for point in points_to_check:
            neighbors = f(seat_map, point[0], point[1])
            if not int(seat_map[point[0]][point[1]]) and not any(neighbors):
                points_to_switch.append(point)
            elif int(seat_map[point[0]][
                    point[1]]) and sum(neighbors) >= neighbor_count:
                points_to_switch.append(point)
        for point in points_to_switch:
            seat_map[point[0]][point[1]] = (int(seat_map[point[0]][point[1]]) +
                                            1) % 2

        if len(points_to_switch) == 0:
            break
    return sum(x for x in seat_map)


def part_one():
    return run_until_equillibrium(get_immediate_neighbors,
                                  [list(x) for x in data], 4)


def part_two():
    return run_until_equillibrium(get_distanced_neighbors,
                                  [list(x) for x in data], 5)


if __name__ == '__main__':
    run_with_timer(part_one)  # 2319 -- took 2077 ms
    run_with_timer(part_two)  # 2117 -- took 17833 ms
Beispiel #16
0
from aoc_utils import run_with_timer

# data will be a list of each line stored as a list in this order: [min, max, letter, password]
data = [[int(y[0].split('-')[0]),
         int(y[0].split('-')[1]), y[1][:-1], y[2]]
        for y in [x.split() for x in open("input.txt").readlines()]]


def part_one():
    return sum(1 for x in data if x[0] <= x[3].count(x[2]) <= x[1])


def part_two():
    return sum(1 for x in data
               if (x[3][x[0] - 1] == x[2]) ^ (x[3][x[1] - 1] == x[2]))


if __name__ == '__main__':
    run_with_timer(part_one)  # 580 -- took 0 ms
    run_with_timer(part_two)  # 611 -- took 0 ms
Beispiel #17
0
    if not date_match.match(f['iyr']) or not int(f['iyr']) in range(
            2010, 2021):
        return False
    if not date_match.match(f['eyr']) or not int(f['eyr']) in range(
            2020, 2031):
        return False
    if not hgt_match.match(f['hgt']) or ('cm' in f['hgt'] and int(
            f['hgt'][:-2]) not in range(150, 194)) or (
                'in' in f['hgt'] and int(f['hgt'][:-2]) not in range(59, 77)):
        return False
    if not hex_match.match(f['hcl']):
        return False
    if f['ecl'] not in ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']:
        return False
    if not pid_match.match(f['pid']):
        return False
    return True


def part_one():
    return sum(1 for x in data if validate_presence(x))


def part_two():
    return sum(1 for x in data if validate_presence(x) and validate_data(x))


if __name__ == '__main__':
    run_with_timer(part_one)  # 170 -- took 0 ms
    run_with_timer(part_two)  # 103 -- took 1 ms
Beispiel #18
0
                            (y.islower() and y not in current_path), m[x]))
        else:
            for x in m:
                if last_node in m[x]:
                    m[x].remove(last_node)
    if len(m[last_node]) > 0:
        for x in m[last_node]:
            next_path = current_path.copy()
            next_path.append(x)
            count_ways_to_node(copy.deepcopy(m), next_path, full_paths,
                               second_visit)


def part_one():
    m = build_map()
    full_paths = set()
    count_ways_to_node(copy.deepcopy(m), ['start'], full_paths, True)
    return len(full_paths)


def part_two():
    m = build_map()
    full_paths = set()
    count_ways_to_node(copy.deepcopy(m), ['start'], full_paths, False)
    return len(full_paths)


if __name__ == '__main__':
    run_with_timer(part_one)  # 5252 -- took 433 ms
    run_with_timer(part_two)  # 147784 -- took 12627 ms
Beispiel #19
0
        else:
            player2.append(two_card)
            player2.append(one_card)
    return False


def play_game(player1, player2, game_num):
    round_num = 0
    game_hands = []
    while len(player1) > 0 and len(player2) > 0:
        round_num += 1
        if (player1, player2) in game_hands:
            return 1
        game_hands.append((player1.copy(), player2.copy()))
        play_round(player1, player2, game_num)
    return 1 if len(player1) > 0 else 2


def part_two():
    player1, player2 = get_decks()

    winner = play_game(player1, player2, 1)

    winning_hand = player1 if winner == 1 else player2
    return sum(i * winning_hand[-i] for i in range(1, len(winning_hand) + 1))


if __name__ == '__main__':
    run_with_timer(part_one)  # 33434 -- took 0 ms
    run_with_timer(part_two)  # 31657 -- took 24304 ms
Beispiel #20
0
    for tile in black_tiles:
        tile_neighbors = get_neighbors(tile)
        adjacent_black_tiles = tile_neighbors.intersection(black_tiles)
        if len(adjacent_black_tiles) == 0 or len(adjacent_black_tiles) > 2:
            flip_to_white.add(tile)
        adjacent_white_tiles = tile_neighbors.difference(black_tiles)
        for wt in adjacent_white_tiles:
            if wt not in visited_white_tiles:
                visited_white_tiles.add(wt)
                wt_neighbors = get_neighbors(wt)
                wt_adjacent_black = wt_neighbors.intersection(black_tiles)
                if len(wt_adjacent_black) == 2:
                    flip_to_black.add(wt)
    return black_tiles.union(flip_to_black).difference(flip_to_white)


def part_one():
    return len(get_black_tiles())


def part_two():
    black_tiles = get_black_tiles()
    for i in range(100):
        black_tiles = perform_flip(black_tiles)
    return len(black_tiles)


if __name__ == '__main__':
    run_with_timer(part_one)  # 512 -- took 9 ms
    run_with_timer(part_two)  # 4120 -- took 1800 ms
Beispiel #21
0
from aoc_utils import run_with_timer

data = [x.strip() for x in open('input.txt').readlines()]


def part_one():
    return sum(
        y.count('\\"') + y.count('\\\\') +
        ((y.count('\\x') - y.count('\\\\x') + y.count('\\\\\\x')) * 3) + 2
        for y in (x[1:-1] for x in data))


def part_two():
    return sum(x.count('"') + x.count('\\') + 2 for x in data)


if __name__ == '__main__':
    run_with_timer(part_one)  # 1350 -- took 0 ms
    run_with_timer(part_two)  # 2085 -- took 0 ms
Beispiel #22
0
            if is4d:
                board[initial_point[0] + x][initial_point[1] +
                                            y][depth][depth] = data[x][y]
            else:
                board[initial_point[0] + x][initial_point[1] +
                                            y][depth] = data[x][y]
    return board


def part_one():
    steps = 6
    board = initialize_board(steps, False)

    for i in range(steps):
        board = run_cycle(board, False)
    return count_active(board, False)


def part_two():
    steps = 6
    board = initialize_board(steps, True)

    for i in range(steps):
        board = run_cycle(board, True)
    return count_active(board, True)


if __name__ == '__main__':
    run_with_timer(part_one)  # 384 -- took 744 ms
    run_with_timer(part_two)  # 2012 -- took 45906 ms
Beispiel #23
0
		picked_cards = [curr["next"], curr["next"]["next"], curr["next"]["next"]["next"]]
		# Effectively REMOVE those three elements by updating points to skip over them.
		curr["next"] = curr["next"]["next"]["next"]["next"]
		curr["next"]["previous"] = curr

		# Get the destination cup
		picked_vals = [x["val"] for x in picked_cards]
		dest_val = (curr["val"] - 1) % num_cups
		if dest_val == 0:
			dest_val = num_cups
		while dest_val in picked_vals:
			dest_val = (dest_val - 1) % num_cups
			if dest_val == 0:
				dest_val = num_cups
		dest_cup = cups[dest_val]

		# Alright, now just adjust pointers to re-insert the picked values.
		picked_cards[2]["next"] = dest_cup["next"]
		picked_cards[2]["next"]["previous"] = picked_cards[2]
		dest_cup["next"] = picked_cards[0]
		picked_cards[0]["previous"] = dest_cup

		# NEXT!
		curr = curr["next"]
	return cups[1]["next"]["val"] * cups[1]["next"]["next"]["val"]


if __name__ == '__main__':
	run_with_timer(part_one)  # 82934675 -- took 0 ms
	run_with_timer(part_two)  # 474600314018 -- took 22712 ms
Beispiel #24
0
        match_found = None
        for j in range(len(prior_set) - 1):
            for k in range(j, len(prior_set)):
                if prior_set[j] + prior_set[k] == data[i]:
                    match_found = (j, k)
        if not match_found:
            return data[i]


def part_one():
    return find_invalid_number(25)


def part_two():
    invalid_num = find_invalid_number(25)

    for i in range(data.index(invalid_num)):
        curr_sum = data[i]
        next_idx = i + 1
        while curr_sum < invalid_num:
            curr_sum += data[next_idx]
            next_idx += 1
        if curr_sum == invalid_num:
            return min(data[i:next_idx]) + max(data[i:next_idx])


if __name__ == '__main__':
    run_with_timer(part_one)  # 1038347917 -- took 35 ms
    run_with_timer(part_two)  # 137394018 -- took 47 ms
Beispiel #25
0
        new_data.append(new_row)

    new_rows = [[y + x if y + x <= 9 else y + x - 9 for y in row]
                for x in range(1, 5) for row in new_data]
    for row in new_rows:
        new_data.append(row)
    return new_data


def part_one():
    m = Grid(values=data)
    m.set_neighbors_for_all(False)
    return a_star(m.get_point(0, 0),
                  m.get_point(m.get_height() - 1,
                              m.get_width() - 1))
    # return dijkstra(m, m.get_point(0, 0), m.get_point(m.get_height()-1, m.get_width()-1))


def part_two():
    m = Grid(values=get_extended_data())
    m.set_neighbors_for_all(False)
    return a_star(m.get_point(0, 0),
                  m.get_point(m.get_height() - 1,
                              m.get_width() - 1))
    # return dijkstra(m, m.get_point(0, 0), m.get_point(m.get_height()-1, m.get_width()-1))


if __name__ == '__main__':
    run_with_timer(part_one)  # 745 -- took 2978 ms
    run_with_timer(part_two)  # 3002 -- took 385831 ms
Beispiel #26
0
from aoc_utils import run_with_timer

data = [x.strip().split() for x in open("input.txt").readlines()]


def part_one():
	dist = sum(int(d[1]) for d in data if d[0] == 'forward')
	depth = sum(int(d[1]) for d in data if d[0] == 'down') - sum(int(d[1]) for d in data if d[0] == 'up')
	return dist * depth


def part_two():
	curr_depth = 0
	curr_dist = 0
	curr_aim = 0
	for d in data:
		match d[0]:
			case 'forward':
				curr_dist += int(d[1])
				curr_depth += curr_aim * int(d[1])
			case 'down':
				curr_aim += int(d[1])
			case 'up':
				curr_aim -= int(d[1])
	return curr_depth * curr_dist


if __name__ == '__main__':
	run_with_timer(part_one)  # 1660158 -- took 0 ms
	run_with_timer(part_two)  # 1604592846 -- took 0 ms
Beispiel #27
0
from aoc_utils import run_with_timer

data = [int(x.strip()) for x in open("input.txt").readlines()]


def part_one():
    return next(first * second for i, first in enumerate(data)
                for second in data[i + 1:] if first + second == 2020)


def part_two():
    return next(first * second * third for i, first in enumerate(data)
                for j, second in enumerate(data[i + 1:])
                for third in data[j + 1:] if first + second + third == 2020)


if __name__ == '__main__':
    run_with_timer(part_one)  # 197451 -- took 0 ms
    run_with_timer(part_two)  # 138233720 -- took 94 ms
Beispiel #28
0
from aoc_utils import run_with_timer

data = [x.strip() for x in open("input.txt").readlines()]


def calc_seat_id(t):
    return (int(t[:7].replace('F', '0').replace('B', '1'), 2)) * 8 + int(
        t[-3:].replace('L', '0').replace('R', '1'), 2)


def part_one():
    return max(calc_seat_id(x) for x in data)


def part_two():
    seat_ids = [-1] * (128 * 8)
    for x in data:
        seat_ids[calc_seat_id(x)] = 1

    for i in range(1, len(seat_ids) - 1):
        if seat_ids[i] == -1 and seat_ids[i - 1] == 1 and seat_ids[i + 1] == 1:
            return i
    return None


if __name__ == '__main__':
    run_with_timer(part_one)  # 911 -- took 1 ms
    run_with_timer(part_two)  # 629 -- took 1 ms
Beispiel #29
0
from aoc_utils import run_with_timer

data = open('input.txt').readline().strip().split(" ")


def get_fill_order(row, col):
	tmp = row + col - 2
	return (tmp * (tmp+1) // 2) + col


def part_one():
	fill_order = get_fill_order(int(data[16][:-1]), int(data[18][:-1]))
	val = 20151125
	for i in range(2, fill_order+1):
		val = (val * 252533) % 33554393
	return val


def part_two():
	return


if __name__ == '__main__':
	run_with_timer(part_one)  #
	run_with_timer(part_two)  #
Beispiel #30
0
from aoc_utils import run_with_timer

data = [int(x) for x in open("input.txt").readline().strip().split(",")]


def calculate_total_fish(days):
    fish = [data.count(x) for x in range(9)]
    for x in range(days):
        next_day_fish = [0] * 9
        for i, e in enumerate(fish):
            if i > 0:
                next_day_fish[i - 1] += e
            else:
                next_day_fish[6] += e
                next_day_fish[8] += e
        fish = next_day_fish
    return sum(x for x in fish)


def part_one():
    return calculate_total_fish(80)


def part_two():
    return calculate_total_fish(256)


if __name__ == '__main__':
    run_with_timer(part_one)  # 386536 -- took 0 ms
    run_with_timer(part_two)  # 1732821262171 -- took 0 ms