Encuentra las operaciones necesarias para obtener resultados

10

Entonces, la tarea es simple, dada la matriz de números y resultados, debe encontrar qué operaciones necesita usar en los números de la matriz, para obtener el resultado solicitado.

Hagámoslo simple para comenzar, y permitamos solo operaciones básicas como: suma, resta, multiplicación y división.

Ejemplo:

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

Para dar alguna ventaja a lenguajes como Java, la solicitud es implementar la función, no el programa completo, y el resultado puede ser devuelto a través de parámetros o imprimir en la consola.

El código se califica en función de la cantidad de bytes y, como es un desafío de código de golf, gana el puntaje más bajo.

Otro requisito es que puede obtener -10 puntos adicionales si para la matriz contiene solo dígitos, soluciones de soporte donde podría construir números a partir de los siguientes dígitos. Es decir

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

Tenga en cuenta que, si las salidas son salidas propuestas, algunos casos pueden tener más de una solución. Depende de usted proporcionar una o más soluciones para una tarea determinada.

EDITAR: El resultado debe ser válido desde el punto de vista matemático, por lo tanto, la división es una división racional, no un número entero, y la precedencia de la operación es la misma que en las matemáticas clásicas (primero multiplicación y división, luego suma y resta).

usuario902383
fuente
44
¿Tiene *y /tiene precedencia sobre +y -? Sus dos ejemplos se contradicen entre sí.
Leaky Nun
1
Por favor, en el futuro, asegúrese de crear recompensas basadas en porcentajes, para un idioma, como java, -10 bytes no es tan bueno como para jalea
Bálint
77
O incluso evitar bonificaciones por completo
Luis Mendo
44
¿Deben usarse los números en orden? Además, para futuros desafíos, recomiendo encarecidamente usar el Sandbox, donde este tipo de problemas se pueden resolver antes de publicar en Main.
AdmBorkBork
2
@ mbomb007 no es un duplicado de ninguno de esos. Estas son entradas numéricas arbitrarias, y solo se permiten operaciones matemáticas básicas, no se supone que generen programas reales.
Patrick Roberts

Respuestas:

4

Oracle SQL 11.2, 322 304 270 bytes

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 es la lista de dígitos
: 2 es el resultado buscado

Sin golf:

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
Jeto
fuente
4

TSQL (sqlserver 2016) 310 294 280 bytes

Qué maravillosa oportunidad para escribir código feo:

Golfizado:

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)

Pruébalo en línea

Legible: (la inserción del punto decimal (.) Y la eliminación de la misma es necesaria para que sql acepte que 4/5 no es 0; la eliminación del pozo es para las personas que lo prueban)

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)

Esta solución también puede manejar estos tipos de entrada:

Entrada: [1,2,3,4,5] 0 Salida: 12-3-4-5

t-clausen.dk
fuente
3

JavaScript (ES6), 165 147 bytes

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`))

Anidado eval... encantador.

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))

Patrick Roberts
fuente
3

Python 3, 170 155 bytes

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})

Cree un generador con todas las órdenes posibles de los operadores, combine eso con los números, luego evalúe hasta obtener la respuesta.

https://repl.it/C2F5

atlasólogo
fuente
2
Puede guardar algunos caracteres reemplazándolos ['+','-','*','/']con '+-*/'; como strings son iterables, lo tratará como si fuera un arrayelemento con cada carácter de cada carácter string, por lo que actuará tal como lo proporcionó con la matriz que tiene actualmente.
nasonfish
2

Pitón, 195 186 bytes

Aquí hay una forma atroz de hacerlo.

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=""

La función xacepta un argumento de a listy aresult , x([1,2,3,4,5], 15)por ejemplo.

El programa comienza un ciclo donde comenzamos a seleccionar aleatoriamente si debemos agregar "+", "-", "*", or "/"entre cada número, o si debemos concatenarlos juntos. Esto parecía una opción más concisa que pasar por permutaciones e intentar cada combinación para encontrar cada resultado, y aunque lleva más tiempo ejecutarlo y es mucho menos eficiente. (¡Afortunadamente eso no es una preocupación en este contexto!)

También agrega "." a cada número para evitar realizar operaciones de redondeo entero como 6/4 = 1. Entonceseval es nuestra expresión y determina si el resultado es igual a lo que esperamos, y si es así, genera la expresión.

Este programa nunca se cierra; seguirá produciendo resultados continuamente hasta que se elimine.

EDITAR 1 : Eliminar nuevas líneas innecesarias donde ifse pueden usar declaraciones de una línea .

pescado de temporada
fuente
Realmente divertida implementación. pero fácil de guardar algunos bytes más ¡ Pruébelo en línea! (176 bytes)
bobrobbob
2

Matlab, 234 238 258 bytes

Supongo, basado en las limitaciones de las otras respuestas, que el orden de números de la matriz de entrada se mantiene mediante 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,[])'

Este código toma una cadena de números x, por ejemplo x = '12345'y un resultado r, dicen r = 15y regresa todas las cadenas de expresiones que puede evaluar para obtener ra partirx el uso de los cuatro operadores.

He usado dos formas diferentes de longitud equivalente para evitar el uso de expresiones ones(length())-type o repmat(length())-type: ~~p(1,:)que devuelve valores not-not en p(es decir, una lista de 1s de la misma longitud que la primera dimensión de p) y 0|p(:,1)que devuelve 0 o is-there -a-value-in p(es decir, una lista de 1s de la misma longitud que la segunda dimensión de p).

Matlab no tiene un método de nchoosek reemplazo , así que dupliqué a los operadores la cantidad correcta de veces, calculé todo el espacio nchoosekpara esa selección más grande de operadores y luego usé una uniquellamada para reducir el resultado a lo que debería ser (eliminando combinaciones equivalentes como '*** +' y '*** +'). Agrego un espacio final para que coincida con la longitud del vector de entrada con fines de concatenación y luego compongo las cadenas del operador con las cadenas de entrada en las columnas de una matriz. Luego evalúo las expresiones en columnas para obtener resultados y encontrar el orden de los operadores que corresponde a esas columnas con resultados que coinciden con nuestra entrada r.

Probar: x = '12345', r = 15:

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

Si tuviera que tomar una matriz de valores de doble precisión, necesitaría x = num2str(x,'%d');para convertir los dígitos en una cadena, agregando 21 (20 sin el ;) a mi puntaje. * Los bytes adicionales eran punto y coma que dejé simplemente para que cualquiera que ejecute este código no vea su símbolo del sistema explotar con matrices largas. Dado que mi edición produce una pila gigante de advertencias sobre lógicas y operandos de dos puntos de todos modos, he eliminado los puntos y comas en la nueva versión.

Edición 2: Olvidé reemplazar un 2*n+2con k.

Vieja respuesta:

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,[])'
sintax
fuente
2

JavaScript (ES6), 88 bytes

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

Lanzó un poco de aleatoriedad a la mezcla. Mucho más fácil que iterar sistemáticamente a través de las combinaciones.

Banco de pruebas

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))

Patrick Roberts
fuente
1

PHP, 108 bytes

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

toma la entrada de los argumentos de la línea de comando en orden inverso. Corre con -r.

Descompostura

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
fuente