found_first_group_size = True
                first_group_candidates.append(first_group)
        if found_first_group_size:
            break
    return min(map(math.prod, first_group_candidates))


u.assert_equals(balancing_packages_into_three(example_packages), 99)
u.answer_part_1(balancing_packages_into_three(package_list))

# part 2
def balancing_packages_into_four(packages: tuple):
    total_weight = sum(packages)
    if total_weight % 4 > 0:
        raise RuntimeError("Impossible to balance the load, christmas is doomed!")
    group_weight = total_weight // 4
    found_first_group_size = False
    first_group_candidates = []
    for first_group_size in range(1, len(packages)):
        for first_group in itertools.combinations(packages, first_group_size):
            if sum(first_group) == group_weight:
                found_first_group_size = True
                first_group_candidates.append(first_group)
        if found_first_group_size:
            break
    return min(map(math.prod, first_group_candidates))


u.assert_equals(balancing_packages_into_four(example_packages), 44)
u.answer_part_2(balancing_packages_into_four(package_list))
示例#2
0
hcl:#888785
hgt:164cm byr:2001 iyr:2015 cid:88
pid:545766238 ecl:hzl
eyr:2022

iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719""".split(
        "\n\n"):
    u.assert_equals(is_this_valid_data(valid_passport), True)

for invalid_passport in """eyr:1972 cid:100
hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926

iyr:2019
hcl:#602927 eyr:1967 hgt:170cm
ecl:grn pid:012533040 byr:1946

hcl:dab227 iyr:2012
ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277

hgt:59cm ecl:zzz
eyr:2038 hcl:74454a iyr:2023
pid:3556412378 byr:2007""".split("\n\n"):
    u.assert_equals(is_this_valid_data(invalid_passport), False)

u.answer_part_2(
    sum(1 for row in filter(is_this_a_valid_passport, raw_input.split("\n\n"))
        if is_this_valid_data(row)))
# 185 too high
# 110 too high
示例#3
0
# [[[3]]] and {"a":{"b":4},"c":-1} both have a sum of 3.
u.assert_equals(sumOfAllNumbers("[[[3]]]"), 3)
u.assert_equals(sumOfAllNumbers('{"a":{"b":4},"c":-1}'), 3)

# {"a":[-1,1]} and [-1,{"a":1}] both have a sum of 0.
u.assert_equals(sumOfAllNumbers('{"a":[-1,1]}'), 0)
u.assert_equals(sumOfAllNumbers('[-1,{"a":1}]'), 0)

# [] and {} both have a sum of 0.
u.assert_equals(sumOfAllNumbers("[]"), 0)
u.assert_equals(sumOfAllNumbers(r"{}"), 0)

u.answer_part_1(sumOfAllNumbers(inputStr))

u.assert_equals(4,
                sumOfAllNumbers(removeRedObjects('[1,{"c":"red","b":2},3]')))
u.assert_equals(
    sumOfAllNumbers(removeRedObjects('{"d":"red","e":[1,2,3,4],"f":5}')), 0)

inputStrWithoutRed = removeRedObjects(inputStr)
u.answer_part_2(sumOfAllNumbers(inputStrWithoutRed))
# part2 85717 too high
# part2 68466 yay!

# Ignore any object (and all of its children) which has any property with the value "red".
# Do this only for objects ({...}), not arrays ([...]).
# [1,2,3] still has a sum of 6.
# [1,{"c":"red","b":2},3] now has a sum of 4, because the middle object is ignored.
# {"d":"red","e":[1,2,3,4],"f":5} now has a sum of 0, because the entire structure is ignored.
# [1,"red",5] has a sum of 6, because "red" in an array has no effect.
def get_further_during_path(path):
    q, r, s = 0, 0, 0
    further = 0
    for step in path.split(","):
        if step == "n":
            s += 1
            r -= 1
        elif step == "s":
            r += 1
            s -= 1
        elif step == "ne":
            r -= 1
            q += 1
        elif step == "se":
            q += 1
            s -= 1
        elif step == "sw":
            q -= 1
            r += 1
        elif step == "nw":
            q -= 1
            s += 1
        current_position = int((abs(q) + abs(r) + abs(s)) / 2)
        if current_position > further:
            further = current_position
    return further


u.answer_part_2(get_further_during_path(raw_input))
    height = len(grid)
    if axis == "y":  # horizontal fold
        if value != (height - 1) / 2:
            return
        new_grid = [[(grid[y][x] or grid[height - 1 - y][x])
                     for x in range(width)]
                    for y in range(int((height - 1) / 2))]
    elif axis == "x":  # vertical fold
        if value != ((width - 1) / 2):
            return
        new_grid = [[(row[x] or row[width - 1 - x])
                     for x in range(int((width - 1) / 2))] for row in grid]
    return new_grid


grid, folds = construct_grid(example)
new_grid = fold_grid(grid, folds[0])
new_grid = fold_grid(new_grid, folds[1])

grid, folds = construct_grid(raw_input)
new_grid = fold_grid(grid, folds.pop(0))
u.answer_part_1(sum(sum(1 if val else 0 for val in row) for row in new_grid))

# part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_

for fold in folds:
    new_grid = fold_grid(new_grid, fold)

u.answer_part_2("RCPLAKHL")
debug_grid(new_grid)
    return max(registries.values())


u.assert_equals(interpret_instructions(example), 1)
u.answer_part_1(interpret_instructions(raw_input))

# part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_


def interpret_instructions_part_2(raw_input):
    reg = re.compile(
        r"([a-z]+) (inc|dec) (-?\d+) if ([a-z]+) ([<>=!]+) (-?\d+)")
    registries = defaultdict(lambda: 0)
    max_ever = 0
    for row in raw_input.splitlines():
        m = reg.match(row)
        groups = m.groups()
        if interpret_condition(groups[3:], registries):
            registry, action, value = groups[:3]
            if action == "dec":
                registries[registry] -= int(value)
            elif action == "inc":
                registries[registry] += int(value)
            if registries[registry] > max_ever:
                max_ever = registries[registry]
    return max_ever


u.assert_equals(interpret_instructions_part_2(example), 10)
u.answer_part_2(interpret_instructions_part_2(raw_input))
示例#7
0
    6: 28,
    7: 41,
    8: 37,
    9: 49,
    10: 37,
    20: 132,
    30: 259,
    40: 406,
    50: 566,
    60: 788,
    70: 1106,
    80: 1373,
    90: 1844,
    100: 2208,
}

for days in range(1, 101):
    example_tiling = build_next_grid(example_tiling)
    if days in tests:
        u.assert_equals(
            count_black_tiles(example_tiling),
            tests[days],
            f" black tiles after {days} days",
        )

for days in range(100):
    tiling = build_next_grid(tiling)

u.answer_part_2(count_black_tiles(tiling))
# 3822 too high because I did only 99 days DUH
24: 14 1

abbbbbabbbaaaababbaabbbbabababbbabbbbbbabaaaa
bbabbbbaabaabba
babbbbaabbbbbabbbbbbaabaaabaaa
aaabbbbbbaaaabaababaabababbabaaabbababababaaa
bbbbbbbaaaabbbbaaabbabaaa
bbbababbbbaaaaaaaabbababaaababaabab
ababaaaaaabaaab
ababaaaaabbbaba
baabbaaaabbaaaababbaababb
abbbbabbbbaaaababbbbbbaaaababb
aaaaabbaabaaaaababaa
aaaabbaaaabbaaa
aaaabbaabbaaaaaaabbbabbbaaabbaabaaa
babaaabbbaaabaababbaabababaaab
aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba"""

u.assert_equals(check_validity_for_messages_part_2(new_example), 12)

u.answer_part_2(check_validity_for_messages_part_2(raw_input))

# needed imbrication level 5 for example to work.
# it was the minimum for getting the good answer on actual input.

# result = 296 with imbrication level 5 & more
# result = 12 with imbrication level 1
# 261 with imbrication 2
# 285 with imbrication 3
# 295 with imbrication 4
        next_sources = evolve_grid(grid, *source)
        sources.extend(next_sources)
    remove_floating_water(grid)


def count_wet_squares(grid: dict):
    min_x, max_x, min_y, max_y = find_min_max_clay_coordinates(grid)
    return sum(1 for x in range(min_x, max_x + 1)
               for y in range(min_y, max_y + 1) if grid[x, y] in ("~", "|"))


def count_resting_water_squares(grid: dict):
    min_x, max_x, min_y, max_y = find_min_max_clay_coordinates(grid)
    return sum(1 for x in range(min_x, max_x + 1)
               for y in range(min_y, max_y + 1) if grid[x, y] == "~")


example_grid = parse_input(example_input)
evolve_grid_until_everything_is_filled(example_grid)
u.assert_equals(count_wet_squares(example_grid), 57)

grid = parse_input(raw_input)
evolve_grid_until_everything_is_filled(grid)
draw_grid(grid)
u.answer_part_1(count_wet_squares(grid))
# 37277 is too low
# 38364 good answer, I was missing the "every x coordinate is valid"

u.assert_equals(count_resting_water_squares(example_grid), 29)
u.answer_part_2(count_resting_water_squares(grid))
            # to first check the combinations which have a greater chance to remove a lot
            # of characters.
            for index in [m.start() for m in re.finditer(mol_to, molecule)]:
                new_molecule = molecule[:index] + molecule[index:].replace(
                    mol_to,  # reversed vs. part 1 (mol_to replaced with mol_from)
                    mol_from,
                    1,
                )
                graph.add_edge(molecule, new_molecule)
                if new_molecule not in examined_molecules:
                    if len(new_molecule) <= shortest_molecule_achieved:
                        # hm! short molecule! interesting!
                        # we append on the right, to pick it first later
                        shortest_molecule_achieved = len(new_molecule)
                        molecules_to_reduce.append(new_molecule)
                        continue
                    # in that case, the molecule may be less interesting to examine,
                    # we append on the other side
                    molecules_to_reduce.appendleft(new_molecule)

    # And now the answer we're looking for: -------------------------
    # In the new graph, look for the shortest path between target and the electron.
    # It's almost too easy with networkx. (The hard part was to build the graph, though)
    return -1 + len(nx.shortest_path(graph, target_molecule, "e"))


u.assert_equals(reduce_molecule("HOH", example_replacements), 3)
u.assert_equals(reduce_molecule("HOHOHO", example_replacements), 6)

u.answer_part_2(reduce_molecule(molecule, replacements))
示例#11
0
    memorization.update(
        {number: [rank]
         for rank, number in enumerate(starting_numbers, 1)})
    last_spoken_number = starting_numbers[-1]
    for rank in range(len(starting_numbers) + 1, n + 1):
        if rank % 1000 == 0:
            print(rank, end="\r")
        if len(memorization[last_spoken_number]) >= 2:
            last_spoken_number = rank - 1 - memorization[last_spoken_number][-2]
        else:
            last_spoken_number = 0
        if rank == n:
            return last_spoken_number
        # maybe for memory optimization we could shorten the list here,
        # to keep only the 2 last indexes. But it worked for both parts
        # without the optimization, so…
        memorization[last_spoken_number].append(rank)


u.assert_equals(find_nth_number_in_drinking_game((0, 3, 6), 10), 0)

for starting_numbers, expected in examples.items():
    u.assert_equals(find_nth_number_in_drinking_game(starting_numbers, 2020),
                    expected)

u.answer_part_1(find_nth_number_in_drinking_game(my_input, 2020))

# part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_

u.answer_part_2(find_nth_number_in_drinking_game(my_input, 30000000))
    counted_groups = dict(army.counting_groups())
    for counter in count():
        army.targeting_phase()
        something_happened = army.attack_phase()
        if not something_happened:
            print("blah, nothing happened this phase")
            break
        army.cleaning_phase()
        counted_groups = dict(army.counting_groups())
        if 0 in counted_groups.values():
            print(f"phew! fight is over after {counter} rounds")
            break
    print(counted_groups)
    return max(counted_groups.values()), counted_groups["Infection"] == 0


u.assert_equals(boosted_fight(example, 0), (5216, False))
u.assert_equals(boosted_fight(example, 1570), (51, True))
u.assert_equals(boosted_fight(raw_input, 0), (23385, False))

for i in range(85, 100):
    remaining, immune_has_won = boosted_fight(raw_input, i)
    if immune_has_won:
        u.answer_part_2(f"{remaining} units with a boost of {i}")
        break

# boosted_fight(raw_input, 92)

# 3516 too high with boost 92
# 2344 units with boost 88 ?
示例#13
0
        drawing.line((fix_x(xa), fix_y(ya), fix_x(xb), fix_y(yb)),
                     fill=room_color,
                     width=3)
    drawing.regular_polygon((fix_x(0), fix_y(0) + 1, w - 3),
                            3,
                            fill=(200, 0, 0))

    imgFile.show()


for regex, expected in examples.items():
    map = build_map_from_regex(regex)
    path_lengths = calculate_shortest_paths(map)
    u.assert_equals(max(path_lengths.values()), expected)

map = build_map_from_regex(raw_input)
draw_map(map)  # whoa, this place is HUGE indeed

print(f"calculating path lengths...")
init_time = time()
path_lengths = calculate_shortest_paths(map)
print(f"Done! It took {time() - init_time:.2f} seconds.")

max_length = max(path_lengths.values())
u.assert_equals(max_length, 3885)
u.answer_part_1(max_length)  # 3885

# part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_

u.answer_part_2(sum(1 for length in path_lengths.values() if length >= 1000))
get_number_of_gifts(991)

# I tried using an increment of 410 to have numbers which
# N/2 and N/3 and N/7 and N/4 would be in the sum…
# It gave me answer 1330560 which is too high.

starting_point = 95970
increment = 6
max_gifts = 1377855

TARGET = 36000000
init_time = time.time()

# use 210 increment so we are targeting multiples of 2 and 3 and 5 and 7,
# so N/2 and N/3 and n/5 and n/7 will be in the sum
for i in range(starting_point, starting_point + 3200 * increment, increment):
    gifts = get_number_of_gifts(i)
    print(
        f"------ house {i} - {gifts:08} gifts - time {time.time() - init_time} -------",
        end="\r",
    )
    if max_gifts < gifts:
        max_gifts = gifts
        print("")
    if gifts > TARGET:
        print("\n")
        u.answer_part_2(i)
        break
print(f"\ntime {time.time() - init_time}")
import utils as u

# Solution inspired by the subreddit:
# instead of calculating the number of gifts from the house number,
# loop on the elves and have them "deliver presents" and store the
# amount of presents in every house.

max_houses = 36000000
house_limit_per_elf = 50
target = 36000000

points = [0] * max_houses
max_points = 0
for elf in range(1, max_houses):
    for house in range(elf, elf * (house_limit_per_elf + 1), elf):
        # print(f"elf {elf} fills house {house}")
        if house < max_houses:
            points[house] += 11 * elf
    if points[elf] > max_points:
        # the house with the same number as the elf will not be filled more,
        # hence the check on points[elf]
        print(f"{points[elf]} in house {elf}")
        max_points = points[elf]
    if points[elf] >= target:
        print("")
        u.answer_part_2(elf)
        break
        for neighbor in nx.neighbors(self.graph, node):
            if neighbor == "start":
                continue
            if (
                one_small_cave_visited_twice
                and neighbor in path
                and self.is_small(neighbor)
            ):
                continue
            elif (
                not one_small_cave_visited_twice
                and neighbor in path
                and self.is_small(neighbor)
            ):
                self.visit(neighbor, path.copy(), True)
                continue
            self.visit(neighbor, path.copy(), one_small_cave_visited_twice)


pf = ImprovedPathFinder(example_10paths)
u.assert_equals(pf.find_all_paths(), 36)

pf = ImprovedPathFinder(example_19paths)
u.assert_equals(pf.find_all_paths(), 103)

pf = ImprovedPathFinder(example_226paths)
u.assert_equals(pf.find_all_paths(), 3509)

pf = ImprovedPathFinder(raw_input)
u.answer_part_2(pf.find_all_paths())
            for k, v in fields_possible_positions.items() if len(v) > 0
        }
    # And now we have the positions, do not forget to map them to the values...
    fields_values = {
        key: my_ticket[position]
        for key, position in fields_positions.items()
    }
    return fields_values


example_input = """class: 0-1 or 4-19
row: 0-5 or 8-19
seat: 0-13 or 16-19

your ticket:
11,12,13

nearby tickets:
3,9,18
15,1,5
5,14,9"""

example_values = relate_fields_to_values_in_ticket(example_input)
u.assert_equals(example_values, {"class": 12, "row": 11, "seat": 13})

my_values = relate_fields_to_values_in_ticket(raw_input)
u.answer_part_2(
    prod(val for key, val in my_values.items() if key.startswith("departure")))
# 45696 too low (I made a product of the positions instead of the values, duh)
# 1307550234719 is the right answer, indeed the previous one was too low
            for i, mask_val in enumerate(mask[::-1]):
                if mask_val == "1":
                    bits[i] = "1"
                elif mask_val == "X":
                    floating_bits.add(i)
            for values in itertools.product(*[["0", "1"]] *
                                            len(floating_bits)):
                target_bits = bits.copy()
                for index, value in zip(floating_bits, values):
                    target_bits[index] = value
                target_addresses.add(bits_to_integer(target_bits))
            # print(
            #     f"writing {target_value} in {', '.join(map(str,sorted(target_addresses)))}"
            # )
            for target_address in target_addresses:
                memory[target_address] = target_value
    return sum(memory.values())


example_program_v2 = """mask = 000000000000000000000000000000X1001X
mem[42] = 100
mask = 00000000000000000000000000000000X0XX
mem[26] = 1"""

u.assert_equals(parse_input_to_program_v2(example_program_v2), 208)
u.answer_part_2(parse_input_to_program_v2(raw_input))

# 3279437161092 not the right answer
# 2851461851581 is too low
# 3278997609887 right answer for part 2
off x=2032..69770,y=-71013..4824,z=7471..94418
on x=43670..120875,y=-42068..12382,z=-24787..38892
off x=37514..111226,y=-45862..25743,z=-16714..54663
off x=25699..97951,y=-30668..59918,z=-15349..69697
off x=-44271..17935,y=-9516..60759,z=49131..112598
on x=-61695..-5813,y=40978..94975,z=8655..80240
off x=-101086..-9439,y=-7088..67543,z=33935..83858
off x=18020..114017,y=-48931..32606,z=21474..89843
off x=-77139..10506,y=-89994..-18797,z=-80..59318
off x=8476..79288,y=-75520..11602,z=-96624..-24783
on x=-47488..-1262,y=24338..100707,z=16292..72967
off x=-84341..13987,y=2429..92914,z=-90671..-1318
off x=-37810..49457,y=-71013..-7894,z=-105357..-13188
off x=-27365..46395,y=31009..98017,z=15428..76570
off x=-70369..-16548,y=22648..78696,z=-1892..86821
on x=-53470..21291,y=-120233..-33476,z=-44150..38147
off x=-93533..-4276,y=-16170..68771,z=-104985..-24507"""

u.assert_equals(part_2(example_1), 39)
u.assert_equals(part_2(example_2), 590784)

example_handcrafted = """on x=1..10,y=1..10,z=1..10
on x=1..2,y=1..2,z=1..2
off x=1..2,y=1..2,z=1..2
off x=1..10,y=1..10,z=1..10"""

u.assert_equals(part_2(example_handcrafted), 0)
u.assert_equals(part_2(example_3), 2758514936282235)

u.answer_part_2(part_2(raw_input))
示例#20
0
# u.assert_equals(t.borders[LEFT], "efgh", "left border after rotation")

# t.flip(LEFT)

# u.assert_equals(t.borders[TOP], "hd84", "top border after flip/horiz axis")
# u.assert_equals(t.borders[RIGHT], "4321", "right border after flip/horiz axis")
# u.assert_equals(t.borders[BOTTOM], "ea51", "bottom border after flip/horiz axis")
# u.assert_equals(t.borders[LEFT], "hgfe", "left border after flip/horiz axis")

# t.flip(TOP)

# u.assert_equals(t.borders[TOP], "48dh", "top border after flip/vertical axis")
# u.assert_equals(t.borders[RIGHT], "hgfe", "right border after flip/vertical axis")
# u.assert_equals(t.borders[BOTTOM], "15ae", "bottom border after flip/vertical axis")
# u.assert_equals(t.borders[LEFT], "4321", "left border after flip/vertical axis")


tiles = build_tile_objects_dict(raw_input)
graph = build_contact_graph(raw_input)
analyze_graph(graph)
assemble_jigsaw(tiles, graph)
display_assembled_tile_ids(tiles)

print("------")
i_map = extract_assembled_map(tiles)
sea = Map(i_map)
look_for_sea_monsters(sea)

u.answer_part_2(str(sea).count("#"))
# 2534 too high
u.assert_equals(get_place_coordinates("BBFFBBFRLL"), (102, 4))

u.assert_equals(get_place_id(70, 7), 567)
u.assert_equals(get_place_id(14, 7), 119)
u.assert_equals(get_place_id(102, 4), 820)

place_ids = [
    get_place_id(*get_place_coordinates(boarding_pass))
    for boarding_pass in raw_input.splitlines()
]

u.answer_part_1(max(place_ids))

# part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_

sorted_place_ids = sorted(place_ids)

for i in range(1, len(sorted_place_ids) - 1):
    seat_id = sorted_place_ids[i]
    next_seat_id = sorted_place_ids[i + 1]
    if seat_id + 1 != next_seat_id:
        u.answer_part_2(seat_id + 1)
        break

# another method using a comprehension, but i'm not sure it's clearer
for seat_id, next_seat_id in ((sorted_place_ids[i:i + 2])
                              for i in range(len(sorted_place_ids) - 1)):
    if seat_id + 1 != next_seat_id:
        u.answer_part_2(seat_id + 1)
        break
u.assert_equals(get_power_consumption(raw_example), 198)
u.answer_part_1(get_power_consumption(raw_input))

# part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_


def get_life_support_rating(raw_input):
    rows = raw_input.splitlines()
    first_row = rows[0]
    width = len(first_row)
    length = len(rows)
    oxygen = rows.copy()
    co2 = rows.copy()
    for bit in range(width):
        o2_sum = sum(int(r[bit]) for r in oxygen)
        o2_criteria = str(int(o2_sum >= len(oxygen) / 2))
        oxygen = [r for r in oxygen if r[bit] == o2_criteria]
        if len(oxygen) == 1:
            break
    for bit in range(width):
        co2_sum = sum(int(r[bit]) for r in co2)
        co2_criteria = str(int(co2_sum < len(co2) / 2))
        co2 = [r for r in co2 if r[bit] == co2_criteria]
        if len(co2) == 1:
            break
    return int(oxygen[0], 2) * int(co2[0], 2)


u.assert_equals(get_life_support_rating(raw_example), 230)
u.answer_part_2(get_life_support_rating(raw_input))
    top_right_segment = next(x for x in eight if x not in six)
    two = next(x for x in five_characters if top_right_segment in x)
    five = next(x for x in five_characters if top_right_segment not in x)

    values = {
        zero: "0",
        one: "1",
        two: "2",
        three: "3",
        four: "4",
        five: "5",
        six: "6",
        seven: "7",
        eight: "8",
        nine: "9",
    }
    return int("".join(values[x] for x in outputs))


def sum_output_of_sequences(raw_input):
    return sum(
        output_sequence_from_entry(entry) for entry in raw_input.splitlines())


example_entry = "acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf"

u.assert_equals(output_sequence_from_entry(example_entry), 5353)
u.assert_equals(sum_output_of_sequences(example_input), 61229)

u.answer_part_2(sum_output_of_sequences(raw_input))
u.assert_equals(look_for_ten_recipes_after_nth(18), "9251071085")

u.answer_part_1(look_for_ten_recipes_after_nth(int(puzzle_input)))

# part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_


def look_for_pattern_in_recipes(pattern: str):
    score = "37"
    elves_position = [0, 1]
    init = time()
    for i in count():
        if i % 10000 == 0:
            print(f"round {i} - len = {len(score)} - time = {time() - init}",
                  end="\r")
        new_scores = str(sum(int(score[pos]) for pos in elves_position))
        score += new_scores
        elves_position = [(pos + int(score[pos]) + 1) % len(score)
                          for pos in elves_position]
        if pattern in score[-7:]:
            print(f"round {i} - len = {len(score)} - time = {time() - init}")
            return score.index(pattern)


u.assert_equals(look_for_pattern_in_recipes("51589"), 9)
u.assert_equals(look_for_pattern_in_recipes("01245"), 5)
u.assert_equals(look_for_pattern_in_recipes("92510"), 18)
u.assert_equals(look_for_pattern_in_recipes("59414"), 2018)

u.answer_part_2(look_for_pattern_in_recipes(puzzle_input))
            return False
    return True


criteria = {
    "children": 3,
    "cats": 7,
    "samoyeds": 2,
    "pomeranians": 3,
    "akitas": 0,
    "vizslas": 0,
    "goldfish": 5,
    "trees": 3,
    "cars": 2,
    "perfumes": 1,
}
parser = r"""Sue\s(\d+)\: # Sue number
\s(\w+)\:\s(\d+), # info 1
\s(\w+)\:\s(\d+), # info 2
\s(\w+)\:\s(\d+) # info 3
"""
pattern = re.compile(parser, re.X | re.M)

for group in pattern.findall(inputStr):
    sueNumber, carac1, nb1, carac2, nb2, carac3, nb3 = group
    sue = {carac1: int(nb1), carac2: int(nb2), carac3: int(nb3)}
    if does_sue_match_criteria_part_1(sue, criteria):
        u.answer_part_1(sueNumber)
    if does_sue_match_criteria_part_2(sue, criteria):
        u.answer_part_2(sueNumber)
        elif dir == "d":
            depth += value
    return x * depth


u.assert_equals(find_where_its_going(raw_example), 150)
u.answer_part_1(find_where_its_going(raw_input))

# part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_


def calculate_with_aim(raw_input):
    x = 0
    depth = 0
    aim = 0
    for row in raw_input.splitlines():
        value = int(row[-1:])
        dir = row[0]
        if dir == "f":
            x += value
            depth += value * aim
        elif dir == "u":
            aim -= value
        elif dir == "d":
            aim += value
    return x * depth


u.assert_equals(calculate_with_aim(raw_example), 900)
u.answer_part_2(calculate_with_aim(raw_input))
# class CaloriesVector(NamedTuple):
# a: int
# b: str
# c: dict
# def __mul__(self, other):
# pass

# from operator import attrgetter
# persons.sort()
# sorted(persons, key=attrgetter('info.age')) # plus performant que la version lambda
# sorted(persons, key=attrgetter('info.age', 'info.taille')) # ha ! va écrire une lambda équivalente
# sorted(persons, key=lambda x: x.info.age)

size = 100  # 156 849 iterations for size 100
generator = ((x, y, z, size - x - y - z) for x in range(1, size)
             for y in range(1, size - x) for z in range(1, size - x - y))
maxScore = 0
maxScores500Calories = 0
for row in generator:
    score = math.prod(
        [max(0, dot(constraint, row)) for constraint in constraints])
    calories = dot(row, caloriesVector)
    if score > maxScore:
        maxScore = score
    if calories == 500 and score > maxScores500Calories:
        maxScores500Calories = score
    # print(f'\033[91m'+'a'*row[0]+'\033[92m'+'b'*row[1]+'\033[94m'+'c'*row[2]+'\033[93m'+'d'*row[3]+f'\033[0m {score}')

u.answer_part_1(maxScore)
u.answer_part_2(maxScores500Calories)
示例#28
0
            next_direction = NORTH
    elif current_direction == WEST:
        if x == -y:
            next_direction = SOUTH
    elif x == y:
        if x > 0:
            next_direction = WEST
        elif x < 0:
            next_direction = EAST
    dx, dy = next_direction
    return next_direction, x + dx, y + dy


def part_2(target):
    x = 0
    y = 0
    values = defaultdict(lambda: 0)
    values[0, 0] = 1
    direction = EAST
    for _ in count(1):
        direction, x, y = next_position(direction, x, y)
        current_value = sum(values[x, y]
                            for x, y in product(range(x - 1, x +
                                                      2), range(y - 1, y + 2)))
        values[x, y] = current_value
        if current_value > target:
            return current_value


u.answer_part_2(part_2(input))
示例#29
0
            if destination < mini:
                destination = maxi
        destination_clockwise = cups[destination]
        cups[destination] = picked[0]
        cups[picked[2]] = destination_clockwise
        current = cups[current]
    return cups


example_chained_list = build_chained_list("389125467", 9)

new_chained_list = crab_moves_cups_but_faster(example_chained_list, 3, 10)

u.assert_equals(cups_to_str(new_chained_list, 8), "837419265")
u.blue("now try with bigger lists...")
example_BIG_list = build_chained_list("389125467", 1000000)
BIG_list_after_10M_moves = crab_moves_cups_but_faster(example_BIG_list, 3, 10000000)

u.assert_equals(BIG_list_after_10M_moves[1], 934001)
u.assert_equals(BIG_list_after_10M_moves[934001], 159792)

my_BIG_list = build_chained_list(my_labeling, 1000000)
my_list_after_10M_moves = crab_moves_cups_but_faster(
    my_BIG_list, int(my_labeling[0]), 10000000
)

clockwise_1st_position = my_list_after_10M_moves[1]
clockwise_2nd_position = my_list_after_10M_moves[clockwise_1st_position]

u.answer_part_2(clockwise_1st_position * clockwise_2nd_position)
    try:
        situation = todo_list.pop()
    except IndexError:
        print(f"todo list is empty at iteration {i}")
        break
    if situation.spent_mp > cheapest_victory_cost:
        continue
    if is_victory(situation) == V:
        if situation.spent_mp < cheapest_victory_cost:
            print(situation.cast_spells)
            cheapest_victory_cost = situation.spent_mp
            print(f"cheapest victory cost: {cheapest_victory_cost}")
            print("---------")
        continue
    elif is_victory == D:
        continue
    for next_situation in find_neighbor_situations(situation):
        todo_list.append(next_situation)

u.assert_equals(cheapest_victory_cost, 1289)  # cf pompage.py

u.answer_part_2(cheapest_victory_cost)
# 1408 too high 296455 iterations
# 1295 too high 4563918 iterations, I keep finding this one
# 847 too low 2980515 iterations
# 900 WRONG 4230201 iterations
# 1295:
# recharge • poison • shield • missile • missile • recharge • poison • shield • missile • missile • missile
# 1289:
# Poison -> Magic Missile -> Recharge -> Poison -> Shield -> Recharge -> Poison -> Drain -> Drain