Convertir una matriz en un problema matemático


35

Dada una lista no vacía de enteros no negativos, considere reescribirlo como un problema aritmético donde:

  • Se +inserta un signo más ( ) entre pares de números que aumentan de izquierda a derecha (también conocido desde el principio de la lista hasta el final).
  • Se -inserta un signo menos ( ) entre pares de números que disminuyen de izquierda a derecha.
  • Se *inserta un signo de multiplicación ( ) entre pares de números que son iguales.

Dicho de otra manera: cualquier sublista se a,bconvierte en a+bif a<b, a-bif a>by a*bif a==b.

Por ejemplo, la lista

[12, 0, 7, 7, 29, 10, 2, 2, 1]

se convertiría en la expresión

12 - 0 + 7*7 + 29 - 10 - 2*2 - 1

que evalúa a 75 .

Escriba un programa o función que tome esa lista y la evalúe, imprimiendo o devolviendo el resultado.

  • El orden de las operaciones importa. Las multiplicaciones deben hacerse antes de cualquier suma o resta.
  • Si la lista de entrada tiene un número, eso debería ser lo que evalúa. Por ejemplo, [64]debería dar 64.
  • El uso de evalo execse permite o similares constructos.

Aquí hay algunos ejemplos adicionales:

[list]
expression
value

[0]
0
0

[1]
1
1

[78557] 
78557
78557

[0,0]
0*0
0

[1,1]
1*1
1

[2,2]
2*2
4

[0,1]
0+1
1

[1,0]
1-0
1

[1,2]
1+2
3

[2,1]
2-1
1

[15,4,4]
15-4*4
-1

[9,8,1]
9-8-1
0

[4,2,2,4]
4-2*2+4
4

[10,9,9,12]
10-9*9+12
-59

[1,1,2,2,3,3]
1*1+2*2+3*3
14

[5,5,4,4,3,3]
5*5-4*4-3*3
0

[3,1,4,1,5,9,2,6,5,3,5,9]
3-1+4-1+5+9-2+6-5-3+5+9
29

[7637,388,389,388,387,12,0,0,34,35,35,27,27,2]
7637-388+389-388-387-12-0*0+34+35*35-27*27-2
7379

El código más corto en bytes gana. Tiebreaker es la respuesta anterior.


55
Con respecto al "orden de las operaciones importa", podría ser bueno establecer explícitamente que la suma y la resta son asociativas a la izquierda y tienen la misma precedencia.
Martin Ender

Respuestas:


15

Python 2, 63 bytes

p=s='print-'
for x in input():s+='*+-'[cmp(x,p)]+`x`;p=x
exec s

Construye y evals la cadena de expresión. El símbolo aritmético se elige comparando el número anterior pcon el actual x. El símbolo se agrega seguido del número actual.

El primer número se maneja con un ingenioso truco de Sp3000. El valor inicial de pse establece en una cadena, que es más grande que cualquier número y, por lo tanto, causa un -antes del primer número. Pero, sse inicializa al print-mismo tiempo que hace que el resultado comience con print--(gracias a xsot por guardar 2 bytes al inicializar con print).


Creo que puedes pasar printa la cadena y usar en execlugar de eval.
xsot

13

Pyth, 31 26 19 17 16 15 bytes

Las expresiones con *no se evaluarán en línea, pero teóricamente funcionarían.

2 bytes gracias a Maltysen.

vsm+@"*-+"._-~k

Conjunto de pruebas (con evaluación).

Los otros casos (sin evaluación).

Historia

  • 31 bytes: M+G@"*-+"->GH<GHv+sgMC,JsMQtJ\x60e
  • 26 bytes: M+G@"*-+"->GH<GHv+sgVQtQ\x60e
  • 19 bytes: vtssVm@"*-+"->Zd<~Z
  • 17 bytes: vtssVm@"*-+"._-~Z
  • 16 bytes: vssVm@"*-+"._-~k
  • 15 bytes: vsm+@"*-+"._-~k

¿Por qué la multiplicación no funciona en línea? Si no está seguro de que funciona, puede ser mejor probar un poco más antes de responder.
Aficiones de Calvin

Porque las cosas de seguridad (la evaluación solo funciona para +y en -línea)
Leaky Nun

@HelkaHomba Todavía no tuve la oportunidad de probarlo sin conexión, pero debería funcionar. El intérprete en línea usa el --safeinterruptor, que reemplaza evalcon ast.literal_eval.
Dennis

OK bastante justo.
Hobbies de Calvin

Confirmado, esto funciona con el intérprete fuera de línea.
Dennis

12

Jalea , 18 16 15 14 bytes

I0;ð1g×⁹⁸œṗP€S

No utiliza evaluaciones integradas. Pruébalo en línea! o verificar todos los casos de prueba .

Cómo funciona

I0;ð1g×⁹⁸œṗP€S  Main link. Input: A (list)

I               Increments; compute the deltas of all adjacent items of A.
 0;             Prepend a 0.
   ð            Begin a new, dyadic chain.
                Left argument: D (0 plus deltas). Right argument: A
    1g          Compute the GCD of 1 and each item in D.
                This yields 1 for non-negative items, -1 for negative ones.
      ×⁹        Multiply each 1 or -1 with the corresponding item of A.
                This negates every item in A that follows a - sign.
        ⁸œṗ     Partition the result by D. This splits at occurrences of non-zero
                values of D, grouping items with identical absolute value.
           P€   Take the product of each group.
             S  Sum; add the results.


1
Bien hecho. Debo agregar a Python evalcomo un átomo ...
Dennis

99
Te supere en golf. : P
Dennis

Bien hecho, ¡te toca a ti!
Leaky Nun

9

MATL , 12 bytes

Y'^l6MdZSh*s

Esto utiliza la muy buena idea de @ aditsu de codificación de longitud de ejecución.

Pruébalo en línea!

Explicación

       % Take input vector implicitly
Y'     % RLE. Produces two vectors: values and lengths
^      % Rise each value to the number of consecutive times it appears. This
       % realizes the product of consecutive equal values
l      % Push 1
6M     % Push vector of values again
d      % Consecutive differences
ZS     % Sign function. Gives 1 or -1 (no 0 in this case)
h      % Concatenate horizontally with previous 1
*      % Multiply. This gives plus or minus depending on increasing character
s      % Sum of vector. This realizes the additions or subtractions
       % Display implicitly

Jaja acababa de escribir algo similar. RLE funciona bien para esto
Suever

@Suever veo :-D
Luis Mendo

7

CJam, 20

q~e`{~_W-g\:W@#*}%:+

Pruébalo en línea

Explicación:

q~       read and evaluate the input (array of numbers)
e`       RLE encode, obtaining [count number] pairs
{…}%     map each pair
  ~_     dump the count and number on the stack, and duplicate the number
  W-     subtract the previous number (W is initially -1 by default)
  g      get the sign of the result
  \      swap with the other copy of the number
  :W     store it in W (for next iteration)
  @#     bring the count to the top, and raise the number to that power
  *      multiply with the sign
:+       add all the results together

7

JavaScript (ES6), 54

p=>eval(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

eval recibe una lista de expresiones separadas por comas y devuelve el valor de la última.

Prueba

f=p=>eval(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

t=p=>(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

function Test() {
  var a=I.value.match(/\d+/g).map(x=>+x) // convert input to a numeric array
  
  var x=f(a),y=t(a)
  O.textContent='Value '+x+'\n(no eval '+y+')'
}  

Test()
#I { width:80%}
<input value='12, 0, 7, 7, 29, 10, 2, 2, 1' id=I>
<button onclick='Test()'>Test</button>
<pre id=O></pre>


44
Ese es el peor abuso del operador de coma que recuerdo haber visto en este sitio ...
Neil



3

R, 92 bytes

Es probable que todavía se pueda hacer un buen golf aquí.

eval(parse(t=paste(i<-scan(),c(ifelse(d<-diff(i),ifelse(d>0,"+","-"),"*"),""),collapse="")))

Sin golf:

i = scan()                # Read list from stdin
d = diff(i)               # Calculate difference between each element of list
s = ifelse(d,             # If d!=0
             ifelse(d>0,  # And if d>1
                    "+",  # Return plus
                    "-"), # Else return minus
             "*")         # Else (i.e. d==0) return multiply.
s = c(s,"")               # Pad the list s with an empty string, so it's the same
                          # length as i
p = paste(i,s,collapse="")# Paste the elements of i and s into one long string.
eval(parse(t=p))          # Evaluate the string as a language object.



2

TI-BASIC, 146 bytes

Lo formatearé bien cuando no esté en el móvil. El sueño se me escapa, así que entiendes esto. Disfrutar.

Prompt L₁
"(→Str1
For(A,1,dim(L₁
{0,1→L₂
{0,L₁(A→L₃
LinReg(ax+b) L₁,L₃,Y₁
Equ►String(Y₁,Str2
sub(Str2,1,-1+inString(Str2,"X→Str2
If A>1
Then
L₁(A-1
2+(Ans>L₁(A))-(Ans<L₁(A
Str1+sub("+*-",Ans,1→Str1
End
Str1+Str2→Str2
End
expr(Str1

2

Javascript ES6, 64 62 caracteres

a=>eval(a.map((x,i)=>x+('*+-'[x<a[++i]|(x>a[i])*2])).join``+1)

3
¿No debería ser esto una función y aun parámetro?
edc65

Esto no es válido tal cual.
Rɪᴋᴇʀ

@ edc65, sí, debería. Pero, de hecho, se contó (61 especificado, pero la longitud del código real era 59), simplemente copié mal un nuevo código (la edición debería ser a[i+1]...a[i+1]=> a[++i]...a[i]- 2 caracteres más cortos, pero reemplacé por error la caída completa del código a=>).
Qwertiy

@ EᴀsᴛᴇʀʟʏIʀᴋ, es solo una pasta incorrecta. Vea el comentario arriba y edite el historial para más detalles.
Qwertiy

@Qwertiy está bien, genial. Buena respuesta por cierto ..
Rɪᴋᴇʀ

1

Java, 384 bytes

int s(int[]l){int n=l[0],m;for(int i=0;i<l.length-1;i++)if(l[i]<l[i+1])if(i<l.length-2&&l[i+1]!=l[i+2])n+=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n+=m;}else if(l[i]>l[i+1])if(i<l.length-2&&l[i+1]!=l[i+2])n-=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n-=m;}else{m=l[i];while(i<l.length-1&&l[i]==l[i+1])m*=l[i++];n+=m;}return n;}

Intente sin golf en línea

int s(int[] l)
{
    int n=l[0], m;

    for(int i=0; i<l.length-1; i++)
    {
        if(l[i] < l[i+1])
        {
            if (i<l.length-2 && l[i+1]!=l[i+2])
            {
                n += l[i+1];
            }
            else
            {
                m = l[i+1];
                while(i<l.length-2 && l[i+1]==l[i+2]) m *= l[(i++)+1];
                n += m;
            }
        }
        else if(l[i] > l[i+1])
        {
            if (i<l.length-2 && l[i+1]!=l[i+2])
            {
                n -= l[i+1];
            }
            else
            {
                m = l[i+1];
                while(i<l.length-2 && l[i+1]==l[i+2]) m *= l[(i++)+1];
                n -= m;
            }
        }
        else
        {
            m = l[i];
            while(i<l.length-1 && l[i]==l[i+1]) m *= l[i++];
            n += m;
        }
    }

    return n;
}

1
Algunos campos de golf rápidas: int a=l.length, &&=> &, poner el int i=0en la misma "línea" como int n=l[0],m.
Leaky Nun

En if(i<l.length-2&&l[i+1]!=l[i+2])n+=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n+=m;, puede reemplazar esto con el contenido dentro del elsebloque.
Leaky Nun

1

Javascript ES6, 79 caracteres

a=>eval(`${a}`.replace(/(\d+),(?=(\d+))/g,(m,a,b)=>a+('*+-'[+a<+b|(+a>+b)*2])))

1

Perl, 49 bytes

48 bytes código + 1 para -p

s/\d+ (?=(\d+))/$&.qw(* - +)[$&<=>$1]/ge;$_=eval

Uso

perl -pe 's/\d+ (?=(\d+))/$&.qw(* - +)[$&<=>$1]/ge;$_=eval' <<< '12 0 7 7 29 10 2 2 1'
75

Notas

Aprendí aquí que puedes capturar un lookahead en PCRE, aunque es un poco intuitivo (en (?=(\d+))lugar de ((?=\d+))). Sin embargo, tiene sentido después de leer, ya que capturaría una coincidencia de longitud cero (la búsqueda anticipada) con la última, y ​​en su lugar capturará la coincidencia con la primera).

¡Gracias a @ninjalj por guardar 8 bytes!


@LeakyNun Nunca sé exactamente qué contar para eso, no puedo encontrar la meta publicación relevante, estoy feliz de aumentar el conteo, pero pensé que, dado que puedes correr -egratis, agregué un resultado pque -pefue +1 ? Se actualizará por ahora, pero si pudieras encontrar una fuente que pudiera citar / vincular para seguir adelante, ¡sería increíble!
Dom Hastings

3
@DomHastings 1 es correcto, por la razón que dices + esta meta publicación
Sp3000

Gracias @ Sp3000! ¡No pude encontrar esa publicación por mi vida! @LeakyNun meta publicación para +1 según el comentario de Sp3000
Dom Hastings

En lugar de usar operadores condicionales encadenados, puede usar el operador de nave espacial para seleccionar de una lista: $&.qw(* - +)[$&<=>$1]en la parte de reemplazo del s///operador.
ninjalj

@ninjalj ¡Por supuesto! increíble, gracias! -8 con eso!
Dom Hastings

1

En realidad, 30 bytes

;2@VpXdX`i-su"+*-"E`M' @o♀+εj≡

Desafortunadamente, porque el eval ( comando ) solo evalúa literales en TIO, este programa no funciona en TIO.

Explicación:

;2@VpXdX`i-su"+*-"E`M' @o♀+εj≡
;                               duplicate input
 2@V                            overlapping sublists of length <= 2
    pXdX                        discard first and last element (length-1 sublists)
        `i-su"+*-"E`M           map: for each pair of elements
         i-su                     flatten, subtract, sign, increment (results in a 0 if b < a, 1 if b == a, and 2 if b > a)
             "+*-"E               select the correct operation
                     ' @o       put a space at the beginning of the list to pad it properly
                         ♀+     pairwise addition (since addition is not defined for strings and integers, this just zips the lists and flattens the result into a single flat list)
                           εj   join with empty string
                             ≡  eval

1

R , 120 44 bytes

r=rle(scan());c(1,sign(diff(r$v)))%*%r$v^r$l

Pruébalo en línea!

El algoritmo es similar a esta respuesta , pero solo me di cuenta después de codificar mi respuesta. Mucho mejor que mi respuesta original que estaba usandoeval(parse) .

Aprovecha al máximo las operaciones vectorizadas de R: *primero realiza la operación rle(x)$values ^ rle(x)$lenghtsy utiliza productos de punto con este vector sign( diff( rle(x)$values ) )(precedido por 1).


1

05AB1E (heredado) , 17 16 15 bytes

ü.S…*-+sè‚ζJJ.E

-2 bytes gracias a @Emigna .

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

ü                  # Pair-wise loop over the (implicit) input-list
                   #  i.e. [12,0,7,7] → [[12,0],[0,7],[7,7]]
 .S                # Calculate the signum of the pair (-1 for a<b; 0 for a==b; 1 for a>b)
                   #  i.e. [[12,0],[0,7],[7,7]] → [1,-1,0]
   …*-+sè          # Index over "*-+" (with wrap-around)
                   #  i.e. [1,-1,0] → ['-','+','*']
         ‚ζ        # Zip the two lists together (appending the operands to the numbers)
                   #  i.e. [12,0,7,7] and ['-','+','*','+']
                   #   → [[12,'-'],[0,'+'],[7,'*'],[7,' ']]
           JJ      # Join them together
                   #  [[12,'-'],[0,'+'],[7,'*'],[7,' ']] → '12-0+7*7 '
             .E    # Evaluate as Python code
                   #  i.e. '12-0+7*7' → 61

1
Debido a la indexación modular, puede eliminar >moviéndose +al final de la cadena.
Emigna

@Emigna No estoy seguro de cómo me perdí eso ... ¡Gracias!
Kevin Cruijssen

1
Puede guardar otro byte eliminando Ćy ¨, si lo usa en ‚ζlugar deø
Emigna

@Emigna ¡Oh, eso es inteligente! Gracias. Sabía que el recinto era un poco extraño, pero no sabía cómo solucionarlo. ‚ζes una alternativa perfecta, ya que el espacio se ignora en la evaluación. Gracias de nuevo. :)
Kevin Cruijssen

0

PHP, 103 bytes

Buen desafío. Esto se hizo más largo de lo esperado. Creo que usandoarray_map o similar no mejorará el recuento de bytes, ya que las funciones anónimas siguen siendo caras en PHP.

foreach(fgetcsv(STDIN)as$v)(0<=$p?$o.=$p.('*-+'[($p>$v)+2*($p<$v)]):_)&&$p=$v;echo eval("return$o$v;");

Se ejecuta desde la línea de comandos, solicitará una lista separada por comas, como:

php array_to_math.php
12, 0, 7, 7, 29, 10, 2, 2, 1

0

PowerShell v2 +, 62 bytes

-join($args|%{"$o"+'*+-'[($o-lt$_)+2*($o-gt$_)];$o=$_})+$o|iex

Toma datos como argumentos de línea de comandos separados por espacios, que se convierten en una matriz automática $args. Realizamos iteraciones a través de cada elemento, utilizando la variable auxiliar $ocada iteración para recordar cuál fue nuestra entrada anterior. Usamos una cadena indexada para extraer el operador apropiado, que se realiza mediante la matemática de los valores booleanos convertidos implícitamente (p. Ej., Si la entrada anterior es más pequeña, la []evaluación 1+2*0también '*+-'[1]significa que+ está seleccionada).

Las cadenas concatenadas se dejan en la tubería. Recopilamos todos esos fragmentos entre sí (por ejemplo, 3-, 1+, 4-, etc.) con una -joinoperación de concatenación del número final (implícitamente convertido en cadena), y el tubo de TI iex(alias para Invoke-Expressiony similares a eval).


Una preocupación es que si la persona que llama ya ha dado el valor $ oa (digamos $ o = 999), la expresión en esta entrada no calculará el valor correcto. Es necesario agregar una inicialización de $ o a esta solución.
Bevo

@Bevo Esto está destinado a ser un script completo, ejecutado a través de la línea de comando, y no una función o a través del shell interactivo. La gran mayoría de mis presentaciones son como tales, ya que en tal escenario, no hay variables predefinidas de las que preocuparse y, por lo tanto, el código puede ser un poco más corto.
AdmBorkBork


0

Japt -x , 21 19 bytes

änJ f mÎí*Uò¦ ®ÎpZÊ

Intentalo


Explicación

                        :Implicit input of array U
  J                     :Prepend -1
än                      :Get deltas
    f                   :Filter (remove 0s)
      m                 :Map
       Î                : Signs
        í               :Interleave
          U             :  Original input
           ò            :  Partition on
            ¦           :   Inequality
              ®         :  Map each sub-array Z
               Î        :    Get first element
                p       :    Raise to the power of
                 ZÊ     :     Length of Z
         *              :Reduce each pair of elements by multiplcation
                        :Implicitly reduce by addition and output
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.