Á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 + dá 5
  2. 5 6 + dá 11
  3. 4 U dá 16
  4. 12 16 + 28
  5. 11 28 +dá 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 U dá 400
  2. 400 30 + dá 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.