Un système de numérotation simple

19

Permettez-moi de vous parler d'un système de numérotation simple. (que j'ai compensé juste pour ce défi)

Ce système contient les fonctions (), [], {}et <>.

1. ()

Quand ()aucun argument n'est donné, il est évalué 0.

Lorsque ()reçoit un ou plusieurs arguments, il évalue la somme des arguments.

2. []

Quand []aucun argument n'est donné, il est évalué -1.

Lorsque []reçoit un ou plusieurs arguments, il évalue le premier argument moins la somme des autres arguments.

3. {}

Quand {}aucun argument n'est donné, il est évalué 1.

Lorsque {}reçoit un ou plusieurs arguments, il évalue le produit de ces arguments.

4. <>

Quand <>aucun argument n'est donné, il est évalué 1.

Quand <>est donné un ou plusieurs arguments, il évalue le premier entier d'argument divisé par le produit des autres arguments.

Ta tâche

Étant donné une chaîne qui contient un nombre valide (cela signifie que les parenthèses sont équilibrées, pas de division par 0, etc.) dans ce système de numérotation simple, imprimez sa valeur.

Cas de test

() -> 0
(()()) -> 0
([][]) -> -2
({}<>) -> 2
({}[]) -> 0
[] -> -1
[[][]] -> 0
[()<>] -> -1
{()} -> 0
{([]<>)} -> 0

N'oubliez pas qu'il s'agit de , donc le code avec le moins d'octets gagne.

Oliver Ni
la source
13
J'ai un grand nom pour cela, que j'ai tout simplement inventé et que je n'ai obtenu nulle part ailleurs: Brain-flake!
ETHproductions
4
@ETHproductions no
Oliver Ni
Type de relation
DJMcMayhem
2
La division est-elle une division flottante ou une division entière?
xnor
1
@Oliver Comment la division entière devrait-elle fonctionner lorsque l'un ou les deux opérandes sont négatifs? Quels sont les 4 résultats attendus pour 5/3, 5/-3, -5/3et -5/-3?
Martin Ender

Réponses:

2

Dyalog APL , 94 octets

o←{(⊂(1⊃⍵),⍺⍺⊃⍵),2↓⍵}⋄u←{(⊃⍵,⍺⍺1)⍺⍺⍵⍵/1↓⍵}⋄⍎⍕'+/o' '-u+o' '×/o' '÷u×o' '(⊂⍬),'[')]}>'⍳⌽⍞],'⊂⍬'

les usages ⎕IO←0

remplace )]}>par un appel de fonction qui prend une pile, applique une opération sur sa trame supérieure, la supprime et ajoute le résultat à sa trame suivante (l'opérateur monadique oest utilisé pour cela; l'opérateur dyadique ugère les cas les plus compliqués de -et ÷)

remplace ([{<par du code qui ajoute un cadre à la pile ( (⊂⍬),)

exécute l'expression résultante (inversée, pour correspondre à l'ordre d'exécution d'APL) avec une pile initiale d'une trame vide ( ⊂⍬)

ngn
la source
5

Haskell, 357 306 277 251 228 224 188 185 180 octets

Un analyseur basé sur des jetons avec une pile explicite. (%)prend une pile de jetons et un caractère et pousse (opcode, defaultnumber) ou (0, number) pour ({[<, ou affiche les premiers chiffres et un opcode et pousse la réponse pour )}]>. Les opcodes sont encodés par un hack d'énumération ascii.

Félicitations à @ChristianSievers pour sa grande réponse à laquelle j'ai emprunté quelques idées.

Bon mot!

s%c|elem c"([<{",g<-div(fromEnum c)25=(g,[0,0,1,-1,1]!!g):s|(a,(o,n):b)<-span((==0).fst)s=(0,[foldr1(flip$[(+),quot,(-),(*)]!!(o-1))$snd<$>a,n]!!(0^length a)):b
snd.head.foldl(%)[]

Maintenant avec moins de gestion des erreurs! Usage:

*Main> map (snd.head.foldl(%)[]) ["()","(()())","([][])","({}<>)","({}[])","[]","[[][]]","[()<>]","{()}","{([]<>)}"]
[0,0,-2,2,0,-1,0,-1,0,0]

Merci @ChristianSievers d'avoir économisé 14 + 3 octets!

Merci @Zgarb pour avoir économisé + 4 octets!

Angs
la source
1
Et (0,[0,0,1,-1,1]!!o):sen cinquième ligne?
Christian Sievers
@ChristianSievers bien sûr!
Angs
Changez les définitions de !, afin que vous puissiez faire (s:_)!_=d scomme le deuxième cas. De plus, je pense que vous pourriez vous lier x<-p$d<$>init a,y<-d$last adans le dernier cas de %.
Zgarb
@Zgarb merci! J'ai trouvé un moyen d'unifier encore plus l'évaluation.
Angs
1
Sur la troisième ligne, %vous pouvez déposer des parens autour _:bet g c.
Zgarb
3

Python 2, 292 265 248 235 223 206 204 octets

r=reduce
s=input()
for n in')]}>':s=s.replace(n,'),')
for a in'(*x:sum(x)','[a=-1,*x:a-sum(x)','{*x:r(int.__mul__,x,1)','<a=1,*x:r(int.__div__,x,a)':s=s.replace(a[0],'(lambda %s)('%a[1:])
print eval(s)[0]

Remplace tous les crochets par un lambda qui fait ce que fait le crochet, puis évalue le code Python résultant. Nécessite son entrée entourée de guillemets, comme '[<><>([]{})]'.

Ce programme stocke le type de parenthèse en tant que premier caractère de chaque chaîne dans le for, et tout ce qui se trouve après le mot-clé en lambdatant que reste. Il utilise ensuite le premier caractère pour remplacer; le reste est combiné en un lambda (lambda*x:sum(x))().

Essayez-le sur Ideone!

Cuivre
la source
3

PEG.js (ES6) , 132 octets

x=a:[([{<]b:x*[)\]}>]{var x='([<'.indexOf(a)
b.length^1||b.push(0)
return~~eval(b.length?b.join(('+-/'[x]||'*')+' '):~-('10'[x]||2))}

Devrait être corrigé maintenant.

Explication

Plus lisible:

x=a:[([{<]
  b:x*
  [)\]}>]
{
  var x='([<'.indexOf(a)
  b.length^1||b.push(0)
  return ~~eval(
    b.length?
      b.join(('+-/'[x]||'*')+' ')
    :~-('10'[x]||2))
  )
}

PEG.js est une version étendue de Javascript spécialement conçue pour l'analyse. C'est TRÈS strict, c'est pourquoi j'ai dû utiliser var. En outre, il semble y avoir un bogue avec des crochets à l'intérieur des chaînes, qui a considérablement gonflé le code.

Pour commencer, nous définissons une règle xqui correspond à n'importe quel crochet aqui peut contenir ou non plusieurs expressions qui correspondent à la règle x.

Pour chaque correspondance à gouverner x, nous poussons un 0 dans le tableau de la correspondance interne bsi bla longueur est 1.

Si bla longueur est> 0, alors nous trouvons l'index de ain ([<et obtenons un caractère en +-/utilisant cet index. Si le résultat n'est pas défini (c'est-à-dire qu'il l' aétait {), alors nous transformons le résultat en *. Enfin, nous clouons sur un espace et rejoignons ble résultat.

Si bla longueur est = 0, alors nous trouvons l'index de ain ([<et obtenons un caractère en 10utilisant cet index. Si le résultat n'est pas défini (c'est-à-dire qui aétait {ou <), alors nous transformons le résultat en 2. Enfin, nous décrémentons simplement.

À la fin, nous pouvons simplement évaluer l'expression et fixer le résultat.

Mama Fun Roll
la source
3

Perl, 113 + 2 = 115 octets

Exécuter avec -lp(pénalité de 2 octets).

/\W/,eval"sub $`\{\$#_?(shift)$&&$'1}"for qw'a+a:1- b-a:- c*c: d/c:';y/([{</a-d/;s/\W/0),/g;s/\pL\K/(/g;$_=eval

Plus lisible (note: cette "version plus lisible" ne fonctionnera pas réellement, car je mets des commentaires dans des endroits où ils ne sont pas autorisés syntaxiquement):

              # -p option: read a line of input into $_ at program start
              # -l option: remove the final newline whenever reading
do {          # for each element of a list, given later:
  /\W/;       # place an initial identifier in $`, the next character in
              # $&, and the rest of the element in $'
  eval qq{    # then evaluate the following template, with substitutions:
    sub $` {  # define a subroutine named $`, that does this:
      \$#_ ?  # if there is more than one argument                   
      (shift) # then return the first argument $&-ed with
      $& &$'  # the result of a recursive call with the tail of the arguments
              # else (the "else" is a colon taken from $', not the template)
      1       # return (the remainder of $' applied to) 1
    }
  }
} for qw'     # specify the list by splitting the following on whitespace:        
  a+a:1-      # a(head,tail) = len(tail>1) ? head+a(tail) : 1-1
  b-a:-       # b(head,tail) = len(tail>1) ? head-a(tail) : -1
  c*c:        # c(head,tail) = len(tail>1) ? head*c(tail) : 1
  d/c:        # d(head,tail) = len(tail>1) ? head/c(tail) : 1
';
y/([{</a-d/;  # replace ( [ { < with a b c d in $_
s/\W/0),/g;   # replace whitespace, punctuation in $_ with the string "0),"
s/\pL\K/(/g;  # place a ( after (\K) each letter (\pL) in $_
$_=eval       # evaluate $_ as a Perl program, storing the result back in $_
              # -p option: print $_ to the user at program end
              # -l option: output a newline whenever printing

L'idée de base est que nous convertissons une entrée comme [()<>]au programme Perl b(a(0),d(0),0),via le traitement de texte; Perl est très bien avec la virgule de fin. Plus tôt, nous avons défini les fonctions a, b, c, dd'avoir le même effet que le (), [], {}, des <>constructions de la langue que nous mettons en œuvre; ils ignorent chacun leur dernier argument (le 0 à la fin), qui est inclus pour s'assurer que toutes les entrées sont analysées correctement, et fonctionnent en utilisant l'implémentation couramment vue dans la programmation fonctionnelle où la tête et la queue sont traitées séparément. Parce que b(e,f,g,0)signifie e-f-g, c'est-à-dire traite son premier argument spécialement, alors que atraite ses arguments symétriquement ( a(e,f,g,0)signifie e+f+g), nous implémentonsarécursivement et bpar appel a. cet dont une relation similaire. Ces quatre fonctions sont très similaires, nous les générons donc au moment de l'exécution plutôt que de les implémenter séparément; nous stockons un modèle qui s'applique aux quatre fonctions dans une chaîne, puis générons les fonctions en substituant des caractères dans le modèle.

Parce que Perl /fait une division en virgule flottante, l'implémenté le {}fait aussi. Je suppose que ce n'est pas un problème en soi, ou -Minteger(sélectionner une variante de langage où toutes les opérations arithmétiques sont des opérations entières) est gratuit, car sinon je devrais dépenser des octets supplémentaires pour écrire une division entière en Perl, ce qui ne semble pas être le fond du problème. (Je pense que vous devrez dépenser quatre octets (shift)pour passer à int+(shift); je n'ai pas testé cela.)


la source
2

Octave, 215 206 198 octets

S='sum(x(:))-sum(x(2:end))';Y='(@(x)isempty(x)';c=']) ';[~,~,u]=unique(['()<>[]{}',input('')]);eval([{'sum([',c,[Y,'+fix((',S,')/prod(x(2:end))))(['],c,[Y,'*-1+',S,'*2)(['],c,'prod([',c}{u(9:end)}])

essayez-le en ligne

rahnema1
la source
2

PHP, 315 300 285 258 250 244 octets

for($s=$argv[1];$r=!$r;)foreach(["(+)1","[-]0","{*}2","</>2]as$p)if(preg_match("#$e$p[0]([-_\d]*)$e$p[2]#",$s,$m)){if(""==$v=strtok($m[1],_))$v=$p[3]-1;while(""<$n=strtok(_))eval("\$v$p[1]=$n;");$s=strtr($s,[$m[$r=0]=>_.$v]);}echo substr($s,1);

remplace les sous-expressions par un soulignement + une valeur; la boucle se casse lorsque l'itération ne fait aucun remplacement.

19 ans depuis ma première rencontre avec C, 17 ans avec PHP;
c'est la première fois que strtokcela a du sens ... aider à économiser 24 octets!

panne

for($s=$argv[1];    // take input from argument
    $r=!$r;)        // toggle $r; loop until no replacement has taken place
    foreach(["(+)1","[-]0","{*}2","</>2]as$p) // loop through operations
        if(preg_match("#$e$p[0]([-_\d]*)$e$p[2]#",$s,$m))   // find a match
        {
            if(""==$v=strtok($m[1],_))  // init $v with first token from sub-match
                $v=$p[3]-1;             // if no token, init with default value
            while(""<$n=strtok(_))      // loop through tokens
                eval("\$v$p[1]=$n;");       // operate
            $s=strtr($s,[$m[$r=0]=>_.$v]);  // reset $r; replace match with underscore+value
        }
echo substr($s,1);  // print result
Titus
la source
@Oliver ne bat personne ici; mais merci pour le plaisir!
Titus
2

ES6 (Javascript), 250, 171, 154, 149, 147 octets

Une version Javascript pure.

La «métaprogrammation» (comme la plupart des autres réponses ici), convertit le texte du programme d'entrée en un programme Javascript correspondant, en lui appliquant un certain nombre de substitutions directes de texte (c'est-à-dire en conservant la structure du programme telle quelle).

Peut probablement être joué plus loin.

MISE À JOUR (v2.1)

  • Moins deux octets (parenthèses supprimées dans l'expression ternaire)
  • Golfé 5 octets de plus, en utilisant une variable pour l'extraction des résultats et en supprimant les "[]" supplémentaires

MISE À JOUR (v2)

Je viens de réaliser que les virgules en attente dans les tableaux ES sont totalement valides, donc tout le code de normalisation des virgules pourrait être supprimé. A également suivi un excellent conseil de @Titus, sur l'optimisation de la recherche alphabétique.

MISE À JOUR (v1)

Suppression de l'alias "remplacer" en double.

MISE À JOUR (v1)

  • Utilisez un meilleur alphabet: () => 1+ [] => 0 {} => 2 * <> => 2 / (chaque caractère peut être directement réutilisé comme valeur ou opérateur)

  • Remplace réduire () par remplacer () (mappage alphabétique)

  • Fusionner le traitement constant des parenthèses en ligne, ouvrir et fermer en une seule étape

Golfé (v2.1)

s=>eval("o="+s.replace(/./g,r=>"2+1-3*3/"["()[]{}<>".indexOf(r)]).replace(/\d\D?|\D/g,r=>r[1]?r[0]-2+",":r*1?'([':`].reduce((r,a)=>r${r}a)),`)+"o

Golfé (v1)

(s,A="(2)+[1]-{3}*<3>/")=>eval(s[R="replace"](/./g,r=>A[A.indexOf(r)+1])[R](/\d\D?|\D/g,r=>r[1]?r[0]-2+",":(r[0]*1?'([':`].reduce((r,a)=>r${r}a)),`))[R](/,(\])|,$/g,"$1"))    

Golfé (v0)

([...s],A="(a)b[c]d{e}f<g>h",R="replace")=>eval(s.reduce((r,c)=>r+=A[A.indexOf(c)+1],'')[R](/ab|cd|ef|gh/g,r=>({d:-1,b:'0'}[r[1]]||1) + ',')[R](/[aceg]/g,"([")[R](/[bdfh]/g,r=>`].reduce((r,a)=>r${"+*-/"["bfdh".indexOf(r)]}a)),`)[R](/,(\])|,$/g,"$1"))

Expliqué (v0)

//BEGIN 

//s - input text, A - alphabet, R - "String.replace()" alias
E=([...s],A="(a)b[c]d{e}f<g>h",R="replace")=>eval(

//Replace input alphabet by a more friendly one, to avoid too much escaping and quoting
// () - ab, [] -cd, {} - ef, <> - gh
s.reduce((r,c)=>r+=A[A.indexOf(c)+1],'')

//Replace no-arg invocations with a corresponding constant value
// () => 0, [] => -1, {} => 1, <> => 1      
[R](/ab|cd|ef|gh/g,r=>({d:-1,b:'0'}[r[1]]||1) + ',')

//Replace opening brackets with "(["
[R](/[aceg]/g,"([")

//Replace closing brackets with "].reduce(...)),"
//An arithmetic operation to apply (+-*/) is chosen based on the bracket type 
//and is substituted into the template 
[R](/[bdfh]/g,r=>`].reduce((r,a)=>r${"+*-/"["bfdh".indexOf(r)]}a)),`)

//Strip excessive commas
[R](/,(\])|,$/g,"$1")
);

//END: eval() the result


Example:
E("{([]<>()<>{})(<><>)}")
=> eval("([([-1,1,0,1,1].reduce((r,a)=>r+a)),([1,1].reduce((r,a)=>r+a))].reduce((r,a)=>r*a))")
=> 4

Tester

E=([...s],A="(a)b[c]d{e}f<g>h",R="replace")=>eval(s.reduce((r,c)=>r+=A[A.indexOf(c)+1],'')[R](/ab|cd|ef|gh/g,r=>({d:-1,b:'0'}[r[1]]||1) + ',')[R](/[aceg]/g,"([")[R](/[bdfh]/g,r=>`].reduce((r,a)=>r${"+*-/"["bfdh".indexOf(r)]}a)),`)[R](/,(\])|,$/g,"$1"))

T=(s,a)=>{
    console.log(s,r=E(s),r==a?"OK":"NOT OK");
}

T("()",0)
T("(()())",0) 
T("([][])",-2)
T("({}<>)",2) 
T("({}[])",0) 
T("[]",-1)
T("[[][]]",0) 
T("[()<>]",-1) 
T("{()}",0) 
T("{([]<>)}",0)

Sortie de test

() 0 OK
(()()) 0 OK
([][]) -2 OK
({}<>) 2 OK
({}[]) 0 OK
[] -1 OK
[[][]] 0 OK
[()<>] -1 OK
{()} 0 OK
{([]<>)} 0 OK
Zeppelin
la source
1
Votre version v0 pourrait-elle aller avec s.reduce((r,c)=>r+="abcdefgh"["()[]{}<>".indexOf(c)],'')(-5)? si c'est le cas, vous pouvez vous indexOfen souvenir dans une variable et prendre l'opérateur d'un troisième littéral de chaîne.
Titus
2

Haskell, 184 179 172 161 161 160 159 151 148 145 octets

s%(c:i)|elem c")}]>"=([1?(*),sum,1?quot,(-1)?(-)]!!mod(fromEnum c)5$s,i)|(r,j)<-[]%i=(s++[r])%j
[v]%e=(v,e)
(v?_)[]=v
(_?o)s=foldl1 o s
fst.([]%)

Descente récursive, enfilant l'entrée car Haskell. Comme d'habitude, la dernière ligne n'est pas une définition, mais indique la fonction qui résout le problème. Donc, pour tester, mettez les lignes sauf la dernière dans un fichier, chargez-le et faites quelque chose comme ceci:

*Main> fst.([]%) $ "{([][][])([][])}"
6

Merci à @Zgarb pour l'inspiration et beaucoup de conseils détaillés, et à @Angs pour l'inspiration de sa solution et d'autres conseils.

Il n'a pas été spécifié comment la division devrait se comporter avec des nombres entiers négatifs. Quoi qu'il en soit, une utilisation répétée divsemble incorrecte, car ce n'est pas la même chose qu'une utilisation divavec le produit des valeurs restantes. Maintenant, en utilisant quot, j'obtiens les mêmes résultats pour <{}([][])[]>et <{}{([][])[]}>.

Pour un code agréable et presque lisible, regardez la première version. Les versions intermédiaires contiennent toutes sortes de code agréable et intimidant et aident à comprendre cette version.

Christian Sievers
la source
Je pense que vous pouvez enregistrer quelques octets en définissant (!)=(,)et en utilisant !au lieu de tuples explicites.
Zgarb
Si vous définissez m xet en d xtant que 1#xet 0#x, vous pouvez fusionner les cas m[x]et d[x]en un seul, ce qui, je pense, économise également quelques octets.
Zgarb
@Zgarb Merci! J'ai failli rater la dernière paire, sans laquelle l' !astuce ne paie pas. Ta deuxième suggestion est diabolique, voilà mon code presque lisible ... Intelligent!
Christian Sievers
Hé, je viens de réaliser que définir s%(c:i)=(s?c,i)et s?')'=sum setc. sera beaucoup plus court, car vous pouvez vous débarrasser des is répétés . ..Attendez, cela ne fonctionnera probablement pas à cause de l' s%(_:i)affaire.
Zgarb
1
Perdez les backticks elemet divcela devrait économiser encore plus d'octets.
Zgarb
1

JavaScript (ES6), non eval, 156 octets

f=s=>s==(s=s.replace(/(.) ?([- \d]*)[\]})>]/,(_,c,s)=>` `+(s?s.split` `.reduce((l,r)=>c<`<`?l- -r:c<`[`?l/r|0:c<`{`?l-r:l*r):c==`[`?-1:c==`(`?0:1)))?+s:f(s)

Explication: L'expression régulière trouve le premier crochet de fermeture non traité et fait correspondre (vraisemblablement) le crochet d'ouverture correspondant et tout argument intermédiaire. Les arguments sont divisés et réduits en fonction de l'opération (malheureusement '(' et '[' ne sont pas la paire optimale pour +et -), ou s'il n'y a pas d'arguments, la valeur appropriée est calculée (encore une fois, la correspondance des caractères aux valeurs n'est pas optimale) de mon point de vue). Le résultat est ensuite remplacé par un espace de tête afin de le séparer des autres résultats. La fonction s'appelle alors récursivement jusqu'à ce qu'il n'y ait plus de modifications à effectuer, auquel cas elle renvoie la valeur résultante. Exemple:

[()<>]
[ 0<>]
[ 0 1]
 -1
Neil
la source
f ("([[] [])") => 0 (au lieu de 2)
zeppelin
Certains autres tests échouent également pour moi (vous pouvez essayer le code de test dans ma réponse ), probablement en raison de: f ("[]") => 0, car "[]" fait partie de chaque test qui échoue.
zeppelin
@zeppelin Oups, c'était dû à un mauvais golf. Je suis revenu à une version précédente, mais malheureusement, cela me coûte quelques octets.
Neil