Advent of Code 2015 — День 4

В День 4 я был очень рад стандартной библиотеке, которую раньше не использовал в Python. Вот первая часть головоломки:

С помощью быстрого Google я выяснил, что Python предоставляет стандартную библиотеку для хэширования, которая называется hashlib. Она содержит множество стандартных алгоритмов хэширования, таких как SHA1, SHA224, SHA256, SHA384, SHA512 и, конечно, MD5.

Ввод строки в модуль и получение шестнадцатеричного значения из него не так просты, как хотелось бы, но документация довольно понятна. Сначала строка должна быть преобразована в байтовый объект (s.encode()), прежде чем ее можно будет передать в md5(). Затем возвращаемое значение должно быть преобразовано в шестнадцатеричное с помощью функции hexdigest().

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

import hashlib

def solve(key, zeroes):

    n = 1
    prefix = zeroes * '0'

    while True:
        s = key + str(n)
        h = hashlib.md5(s.encode()).hexdigest()[:zeroes]
        if h == prefix:
            return n
        n += 1

print(solve('yzbqklnj', 5))
Вход в полноэкранный режим Выход из полноэкранного режима

Я не был в восторге от while True, но не видел альтернативы, кроме установки произвольно высокой верхней границы. Я видел код типа for i in range(1, 1000000) и даже for i in itertools.count() в мегатреде, который не казался намного лучше. Хорошая вещь в решении головоломок — знать, что решение есть, поэтому вы знаете, что в какой-то момент выйдете из цикла.

Код решил задачу для пяти ведущих нулей примерно за 0.8 с, что больше связано с реализацией hashlib, чем с тем, что я делал, что по сути является грубой силой.

Часть 2 была самым коротким расширением на данный момент, и одним из самых коротких, которые я когда-либо видел:

Теперь найдите такое, которое начинается с шести нулей.

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

print(solve('yzbqklnj', 6))
Войти в полноэкранный режим Выйти из полноэкранного режима

Это работает немного медленнее, но я ожидал этого и был вполне доволен тем, что решение было найдено менее чем за 30 секунд.

А настоящие программисты Python?

Большинство Pythonistas решили эту задачу примерно так же, как и я, но есть пара решений, которые используют многопоточность, чтобы распределить грубую силу на несколько CPU. Я никогда раньше не занимался многопоточностью, так что, возможно, мне стоит обратить на это внимание.

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

  • zip()
  • наборы
  • многопоточность
  • итераторы

Оцените статью
devanswers.ru
Добавить комментарий