Presse-papiers de fonction: copier


17

Ce défi est lié à certaines des fonctionnalités du langage MATL, dans le cadre de l' événement Langue du mois de mai 2018 . Défi associé : Fonction presse-papiers: coller .


introduction

MATL a plusieurs presse - papiers , où vous pouvez stocker des valeurs (copier) pour les récupérer plus tard (coller). Certains presse-papiers sont automatiques , ce qui signifie que la copie est automatiquement déclenchée par certains événements. Ce défi se concentre sur l'un des presse-papiers automatiques, appelé presse-papiers d'entrée de fonction , ou simplement presse-papiers de fonction .

Ce presse-papiers stocke les entrées des quatre derniers appels aux fonctions normales de prise d'entrée. Les fonctions normales sont le type de fonctions le plus courant dans MATL. La prise d'entrée signifie que la fonction prend au moins une entrée (les fonctions qui n'acceptent aucune entrée ne sont pas prises en compte par le presse-papiers de la fonction).

Ceci est mieux expliqué avec les exemples suivants, qui utilisent deux fonctions normales:

  • +, qui extrait deux nombres de la pile et pousse leur somme.
  • U, qui fait apparaître un chiffre et pousse son carré.

Exemple 1 :

3 2 + 6 + 12 4 U + +

produit le résultat 39. Le code est interprété comme suit:

  • Les littéraux numériques tels que 3ou 12sont poussés vers la pile
  • Des fonctions telles que +pop leurs entrées et pousser leurs sorties vers la pile.

Les appels de fonction, par ordre chronologique, sont les suivants:

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

Le presse-papiers peut être vu comme une liste de quatre listes. Chaque liste interne contient les entrées d'un appel de fonction, avec les appels les plus récents en premier . Dans chaque liste interne, les entrées sont dans leur ordre d'origine .

Donc, après avoir exécuté le code, le contenu du presse-papiers est (en notation Python):

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

Exemple 2 :

10 20 U 30 +

laisse des chiffres 10et 430sur la pile. La pile est affichée de bas en haut à la fin du programme.

Les appels de fonction sont

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

Puisqu'il n'y a eu que deux appels de fonction, certaines des listes internes définissant le presse-papiers seront vides . Notez également comment 10n'est utilisé comme entrée pour aucune fonction.

Ainsi, le contenu du presse-papiers après l'exécution du code est:

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

Exemple 3 (invalide):

10 20 + +

est considéré comme invalide, car une entrée à la seconde +est manquante (dans MATL, cela déclencherait implicitement une entrée utilisateur).

Le défi

Entrée : une chaîne S avec des littéraux numériques +et U, séparés par des espaces.

Sortie : le contenu du presse - papiers de fonction après l' évaluation de la chaîne S .

Précisions:

  • Vous pouvez utiliser deux symboles cohérents pour représenter ces fonctions, autres que des chiffres. En outre, vous pouvez utiliser n'importe quel symbole cohérent comme séparateur, au lieu de l'espace.
  • Seules les deux fonctions indiquées seront prises en compte.
  • La chaîne d'entrée contiendra au moins un littéral numérique et au moins une fonction.
  • Tous les nombres seront des entiers positifs, éventuellement avec plus d'un chiffre.
  • Il est possible que certains littéraux numériques ne soient utilisés par aucune fonction, comme dans l'exemple 2.
  • L'entrée est garantie comme étant un code valide, sans nécessiter de numéros supplémentaires. Ainsi, une chaîne comme dans l'exemple 3 ne se produira jamais.
  • La fin des listes internes vides dans la sortie peut être supprimée. Ainsi, le résultat de l'exemple 2 peut être[[400, 30], [20]]
  • Tout format de sortie raisonnable et sans ambiguïté est acceptable. Par exemple, une chaîne de caractères avec la virgule comme séparateur interne et externe virgule comme séparateur: 400,30;20;;.

Règles supplémentaires:

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

La [[28, 11], [16, 12], [4], [6, 5]]sortie est-elle valide pour le premier exemple?
ovs

@ovs Non, les entrées dans chaque liste intérieure doivent être dans l'ordre d'origine, c'est-à-dire, comme dans l'appel de fonction
Luis Mendo

Hm, sommes-nous découragés de, eh, juste résoudre cela en MATL? : P
Erik the Outgolfer

1
Est-ce ce presse M- papiers ?
Giuseppe

1
@Giussepe Exactement! Je n'ai pas mentionné ce nom ici parce que nous n'utilisons pas la fonction M. Je le ferai dans le défi "coller"
Luis Mendo

Réponses:



5

Bash , 43 octets

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

Essayez-le en ligne!

Cela imprime le presse-papiers dans le format suivant, notez l'utilisation de \ x0F comme séparateur.

item_1\x0Fitem_2
item_3
.
.
item_m\x0Fitem_n

L'idée clé est de passer ceci en dc, un langage basé sur la pile, de sorte que les éléments de pile requis soient imprimés.

L'entrée est dirigée vers sed où chaque +est remplacé par rdnFPrp+, qui en dc imprime le deuxième numéro de la pile suivi de \ x0F puis du premier numéro avant d'effectuer l'addition. sed remplace également chaque Uavec p2^, imprimez l'élément supérieur de la pile et mettez-le au carré.

La première commande de substitution sremplace l' ensemble, comme cela est indiqué par le g drapeau lobes g, +est à rdnFPrp+. En DC, rpermute les deux éléments de pile supérieurs, dduplique l'élément supérieur, l' nimprime sans nouvelle ligne, Fpousse 15 sur la pile et l' Pimprime en tant que caractère (qui est le délimiteur), rpermute à nouveau, pimprime l'élément supérieur de la pile, puis +exécute ajout sur les deux premiers éléments de la pile.

Nous avons une autre commande, et dans sed, les commandes sont séparées par des points-virgules ou des sauts de ligne, dont la première option est choisie. Le simple fait d'avoir ;bash interprétera cela comme la fin de la commande sed, donc il s'échappe avec a \.

Dans la dernière commande de substitution, Uest remplacé globalement par p2^. En courant continu, pimprime et 2^élève la seconde puissance.

Le résultat de sed est évalué en tant que code dc, imprimant tout le presse-papiers.

Le canal vers dc fait interpréter cela par DC comme du code DC. Maintenant, les appels les plus récents sont en bas et les plus anciens en haut.

Puisque les lignes sont dans l'ordre inverse, tac(inverse cat) est utilisé pour corriger cela.

Et enfin, sed choisit les 4 premières lignes de tac.

C'est une façon plus courte de faire head -4. sed exécute les commandes sur chaque ligne de l'entrée une par une. S'il n'y a pas de commandes, rien n'est fait à l'entrée et elle est renvoyée telle quelle. 4qindique à sed d'exécuter la commande qsur la ligne 4. Lorsque sed traite la ligne 4 de l'entrée, les trois premières entrées ont déjà été imprimées. La commande qquitte le programme, elle imprime donc la quatrième ligne et se ferme, réalisant ainsi l'équivalent de head -4.



4

Haskell , 113 109 octets

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 première ligne définit une fonction anonyme qui prend une chaîne de caractères, par exemple "3 2 + 6 + 12 4 U + +", et retourne une liste de listes de ints: [[11,28],[12,16],[4],[5,6]]. Essayez-le en ligne!


2

Propre , 140 octets

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)

Essayez-le en ligne!

Dans le style Clean classique, c'est la solution Haskell, sauf environ 50% plus longtemps.


2

JavaScript (ES6), 107 octets

Prend l'entrée comme une liste composée d'entiers, '+'et 'U'. Renvoie une autre liste composée d'entiers, de tableaux de 2 entiers et '_'pour des emplacements vides.

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)

Essayez-le en ligne!

Commenté

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

Aller, 305 303 295 octets

Perte de 8 octets grâce à @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])}

Essayez-le en ligne!


2

Octave , 206 octets

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)

Essayez-le en ligne!

Si seulement Octave avait une popsyntaxe. mest le presse-papiers de la mémoire, tla pile.


pourriez-vous construire met tinversement, en ajoutant des éléments à l'avant plutôt qu'à la fin?
Giuseppe

178 octets en utilisant la stratégie décrite ci
Giuseppe

@Guiseppe Clever. J'ai toujours le sentiment que l'ajout est généralement plus court que le préfixe, mais dans ce cas, le grand nombre de «fins» aurait dû me faire reconsidérer
Sanchises

1

Python 3 , 218 204 octets

-14 octets grâce aux 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])

Essayez-le en ligne!


1

Rouge , 335 330 octets

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]

Essayez-le en ligne!

Plus lisible:

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 octets

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

Essayez-le en ligne!

Mest le presse-papiers de la mémoire, Ple programme et Sla pile.

Techniquement, il Sest initialisé comme un vecteur contenant un seul zéro, mais comme nous n'obtenons jamais d'entrée invalide, il me fait gagner un octet S={}.


1

C (gcc) , 264 octets

J'ai utilisé la récursivité pour pouvoir utiliser la pile de fonctions comme pile de données: la liste d'entrée est parcourue et les opérations sont effectuées: les résultats sont affichés dans l'ordre inverse, avec les poussées de pile non affichées.

La pile est implémentée sous forme de liste chaînée. Voici comment ça fonctionne:

  • Le nœud actuel est configuré avec [pointeur sur la valeur, pointeur sur le nœud précédent]
  • Pour pousser une valeur, elle est stockée et la fonction est appelée à nouveau avec le nœud actuel.
  • Pour afficher une valeur ou modifier la valeur en haut de la pile, la valeur d'un nœud précédent est modifiée et la fonction est à nouveau appelée avec le nœud précédent.

J'ai utilisé à l'origine une structure pour les nœuds, mais je suis passé à des pointeurs nus pour économiser de l'espace. Une caractéristique intéressante de cette liste chaînée est qu'elle se nettoie une fois la récursivité terminée.

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

Essayez-le en ligne!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.