Portapapeles de funciones: copia

17

Este desafío está relacionado con algunas de las características del lenguaje MATL, como parte del evento Idioma del mes de mayo de 2018 . Desafío asociado : Portapapeles de funciones: pegar .


Introducción

MATL tiene varios portapapeles , donde puede almacenar valores (copiar) para recuperarlos más tarde (pegar). Algunos portapapeles son automáticos , lo que significa que la copia se activa automáticamente por ciertos eventos. Este desafío se centra en uno de los portapapeles automáticos, llamado portapapeles de entrada de funciones , o simplemente portapapeles de funciones .

Este portapapeles almacena las entradas a las cuatro llamadas más recientes a las funciones normales de toma de entrada. Las funciones normales son el tipo más común de funciones en MATL. La toma de entrada significa que la función toma al menos una entrada (las funciones que no toman ninguna entrada no son consideradas por el portapapeles de la función).

Esto se explica mejor con los siguientes ejemplos, que utilizan dos funciones normales:

  • +, que saca dos números de la pila y empuja su suma.
  • U, que muestra un número y empuja su cuadrado.

Ejemplo 1 :

3 2 + 6 + 12 4 U + +

produce el resultado 39. El código se interpreta de la siguiente manera:

  • Números literales como 3o 12ser empujado a la pila
  • Funciones como hacer +estallar sus entradas y empujar sus salidas a la pila.

Las llamadas a funciones, en orden cronológico, son:

  1. 3 2 + da 5
  2. 5 6 + da 11
  3. 4 U da 16
  4. 12 16 + 28
  5. 11 28 +da 39.

El portapapeles se puede ver como una lista de cuatro listas. Cada lista interna contiene las entradas a una llamada de función, con las llamadas más recientes primero . Dentro de cada lista interna, las entradas están en su orden original .

Entonces, después de ejecutar el código, el contenido del portapapeles es (en notación Python):

[[11, 28], [12, 16], [4], [5, 6]]

Ejemplo 2 :

10 20 U 30 +

deja números 10y 430en la pila. La pila se muestra de abajo hacia arriba al final del programa.

Las llamadas a funciones son

  1. 20 U da 400
  2. 400 30 + da 430

Como solo ha habido dos llamadas a funciones, algunas de las listas internas que definen el portapapeles estarán vacías . Tenga en cuenta también cómo 10no se utiliza como entrada para ninguna función.

Por lo tanto, el contenido del portapapeles después de ejecutar el código es:

[[400, 30], [20], [], []]

Ejemplo 3 (inválido):

10 20 + +

se considera inválido, porque +falta una entrada para el segundo (en MATL esto provocaría implícitamente la entrada del usuario).

El reto

Entrada : una cadena S con literales numéricos +y Useparados por espacios.

Salida : el contenido del portapapeles función después de la evaluación de la cadena S .

Aclaraciones:

  • Puede usar dos símbolos consistentes para representar esas funciones, que no sean dígitos. Además, puede usar cualquier símbolo consistente como separador, en lugar de espacio.
  • Solo se considerarán las dos funciones indicadas.
  • La cadena de entrada contendrá al menos un número literal y al menos una función.
  • Todos los números serán enteros positivos, posiblemente con más de un dígito.
  • Es posible que algunas funciones no utilicen algunos literales numéricos, como en el ejemplo 2.
  • Se garantiza que la entrada será un código válido, sin requerir números adicionales. Entonces, una cadena como en el ejemplo 3 nunca ocurrirá.
  • Se pueden omitir las listas internas vacías en la salida. Entonces el resultado en el ejemplo 2 puede ser[[400, 30], [20]]
  • Cualquier formato de salida razonable e inequívoco es aceptable. Por ejemplo, una cadena con una coma como separador interior y punto y coma como separador exterior: 400,30;20;;.

Reglas adicionales:

Casos de prueba

Input
Output

3 2 + 6 + 12 4 U + +
[[11, 28], [12, 16], [4], [5, 6]]

15 3 4 + 2 U 8 + U +
[[7, 144], [12], [4, 8], [2]]

3 6 9 12 + + 10 8 U 6
[[8], [6, 21], [9, 12], []]

8 41 12 25 4 5 33 7 9 10 + + + + + + + +
[[41, 105], [12, 93], [25, 68], [4, 64]]

10 1 1 + U U U U U
[[65536], [256], [16], [4]]
Luis Mendo
fuente
¿Es [[28, 11], [16, 12], [4], [6, 5]]una salida válida para el primer ejemplo?
ovs
@ovs No, las entradas dentro de cada lista interna deben estar en el orden original, es decir, como en la llamada a la función
Luis Mendo
Hm, ¿estamos desanimados de, eh, solo resolver esto en MATL? : P
Erik the Outgolfer
1
¿Es este portapapeles M?
Giuseppe
1
@Giussepe ¡Exactamente! No he mencionado ese nombre aquí porque no estamos usando la función M. Lo haré en el desafío de "pegar"
Luis Mendo

Respuestas:

3

05AB1E , 20 bytes

A"D¸ˆn‚DˆO"4ô‡.V¯R4£

Pruébalo en línea!

-4 gracias a Emigna (así como -8 gracias a él actualizándome sobre las reglas).

  • U: a
  • +: b
Erik el Outgolfer
fuente
44
:( ... ¿Por qué tan seRïõS?
Luis Mendo
@LuisMendo Este puntaje es tan seRïõSly £ arge. :(
Erik the Outgolfer
Continuemos esta discusión en el chat .
Erik the Outgolfer
5

Bash , 43 bytes

sed s/+/rdnFPrp+/g\;s/U/p2^/g|dc|tac|sed 4q

Pruébalo en línea!

Esto imprime el portapapeles en el siguiente formato, tenga en cuenta el uso de \ x0F como separador.

item_1\x0Fitem_2
item_3
.
.
item_m\x0Fitem_n

La idea clave es pasar esto a dc, un lenguaje basado en pila, de modo que se impriman los elementos de pila necesarios.

La entrada se canaliza a sed donde +se reemplaza cada uno rdnFPrp+, que en dc imprime el segundo número en la pila seguido de \ x0F y luego el número superior antes de realizar la suma. sed también reemplaza cada Ucon p2^, imprime el elemento de la pila superior y cuadrázalo.

El primer comando de sustitución sreemplaza a todos, como lo indica la bandera g lobal g, +s con rdnFPrp+. En DC, rintercambia los dos elementos superiores de la pila, dduplica el elemento superior, lo nimprime sin una nueva línea, Fempuja 15 en la pila y lo Pimprime como un personaje (que es el delimitador), rintercambia nuevamente, pimprime el elemento de la pila superior y luego +realiza Además en los dos primeros elementos de la pila.

Tenemos otro comando, y en sed, los comandos están separados por punto y coma o líneas nuevas, de las cuales se elige la primera opción. Simplemente tener ;hará que bash interprete eso como el final del comando sed, por lo que se escapa con a \.

En el último comando de sustitución, Use reemplaza globalmente con p2^. En dc, pimprime y lo 2^eleva a la segunda potencia.

El resultado de sed se evalúa como código dc, imprimiendo todo el portapapeles.

La canalización a dc hace que dc lo interprete como código dc. Ahora, las llamadas más recientes están en la parte inferior y las más antiguas en la parte superior.

Como las líneas están en orden inverso, se usa tac(reverso cat) para arreglar eso.

Y finalmente, sed recoge las primeras 4 líneas de tac.

Esta es una forma más corta de hacerlo head -4. sed ejecuta los comandos en cada línea de la entrada de uno en uno. Si no hay comandos, no se hace nada en la entrada y se devuelve como está. 4qle dice a sed que ejecute el comando qen la línea 4. Cuando sed está procesando la línea 4 de la entrada, las primeras tres entradas ya se han impreso. El comando qcierra el programa, por lo que imprime la cuarta línea y se cierra, realizando así el equivalente de head -4.

Kritixi Lithos
fuente
4

Python 2 , 126 bytes

s=[0];b=[]
for c in input().split():k='U+'.find(c)+1;b=[s[k-1::-1]][:k]+b;s=[int([c,s[0]**2,sum(s[:2])][k])]+s[k:]
print b[:4]

Pruébalo en línea!

ovs
fuente
4

Haskell , 113 109 bytes

take 4.([]#).words
x:y:s#"+":r=(x+y:s#r)++[[y,x]]
x:s#"U":r=(x*x:s#r)++[[x]]
s#n:r=read n:s#r
_#_=[]
infix 4#

La primera línea define una función anónima que toma una cadena, por ejemplo "3 2 + 6 + 12 4 U + +", y devuelve una lista de listas de INT: [[11,28],[12,16],[4],[5,6]]. Pruébalo en línea!

Laikoni
fuente
2

Limpio , 140 bytes

import StdEnv,Text
k[a,b:n]["+":s]=k[a+b:n]s++[[b,a]]
k[a:n]["U":s]=k[a^2:n]s++[[a]]
k n[v:s]=k[toInt v:n]s
k _[]=[]
$s=k[](split" "s)%(0,3)

Pruébalo en línea!

En el estilo clásico limpio, es la solución de Haskell, excepto aproximadamente un 50% más.

Οurous
fuente
2

JavaScript (ES6), 107 bytes

Toma la entrada como una lista que consta de enteros '+'y 'U'. Devuelve otra lista que consta de enteros, matrices de 2 enteros y '_'para ranuras vacías.

a=>a.map(x=>s.push(+x?x:(c=[x>[a=s.pop(),r=a*a]?a:[r=s.pop(),(r+=a,a)],...c],r)),s=[c='___'])&&c.slice(0,4)

Pruébalo en línea!

Comentado

a =>                          // a[] = input array
  a.map(x =>                  // for each entry x in a[]:
    s.push(                   //   update the stack:
      +x ?                    //     if x is a positive integer:
        x                     //       push x onto the stack
      :                       //     else:
        ( c = [               //       update the clipboard:
            x > [             //         compare x with '['
              a = s.pop(),    //         a = first operand
              r = a * a       //         use a² as the default result
            ] ?               //         if x is 'U' (greater than '['):
              a               //           save the 1st operand in the clipboard
            :                 //         else:
              [ r = s.pop(),  //           r = 2nd operand
                (r += a, a)   //           add the 1st operand
              ],              //           save both operands in the clipboard
            ...c              //         append the previous clipboard entries
          ],                  //       end of clipboard update
          r                   //       push r onto the stack
        )                     //
    ),                        //     end of stack update
    s = [c = '___']           //   initialize the stack; start with c = '___'
  ) &&                        // end of map()
  c.slice(0, 4)               // return the last 4 entries of the clipboard
Arnauld
fuente
2

Go, 305 303 295 bytes

Se descartaron 8 bytes gracias a @ovs

func e(s string){b,v,w,x,r:=[][]int{{},{},{},{}},[]int{},0,0,0;for _,d:=range Split(s," "){if d=="+"{w,x,v=v[0],v[1],v[2:];r=w+x;b=append([][]int{[]int{x,w}},b...)}else if d=="U"{w,v=v[0],v[1:];r=w*w;b=append([][]int{[]int{w}},b...)}else{n,_:=Atoi(d);r=n};v=append([]int{r},v...)};Print(b[0:4])}

Pruébalo en línea!

ollien
fuente
2

Octava , 206 bytes

s=strsplit(input(''));m=t=[];for z=s
if(q=str2num(p=z{1}))t=[t q];else
if(p-43)m{end+1}=(k=t(end));t(end)=k^2;else
m{end+1}=(k=t(end-1:end));t(end-1:end)=[];t(end+1)=sum(k);end
end
end
m(1:end-4)=[];flip(m)

Pruébalo en línea!

Si tan solo Octave tuviera una popsintaxis. mes el portapapeles de memoria, tla pila.

Sanchises
fuente
¿podrías construir my, ta la inversa, agregar elementos al frente en lugar del final?
Giuseppe
178 bytes utilizando la estrategia descrita anteriormente
Giuseppe
@Guiseppe Clever. Siempre tengo la sensación de que agregar es generalmente más corto que preponer, pero en este caso la gran cantidad de "finales" debería haberme hecho reconsiderar
Sanchises
1

Python 3 , 218204 bytes

-14 bytes gracias a los ovs

from collections import*
def f(s):
	a=deque(maxlen=4);z=a.appendleft;b=[];x=b.pop
	for i in s.split():
		if'+'==i:c=x(),x();z(c);r=sum(c)
		elif'U'==i:c=x();z(c);r=c*c
		else:r=int(i)
		b+=r,
	print([*a])

Pruébalo en línea!

Draconis
fuente
1

Rojo , 335 330 bytes

func[s][b: copy[]foreach c split s" "[append b either c >"+"and(c <"U")[do c][c]]r: copy[]until[t: 0 until[not parse
b[to copy c[2 integer!"+"](insert/only r reduce[c/1 c/2]replace b c c/1 + c/2 t: 1)to end]]until[not parse b[to copy
c[integer!"U"](insert/only r to-block c/1 replace b c c/1 ** 2 t: 1)to end]]t = 0]take/part r 4]

Pruébalo en línea!

Más legible:

f: func[s] [
    s: split s " "
    b: copy []
    foreach c s [
        append b either (c > "+") and (c < "U")[do c] [c]
    ]
    r: copy []
    until [
        t: 0
        until [
            not parse b [to copy c[2 integer! "+"]
            (insert/only r reduce[c/1 c/2]
            replace b c c/1 + c/2
            t: 1)
            to end]
        ]
        until [
            not parse b [to copy c[integer! "U"]
            (insert/only r to-block c/1
            replace b c c/1 ** 2
            t: 1)
            to end]
        ]
        t = 0
    ]
    take/part r 4  
]
Galen Ivanov
fuente
1

R , 205 182 bytes

function(P){S=F
M=list()
for(K in el(strsplit(P," "))){if(is.na(x<-strtoi(K))){if(K>1){M=c(m<-S[1],M)
S[1]=m^2}else{M=c(list(m<-S[2:1]),M)
S=c(sum(m),S[-2:0])}}else S=c(x,S)}
M[1:4]}

Pruébalo en línea!

Mes el portapapeles de memoria, Pes el programa y Ses la pila.

Técnicamente Sse inicializa como un vector que contiene un solo cero, pero como nunca obtenemos una entrada no válida, me ahorra un byte S={}.

Giuseppe
fuente
1

C (gcc) , 264 bytes

Utilicé la recursión para poder usar la pila de funciones como la pila de datos: se recorre la lista de entrada y se realizan las operaciones: los resultados se muestran en orden inverso, sin mostrar los empujes de la pila.

La pila se implementa como una lista vinculada. Así es como funciona:

  • El nodo actual se configura con [puntero al valor, puntero al nodo anterior]
  • Para empujar un valor, se almacena y se llama nuevamente a la función con el nodo actual.
  • Para hacer estallar un valor o modificar el valor en la parte superior de la pila, se modifica el valor de un nodo anterior y se llama nuevamente a la función con el nodo anterior.

Originalmente usé una estructura para los nodos, pero cambié a punteros desnudos para ahorrar espacio. Una característica interesante de esta lista vinculada es que se limpia cuando se completa la recursividad.

#define _ printf
f(char**s,int**p){int**w,v,*y[]={&v,p},m,n,t,z;w=y;z=1;return(*s?(**s-85?**s-43?(--z,t=14,v=atoi(*s)):(t=6,w=p[1],m=**w,**w+=n=**p):(t=0,w=p,**w*=m=**p),v=f(s+1,w),_(v<4?",[%d]\0,[%d,%d]\0"+t+!v:"",m,n),v+z):0);}g(char**s){_("[");f(s,0);_("]\n");}

Pruébalo en línea!

ErikF
fuente