Этот пост изначально появился на 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
Моделирование реакции
Полная реакция может быть смоделирована с помощью стек удерживать единицы полимера по мере развития реакции:
- Инициализировать пустой стек
- Для каждой единицы в полимере:
- Если устройство не вызывает реакции, нажмите на стек
- Иначе выпейте предыдущий блок из стека (уничтожьте пару)
- Единицы, оставшиеся в стеке, представляют собой полностью отреагированный полимер
Пара единиц будет реагировать, если они одинаковы и противоположной полярности. Эта связь может быть представлена с использованием словаря, который отображает от каждого возможного блока в соответствующую реакцию:
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 алгоритма на самом деле такие же, как часть 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”