Найти операции, необходимые для получения результата

10

Таким образом, задача проста, учитывая массив чисел и результат, вам нужно найти, какие операции нужно использовать над числами из массива, чтобы получить запрошенный результат.

Давайте сделаем это простым для запуска и разрешим только основные операции, такие как: сложение, вычитание, умножение и деление.

Пример:

Input  : [5,5,5,5,5] 100
Output : 5*5*5-5*5

Чтобы дать какое-то преимущество таким языкам, как Java, запрос состоит в реализации функции, а не всей программы, и результат можно вернуть через параметр или вывести на консоль.

Код оценивается на основе количества байтов, и, поскольку это вызов кода гольфа, выигрывает самый низкий балл.

Еще одно требование: Вы можете получить дополнительные -10 баллов, если массив содержит только цифры, поддерживая решения, в которых вы могли бы строить числа из следующих цифр. Т.е.

Input  : [1,2,3,4,5] 0
Output : 12-3-4-5

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

РЕДАКТИРОВАТЬ: Результат должен быть действительным с математической точки зрения, следовательно, деление это рациональное деление, а не целое число, и приоритет операции такой же, как в классической математике (сначала умножение и деление, а затем сложение и вычитание).

user902383
источник
4
Есть ли *и /имеет приоритет над +и -? Ваши два примера противоречат друг другу.
Дрянная Монахиня
1
Пожалуйста, в будущем убедитесь, что вы создадите вознаграждения в процентах для языка, такого как java, -10 байт не так хорошо, как для желе
Балинт
7
Или вообще избегать бонусов
Луис Мендо
4
Нужно ли использовать номера по порядку? Кроме того, для будущих проблем я от всей души рекомендую использовать Песочницу, где подобные проблемы могут быть устранены перед публикацией в Main.
AdmBorkBork
2
@ mbomb007 это не дубликат ни того, ни другого. Это произвольные числовые входы, и допускаются только основные математические операции, они не должны выводить реальные программы.
Патрик Робертс

Ответы:

4

Oracle SQL 11.2, 322 304 270 байт

SELECT o FROM(SELECT REPLACE(SUBSTR(:1,1,1)||REPLACE(SYS_CONNECT_BY_PATH(a||SUBSTR(:1,LEVEL*2+1,1),','),','),'_')o,LEVEL l FROM(SELECT SUBSTR('+-*/_',LEVEL,1)a FROM DUAL CONNECT BY LEVEL<6)CONNECT BY LEVEL<LENGTH(:1)/2)WHERE:2=dbms_aw.eval_number(o)AND l>LENGTH(:1)/2-1;

: 1 - список цифр
: 2 - результат поиска

Без гольфа:

SELECT o
FROM   (
         SELECT REPLACE(SUBSTR(:1,1,1)||REPLACE(SYS_CONNECT_BY_PATH(a||SUBSTR(:1,LEVEL*2+1,1),','),','),'_')o,LEVEL l 
         FROM ( -- Create one row per operator 
                SELECT SUBSTR('+-*/_',LEVEL,1)a FROM DUAL CONNECT BY LEVEL<6
              ) CONNECT BY LEVEL<LENGTH(:1)/2  -- Create every combination of operators, one per ','
)
WHERE :2=dbms_aw.eval_number(o)  -- filter on result = evaluation
  AND l>LENGTH(:1)/2-1           -- keep only expressions using every digits
школа для водителей
источник
4

TSQL (sqlserver 2016) 310 294 280 байт

Какая замечательная возможность написать некрасивый код:

Golfed:

DECLARE @ varchar(max)= '5,5,5'
DECLARE @a varchar(20) = '125'

,@ varchar(max)='';WITH D as(SELECT @a a UNION ALL SELECT STUFF(a,charindex(',',a),1,value)FROM STRING_SPLIT('*,+,./,-,',',')x,d WHERE a like'%,%')SELECT @+=a+','''+REPLACE(a,'.','')+'''),('FROM D WHERE a not like'%,%'EXEC('SELECT y FROM(values('+@+'null,null))g(x,y)WHERE x='+@b)

Попробуйте онлайн

Читаемо: (вставка десятичной точки (.) И ее удаление необходимы для того, чтобы sql мог принять, что 4/5 - это не 0 - это хорошо для людей, которые его тестируют)

DECLARE @a varchar(max)= '5,5,5'
DECLARE @b varchar(20) = '5'

,@ varchar(max)=''
;WITH D as
(
  SELECT @a a
  UNION ALL
  SELECT STUFF(a,charindex(',',a),1,value)
  FROM STRING_SPLIT('*,+,./,-,',',')x,d
  WHERE a like'%,%'
)
SELECT @+=a+','''+REPLACE(a,',','')+'''),('
FROM D
WHERE a not like'%,%'

EXEC('SELECT y FROM(values('+@+'null,null))g(x,y)WHERE x='+@b)

Это решение также может обрабатывать следующие типы ввода:

Вход: [1,2,3,4,5] 0 Выход: 12-3-4-5

t-clausen.dk
источник
3

JavaScript (ES6), 165 147 байт

a=>o=>(c=[],i=c=>{for(j=0;!((c[j]?++c[j]:c[j]=1)%5);)c[j++]=0},eval(`while(eval(e=(a+'').replace(/,/g,(_,j)=>'+-*/'.charAt(c[~-j/2])))!=o)i(c);e`))

Вложенный eval... прекрасный.

f=a=>o=>(c=[],i=c=>{for(j=0;!((c[j]?++c[j]:c[j]=1)%5);)c[j++]=0},eval(`while(eval(e=(a+'').replace(/,/g,(_,j)=>'+-*/'.charAt(c[~-j/2])))!=o)i(c);e`))
console.log(f([5,5,5,5,5])(100))
console.log(f([1,2,3,4,5])(0))
console.log(f([3,4])(0.75))
console.log(f([3,4,5,6])(339))

Патрик Робертс
источник
3

Python 3, 170 155 байт

from itertools import*
def f(n,o):print({k for k in[''.join(map(str,sum(j,())))[1:]for j in[zip(x,n)for x in product('+-*/',repeat=len(n))]]if eval(k)==o})

Создайте генератор со всеми возможными порядками операторов, объедините его с числами, затем вычисляйте до тех пор, пока мы не получим ответ.

https://repl.it/C2F5

atlasologist
источник
2
Вы можете сохранить несколько символов, заменив их ['+','-','*','/']на '+-*/'; Так как strings итерируемы, он будет обрабатывать его как a, arrayгде каждый элемент является каждым символом в string- так что он будет действовать так же, как вы предоставили ему массив, который у вас есть в данный момент.
nasonfish
2

Python, 195 186 байт

Вот ужасный способ сделать это.

def x(i,r):
 t=""
 from random import choice as c
 while True:
  for j in i:
   t+=str(j)
   if c([0,1]):t+="."+c("+-/*")
  t=t.strip("+-*/.")+"."
  v=eval(t)
  if v == r:print t
  t=""

Функция xпринимает аргументы a listи a result- x([1,2,3,4,5], 15)например.

Программа начинает цикл, в котором мы начинаем случайный выбор, добавлять ли мы "+", "-", "*", or "/"между каждым числом или объединять их вместе. Это казалось более лаконичным вариантом, чем на самом деле проходить перестановки и пробовать каждую комбинацию, чтобы найти каждый результат, и хотя это занимает больше времени и гораздо менее эффективно. (К счастью, это не проблема в этом контексте!)

Также добавляется "." для каждого числа, чтобы избежать выполнения целочисленных операций, таких как 6/4 = 1. Затем оно evalвыражает наше выражение и определяет, равен ли результат тому, что мы ожидаем, и если да, выводит выражение.

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

РЕДАКТИРОВАТЬ 1 : удалить ненужные новые строки, где ifможно использовать однострочные операторы.

nasonfish
источник
действительно смешная реализация. но легко сохранить еще несколько байтов Попробуйте онлайн! (176 байт)
бобробоб
2

Матлаб, 234 238 258 байтов

Исходя из ограничений других ответов, я предполагаю, что порядок чисел входного массива поддерживается fiat.

n=length(x)-1
k=n*2+2
p=unique(nchoosek(repmat('*-+/',1,n),n),'rows')
p=[p char(' '*~~p(:,1))]'
c=char(x'*~~p(1,:))
o=p(:,r==cellfun(@eval,mat2cell(reshape([c(:) p(:)]',k,[]),k,0|p(1,:))))
reshape([repmat(x',size(o,2),1) o(:)]',k,[])'

Этот код берет строку чисел x, скажем , x = '12345'и в результате r, скажем , r = 15и возвращает все строки из выражений , которые вы можете оценить , чтобы получить rотx использования четырех операторов.

Я использовал два различных эквивалентных по длине способа избегания использования выражений ones(length())-type или repmat(length())-type: ~~p(1,:)который возвращает значения not-not в p(т. 1Е. Список с той же длиной, что и первое измерение p) и 0|p(:,1)который возвращает 0 или is-there -a-значение-в- p(т. е. список 1s такой же длины, что и второе измерение p).

Matlab не имеет метода nchoosek с заменой , поэтому я продублировал правильное количество раз, вычислил все пространство nchoosekдля большего выбора операторов, а затем использовал uniqueвызов, чтобы свести результат к тому, что должно быть (удаление эквивалентных комбинаций, таких как «*** +» и «*** +»). Я добавляю завершающий пробел, чтобы соответствовать длине входного вектора для целей конкатенации, а затем объединяю строки оператора со входными строками в столбцы матрицы. Затем я оцениваю выражения по столбцам, чтобы получить результаты и найти порядок операторов, соответствующий тем столбцам с результатами, которые соответствуют нашему вводу r.

Тест: x = '12345', r = 15:

1*2*3+4+5 
1+2+3+4+5 
1-2*3+4*5 

Если бы мне нужно было взять массив значений двойной точности, мне нужно было x = num2str(x,'%d');бы преобразовать цифры в строку, добавив 21 (20 без ;) к моему счету. * Дополнительные байты были точками с запятой, которые я оставил только для того, чтобы любой, кто запускает этот код, не видел, чтобы их командная строка была взорвана длинными массивами. Так как мое редактирование теперь генерирует огромную кучу предупреждений о логиках и операндах двоеточия, я удалил точки с запятой в новой версии.

Изменить 2: Забыла замените 2*n+2с k.

Старый ответ:

n=length(x)-1;
p=unique(nchoosek(repmat(['*','-','+','/'],1,n),n),'rows');
l=length(p);
p=[p repmat(' ',l,1)]';
c=reshape([repmat(x',l,1) p(:)]',n*2+2,[]);
o = p(:,r == cellfun(@eval, mat2cell(c,n*2+2,ones(l,1))));
reshape([repmat(x',size(o,2),1) o(:)]',n*2+2,[])'
синтаксис
источник
2

JavaScript (ES6), 88 байт

a=>o=>eval(`while(eval(e=(a+'').replace(/,/g,_=>'+-*/'.charAt(Math.random()*5)))!=o);e`)

Добавил немного случайности в смесь. Гораздо проще, чем систематически повторять комбинации.

Тестирование

f=a=>o=>eval(`while(eval(e=(a+'').replace(/,/g,_=>'+-*/'.charAt(Math.random()*5)))!=o);e`)
console.log(f([5,5,5,5,5])(100))
console.log(f([1,2,3,4,5])(0))
console.log(f([3,4])(0.75))
console.log(f([3,4,5,6])(339))

Патрик Робертс
источник
1

PHP, 108 байт

for(;$i=$argc;eval("$s-$argv[1]?:die(\$s);"))for($s="",$x=$p++;--$i>1;$x/=4)$s.="+-*/"[$s?$x&3:4].$argv[$i];

принимает входные данные из аргументов командной строки в обратном порядке. Беги с -r.

сломать

for(;                   # infinite loop:
    $i=$argc;               # 1. init $i to argument count
    eval("$s-$argv[1]?:"    # 3. if first argument equals expression value,
        ."die(\$s);")       #    print expression and exit
    )
    for($s="",              # 2. create expression:
        $x=$p++;            #    init map
        --$i>1;                 # loop from last to second argument
        $x/=4)                  # C: shift map by two bits
        $s.="+-*/"[$s?$x&3:4]   # A: append operator (none for first operand)
            .$argv[$i];         # B: append operand
Titus
источник