Найти - Пользователи
Полная версия: Вставить знаки между цифрами, чтобы получить число
Начало » Python для экспертов » Вставить знаки между цифрами, чтобы получить число
1 2
Master_Sergius
Написал скрипт для решения вот таких задач:
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

Думал, может быть, другую функцию из itertools использовать, но, увы, другие не дают и половины верных ответов, да и не логично тут другие вроде бы… Вот главный вопрос - как избавится от таких повторений с перестановкой слагаемых?

п.с. и ещё одно - как сделать, чтобы были видны здесь пустые строки в коде? а то форум их “хавает”
Budulianin
Master_Sergius
Написал скрипт для решения вот таких задач:
8 8 8 8 8 8 8 8 = 1000

Что за задача такая и зачем её решать?
Master_Sergius
Ну, что за задача - в теме вопроса “Вставить арифметичские знаки между числами, чтобы получить равность”. А зачем решать - скажем так, обращались некоторые двоечники за помощью, а схожих задач много, решил запрогать, ну и самому интересно стало запрогать - на паскале хрен бы я такое запрогал бы )
py.user.next
Master_Sergius
как избавится от таких повторений с перестановкой слагаемых?
нужно их запоминать в отсортированном виде во множестве
это другая задача, не заморачивайся
(нужно разделять на лексемы, анализировать операции, определять коммутативные и не очень, ещё там вложенные скобки бывают)

Master_Sergius
как сделать, чтобы были видны здесь пустые строки в коде?
вставлять один пробел в начале

Master_Sergius
ONE_NUMBER_IN_BRACKETS = r'\(\d*\)'
USELESS_BRACKETS = r'(\+|\-)\(.*?\)(\+|\-)'
это не brackets, а parentheses
Master_Sergius
py.user.next
это другая задача, не заморачивайся
(нужно разделять на лексемы, анализировать операции, определять коммутативные и не очень, ещё там вложенные скобки бывают)
Наверное и не стоит… но так хотелось…

А вообще, спасибо…
п.с. brackets - в общем, обозначает скобки, вот например curly brackets - фигурные, а parentheses - round brackets
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)

в контексте компов обычно: bracket - квадратная скобка, brace - фигурная, parenthesis - круглая


Master_Sergius
Наверное и не стоит… но так хотелось…
dip3. advanced iterators
здесь он вообще находит первое и выдаёт, похоже, по той же причине

хотя Hettinger (автор itertools), решает без остановки
sergeek
Тут надо деревья сначала генерировать а потом уже выражение. Тогда исчезнут трудности с дубликатами, коммутативностью, вложенными скобками.
Операторы - тоже объекты, поэтому лучше без eval'a делать
sergeek
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
Вот главный вопрос - как избавится от таких повторений с перестановкой слагаемых?
там еще могут быть множители с таким же свойством, может быть еще какой-нибудь критерий по которому будут определятся “эквивалентные” выражения. Так что непонятно что дальше делать с этими деревьями
Master_Sergius
У меня появилась извращенная мысль - может быть, ответы хранить в каком-то списке, и при появлении нового ответа запускать отдельный тред, который будет делать такую хрень: делать все возможные перестановки чисел с знаками в выражении, если хоть одно полученное новое выражение совпадет из каким-то из списка - то его не принимать в список. Как такова идея?
Shaman
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
По условиям задачи это разные решения.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB