Создайте правильное уравнение, используя указанные пользователем числа

10

Это основано на игре, в которую один из моих учителей математики играл в средней школе. Он написал бы 5 случайных однозначных чисел на доске, а затем случайное двузначное число. Мы попытались бы создать уравнение, которое использовало бы все 5 однозначных чисел для получения двузначного числа. Вот несколько примеров с решениями, чтобы объяснить это лучше:

Input:           Solution:
7 5 4 8 4 34     5*8-7+4/4 = 34
3 1 5 7 6 54     (7+3)*6-5-1 = 54
3 9 2 1 6 87     9*(2+1)*3+6 = 87
2 1 6 9 7 16     (9-7+6*1)*2 = 16
2 4 5 8 6 96     8*(5+6)+2*4 = 96
3 8 4 5 4 49     8*(4+4)-3*5 = 49

Эта задача состоит в том, чтобы написать программу, которая может генерировать такие уравнения для заданного ввода. Ввод может быть предоставлен либо через командную строку или через приглашение. 5 однозначных чисел всегда будут вводиться первыми (без определенного порядка), за которыми следует двузначный номер. Затем программа распечатает найденное уравнение решения; Вам не нужно обращаться с ситуациями, когда нет решения. Функция должна быть способна использовать следующие операции в уравнении: сложение, вычитание, умножение и деление. Если вы хотите разрешить дополнительные базовые операции, это нормально, если они остаются в духе задачи (отрицание, возведение в степень и модуль были бы хорошими дополнениями). Порядок операций соответствует стандартным математическим правилам, поэтому для группировки потребуется скобка.

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

Sir_Lagsalot
источник
Это очень похожая задача, но я думаю, что дополнительный термин и отсутствие ограничений на то, как сгруппированы выражения, должны достаточно расширить проблему, чтобы она была интересной. Кроме того, это задача игры в гольф, а не проблема кода, которая потребует различных решений.
Sir_Lagsalot
Как насчет объединения? например, если дано 7 5 4 8 4 34, выход 7 + 54/8 * 4 будет разрешен?
Патрик Робертс

Ответы:

7

Python 2.7 (284), Python 3.x (253)

from __future__ import division #(Remove for Python 3.x)
from itertools import *
a=raw_input().split()
for i in permutations(a[:-1],5):
 for j in product('+-*/',repeat=5):
  for k,l in combinations(range(1,12,2),2):
   d=''.join(sum(zip(i,j),()))[:-1];d='('+d[:l]+')'+d[l:]
   if eval(d)==int(a[-1]):print d;b

Выдает ошибку (вызов неизвестной функции b) при решении.

По сути, это гигантская грубая сила. Он принимает входные данные, разделяет их по пробелам ( 1 2 -> [1,2]) и затем перебирает этот список. При каждой перестановке он будет перебирать все возможные строки длиной 5, используя символы +-*/. С каждой из этих итераций он будет генерировать комбинации длины 2 списка [1,3,5,7,9,11], переплетать перестановку и строку вместе ( 12345 *-/+- -> 1*2-3/4+5-) и помещать в скобки. Наконец, он оценит его, и если ответ и уравнение верны, то он напечатает уравнение и остановится.

Это ужасно неэффективно, O(n!/(n-5)!)=O(n^5)но работает в разумные сроки для тестовых входов.

beary605
источник
1
Целочисленная математика может вызвать неправильный вывод при использовании деления. Например, вход "3 6 8 7 1 29" приводит к "(3 + 8/6) * 7 + 1", что равно 31 1/3, а не 29. Я обновлю описание, чтобы сделать это явным.
Sir_Lagsalot
Это дает (3/6)*8*7+1для меня.
beary605
Хорошо, я объясню это как проблему с переводчиком, которого я использовал.
Sir_Lagsalot
3

Scala 368:

2-ую g = -Line проще тестировать, первый гибкий для получения аргументов команды, и оба имеют одинаковую длину, поэтому я считаю только от второго - удалите его, чтобы передать аргументы:

val g=(args.map(_.toDouble))
val g=Array(3,9,2, 1, 6, 87)
val k="+*/-DQ"
val i=(0 to 5)
val f:Seq[(Double,Double)=>Double]=Seq(_+_,_*_,_/_,_-_,(a,b)=>b-a,(a,b)=>b/a)
val h=g.init.permutations;
for(j<-h;o<-i;p<-i;q<-i;r<-i;z=try{f(r)(f(q)(f(p)(f(o)(j(0),j(1)),j(2)),j(3)),j(4))}catch{case _ => 0}
if(z==g(5)))printf("(((%d%c%d)%c%d)%c%d)%c%d=%d\n",j(0),k(o),j(1),k(p),j(2),k(q),j(3),k(r),j(4),g(5))

Пример вывода (у вас может возникнуть вопрос прямо сейчас - на минутку):

(((5+7)/1)+6)*3=54
(((5-7)D1)*6)*3=54
(((5D7)+1)*6)*3=54
(((5+7)+6)Q1)Q3=54

Как насчет этого 5D7? D1? Это шестнадцатеричное? Есть Q1, Q3 - что это.

Sir_Lagsalot разрешил новые базовые операции в духе задачи, и да, это базовые операции, Delta и Quotient.

Они отличаются от a / b и ab тем, что aQb означает b / a, а aDb означает ba. Давайте назовем это украинской нотацией.

Так

(((5-7)D1)*6)*3=54

средства

((1-(5-7))*6)*3=54
 (1-(-2))*6*3
   3*6*3 = 18*3=54

К более интересному вопросу о том, как и почему: вначале я разозлился о возможности поставить круглые скобки и о том, (a + b) -c = a + bc = (a + bc) = ((a + b ) -c) = (b + a) -c и так далее. Вы можете рассердиться из-за этого вопроса, но если вы запишите возможные комбинации скобок, вы иногда выбрасываете блокнот и сталкиваетесь с фактом: вы всегда выполняете 4 операции между 5 значениями и начинаете с одного из них. Если шаблон всегда (((_x_)x_)x_)x_ ?= _(x является одним из 4 операторов) и допускает противоположное направление (xb) и (bxa), вы обратились к каждой возможности.

Теперь для a + b и a * b нам не нужно противоположное направление, они коммутативны. Поэтому я изобрел операторы D и Q, которые просто переключают направление. Теперь у меня есть еще 2 оператора, но мне не нужно менять направление. Хорошо - это делается в функции Sequence:

 (a,b)=>b-a,(a,b)=>b/a

Мое простое понимание берет значения из массива g и распределяет их от a до e, затем я выбираю 4 индекса, чтобы выбрать функцию, а затем (только по индексу) связанный символ оператора. Я должен ловить ошибки div / 0, так как вычитание может привести к нулям, в то время как пример входных данных не содержит 0.

Пользователь неизвестен
источник
Операторы Дельта и Фактор в порядке. Если вы планируете играть в гольф, вам нужно добавить круглые скобки в вывод.
Sir_Lagsalot
Вывод теперь печатает скобки.
пользователь неизвестен