Advent of Code 2022 day 20

Relatively straightforward, aside from using % (len(data) - 1). Part 2 wasn’t a great deal more complicated.

Part 1

with open("20.txt") as f:
    data = [
        {"number": int(x), "pos": i}
        for i, x in enumerate(f.read().splitlines())
    ]

def print_data(l):
    print([(x["number"], x["pos"]) for x in l])

new_data = data.copy()

for i in range(len(data)):
    x = data[i]
    number = x["number"]
    pos = x["pos"]

    to = (pos+number) % (len(data) - 1)
    if to == 0:
        to = len(data) - 1

    x["pos"] = to

    if to < pos:
        new_data = new_data[:to] + [x] + new_data[to:pos] + new_data[pos+1:]
        for a in new_data[to+1:pos+1]:
            a["pos"] += 1
    elif to > pos:
        new_data = (
            new_data[:pos] + new_data[pos+1:to+1] + [x] + new_data[to+1:]
        )
        for a in new_data[pos:to]:
            a["pos"] -= 1
    else:
        new_data = new_data

zero_at = min(i for i, x in enumerate(new_data) if x["number"] == 0)
print(
    sum([
        new_data[(1000+zero_at) % len(new_data)]["number"],
        new_data[(2000+zero_at) % len(new_data)]["number"],
        new_data[(3000+zero_at) % len(new_data)]["number"],
    ])
)

Part 2

with open("20.txt") as f:
    data = [
        {"number": int(x)*811589153, "pos": i}
        for i, x in enumerate(f.read().splitlines())
    ]

def print_data(l):
    print([(x["number"], x["pos"]) for x in l])

new_data = data.copy()

for _ in range(10):
    for i in range(len(data)):
        x = data[i]
        number = x["number"]
        pos = x["pos"]

        to = (pos+number) % (len(data) - 1)
        if to == 0:
            to = len(data) - 1

        x["pos"] = to

        if to < pos:
            new_data = new_data[:to] + [x] + new_data[to:pos] + new_data[pos+1:]
            for a in new_data[to+1:pos+1]:
                a["pos"] += 1
        elif to > pos:
            new_data = (
                new_data[:pos] + new_data[pos+1:to+1] + [x] + new_data[to+1:]
            )
            for a in new_data[pos:to]:
                a["pos"] -= 1
        else:
            new_data = new_data

zero_at = min(i for i, x in enumerate(new_data) if x["number"] == 0)
print(
    sum([
        new_data[(1000+zero_at) % len(new_data)]["number"],
        new_data[(2000+zero_at) % len(new_data)]["number"],
        new_data[(3000+zero_at) % len(new_data)]["number"],
    ])
)