Área de transferência de funções: cópia


17

Esse desafio está relacionado a alguns dos recursos da linguagem MATL, como parte do evento de linguagem do mês de maio de 2018 . Desafio associado : Área de transferência de funções: colar .


Introdução

O MATL possui várias pranchetas , nas quais é possível armazenar valores (cópia) para serem recuperados posteriormente (colar). Algumas áreas de transferência são automáticas , o que significa que a cópia é automaticamente acionada por determinados eventos. Esse desafio se concentra em uma das pranchetas automáticas, denominada área de transferência de entrada de função ou simplesmente área de transferência de função .

Essa área de transferência armazena as entradas nas quatro chamadas mais recentes para as funções normais de captação de entradas. Funções normais são o tipo mais comum de funções no MATL. Entrada de entrada significa que a função recebe pelo menos uma entrada (funções que não recebem entrada não são consideradas pela área de transferência da função).

Isso é melhor explicado com os seguintes exemplos, que usam duas funções normais:

  • +, que exibe dois números da pilha e aumenta sua soma.
  • U, que exibe um número e empurra seu quadrado.

Exemplo 1 :

3 2 + 6 + 12 4 U + +

produz o resultado 39. O código é interpretado da seguinte maneira:

  • Literais numéricos como 3ou 12são empurrados para a pilha
  • Funções como +acionar suas entradas e enviar suas saídas para a pilha.

As chamadas de função, em ordem cronológica, são:

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

A área de transferência pode ser vista como uma lista de quatro listas. Cada lista interna contém as entradas para uma chamada de função, com as chamadas mais recentes primeiro . Dentro de cada lista interna, as entradas estão em sua ordem original .

Então, depois de executar o código, o conteúdo da área de transferência é (em notação Python):

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

Exemplo 2 :

10 20 U 30 +

deixa números 10e 430na pilha. A pilha é exibida de baixo para cima no final do programa.

As chamadas de função são

  1. 20 U400
  2. 400 30 +430

Como houve apenas duas chamadas de função, algumas das listas internas que definem a área de transferência estarão vazias . Observe também como 10não é usado como entrada para nenhuma função.

Assim, o conteúdo da área de transferência após a execução do código é:

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

Exemplo 3 (inválido):

10 20 + +

é considerado inválido, porque +falta uma entrada para a segunda (em MATL, isso implicitamente acionaria a entrada do usuário).

O desafio

Entrada : uma sequência S com números literais +e Useparados por espaços.

Saída : o conteúdo da área de transferência função após analisar a string S .

Esclarecimentos:

  • Você pode usar quaisquer dois símbolos consistentes para representar essas funções, exceto dígitos. Além disso, você pode usar qualquer símbolo consistente como separador, em vez de espaço.
  • Somente as duas funções indicadas serão consideradas.
  • A sequência de entrada conterá pelo menos um número literal e pelo menos uma função.
  • Todos os números serão inteiros positivos, possivelmente com mais de um dígito.
  • É possível que alguns literais numéricos não sejam utilizados por nenhuma função, como no exemplo 2.
  • A entrada é garantida como um código válido, sem a necessidade de números adicionais. Portanto, uma string como no exemplo 3 nunca ocorrerá.
  • O rastreamento de listas internas vazias na saída pode ser omitido. Portanto, o resultado no exemplo 2 pode ser[[400, 30], [20]]
  • Qualquer formato de saída razoável e inequívoco é aceitável. Por exemplo, uma cadeia com vírgula como separador interno e vírgula como separador exterior: 400,30;20;;.

Regras adicionais:

Casos de teste

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

A [[28, 11], [16, 12], [4], [6, 5]]saída é válida para o primeiro exemplo?
ovs 13/05/19

@ovs Não, entradas de cada lista interna deve ser da ordem original, isto é, como na chamada de função
Luis Mendo

Hum, estamos desencorajados de, eh, apenas resolver isso no MATL? : P
Erik the Outgolfer

1
Esta prancheta M?
Giuseppe

1
@Giussepe Exactly! Eu não mencionei esse nome aqui porque não estamos usando a função M. Farei isso no desafio "colar"
Luis Mendo

Respostas:



5

Bash , 43 bytes

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

Experimente online!

Isso imprime a área de transferência no seguinte formato, observe o uso de \ x0F como separador.

item_1\x0Fitem_2
item_3
.
.
item_m\x0Fitem_n

A idéia principal é passar isso para dc, um idioma baseado em pilha, de forma que os itens de pilha necessários sejam impressos.

A entrada é canalizada para sed, onde todos +são substituídos rdnFPrp+, o que em dc imprime o segundo número na pilha, seguido por \ x0F e, em seguida, o número superior antes de realizar a adição. sed também substitui todos Ucom p2^, imprimir o elemento superior da pilha e quadrado dele.

O primeiro comando de substituição ssubstitui todos, como é indicado por o g bandeira lobal g, +s com rdnFPrp+. Em dc, ralterna os dois itens principais da pilha, dduplica o item superior, nimprime-o sem uma nova linha, Fcoloca 15 na pilha e Pimprime-o como um caractere (que é o delimitador), ralterna novamente, pimprime o item da pilha superior e +executa adição nos dois itens principais da pilha.

Temos outro comando e, no sed, os comandos são separados por ponto-e-vírgula ou novas linhas, das quais a primeira opção é escolhida. Simplesmente ter ;fará com que o bash interprete isso como o fim do comando sed, portanto ele é escapado com a \.

No último comando de substituição, Ué substituído globalmente por p2^. Em dc, pimprime e 2^aumenta para a segunda potência.

O resultado do sed é avaliado como código dc, imprimindo a área de transferência inteira.

O canal para dc faz com que dc interprete isso como código dc. Agora, as chamadas mais recentes estão na parte inferior e as mais antigas na parte superior.

Como as linhas estão na ordem inversa, tac(reversa cat) é usada para corrigir isso.

E, finalmente, o sed escolhe as 4 primeiras linhas do tac.

Esta é uma maneira mais curta de fazer head -4. sed executa os comandos para cada linha da entrada, uma de cada vez. Se não houver comandos, nada será feito na entrada e ela será retornada como está. 4qdiz ao sed para executar o comando qna linha 4. Quando o sed está processando a linha 4 da entrada, as três primeiras entradas já foram impressas. O comando qsai do programa, imprime a quarta linha e sai, executando o equivalente a head -4.


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]

Experimente online!


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#

A primeira linha define uma função anônima que leva uma corda, por exemplo "3 2 + 6 + 12 4 U + +", e retorna uma lista de listas de ints: [[11,28],[12,16],[4],[5,6]]. Experimente online!


2

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

Experimente online!

No estilo Clean clássico, é a solução Haskell, exceto cerca de 50% a mais.


2

JavaScript (ES6), 107 bytes

Recebe a entrada como uma lista composta por números inteiros '+'e 'U'. Retorna outra lista que consiste em números inteiros, matrizes de 2 números inteiros e '_'para slots vazios.

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)

Experimente online!

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

2

Go, 305 303 295 bytes

Foram eliminados 8 bytes graças 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])}

Experimente online!


2

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

Experimente online!

Se apenas o Octave tivesse uma popsintaxe. mé a área de transferência da memória, ta pilha.


você poderia construir me tao contrário, adicionando elementos à frente e não ao fim?
Giuseppe

178 bytes usando a estratégia descrita acima
Giuseppe

@Guiseppe Clever. Eu sempre tenho essa sensação de que anexando é geralmente mais curto do que prepending mas neste caso o grande número de s "fim" deveria ter me fez reconsiderar
Sanchises

1

Python 3 , 218 204 bytes

-14 bytes graças a 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])

Experimente online!


1

Vermelho , 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]

Experimente online!

Mais legível:

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  
]

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

Experimente online!

Mé a área de transferência da memória, Pé o programa e Sé a pilha.

Tecnicamente, Sé inicializado como um vetor que contém um único zero, mas como nunca recebemos uma entrada inválida, ele me salva um byte de S={}.


1

C (gcc) , 264 bytes

Usei a recursão para poder usar a pilha de funções como a pilha de dados: a lista de entrada é percorrida e as operações são executadas: os resultados são exibidos em ordem inversa, com os impulsos de pilha não exibidos.

A pilha é implementada como uma lista vinculada. Veja como funciona:

  • O nó atual é configurado com [ponteiro para valor, ponteiro para o nó anterior]
  • Para empurrar um valor, ele é armazenado e a função é chamada novamente com o nó atual.
  • Para exibir um valor ou modificar o valor na parte superior da pilha, o valor de um nó anterior é modificado e a função é chamada novamente com o nó anterior.

Originalmente, usei uma estrutura para os nós, mas mudei para ponteiros simples para economizar espaço. Um recurso interessante dessa lista vinculada é que ela se limpa quando a recursão é concluída.

#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");}

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.