Рубрики
Без рубрики

Появление кода 2018 День 5: Алхимическое сокращение

Представление эльфов в полимерную инженерию. Tagged с AOC2018, Python, Puzzle, Challenge.

Этот пост изначально появился на Steadbytes.com

Полное решение можно найти на GitHub

Первая часть

Дал Ввод головоломки Содержив строковое представление полимера, используемого в костюме Санты, нас просят найти Сколько единиц остается после полного реагирования полимера Анкет Нам говорят, что реакции происходят между прилегающий Единицы того же Тип но напротив полярность :

  • Тип
  • полярность /нижний регистр
aA -> reaction
ab -> no reaction
aB -> no reaction
aa -> no reaction

Когда реагируют пара соседних единиц, они уничтожаются, которые затем могут дать еще одну реакцию пары единиц, которые сейчас соседней, например:

abBAbA -> aAbA -> bA

Анализ ввода

Это простой случай считывания во всем входе в качестве одной строки:

with open("input.txt") as f:
    polymer = f.read().strip() # remove leading/trailing whitespace just in case

Моделирование реакции

Полная реакция может быть смоделирована с помощью стек удерживать единицы полимера по мере развития реакции:

  1. Инициализировать пустой стек
  2. Для каждой единицы в полимере:
    • Если устройство не вызывает реакции, нажмите на стек
    • Иначе выпейте предыдущий блок из стека (уничтожьте пару)
  3. Единицы, оставшиеся в стеке, представляют собой полностью отреагированный полимер

Пара единиц будет реагировать, если они одинаковы и противоположной полярности. Эта связь может быть представлена с использованием словаря, который отображает от каждого возможного блока в соответствующую реакцию:

import string

unit_pairs_map = {
    **{ch: ch.upper() for ch in string.ascii_lowercase},
    **{ch: ch.lower() for ch in string.ascii_uppercase},
}

Учитывая полимерную единицу, необходимая соседняя единица для реакции, которая будет проходить, можно найти, посмотрев его в unit_pairs_map :

# find required adjacent unit for 'a'
unit_pairs_map['a']
# A

# find required adjacent unit for 'A'
unit_pairs_map['A']
# a

Алгоритм выше теперь может быть реализован:

def part_1(polymer):
    stack = []
    for unit in polymer:
        # there is a previous unit and it reacts with the current unit
        if stack and unit == unit_pairs_map[stack[-1]]:
            # reaction -> destroy the units
            stack.pop()
        else:
            # no reaction -> unit remains
            stack.append(unit)
    return len(stack)

Для ввода моей головоломки результат – 10496 Анкет

Часть вторая

Затем нам говорят, что более полная реакция может быть уменьшена, если определенный тип полимера будет удален. Нас просят найти Длина самого короткого Возможный полимер путем удаления всех единиц точности одного типа и полностью реагировать результат.

  1. Для каждого возможного типа блока
    • Удалить все входы устройства из исходного полимера
    • Полностью реагировать полимер
    • Измерьте длину реагированного полимера
  2. Вернуть кратчайшую длину

Подзадачи для шага 1 алгоритма на самом деле такие же, как часть 1 головоломки. Сохранить Вещи сухой, эта логика может быть извлечена из part_1 Функция:

def react_polymer(polymer):
    # reaction logic from part 1
    stack = []
    for unit in polymer:
        if stack and unit == unit_pairs_map[stack[-1]]:
            stack.pop()
        else:
            stack.append(unit)
    return stack

def part_1(polymer):
    return len(react_polymer(polymer))

Решение для второй части теперь может использовать React_polymer Функция для подзадатов шага 1 в алгоритме:

def part_2(polymer):
    # original polymer length is the shortest so far
    best = len(polymer)
    for ch in string.ascii_lowercase: # unit types = letters of the alphabet
        reacted_polymer = react_polymer(
            # remove all occurrences (both polarities)
            [u for u in polymer if u != ch and u != ch.upper()]
        )
        # keep track of the shortest polymer found so far
        best = min(best, len(reacted_polymer))
    return best

Для ввода моей головоломки результат – 5774 Анкет

Ресурсы

– Использование списков Python в качестве стеков

Оригинал: “https://dev.to/steadbytes/aoc-2018-day-5-alchemical-reduction-10g0”