Funktions-Zwischenablage: Kopieren

17

Diese Herausforderung steht im Zusammenhang mit einigen Funktionen der MATL-Sprache im Rahmen des Events Sprache des Monats im Mai 2018 . Assoziierte Herausforderung : Funktion Zwischenablage: Einfügen .


Einführung

MATL verfügt über mehrere Zwischenablagen , in denen Sie Werte speichern (kopieren) und später abrufen (einfügen) können. Einige Zwischenablagen sind automatisch , was bedeutet, dass das Kopieren automatisch durch bestimmte Ereignisse ausgelöst wird. Diese Herausforderung konzentriert sich auf eine der automatischen Zwischenablagen, die als Funktionseingabe-Zwischenablage oder einfach als Funktionszwischenablage bezeichnet wird .

In dieser Zwischenablage werden die Eingaben zu den vier letzten Aufrufen für normale Eingabeaufnahmefunktionen gespeichert. Normale Funktionen sind der häufigste Funktionstyp in MATL. Eingaben annehmen bedeutet, dass die Funktion mindestens eine Eingabe annimmt (Funktionen, die keine Eingabe annehmen, werden von der Funktions-Zwischenablage nicht berücksichtigt).

Dies wird am besten anhand der folgenden Beispiele erläutert, in denen zwei normale Funktionen verwendet werden:

  • +, der zwei Zahlen vom Stapel wirft und ihre Summe schiebt.
  • U, der eine Zahl knallt und sein Quadrat drückt.

Beispiel 1 :

3 2 + 6 + 12 4 U + +

erzeugt das Ergebnis 39. Der Code wird wie folgt interpretiert:

  • Zahlenliterale wie 3oder 12werden auf den Stapel geschoben
  • Funktionen wie +Pop ihre Eingänge und Push ihre Ausgänge auf den Stapel.

Die Funktionsaufrufe sind in chronologischer Reihenfolge:

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

Die Zwischenablage kann als Liste von vier Listen angezeigt werden. Jede innere Liste enthält die Eingaben für einen Funktionsaufruf, wobei die letzten Aufrufe zuerst angezeigt werden . In jeder inneren Liste sind die Eingaben in ihrer ursprünglichen Reihenfolge .

Nach dem Ausführen des Codes lautet der Inhalt der Zwischenablage (in Python-Notation):

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

Beispiel 2 :

10 20 U 30 +

hinterlässt Zahlen 10und 430auf dem Stapel. Der Stapel wird am Ende des Programms von unten nach oben angezeigt.

Die Funktionsaufrufe sind

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

Da es nur zwei Funktionsaufrufe gab, sind einige der inneren Listen, die die Zwischenablage definieren, leer . Beachten Sie auch, wie 10keine Funktion als Eingabe verwendet wird.

Somit sind die Inhalte der Zwischenablage nach dem Ausführen des Codes:

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

Beispiel 3 (ungültig):

10 20 + +

wird als ungültig angesehen, da eine Eingabe für die Sekunde +fehlt (in MATL würde dies implizit Benutzereingaben auslösen).

Die Herausforderung

Eingabe : ein String S mit Zahlenliteralen +und Udurch Leerzeichen getrennt.

Ausgabe : der Inhalt der Zwischenablage - Funktion nach der String Auswertung S .

Klarstellungen:

  • Sie können zwei beliebige konsistente Symbole verwenden, um diese Funktionen darzustellen, die keine Ziffern sind. Sie können anstelle des Leerzeichens auch ein beliebiges konsistentes Symbol als Trennzeichen verwenden.
  • Es werden nur die beiden angegebenen Funktionen berücksichtigt.
  • Die Eingabezeichenfolge enthält mindestens ein Zahlenliteral und mindestens eine Funktion.
  • Alle Zahlen sind positive ganze Zahlen, möglicherweise mit mehr als einer Ziffer.
  • Es ist möglich, dass einige Zahlenliterale von keiner Funktion verwendet werden, wie im Beispiel 2.
  • Die Eingabe ist garantiert ein gültiger Code, ohne dass zusätzliche Nummern erforderlich sind. Ein String wie in Beispiel 3 wird also niemals vorkommen.
  • Nachgestellte leere innere Listen in der Ausgabe können weggelassen werden. So kann das Ergebnis in Beispiel 2 sein[[400, 30], [20]]
  • Jedes vernünftige, eindeutige Ausgabeformat ist akzeptabel. Zum Beispiel wird eine Zeichenkette mit Komma als inneres Trennelement und Semikolon als äußeren Trenn: 400,30;20;;.

Zusätzliche Regeln:

Testfälle

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
quelle
Ist [[28, 11], [16, 12], [4], [6, 5]]die Ausgabe für das erste Beispiel gültig?
Ovs
@ovs Nein, Eingaben in jeder inneren Liste müssen in der ursprünglichen Reihenfolge erfolgen, dh wie im Funktionsaufruf
Luis Mendo,
Hm, sind wir entmutigt, eh, das nur in MATL zu lösen? : P
Erik der Outgolfer
1
Ist das Zwischenablage M?
Giuseppe
1
@ Giussepe Genau! Ich habe diesen Namen hier nicht erwähnt, weil wir keine Funktion verwenden M. Ich werde es in der "Paste" Herausforderung tun
Luis Mendo

Antworten:

5

Bash , 43 Bytes

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

Probieren Sie es online!

Dadurch wird die Zwischenablage im folgenden Format gedruckt. Beachten Sie die Verwendung von \ x0F als Trennzeichen.

item_1\x0Fitem_2
item_3
.
.
item_m\x0Fitem_n

Die Schlüsselidee ist, dies in dc, eine stapelbasierte Sprache, zu übergeben, so dass die erforderlichen Stapelelemente gedruckt werden.

Die Eingabe wird an sed weitergeleitet, wo jedes +durch ersetzt rdnFPrp+wird. In dc wird die zweite Zahl auf dem Stapel gedruckt, gefolgt von \ x0F und der höchsten Zahl, bevor die Addition durchgeführt wird. sed ersetzt auch jedes Udurch p2^, druckt das oberste Stapelelement und quadriert es.

Der erste Wechsel - Befehl sersetzt alle, wie es durch die bezeichnete g lobal Flag g, +S mit rdnFPrp+. Vertauscht in dc rdie beiden dobersten nStapelelemente , dupliziert das oberste Element, druckt es ohne Zeilenvorschub, Fschiebt 15 auf den Stapel und Pdruckt es als Zeichen (das Trennzeichen), rvertauscht es erneut, pdruckt das oberste Stapelelement und +führt dann eine Ausführung durch Außerdem auf den beiden obersten Stapelelementen.

Wir haben einen anderen Befehl, und in sed werden Befehle entweder durch Semikolons oder durch Zeilenumbrüche getrennt, von denen die erste Option ausgewählt wird. Wenn Sie dies einfach ;tun, interpretiert bash dies als das Ende des sed-Befehls, sodass es mit einem Escapezeichen versehen wird \.

Im letzten Ersetzungsbefehl Uwird global durch ersetzt p2^. In dc wird pgedruckt und 2^auf die zweite Potenz angehoben.

Das Ergebnis von sed wird als DC-Code ausgewertet und die gesamte Zwischenablage gedruckt.

Die Pipe zu DC lässt DC das als DC-Code interpretieren. Jetzt sind die letzten Anrufe ganz unten und die älteren ganz oben.

Da die Zeilen in umgekehrter Reihenfolge sind, wird tac(reverse cat) verwendet, um dies zu beheben.

Und schließlich wählt sed die ersten 4 Zeilen von tac aus.

Dies ist eine kürzere Methode head -4. sed führt die Befehle für jede Zeile der Eingabe einzeln aus. Wenn es keine Befehle gibt, wird nichts mit der Eingabe gemacht und sie wird so wie sie ist zurückgegeben. 4qWeist sed an, den Befehl qin Zeile 4 auszuführen. Wenn sed Zeile 4 der Eingabe verarbeitet, wurden die ersten drei Eingaben bereits gedruckt. Der Befehl qbeendet das Programm, gibt also die vierte Zeile aus und beendet das Programm. Auf diese Weise wird das Äquivalent von ausgeführt head -4.

Kritixi Lithos
quelle
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#

Die erste Zeile definiert eine anonyme Funktion , die einen String, zum Beispiel "3 2 + 6 + 12 4 U + +", und gibt eine Liste von Listen von Ints: [[11,28],[12,16],[4],[5,6]]. Probieren Sie es online!

Laikoni
quelle
2

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

Probieren Sie es online!

Im klassischen Clean-Stil ist es die Haskell-Lösung mit einer um etwa 50% längeren Laufzeit.

Οurous
quelle
2

JavaScript (ES6), 107 Byte

Nimmt die Eingabe als eine Liste bestehend aus ganzen Zahlen '+'und 'U'. Gibt eine weitere Liste zurück, die aus Ganzzahlen, Arrays mit 2 Ganzzahlen und '_'für leere Slots besteht.

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)

Probieren Sie es online!

Kommentiert

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
quelle
2

Los, 305 303 295 Bytes

8 Bytes dank @ovs gelöscht

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

Probieren Sie es online!

ollien
quelle
2

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

Probieren Sie es online!

Wenn nur Octave eine popSyntax hätte. mist die Speicher-Zwischenablage, tder Stapel.

Sanchises
quelle
Könnten Sie in umgekehrter Reihenfolge konstruieren mund tElemente eher an der Vorderseite als am Ende anbringen?
Giuseppe
178 Bytes mit der oben beschriebenen Strategie
Giuseppe
@ Guiseppe Clever. Ich habe immer das Gefühl, dass das Anhängen im Allgemeinen kürzer ist als das Voranstellen, aber in diesem Fall hätte ich es mir wegen der großen Anzahl von "Enden"
überlegen müssen
1

Python 3 , 218 204 Bytes

-14 bytes dank 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])

Probieren Sie es online!

Draconis
quelle
1

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

Probieren Sie es online!

Besser lesbar:

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

Probieren Sie es online!

Mist die Speicher-Zwischenablage, Pist das Programm und Sist der Stapel.

Technisch Swird es als Vektor mit einer einzelnen Null initialisiert, aber da wir nie eine ungültige Eingabe erhalten, erspart es mir ein Byte von S={}.

Giuseppe
quelle
1

C (gcc) , 264 Bytes

Ich habe die Rekursion verwendet, um den Funktionsstapel als Datenstapel zu verwenden: Die Eingabeliste wird durchlaufen und die Operationen werden ausgeführt: Die Ergebnisse werden in umgekehrter Reihenfolge angezeigt, wobei Stapelschübe nicht angezeigt werden.

Der Stack ist als verknüpfte Liste implementiert. So funktioniert das:

  • Der aktuelle Knoten wird mit [Zeiger auf Wert, Zeiger auf vorherigen Knoten] eingerichtet.
  • Um einen Wert zu pushen, wird dieser gespeichert und die Funktion mit dem aktuellen Knoten erneut aufgerufen.
  • Um einen Wert einzufügen oder den Wert oben im Stapel zu ändern, wird der Wert eines vorherigen Knotens geändert und die Funktion mit dem vorherigen Knoten erneut aufgerufen.

Ich habe ursprünglich eine Struktur für die Knoten verwendet, aber ich habe auf leere Zeiger gewechselt, um Platz zu sparen. Ein interessantes Merkmal dieser verknüpften Liste ist, dass sie sich selbst bereinigt, wenn die Rekursion abgeschlossen ist.

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

Probieren Sie es online!

ErikF
quelle