Форум сайта python.su
Написал скрипт для решения вот таких задач:
8 8 8 8 8 8 8 8 = 1000
Вставлять можно любые знаки, скобки, а также объединять цифры.
import re import itertools ONE_NUMBER_IN_BRACKETS = r'\(\d*\)' USELESS_BRACKETS = r'(\+|\-)\(.*?\)(\+|\-)' if __name__ == '__main__': numbers = [8] * 8 expr = '%s'.join([str(number) for number in numbers]) possible_symbols = ['+', '-', '*', '/', '', '+(', '-(', '*(', '/(', ')+', ')-', ')*', ')/', '(', ')'] result = 1000 count = 0 for item in itertools.product(possible_symbols, repeat=len(numbers)-1): full_expression = expr % item try: if re.search(ONE_NUMBER_IN_BRACKETS, full_expression): continue if re.search(USELESS_BRACKETS, full_expression): continue if eval(full_expression) == result: print '%s=%s' % (full_expression, result) count += 1 except KeyboardInterrupt: break except: pass print 'Checked %s combinations.' % (count,)
8+8+8+88+888=1000
8+8+8+888+88=1000
8+8+88+8+888=1000
8+8+88+888+8=1000
8+8+888+8+88=1000
8+8+888+88+8=1000
8+88+8+8+888=1000
8+88+8+888+8=1000
Отредактировано Master_Sergius (Дек. 10, 2013 15:38:44)
Офлайн
Master_Sergius
Написал скрипт для решения вот таких задач:
8 8 8 8 8 8 8 8 = 1000
Офлайн
Ну, что за задача - в теме вопроса “Вставить арифметичские знаки между числами, чтобы получить равность”. А зачем решать - скажем так, обращались некоторые двоечники за помощью, а схожих задач много, решил запрогать, ну и самому интересно стало запрогать - на паскале хрен бы я такое запрогал бы )
Офлайн
Master_Sergiusнужно их запоминать в отсортированном виде во множестве
как избавится от таких повторений с перестановкой слагаемых?
Master_Sergiusвставлять один пробел в начале
как сделать, чтобы были видны здесь пустые строки в коде?
Master_Sergiusэто не brackets, а parenthesesONE_NUMBER_IN_BRACKETS = r'\(\d*\)' USELESS_BRACKETS = r'(\+|\-)\(.*?\)(\+|\-)'
Офлайн
py.user.nextНаверное и не стоит… но так хотелось…
это другая задача, не заморачивайся
(нужно разделять на лексемы, анализировать операции, определять коммутативные и не очень, ещё там вложенные скобки бывают)
Офлайн
>>> import unicodedata >>> unicodedata.name('[') 'LEFT SQUARE BRACKET' >>> unicodedata.name('(') 'LEFT PARENTHESIS' >>> unicodedata.name('{') 'LEFT CURLY BRACKET' >>>
<--- Free On-Line Dictionary of Computing --->
bracket
bracket
<character> (Or square bracket) A {left bracket} or {right
bracket}.
Often used loosely for {parentheses}, {square brackets},
{braces}, {angle brackets}, or any other kind of unequal
paired {delimiters}.
(1996-09-08)
Master_Sergiusdip3. advanced iterators
Наверное и не стоит… но так хотелось…
Отредактировано py.user.next (Дек. 12, 2013 04:34:10)
Офлайн
Тут надо деревья сначала генерировать а потом уже выражение. Тогда исчезнут трудности с дубликатами, коммутативностью, вложенными скобками.
Операторы - тоже объекты, поэтому лучше без eval'a делать
Офлайн
from functools import partial, reduce from operator import add, sub, mul, truediv from itertools import product consume = lambda els, pos : els[:pos] + [els[pos]*10+8] + els[pos+2:] def gen_eights(els, n): if n + 1 < len(els) > 2: cels = consume(els, n) return [cels] + gen_eights(cels, n) + gen_eights(els, n+1) else: return [] op_repr = {add : '+', sub : '-', mul : '*', truediv : '/'} class Expr_tree: def __init__(self, operator, op1, op2): self.operator = op_repr[operator] self.op1 = op1 self.op2 = op2 def __repr__(self): if self.operator in ('*', '/') and isinstance(self.op1, Expr_tree): return '({}) {} {}'.format(self.op1, self.operator, self.op2) else: return '{} {} {}'.format(self.op1, self.operator, self.op2) def build_expr_tree(els, ops): ex, *exs = els if exs: ox, *oxs = ops return Expr_tree(ox, build_expr_tree(exs, oxs), ex) return ex op_applicator = lambda op_iter : lambda res, n : next(op_iter)(res, n) els = [8]*8 eights = gen_eights(els, 0) + [els] for e_comb in eights: for op_seq in product((add, sub, mul, truediv), repeat=len(e_comb)-1): if reduce(op_applicator(iter(op_seq)), e_comb) == 1000: tree = build_expr_tree(reversed(e_comb), reversed(op_seq)) expr = repr(tree) print(expr, '=', eval(expr))
Master_Sergiusтам еще могут быть множители с таким же свойством, может быть еще какой-нибудь критерий по которому будут определятся “эквивалентные” выражения. Так что непонятно что дальше делать с этими деревьями
Вот главный вопрос - как избавится от таких повторений с перестановкой слагаемых?
Офлайн
У меня появилась извращенная мысль - может быть, ответы хранить в каком-то списке, и при появлении нового ответа запускать отдельный тред, который будет делать такую хрень: делать все возможные перестановки чисел с знаками в выражении, если хоть одно полученное новое выражение совпадет из каким-то из списка - то его не принимать в список. Как такова идея?
Офлайн
8+8+8+88+888=1000По условиям задачи это разные решения.
8+8+8+888+88=1000
8+8+88+8+888=1000
8+8+88+888+8=1000
8+8+888+8+88=1000
8+8+888+88+8=1000
8+88+8+8+888=1000
8+88+8+888+8=1000
Офлайн