Interpréter Kipple!


12

introduction

Kipple est un langage de programmation ésotérique basé sur une pile inventé par Rune Berg en mars 2003.

Kipple a 27 piles, 4 opérateurs et une structure de contrôle.

Piles

Les piles sont nommés a- zet contiennent des entiers signés 32 bits. Il existe également une pile spéciale @pour rendre la sortie des numéros plus pratique. Lorsqu'un numéro est poussé @, les valeurs ASCII des chiffres de ce numéro sont en fait poussées à la place. (Par exemple, si vous appuyez sur 12 vers @, il poussera 49 puis 50 vers à la @place.)

L'entrée est poussée sur la pile d'entrée iavant l'exécution du programme. L'interprète demandera des valeurs à stocker iavant l'exécution. Une fois l'exécution terminée, tout ce qui se trouve sur la pile de sortie oest renvoyé à la sortie sous forme de caractère ASCII. Comme il s'agit du seul mécanisme d'E / S de Kipple, l'interaction avec un programme Kipple est impossible.

Les opérateurs

Un opérande est soit un identifiant de pile, soit un entier 32 bits signé.

Appuyez: >ou<

Syntaxe: Operand>StackIndentifierouStackIndentifier<Operand

L'opérateur Push prend l'opérande vers la gauche et le pousse sur la pile spécifiée. Par exemple, 12>apoussera la valeur 12 sur la pile a. a>bfera apparaître la valeur la plus élevée de la pile aet la poussera sur la pile b. Popping une pile vide renvoie toujours 0. a<best équivalent à b>a. a<b>caffiche la valeur la plus élevée de bet pousse à la fois sur cet a.

Ajouter: +

Syntaxe: StackIndentifier+Operand

L'opérateur Ajouter pousse la somme de l'élément le plus haut de la pile et de l'opérande sur la pile. Si l'opérande est une pile, la valeur en est extraite. Par exemple, si la valeur la plus élevée de la pile aest 1, alors a+2poussera 3 dessus. Si aest vide, alors a+2poussera 2 dessus. Si les valeurs les plus élevées de la pile aet bsont 1 et 2, alors a+bsautera la valeur 2 de la pile bet poussera 3 sur la pile a.

Soustraire: -

Syntaxe: StackIndentifier-Operand

L'opérateur Soustraire fonctionne exactement comme l'opérateur Ajouter, sauf qu'il soustrait au lieu d'ajouter.

Clair: ?

Syntaxe: StackIndentifier?

L'opérateur Clear vide la pile si son élément le plus haut est 0.

L'interprète ignore tout ce qui est pas à côté de l'opérateur, de sorte que le programme suivant fonctionnerait: a+2 this will be ignored c<i. Cependant, la bonne façon d'ajouter des commentaires est d'utiliser le #caractère. Tout ce qui se trouve entre un #et un caractère de fin de ligne est supprimé avant l'exécution. Le caractère ASCII # 10 est défini comme fin de ligne dans Kipple.

Les opérandes peuvent être partagés par deux opérateurs, par exemple a>b c>b c?peuvent être écrits comme a>b<c?.

Le programme 1>a<2 a+ase traduira par acontenir les valeurs [1 4](de bas en haut) et non [1 3]. De même pour l' -opérateur.

La structure de contrôle

Il n'y a qu'une seule structure de contrôle dans Kipple: la boucle.

Syntaxe: (StackIndentifier code )

Tant que la pile spécifiée n'est pas vide, le code entre parenthèses correspondant sera répété. Les boucles peuvent contenir d'autres boucles. Par exemple, (a a>b)déplace toutes les valeurs de pile asur pile b, bien que l'ordre soit inversé . Une façon fonctionnellement identique mais plus élégante de le faire est (a>b).

Exemples

100>@ (@>o)

Cela produira 100

33>o 100>o 108>o 114>o 111>o 87>o 32>o 111>o 108>o 108>o 101>o 72>o

Cela s'imprimera "Hello World!". Lorsque la opile est en cours de sortie, elle commence à faire apparaître des caractères du haut vers le bas.

#prime.k by Jannis Harder
u<200
#change 200


k<2>m
u-2
(u-1 u>t u>z u<t
  (k>e e+0 e>r)
  (e>k)
  m+1
  m>t
  m>z
  m<t
  t<0>z? t?
  1>g
  (r>b
    m+0 m>a
    b+0 b>w
    (a-1 
      b+0 b>j
      j?
      1>s
      (j<0>s j?)
      s?
      (s<0 w+0 w>b s?)
      a>t
      a>z
      t>a
      b-1
      b>t
      b>z
      t>b
      z<0>t? z?
    a?)
    b?
    1>p
    (b<0 b? 0>p)
    p?
    (p 0>r? 0>p? 0>g)
  )
  g?
  (g m+0 m>k 0>g?)
u?)
(k>@
  10>o
  (@>o)
)

Ceci est un générateur de nombres premiers, mais je ne sais pas comment cela fonctionne.

Règles

  • Vous devez écrire un programme / fonction qui interprète Kipple. Ce programme / fonction peut obtenir un programme Kipple via un fichier source, ou l'obtenir via STDIN directement auprès de l'utilisateur. Si STDIN n'est pas disponible, il doit l'obtenir à partir de la saisie au clavier et continuer à obtenir la saisie jusqu'à ce qu'un caractère non imprimable spécifique soit entré. Par exemple, si votre interpréteur est écrit en code machine x86, il obtiendrait le caractère du programme Kipple par caractère à partir du clavier, et continuerait jusqu'à ce que esc(ou toute autre touche autre qui n'émet pas de caractère imprimable) soit enfoncée.

  • S'il y a une erreur, par exemple une erreur de syntaxe ou un débordement de pile, il doit le reconnaître d'une manière ou d'une autre, par exemple en renvoyant 10 au lieu de 0 ou des messages d'erreur produits par l'interpréteur / compilateur, MAIS PAS D'IMPRESSION DE MESSAGES D'ERREUR .

  • Toute autre règle régulière pour le golf de code s'applique à ce défi.

  • Votre code sera testé avec certains des exemples dans l'archive d' exemples de Kipple

Ceci est un . Le code le plus court en octets gagnera. Bonne chance!


Notez qu'il y a un opérateur optionnel dans Kipple, "mais il ne fait pas partie de la spécification et juste une fonctionnalité supplémentaire dans l'interpréteur officiel. Je ne l'ai pas mentionné ici, il n'a donc pas besoin d'être soutenu dans votre soumission.

Si vous avez un doute sur une partie de la spécification, vous pouvez l'examiner avec un interpréteur officiel écrit en Java . Cela téléchargera un fichier zip contenant le programme compilé et le code source. Il est sous licence GPL.


1
Avons-nous avons d'utiliser des entiers signés ou nous pouvons 32 bits aller avec le type entier naturel de la mise en œuvre d'accueil? (Les cas les plus importants sont probablement des entiers 32 bits non signés, des entiers 8 bits signés ou non signés et des entiers de précision arbitraire.)
Martin Ender

eh bien, c'est ce que j'ai trouvé sur le wiki ésotrique. oui, car votre interprète peut être incompatible avec d'autres programmes kipple dont leur mécanisme est basé sur cette fonctionnalité

Pouvez-vous être plus précis sur le comportement en cas d'erreur? Nous pouvons donc retourner une réponse incorrecte ou émettre une erreur, mais nous ne pouvons pas imprimer l'erreur?
Alex A.

@Alex A. Oui, car il peut être considéré comme la sortie du programme et vous pouvez créer un programme kipple qui peut avoir la même sortie que le message d'erreur. Il est également "moins cher" (utilise moins de caractères) de ne pas avoir de fonction / instruction qui affiche un message d'erreur.

3
Quels espaces peuvent se produire dans un programme source? Comment puis-je demander une entrée isi je prends le programme source de stdin?
orlp

Réponses:


6

C, 709 702 octets

Le score d'octets est avec les sauts de ligne (qui peuvent être supprimés) supprimés, mais pour faciliter la lecture, je le poste ici avec les sauts de ligne:

#define R return
#define C ;break;case
c[999]={};*P=c;*S[28];M[99999]={};t;*T;
u(s,v){S[s]+=28;*S[s]=v;
if(s>26){for(t=v/10;t;t/=10)S[s]+=28;T=S[s];do{*T=48+v%10;T-=28;}while(v/=10);}}
o(s){t=S[s]-M>27;S[s]-=28*t;R S[s][28]*t;}
I(s){R s<65?27:s-97;}
O(int*p){if(!isdigit(*p))R o(I(*p));
for(;isdigit(p[-1]);--p);for(t=0;isdigit(*p);t*=10,t+=*p++-48);R t;}

main(i,a){for(i=0;i<28;++i)S[i]=M+i;
for(;~(*++P=getchar()););P=c+1;
for(;;){i=I(P[-1]);switch(*P++){
case 35:for(;*P++!=10;)
C'<':u(i,O(P))
C'>':u(I(*P),O(P-2))
C'+':u(i,*S[i]+O(P))
C'-':u(i,*S[i]-O(P))
C'?':if(!*S[i])S[i]=M+i
C'(':for(i=1,T=P;i;++T)i+=(*T==40)-(*T==41);if(S[I(*P)]-M<28)P=T;else u(26,P-c)
C')':P=c+o(26)-1
C-1:for(;i=o(14);)putchar(i); R 0;}}}

Compilez avec gcc -w golf.c(fait -wtaire les avertissements pour votre santé mentale).

Prend en charge tout sauf l' ientrée, car le demandeur n'a pas encore répondu à ma demande sur la façon de le faire si vous prenez le code de stdin. Il ne signale pas les erreurs de syntaxe.


J'ai répondu à votre question sur la pile "i" dans les commentaires du post principal.

btw comment il lit les programmes kipple? via des arguments de commande? comment dois-je l'utiliser?

@GLASSIC Il attend le programme sur stdin.
orlp

Jusqu'a quand ? Comment commencer l'excution?

@GLASSIC Passez simplement le programme sur stdin. Par exemple ./a.out < prime.k.
orlp

3

Ruby, 718 octets (actuellement non compétitif)

Je suis très fatigué

Le fichier est chargé comme argument de ligne de commande et l'entrée est envoyée via STDIN. Alternativement, canalisez le fichier dans STDIN si vous n'avez pas besoin d'entrée dans votrei registre.

En raison d'une certaine confusion concernant la spécification, la version actuelle ne se gère pas a<b>ccorrectement et n'est donc pas compétitive jusqu'à ce qu'elle soit corrigée.

a<b>cest corrigé maintenant. Cependant, il retourne toujours le mauvais résultat lors de l'exécution de la fonction primes, il reste donc comme une réponse non compétitive.

(f=$<.read.gsub(/#.*?\n|\s[^+-<>#()?]*\s/m,' ').tr ?@,?`
t=Array.new(27){[]}
t[9]=STDIN.read.bytes
k=s=2**32-1
r=->c{c=c[0];c[0]==?(?(s[c[1..-2]]while[]!=t[c[1].ord-96]):(c=c.sub(/^(.)<(\D)>(.)/){$1+"<#{t[$2.ord-96].pop||0}>"+$3}.sub(/(\d+|.)(\W)(\d+|.)?/){_,x,y,z=*$~
a=x.ord-96
b=(z||?|).ord-96
q=->i,j=z{j[/\d/]?j.to_i: (t[i]||[]).pop||0}
l=t[a]
y<?-?(x==z ?l[-1]*=2:l<<(l.pop||0)+q[b]
l[-1]-=k while l[-1]>k/2):y<?.?(x==z ?l[-1]=0:l<<(l.pop||0)-q[b]
l[-1]+=k while l[-1]<-k/2-1):y<?>?t[a]+=a<1?q[b].to_s.bytes: [q[b]]:y<???
(t[b]+=b<1?q[a,x].to_s.bytes: [q[a,x]]): l[-1]==0?t[a]=[]:0
z||x}while c !~/^(\d+|.)$/)}
s=->c{(z=c.scan(/(\((\g<1>|\s)+\)|[^()\s]+)/m)).map &r}
s[f]
$><<t[15].reverse.map(&:chr)*'')rescue 0

+1 de toute façon. Avez-vous essayé le programme fibonacci?
edc65

@ edc65 Le programme de séquence de Fibbonacci imprime également la mauvaise chose: 0 1 1 2 4 8 16...je me demande s'il s'agit d'une erreur de spécification
Value Ink

Non, le programme Fibonacci est de la merde, par exemple, la ligne a+0est un non
edc65

Je suppose que le problème des nombres premiers est qu'il ne gère pas les structures de contrôle imbriquées, mais je ne connais pas grand-chose à Ruby, je doute que ma supposition soit correcte.

Ce programme doit gérer correctement les ensembles de parens imbriqués en raison de la correspondance d'expression régulière récursive /(\((\g<1>|\s)+\)|[^()\s]+)/mqu'il utilise pour fractionner les jetons et les groupes de jetons. ( Testez-le sur regex101 ). C'est probablement une erreur dans le reste de mon analyse, mais je ne sais pas où.
Value Ink
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.