Advertisement
Guest User

Untitled

a guest
Aug 26th, 2015
33
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.39 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. import itertools
  4. import sys
  5.  
  6. def get_square_checker(top):
  7.     """
  8.    Возвращает функцию, эффективно проверяющую, является ли число квадратом.
  9.    `top` — максимальное значение квадрата.
  10.    """
  11.     squares = set(itertools.takewhile(lambda x: x <= top, (i ** 2 for i in itertools.count())))
  12.     return lambda x: x in squares
  13.  
  14. def get_nexts(range_):
  15.     """
  16.    Возвращает словарь, ключом в котором является каждое число из диапазона `range_`,
  17.    а значением — set допустимых пар для этого числа, дополняющих его до квадрата.
  18.    """
  19.     pairs = filter(lambda pair: is_square(sum(pair)), itertools.combinations(range_, 2))
  20.     nexts = {}
  21.     for (a, b) in pairs:
  22.         nexts.setdefault(a, set()).add(b)
  23.         nexts.setdefault(b, set()).add(a)
  24.     return nexts
  25.  
  26. def get_lists(current_list, used_digits, remaining_digits, nexts):
  27.     """
  28.    Возвращает списки, подходящие для условий задачи.
  29.    Функция рекурсивная и в `current_list` принимает текущий создаваемый список,
  30.    в `used_digits` и `remaining_digits` – уже использованные и оставшиеся цифры
  31.    (можно не передавать их, а выводить из `current_list` и максимального значения,
  32.    но передавать — лучше для производительности), в `nexts` — словарь допустимых пар,
  33.    созданный с помощью `get_nexts()`.
  34.    """
  35.     if not remaining_digits:
  36.         yield current_list
  37.     else:
  38.         cur_digit = current_list[-1]
  39.         for next_digit in nexts[cur_digit] - used_digits:
  40.             yield from get_lists(current_list + [next_digit], used_digits | {next_digit}, remaining_digits - {next_digit}, nexts)
  41.  
  42. if __name__ == '__main__':
  43.     max_ = int(sys.argv[1])
  44.     range_ = range(1, max_ + 1)
  45.     is_square = get_square_checker(top=2 * max_ - 1)
  46.     nexts = get_nexts(range_=range_)
  47.  
  48.     for first_digit in range_:
  49.         for r in get_lists([first_digit], {first_digit}, set(range_) - {first_digit}, nexts):
  50.             print(r)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement