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

Пришествие кода 2020: День 22 с Python

Еще один быстрый сегодня. Просто несколько простых старых манипуляций с списком питона и рекурсии Cha … с меткой AdventofCode, Python.

Еще один быстрый сегодня. Просто несколько простых старых манипуляций с списком питона и рекурсии

Ссылка на вызов на веб -сайте Advent of Code 2020

Задача включает в себя разыгрывание карточной игры, которая имеет простой набор правил. Таким образом, включает в себя отслеживание двух стеков карт. Правила просты: оба игрока играют в одну карту с вершины своей колоды, выигрыш с самыми высокими картами, победившая игрок сохраняет обе карты.

Решение

Начиная с импорта без излишеств: просто разделить данные вручную, чтобы сэкономить время, и поднять все на INTS

data = open("input.txt").read().splitlines()
player1 = list(map(int, data[1:26]))
player2 = list(map(int, data[28:54]))

Тогда в значительной степени просто цикл, пока один игрок не пуст, используя .pop () удалить элемент из списка

while player1 and player2:
    card1 = player1.pop(0)
    card2 = player2.pop(0)
    if card1 > card2:
        player1.extend([card1, card2])
    else:
        player2.extend([card2, card1])

Наконец, рассчитайте сумму в соответствии с правилами задачи: последняя карта стоит 1, следующая стоит 2 и т. Д.

win = player1 if player1 else player2
print("sum", sum((a+1) * b for a, b in enumerate(reversed(win))))

Полный код для решения для части 1:

data = open("input.txt").read().splitlines()
player1 = list(map(int, data[1:26]))
player2 = list(map(int, data[28:54]))

while player1 and player2:
    card1 = player1.pop(0)
    card2 = player2.pop(0)
    if card1 > card2:
        player1.extend([card1, card2])
    else:
        player2.extend([card2, card1])

win = player1 if player1 else player2
print("sum", sum((a+1) * b for a, b in enumerate(reversed(win))))

Задача, часть 2

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

Существует также дополнительное положение для записи каждой руки подгруппы и прерывать, если он начинает цикл.

Итак … нам нужно отслеживать руки. Поскольку DICTS – это (1) поиск, мы будем использовать это, и мы просто задаем твердые (так как это удобно).

Здесь мы возвращаем 0 для победы Player1 (как того требует правила)

def game(player1, player2):
    records = {}

    while player1 and player2:
        key = str(player1)+str(player2)
        if key in records:
            return 0
        records[key] = None

        ...

Далее мы добавляем дополнительное правило игры для повторения в подгры и возвращаем победителя. В подмножестве используется подмножество карт, которое генерируется с использованием среза. Это копирует список, поэтому он оставляет оригинал нетронутым, что желательно. Остальные правила игры одинаковы

    card1 = player1.pop(0)
    card2 = player2.pop(0)

    if len(player1) >= card1 and len(player2) >= card2:
        winner = game(player1[:card1], player2[:card2])
    else:
        winner = card2 > card1

    if winner:
        player2.extend([card2, card1])
    else:
        player1.extend([card1, card2])

Полный цикл выглядит так:

def game(player1, player2):
    records = {}

    while player1 and player2:
        key = str(player1)+str(player2)
        if key in records:
            return 0
        records[key] = None

        card1 = player1.pop(0)
        card2 = player2.pop(0)

        if len(player1) >= card1 and len(player2) >= card2:
            winner = game(player1[:card1], player2[:card2])
        else:
            winner = card2 > card1

        if winner:
            player2.extend([card2, card1])
        else:
            player1.extend([card1, card2])

    return winner

winner = game(player1, player2)

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

Полный код:

data = open("input.txt").read().splitlines()
player1 = list(map(int, data[1:26]))
player2 = list(map(int, data[28:54]))

def game(depth, player1, player2):
    records = {}

    while player1 and player2:
        key = str(player1)+str(player2)
        if key in records:
            return 0
        records[key] = None

        card1 = player1.pop(0)
        card2 = player2.pop(0)

        if len(player1) >= card1 and len(player2) >= card2:
            winner = game(depth+1, player1[:card1], player2[:card2])
        else:
            winner = card2 > card1

        if winner:
            player2.extend([card2, card1])
        else:
            player1.extend([card1, card2])

    if depth == 0:
        return (player2 if winner else player1)

    return winner

windeck = game(0, player1, player2)
print("sum", sum((a+1) * b for a, b in enumerate(reversed(windeck ))))

Все сделано. Впереди!

Оригинал: “https://dev.to/meseta/advent-of-code-day-22-263i”