Appunti di funzione: copia


17

Questa sfida è legata ad alcune delle funzionalità del linguaggio MATL, nell'ambito dell'evento Lingua del mese di maggio 2018 . Sfida associata : Appunti di funzione: incolla .


introduzione

MATL ha diversi appunti , in cui è possibile memorizzare valori (copia) da recuperare in seguito (incolla). Alcuni appunti sono automatici , il che significa che la copia viene automaticamente attivata da determinati eventi. Questa sfida si concentra su uno degli appunti automatici, chiamati appunti di input di funzioni , o semplicemente appunti di funzioni .

Questo appunti memorizza gli input delle quattro chiamate più recenti in normali funzioni di input-input. Le funzioni normali sono il tipo più comune di funzioni in MATL. Input-taking significa che la funzione accetta almeno un input (le funzioni che non accettano alcun input non sono considerate dagli appunti della funzione).

Questo è meglio spiegato con i seguenti esempi, che usano due normali funzioni:

  • +, che estrae due numeri dallo stack e spinge la loro somma.
  • U, che fa apparire un numero e spinge il suo quadrato.

Esempio 1 :

3 2 + 6 + 12 4 U + +

produce il risultato 39. Il codice viene interpretato come segue:

  • Numerali letterali come 3o 12vengono inseriti nello stack
  • Funzioni come +pop i loro input e spingere i loro output nello stack.

Le chiamate di funzione, in ordine cronologico, sono:

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

Gli appunti possono essere visualizzati come un elenco di quattro elenchi. Ogni elenco interno contiene gli input per una chiamata di funzione, con prima le chiamate più recenti . All'interno di ciascun elenco interno, gli input sono nel loro ordine originale .

Quindi, dopo aver eseguito il codice, i contenuti degli appunti sono (in notazione Python):

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

Esempio 2 :

10 20 U 30 +

lascia i numeri 10e 430in pila. Lo stack viene visualizzato dal basso verso l'alto alla fine del programma.

Le chiamate di funzione sono

  1. 20 U400
  2. 400 30 +430

Poiché ci sono state solo due chiamate di funzione, alcuni degli elenchi interni che definiscono gli appunti saranno vuoti . Nota anche come 10non viene utilizzato come input per nessuna funzione.

Pertanto, i contenuti degli appunti dopo aver eseguito il codice sono:

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

Esempio 3 (non valido):

10 20 + +

è considerato non valido, poiché +manca un input per il secondo (in MATL ciò implicherebbe implicitamente l'input dell'utente).

La sfida

Input : una stringa S con numero letterale +e U, separata da spazi.

Uscita : il contenuto della funzione di appunti dopo valutare la stringa S .

chiarimenti:

  • È possibile utilizzare due simboli coerenti per rappresentare tali funzioni, ad eccezione delle cifre. Inoltre, puoi utilizzare qualsiasi simbolo coerente come separatore, anziché spazio.
  • Saranno prese in considerazione solo le due funzioni indicate.
  • La stringa di input conterrà almeno un numero letterale e almeno una funzione.
  • Tutti i numeri saranno numeri interi positivi, possibilmente con più di una cifra.
  • È possibile che alcuni letterali numerici non vengano utilizzati da nessuna funzione, come nell'esempio 2.
  • È garantito che l'input sia un codice valido, senza richiedere numeri aggiuntivi. Quindi una stringa come nell'esempio 3 non si verificherà mai.
  • È possibile ommettere trailing liste interne vuote nell'output. Quindi il risultato nell'esempio 2 può essere[[400, 30], [20]]
  • È accettabile qualsiasi formato di output ragionevole e inequivocabile. Ad esempio, una stringa con virgola come separatore interno e virgola come separatore esterno: 400,30;20;;.

Regole aggiuntive:

Casi test

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

L' [[28, 11], [16, 12], [4], [6, 5]]output è valido per il primo esempio?
Ovs,

@ovs No, gli input all'interno di ciascuna lista interna devono essere nell'ordine originale, cioè come nella chiamata di funzione
Luis Mendo

Ehm, siamo scoraggiati da, eh, risolvendo questo problema in MATL? : P
Erik the Outgolfer,

1
Sono appunti M?
Giuseppe,

1
@Giussepe Exactly! Non ho menzionato quel nome qui perché non stiamo usando la funzione M. Lo farò nella sfida "incolla"
Luis Mendo,

Risposte:



5

Bash , 43 byte

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

Provalo online!

Questo stampa gli appunti nel seguente formato, notare l'uso di \ x0F come separatore.

item_1\x0Fitem_2
item_3
.
.
item_m\x0Fitem_n

L'idea chiave è passare questo in dc, un linguaggio basato sullo stack, in modo tale che gli articoli dello stack richiesti vengano stampati.

L'input viene reindirizzato a sed dove ogni +viene sostituito rdnFPrp+, che in cc stampa il secondo numero sullo stack seguito da \ x0F e quindi il numero superiore prima di eseguire l'aggiunta. sed sostituisce anche ogni Ucon p2^, stampa l'elemento superiore dello stack e lo piazza.

Il primo comando di sostituzione s sostituisce tutto, come indicato dalla bandiera g lobal g, +s con rdnFPrp+. In cc, rscambia i primi due oggetti dello stack, dduplica l'elemento superiore, lo nstampa senza una nuova riga, Fspinge 15 nello stack e lo Pstampa come un personaggio (che è il delimitatore), rscambia di nuovo, pstampa l'elemento dello stack superiore e quindi +esegue aggiunta sui primi due oggetti dello stack.

Abbiamo un altro comando, e in sed, i comandi sono separati da punti e virgola o newline, di cui viene scelta la prima opzione. Il semplice fatto di ;far interpretare bash come la fine del comando sed, quindi viene evaso con a \.

Nell'ultimo comando di sostituzione, Uviene sostituito globalmente con p2^. In cc, pstampa e 2^aumenta alla seconda potenza.

Il risultato di sed viene valutato come codice cc, stampando l'intero blocco appunti.

La pipe a DC fa interpretare DC come codice DC. Ora, le chiamate più recenti sono in basso e quelle più vecchie in alto.

Poiché le linee sono in ordine inverso, tac(inverso cat) viene utilizzato per risolvere il problema.

E infine, sed seleziona le prime 4 righe da tac.

Questo è un modo più breve di fare head -4. sed esegue i comandi su ogni riga dell'ingresso uno alla volta. Se non ci sono comandi, non viene fatto nulla per l'input e viene restituito così com'è. 4qdice a sed di eseguire il comando qsulla riga 4. Quando sed sta elaborando la riga 4 dell'input, i primi tre input sono già stati stampati. Il comando qchiude il programma, quindi stampa la quarta riga e si chiude, eseguendo così l'equivalente dihead -4 .


4

Python 2 , 126 byte

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]

Provalo online!


4

Haskell , 113 109 byte

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 prima riga definisce una funzione anonima che prende una stringa, ad esempio "3 2 + 6 + 12 4 U + +", e restituisce una lista di liste di int: [[11,28],[12,16],[4],[5,6]]. Provalo online!


2

Pulito , 140 byte

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)

Provalo online!

In classico stile Clean, è la soluzione Haskell tranne circa il 50% in più.


2

JavaScript (ES6), 107 byte

Prende l'input come un elenco composto da numeri interi '+'e 'U'. Restituisce un altro elenco composto da numeri interi, matrici di 2 numeri interi e '_'per slot vuoti.

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)

Provalo online!

Commentate

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

Vai, 305 303 295 byte

Dropped 8 byte grazie 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])}

Provalo online!


2

Ottava , 206 byte

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)

Provalo online!

Se solo Octave avesse una popsintassi. msono gli appunti di memoria, tlo stack.


potresti costruire me tal contrario, aggiungendo elementi al fronte piuttosto che alla fine?
Giuseppe,

178 byte usando la strategia descritta sopra
Giuseppe,

@Guiseppe Clever. Ho sempre la sensazione che accodare sia generalmente più breve di anteporre, ma in questo caso il gran numero di "fine" avrebbe dovuto farmi riconsiderare
Sanchises

1

Python 3 , 218 204 byte

-14 byte grazie agli 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])

Provalo online!


1

Rosso , 335 330 byte

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]

Provalo online!

Più leggibile:

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 byte

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

Provalo online!

Mè gli appunti di memoria, Pè il programma ed Sè lo stack.

Tecnicamente Sviene inizializzato come un vettore contenente un singolo zero ma poiché non otteniamo mai un input non valido, mi salva un byte da S={}.


1

C (gcc) , 264 byte

Ho usato la ricorsione in modo da poter usare lo stack di funzioni come stack di dati: l'elenco di input viene esaminato e le operazioni vengono eseguite: i risultati vengono visualizzati in ordine inverso, con push dello stack non visualizzati.

Lo stack è implementato come un elenco collegato. Ecco come funziona:

  • Il nodo corrente è impostato con [puntatore al valore, puntatore al nodo precedente]
  • Per inviare un valore, questo viene memorizzato e la funzione viene nuovamente richiamata con il nodo corrente.
  • Per far apparire un valore o modificare il valore nella parte superiore dello stack, viene modificato il valore di un nodo precedente e la funzione viene richiamata nuovamente con il nodo precedente.

Inizialmente ho usato una struttura per i nodi, ma sono passato a puntatori nudi per risparmiare spazio. Una caratteristica interessante di questo elenco collegato è che si ripulisce al termine della ricorsione.

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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.