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

Advent of Code 2018 день 3: Независимо от того, как вы ловусят Это

Видимо эльфы не велики в командной работе. Помечено AC2018, Python, Puzzle, Challenge.

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

Полное решение можно найти на Гадость

Часть первая

Учитывая Ввод головоломки претензии нам просят найти Количество квадратных дюймов ткани в течение двух или более претензий Отказ

  1. Разбирайте ввод в последовательность претензий ткани
  2. Для каждого квадратного дюйма ткани найдите количество претензий, содержащих его
  3. Подсчитать общее количество квадратных дюймов ткани, где счет претензии больше, чем один

Разборка ввода

Каждая строка ввода представляет собой претензию в следующем формате:

# @ ,: x

Например, # 123 @ 3,2: 5x4 Соответствует прямоугольнику с ID 123 , 3 С левого края 2 дюймы с верхнего края, 5 дюймов в ширину и 4 дюймов.

  1. Разделить вход в новинки
  2. Для каждой строки извлечь данные об утверждении:
    • Я БЫ
    • Расстояние от левого края
    • Расстояние от верхнего края
    • Ширина
    • Высота

Извлечение данных претензий могут быть достигнуты с помощью A Регулярное выражение :

import re

claim_re = re.compile(
    r"#(?P<_id>[0-9]+) @ "
    r"(?P[0-9]+),(?P[0-9]+): "
    r"(?P[0-9]+)x(?P[0-9]+)"
)

m = claim_re.match("#123 @ 3,2: 5x4")
# retrieve all cptured values
m.groups() # -> ('123', '3', '2', '5', '4')
# retreieve a specific captured value
m.groups('_id') # -> '123'

Извлеченные значения из регулярного выражения – это строки, однако для этой головоломки они представляют целые числа. Кроме того, после извлеченных значений регулярная экспрессия объекта совпадения не требуется, и претензия может быть представлена собственным объектом. Так как это Python, A Дикт сделаю трюк!

Учитывая претензию от ввода головоломки:

  1. Сопоставьте каждое значение, используя Prec_re регулярное выражение
  2. Создать Дикт Там, где клавиши являются именами групп, а значения – это извлеченные строки, припаренные к целым числам:
def parse_claim(claim_string):
    m = claim_re.match(claim_string)
    return {k: int(v) for k, v in m.groupdict().items()}

parse_claim("#123 @ 3,2: 5x4")
# {'_id': 123, 'left': 3, 'top': 2, 'width': 5, 'height': 4}

Представляющий ткань

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

00000000000
00000000000
00011111000
00011111000
00011111000
00011111000
00000000000
00000000000
00000000000

Для каждого претензии:

  1. Найти «физическую» площадь (координаты в сетке), она будет покрывать
  2. Увеличить соответствующее количество претензий в ткани

Найти область, представленную претензию, может быть достигнута с использованием позиций (левый, верхний) и размеры (ширина, высота), извлеченные из ввода головоломки:

def claim_area(claim):
    return (
        (i, j)
        for i in range(claim["left"], claim["left"] + claim["width"])
        for j in range(claim["top"], claim["top"] + claim["height"])
    )

Эта функция принимает претензию Дикт производится предыдущим parse_claim Функция и возвращает Генератор который дает пары (х, у) Координаты в тканевой сетке, которая сводится в пределах претензии.

Наиболее интуитивно понятный способ представления ткани сетки с использованием структуры 2D массива:

fabric = []
for y in range(height_of_fabric):
    row = []
    for x in range(width_of_fabric):
        row.append(0)
    fabric.append(row)

# to update the fabric counters for a claim
for x, y in claim_area("#123 @ 3,2: 5x4"):
    fabric[y][x] += 1

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

Весь кусок ткани, на которой они работают, это очень большой квадрат – по крайней мере 1000 дюймов на каждой стороне.

Чтобы избежать ненужных накладных расходов на строительство и итерацию по сравнению с большим 2D-массивом, мы можем использовать словарь, в котором ключи являются координатами, а значения – количество претензий на эту позицию:

fabric =  {}

# to add a claim
for coord in claim_area("#123 @ 3,2: 5x4"):
    if coord in fabric:
        fabric[coord] += 1
    else:
        fabric[coord] = 1

fabric[(3, 2)] # -> 1

С этим улучшением мы больше не храним значения для позиций в ткани без претензий. Подсчет ценностей в словаре, подобное это – это общая операция, а как таковая, Python включает в себя встроенный Счетчик Структура данных в Коллекции модуль. Учитывая список претензии Создание каждого претензии, проанализированной от ввода головоломки, вся ткань может быть представлена как таковая:

fabric = Counter(coord for claim in claims for coord in claim_area(claim))

fabric[(3, 2)] # -> number of claims at position (3, 2)

Нахождение перекрывающихся претензий

Вооружен нашим ткань Нахождение количества квадратных дюймов в течение двух или более претензий требует подсчета общего количества значений в ткань которые больше 1:

def part_1(fabric):
    return sum([1 for claim_count in fabric.values() if claim_count > 1])

Для моей ввода головоломки результат – 115348 Отказ

Часть 2

Далее нам говорят, что есть одинокий претензия, который не имеет совпадающих с любыми другими и просят найти ID указанного претензии.

Эта претензия будет иметь счетчик Country of 1 Для каждого из координат, содержащихся в нем в ткань Отказ

  1. ИТЕРТЬ НА КАЖЕ ПРЕТЕНЗИИ
  2. Получить счетчик счетчиков от ткань каждой координаты в пределах претензии
  3. Если каждое значение равно 1 вернуть идентификатор претензии
def part_2(claims, fabric):
    for claim in claims:
        # all returns True if and only if each value is True
        if all(fabric[coord] == 1 for coord in claim_area(claim)):
            return claim["_id"]

Для моей ввода головоломки результат – ID 188 Отказ

Ресурсы

Оригинал: “https://dev.to/steadbytes/aoc-2018-day-3-no-matter-how-you-slice-it-4afo”