zenithstar95

I love you Aymeric

  • he/him

28 - queer dude - irish - 🏳️‍🌈🏳️‍⚧️🏴
__
Software dev.
I draw suggestive things sometimes.
__
Boyfriend: @hephaistos


CSS Adventurer Plate Generator
stellarzenith.github.io/adventurer-plate/

My part 2 solution feels completely fucking bonkers.


Part 1

def parse_input():
    with open("input.txt", "r") as f:
        input = f.readlines()

    seeds = input[0].split(":")[1].split()
    map = False
    maps = []
    values = []
    for i in range(len(input)):
        if input[i][0].isdigit():
            map = True
            dest_start, source_start, offset = input[i].split()
            values.append(
                dict(
                    dest_start=int(dest_start),
                    source_start=int(source_start),
                    offset=int(offset),
                )
            )
        if i == len(input) - 1:
            map = False
        if not map and len(values) > 0:
            maps.append(values)
            values = []
        map = False
    maps = dict(
        seed_to_soil=maps[0],
        soil_to_fertilizer=maps[1],
        fertilizer_to_water=maps[2],
        water_to_light=maps[3],
        light_to_temp=maps[4],
        temp_to_humidity=maps[5],
        humidity_to_location=maps[6],
    )
    return seeds, maps


def convert(value, map):
    for m in map:
        if value >= m["source_start"] and value <= m["source_start"] + m["offset"]:
            return value + m["dest_start"] - m["source_start"]
    return value


seeds, maps = parse_input()
lowest = 0
for seed in seeds:
    seed = int(seed)
    soil = convert(seed, maps["seed_to_soil"])
    fertilizer = convert(soil, maps["soil_to_fertilizer"])
    water = convert(fertilizer, maps["fertilizer_to_water"])
    light = convert(water, maps["water_to_light"])
    temp = convert(light, maps["light_to_temp"])
    humidity = convert(temp, maps["temp_to_humidity"])
    location = convert(humidity, maps["humidity_to_location"])
    if lowest == 0 or location < lowest:
        lowest = location
print(lowest)
syntax highlighting by codehost

Fairly straightforward. If a number is between the right values, modify it to the correct value.

Part 2

def parse_input():
    with open("input.txt", "r") as f:
        input = f.readlines()

    seeds = input[0].split(":")[1].split()
    seed_ranges = []
    range_container = []
    for i in range(len(seeds)):
        if not i % 2:
            seed = dict()
            seed.update(start=int(seeds[i]))
        else:
            seed.update(end=seed["start"] + int(seeds[i]) - 1)
            range_container.append(seed)
            seed_ranges.append(range_container)
            range_container = []
    map = False
    maps = []
    values = []
    for i in range(len(input)):
        if input[i][0].isdigit():
            map = True
            dest_start, source_start, offset = input[i].split()
            values.append(
                dict(
                    dest_start=int(dest_start),
                    source_start=int(source_start),
                    offset=int(offset),
                )
            )
        if i == len(input) - 1:
            map = False
        if not map and len(values) > 0:
            maps.append(values)
            values = []
        map = False
    maps = dict(
        seed_to_soil=maps[0],
        soil_to_fertilizer=maps[1],
        fertilizer_to_water=maps[2],
        water_to_light=maps[3],
        light_to_temp=maps[4],
        temp_to_humidity=maps[5],
        humidity_to_location=maps[6],
    )
    return seed_ranges, maps

def convert(data, map):
    for source in data:
        lowest = source["start"]
        highest = source["end"]
        for m in map:
            dest_start = m["dest_start"]
            source_start = m["source_start"]
            offset = m["offset"]
            if lowest >= source_start and lowest <= source_start + offset:
                lowest += dest_start - source_start
                if highest > source_start + offset:
                    new_source = dict(start=source_start + offset + 1, end=highest)
                    data.append(new_source)
                    highest = source_start + offset
                highest += dest_start - source_start
                source["start"] = lowest
                source["end"] = highest
                break
            elif highest >= source_start and highest <= source_start + offset:
                new_source = dict(start=lowest, end=source_start - 1)
                data.append(new_source)
                highest += dest_start - source_start
                source["start"] = dest_start
                source["end"] = highest
                break
    return data

seed_ranges, maps = parse_input()
lowest = 0
for seeds in seed_ranges:
    soil = convert(seeds, maps["seed_to_soil"])
    fertilizer = convert(soil, maps["soil_to_fertilizer"])
    water = convert(fertilizer, maps["fertilizer_to_water"])
    light = convert(water, maps["water_to_light"])
    temp = convert(light, maps["light_to_temp"])
    humidity = convert(temp, maps["temp_to_humidity"])
    locations = convert(humidity, maps["humidity_to_location"])
    for location in locations:
        if lowest == 0 or location["start"] < lowest:
            lowest = location["start"]
print(lowest)
syntax highlighting by codehost

This could be much tidier but I'm just glad it worked. You do not need to check every individual number, just the lowest and highest for any given stretch of seed numbers. If they're both in range, great. If one of them is in range but the other isn't, split it up, convert the part that is in range, and check the left over part against other ranges instead. This took a while to wrap my head around.


You must log in to comment.