{Nombres Bouclés};

33

Dans le langage de programmation ésotérique Curly, les programmes sont composés uniquement d'accolades {}et de points-virgules ;. En dépit de cet outil modeste, Curly a des littéraux qui peuvent représenter n’importe quel entier non négatif. Le format est un peu difficile à lire pour les non-initiés, cependant, écrivons un peu de code pour effectuer la conversion pour nous.

Format des nombres

Les nombres bouclés sont structurés selon les règles suivantes:

  1. L'ajout d'un point-virgule en ajoute un au nombre.
  2. Un nombre entre accolades est multiplié par quatre.
  3. Les groupes d'accolades peuvent être imbriqués mais non concaténés. Les accolades doivent correspondre correctement.
  4. Les points-virgules en dehors d'un ensemble d'accolades doivent venir après, pas avant.
  5. Pour éviter toute ambiguïté dans l'analyse, un nombre doit toujours commencer par une accolade.

Quelques exemples:

{;;}     2*4 = 8
{{;};};  (1*4+1)*4+1 = 21
{};;;    0*4+3 = 3

(Notez que la règle 5 signifie que les chiffres 0 à 3 doivent commencer par une paire d'accolades vides.)

Et quelques exemples non valides:

{{;}{;;}}  Curly brace groups side-by-side, not nested
{;}}       Unmatched brace
{;{;}}     Semicolon before curly-brace group
;;;        Number does not start with curly brace

Voici une grammaire BNF pour les nombres Curly:

<number> ::= "{" <inner> "}" <semis>
<inner>  ::= <semis>
           | <number>
<semis>  ::= ";" <semis>
           | ""

Des nombres tels que {;;;;}(plus de 3 points-virgules à la suite) ou {{};}(groupes d'accolades vides inutiles) sont appelés des nombres de Curly inappropriés . Ils obéissent à la grammaire ci-dessus et peuvent être évalués de la manière habituelle, mais ils sont également capables de représentations plus courtes (pour les exemples ci-dessus {{;}}et {;}respectivement).

Le défi

Écrivez un programme ou une fonction qui entre / reçoit une chaîne. Si la chaîne est un entier décimal non négatif, sortie / retourne la représentation Curly correcte (c'est-à-dire la plus courte possible) pour cet entier. Si la chaîne est un nombre Curly, affiche / retourne sa représentation décimale.

L'entrée peut être reçue via STDIN, un argument de ligne de commande ou un paramètre de fonction. Ce doit être une ficelle; Autrement dit, vous ne pouvez pas écrire une fonction qui accepte les chaînes pour les nombres Curly, mais les entiers pour les nombres décimaux.

La sortie peut être imprimée sur STDOUT ou renvoyée par la fonction. Une fonction peut renvoyer un entier, le cas échéant, ou des chaînes dans toutes les situations.

Votre programme ne doit pas nécessairement traiter des entrées incorrectes (nombres Curly qui enfreignent les règles de formatage, nombres à virgule flottante, nombres entiers négatifs, texte aléatoire), et il n'est pas nécessaire de gérer des nombres Curly incorrects (voir ci-dessous). La saisie consistera uniquement en caractères ASCII imprimables.

Notation

Le code le plus court en octets gagne. Si votre programme peut effectuer les deux opérations suivantes:

  1. gérer correctement les numéros Curly inappropriés, et
  2. quand on leur donne un numéro Curly, ignore tous les caractères supplémentaires qui ne sont pas {};

puis soustrayez 10% de votre score. (L'entrée entière n'aura jamais de caractères superflus, même pour le bonus.)

Cas de test

Input       Output
{;;}        8
{{;};};     21
{};;;       3
{{{{;}}};}  260
{}          0
4           {;}
17          {{;}};
1           {};
0           {}
96          {{{;};;}}

Pour le bonus:

{};;;;;     5
{{;;;;};;}  72
c{u;r;l}y;! 9
42{;} ;;;;  8

Remarque: Curly n'est pas encore implémenté. Mais si cette question se pose bien, je pourrai la développer davantage.

DLosc
la source
comment doit-il gérer la casse si le nombre de parenthèses ne correspond pas? ou devrais-je supposer que cela ne sera jamais arrivé?
user902383
@ user902383 Vous pouvez supposer que des accolades qui ne correspondent pas ne se produiront jamais.
DLosc
2
J'allais faire une solution Retina, mais après l'avoir fait gérer une chaîne Curly (seulement 20 octets), j'ai réalisé qu'elle devait également gérer des entiers positifs -> Curly, j'ai donc abandonné.
mbomb007
@DLosc Ouais, ça ne gagnerait pas, alors je ne vais pas passer le temps.
mbomb007
@ mbomb007 Je voulais dire spécifiquement sur cette question, où la solution Pyth est déjà 22% plus courte que la solution CJam la plus courte et se qualifie pour le bonus. Quoi qu’il en soit, c’était une question rhétorique qui tentait de dire: "Non, mais ça pourrait quand même être amusant et faire l’objet d’une augmentation." Si vous êtes en désaccord avec la partie "amusante", ça va.
DLosc

Réponses:

15

Pyth, 35 32 octets - 10% = 28,8

.x.U+jb`HZ*R\;.[Z2jsz4i/R\;cz\}4

Essayez-le en ligne: démonstration ou suite de tests

edit: Il s’est avéré que j’ai aussi accidentellement pu gérer des numéros Curly inappropriés. Ce n'était pas prévu du tout. ;-)

Explication:

Il y a deux expressions dans le code. Le premier convertit un nombre en un nombre bouclé, et le second convertit un nombre bouclé en un nombre régulier. .xpoignées, quelle expression est imprimée. Il essaiera d’imprimer la première expression. S'il n'y a pas de chiffres dans l'entrée, la première expression échoue (via Exception). .xattrape l'exception et imprime la seconde.

.U+jb`HZ*R\;.[Z2jsz4   # number to Curly Number
                 sz    read the input and converts it to an int
                j  4   convert to base 4
            .[Z2       pad zeros on the left, until length is >= 2
        *R\;           convert each digit to ";"s
                       lets call this list of ";"s Y
.U                     reduce this list, start with b=Y[0], 
                       Z iterates over Y[1], Y[2], ..., 
                       update b in each step with:
   jb`H                   put b into curly brackets
  +    Z                  and append Z

i/R\;cz\}4             # Curly Number to regular number
     cz\}              split the input by "}"
 /R\;                  count the ";"s in each string
i        4             convert this list from base 4 to base 10
Jakube
la source
2
Le pistolet le plus rapide de l'ouest :( J'avais cette solution exacte sauf que j'avais oublié que .[Z2c'était nécessaire.
orlp
12

CJam, 51 47 44 41 octets

r_'{-_@={i4bYUe[';f*{{}s@*\+}*}{'}/:,4b}?

Essayez-le en ligne: exemple de parcours | suite de tests

Comment ça marche

r        e# Read a token from STDIN.
_'{-     e# Remove all left curly brackets from a copy of the token.
_@       e# Copy the modified token and rotate the original on top of it.
=        e# Check for equality.
{        e# If the strings were equal:
  i4b    e#   Convert to integer, then to base 4.
  YUe[   e#   Left-pad the resulting array with zeroes to a length of 2.
  ';f*   e#   Replace each digit with that many semicolons.
  {      e#   For each string of semicolons but the first:
    {}s  e#     Push the string "{}".
    @    e#     Rotate the first string or the result of the previous 
         e#     iteration on top of the stack.
    *    e#     Join, i.e., surround the string with curly brackets.
    \+   e#     Append the current string of semicolons to the result.
  }*     e#
}{       e# Else:
  '}/    e#   Split the modified input at right curly brackets.
  :,     e#   Replace each run of 0 to 3 semicolons by its length.
  4b     e#   Convert from base 4 to integer.
}?       e#
Dennis
la source
7

Python 2, 167 octets - 10% = 150.3

d=lambda x:("{"+d(x//4)+"}"if x>3 else"")+";"*(x%4)
c=lambda n:"{}"*(int(n)<4)+d(int(n))if n.isdigit()else reduce(lambda x,y:x*4+y,[x.count(";")for x in n.split("}")])

Dans cette implémentation, cest la fonction qui répond aux exigences. Il retourne une chaîne si un entier non négatif est donné en entrée ou un entier si un nombre bouclé est donné en entrée.

Greg Hewgill
la source
6

Python 266 octets - 10% = 1268.1 326.7 239.4 octets

Boy je ne suis pas un golfeur de code encore = /, mais que 10% aidé m'a un beaucoup quand mon score était encore de plus de 1000!

J'ai une version entièrement développée (et verbeuse) de ce code ici. Il reconnaîtra la validité des nombres bouclés et fournira une interface en boucle pour saisir les nombres à tester.

(Commentaires juste pour clarification)

Voir ce code en action

def c(t):                           # curly to int function
 v=0                                #  int value of input
 for a in t:                        #  for each character of input
  if a==';':v+=1                    #   if you find a ';', add one to total
  if a=='}':v*=4                    #   if you find a '}', multiply total by 4
 print v                            #  print value
def i(t):                           # int to curly function
 v=int(t);f,b="{}"if v<4 else"",""  #  get integer value. initialize front (f) and back (b) strings
 while 1:                           #  loop until stopped
  r,v=v%4,int(v/4)                  #   get remainder of v/4 and int value of v/4
  if r>0:b=';'*r+b                  #   if remainder exists, prepend that many ';' to back string
  if v>0:f=f+'{';b='}'+b            #   if remaining value > 4, append '{' to front and prepend '}' to back
  if v<4:b=';'*v+b;break            #   if remaining value < 4, prepend that many ';' to back string and break
 print f+b                          #  print result
t=raw_input()                       # get raw input
try:int(t);i(t)                     # use try block to determine which function to call
except:c(t)                         # 

Merci à Erik Konstantopoulos pour une réduction importante des octets! Vous pourriez dire… il a vraiment pris un… octet… de mon code… * self five *

Taylor Lopez
la source
4
Bienvenue chez PPCG! Votre code contient beaucoup d' printinstructions non requises et un commentaire, vos noms de variables sont trop longs et certains espaces peuvent être éliminés. Je recommande également de lire des astuces pour jouer au golf à Pyrhon .
Dennis
Excellente ressource, merci! Je vais apporter les modifications appropriées à ce code et voir dans quelle mesure il me mène. On dirait que si je veux être n'importe qui sur ce site, je dois soit apprendre CJam ou Pyth, soit écrire mon propre langage lol.
Taylor Lopez
3
@ iAmMortos Pas nécessairement . Faites-le si vous trouvez cela agréable ou restez fidèle à Python. :)
DLosc
2
Le golf se fait généralement en trois étapes: 1) faites votre programme comme vous le feriez normalement, aussi minime que possible (c.-à-d. Aucune instruction de débogage, pas besoin de gérer une entrée invalide, une sortie minimale) 2) enlevez autant que possible : les espaces blancs , renommer les variables ( valueen vetc), 3) faire des choses de golf intelligentes : c’est le point où vous devez regarder le lien de Dennis. Je suis curieux de voir à quel point vous pouvez réduire cela!
Sanchises
1
Je n'ai jamais reçu un accueil aussi chaleureux dans une communauté. lol, je pense que je l'aime ici.
Taylor Lopez
4

CJam, 87 octets 80.1 score (89 octets - 10% de bonus)

Mettez à jour la version qui qualifie pour le bonus en augmentant de 2 octets:

l_'{#){VX@{";{}"#)" _@+\ 4* 4/"S/=~}/;}{i_4<{"{}"\';*}{{4md\_{F'{\+'}+}{;L}?\';*+}:F~}?}?

Essayez-le en ligne

La première fois que j'ai utilisé la récursivité dans CJam! Le tout peut sembler long, mais les deux conversions complètement distinctes s’additionnent.

J'ai utilisé un cas complètement séparé pour convertir des nombres inférieurs à 4 en Curly. Il est probablement possible d'éviter cela, mais incorporer la gestion des cas spéciaux à la fonction récursive ne serait pas tout à fait trivial. Et ajouter l’extra {}comme étape de post-traitement n’était pas vraiment plus intéressant, même si je devrais réessayer si elle était légèrement plus courte.

Reto Koradi
la source
Votre score ne serait-il pas de 80,1?
PurkkaKoodari
4
@ Pietu1998 Merci. Non seulement mes solutions sont trop longues, mais apparemment je ne parviens pas non plus à l'arithmétique de base ...
Reto Koradi
3

C #, 173 - 10% = 155,7 171,0, 177,3

Cela ne fait pas de validation et seulement pour les regards ;et les }personnages. Cela suppose que tous les {caractères viennent avant tous les ;personnages. La chose la plus difficile que j'ai trouvée a été de ne pas insérer un nombre {}au milieu d'un nombre Curly.

Les sauts de ligne et les retraits pour plus de clarté:

string C(string a,int b=0){
    int n;
    if(int.TryParse(a,out n))
        a=(n>=b?"{"+C(""+n/4,4)+"}":"")+";;;".Remove(n%4);
    else
        foreach(int c in a)
            a=""+(c==59?++n:c==125?n*=4:n);
    return a;
}
Hand-E-Food
la source
Vous pouvez enregistrer un octet en utilisant var au lieu de char dans les boucles foreach.
Raznagul
@DLosc, désolé, le bonus n ° 1 m'a confondu. Je pensais que cela s’appliquait à la sortie plutôt qu’à l’entrée.
Hand-E-Food le
2

Java 326 octets - 10% = 294 octets

C'est un programme complet écrit en java,

public class a{static String c(long a,int v){if(a==0)return v==0?"{}":"";String x="";for(int i=0;i<a%4;i++)x+=";";return "{"+c(a/4,v+1)+"}"+x;}public static void main(String[]c){try{System.out.println(c(Long.parseLong(c[0]),0));}catch(Exception e){System.out.println(c[0].chars().reduce(0,(a,b)->b==';'?a+1:b=='}'?a*4:a));}}}

Je suis sûr que cela peut être beaucoup plus court mais je ne peux pas avoir beaucoup de temps maintenant pour l'optimiser

utilisateur902383
la source
@DLosc putain, à droite, et je pense avoir un bon résultat avec java :(
user902383
aussi: l'optimisation commune sur Java est d'éviter la public classe d'avant
masterX244
remplacer le public static void main(String[]c){avecstatic{
das_j
2

GNU sed, 330 326 - 10% = 293,4

(J'ai ajouté un pour l'utilisation de -ravant de réclamer le bonus de 10%; j'espère que c'est correct)

/;/{
s/[^};]//g
:c
s/(;*)\}/\1\1\1\1/
tc
:d
/;/{
s/;;;;;/v/g
s/vv/x/g
/[;v]/!s/\b/0/2
s/;;/b/g
s/bb/4/
s/b;/3/
s/v;/6/
s/vb/7/
s/v3/8/
s/v4/9/
y/;bvx/125;/
td
}
n
}
:u
s/\b9/;8/
s/\b8/;7/
s/\b7/;6/
s/\b6/;5/
s/\b5/;4/
s/\b4/;3/
s/\b3/;2/
s/\b2/;1/
s/\b1/;0/
s/\b0//
/[^;]/s/;/&&&&&&&&&&/g
tu
:v
s/;;;;/v/g
s/v+/{&}/
y/v/;/
tv

La version complète montre que la plupart de ce qui précède est une conversion entre décimal et unaire:

#!/bin/sed -rf

/;/{

# Delete non-Curly characters
s/[^};]//g

# Curly to unary
:c
s/(;*)\}/\1\1\1\1/
tc

# unary to decimal
:d
/;/{
s/;;;;;/v/g
s/vv/x/g
/[;v]/!s/\b/0/2
s/;;/b/g
s/bb/4/
s/b;/3/
s/v;/6/
s/vb/7/
s/v3/8/
s/v4/9/
y/;bvx/125;/
td
}

# done
n

}


# Decimal to unary
:u
s/\b9/;8/
s/\b8/;7/
s/\b7/;6/
s/\b6/;5/
s/\b5/;4/
s/\b4/;3/
s/\b3/;2/
s/\b2/;1/
s/\b1/;0/
s/\b0//
/[^;]/s/;/&&&&&&&&&&/g
tu

# Unary to Curly
:v
s/;;;;/v/g
s/v+/{&}/
y/v/;/
tv
Toby Speight
la source
Malheureusement, cette question indique explicitement que la virgule décimale est requise, ce qui explique pourquoi j'ai dérangé la conversion.
Toby Speight le
Vous avez raison, ce qui m'étonne un peu car exclure le unaire n'était pas mon intention. Oh bien, suppose qu'il est trop tard pour changer la question maintenant. Je réaffirme mon +1, monsieur.
DLosc
2

Perl, 183 177

Ce n'est peut-être pas la réponse Perl la plus courte, mais je pense qu'il est assez intéressant de poster (entrée $_, sortie comme valeur de retour):

sub f{if(/}/){s/[{}]/00/g;oct'0b'.s/00(;+)/sprintf'%02b',length$1/ger}else{$_=sprintf'%064b',$_;s/../oct"0b$&"/ge;s/^0+(?!$)//;$_='{'x length.$_;s/\d/'}'.';'x$&/ge;s/\Q{{}/{/r}}

Nous observons que Curly est simplement une notation quaternaire (base 4). Nous sommes un peu gênés par le manque de support natif de Perl pour le quaternaire, mais heureusement, chaque quaternit a deux bits en binaire, et nous pouvons lire et écrire en binaire. Nous avons donc les éléments suivants:

  1. Curly to decimal: convertissez chaque chiffre Curly en 2 chiffres binaires, concaténez et convertissez-le en décimal
  2. Décimal à Curly: affiche le nombre en binaire (forçant un nombre pair de chiffres), puis convertit chaque paire de bits en Curly.

Version élargie

sub f
{
    if (/}/) {
        s/[{}]/00/g;     # digits are now 00 00; 00;; 00;;;
                         # and opening braces become harmless leading zeros
        s/00(;+)/sprintf'%02b',length $1/ge;
                         # convert semicolons to binary, leaving zeros alone
        oct "0b$_"       # now to decimal
    } else {
        $_=sprintf'%064b',$_;   # decimal to binary
        s/../oct"0b$&"/ge;      # bit-pair to quaternit
        s/^0+(?!$)//;           #/remove leading zeros
        $_='{'x length.$_;      # prefix enough opening braces
        s/\d/'}'.';'x$&/ge;     #/digit to semicolons
        s/{{}/{/r               # first empty brace, unless $_ <= {};;;
    }
}
Toby Speight
la source
1

JavaScript (ES6), 95 (105-10%)

f=(n,r='{}')=>-1-n?(n>3?'{'+f(n>>2,'')+'}':r)+';'.repeat(n&3):n.replace(/[;}]/g,c=>c>';'?n*=4:++n,n=0)&&n

Testez l'exécution de l'extrait ci-dessous

f=(n,r='{}')=>-1-n?(n>3?'{'+f(n>>2,'')+'}':r)+';'.repeat(n&3)
:n.replace(/[;}]/g,c=>c>';'?n*=4:++n,n=0)&&n

// Test
function out(x) { O.innerHTML=x+'\n'+O.innerHTML; }

function go() { out(I.value + ' --> ' + f(I.value)) }

;[ 
  ['{;;}', 8]
, ['{{;};};', 21 ]
, ['{};;;', 3 ]
, ['{{{{;}}};}', 260 ]
, ['{}', 0 ]
, [ 4, '{;}' ]
, [ 17, '{{;}};' ]
, [ 1,'{};' ]
, [ 0, '{}' ]
, [ 96, '{{{;};;}}' ]
, ['{};;;;;', 5 ]
, ['{{;;;;};;}' , 72 ]
, ['c{u;r;l}y;!', 9 ]
, ['42{;} ;;;;', 8 ]
].forEach(t => {
  r=f(t[0])
  k=t[1]
  out('Test ' +(r==k?'OK':'Fail')+'\nInput:  '+t[0]+'\nResult: '+r+'\nCheck:  '+k+'\n')
})
Custom test <input id=I><button onclick='go()'>-></button>
<pre id=O></pre>

edc65
la source
Pourriez-vous s'il vous plaît poster votre code actuel? En outre, votre score est de 94,5.
Erik the Outgolfer
@ErikKonstantopoulos, mon code actuel a été posté en haut de l'extrait de test. Maintenant, il est également au sommet de la réponse. En ce qui concerne le score (qui devrait être exprimé en octets), je me sens toujours drôle de mesurer un demi-octet (ou moins) et de préférer le rouniding
edc65
edc65: Oui, mais arrondir est mauvais pour vous! 94,5 <95, donc un score plus petit, ce qui signifie qu'il bat probablement plus de soumissions. En outre, le "sommet de l'extrait de code" n'est pas l'endroit pour afficher votre code.
Erik the Outgolfer
1

Ruby, 126,9 129,6 (144 - 10%)

Utilise la récursion pour convertir le nombre décimal en forme bouclée. Supprimer le test pour ignorer les caractères en dehors de /[;{}]/augmente le score de 0.4pour le moment.

f=->s{s=~/^\d+$/?(n=s.to_i
"{#{n<1?'':f[(n/4).to_s].gsub('{}','')}}#{?;*(n%4)}"):eval(s.tr("^{;}","").gsub(/./){|c|c<?A?"+1":c>?|?")*4":"+(0"})}
Valeur d'encre
la source
C'est corrigé maintenant. Merci d'avoir signalé le bogue; le score a été mis à jour.
Valeur d'encre
1

Perl 5, 154 ( 185 170 octets - 10% + 1 pénalité)

$e=$/;if($_=~/{/){s/[^{};]//g;s/;/+1/g;s/{/+4*(/g;s/}/+0)/g;$b=eval}else{$r=$_;$b=$r<4?"{}":"";while($r>0){if($r%4>0){$r--;$e=";$e"}else{$b.="{";$e="}$e";$r/=4}}}$_=$b.$e

Regex & eval résolvent les curlies.
La génération des curlies se fait différemment.

Tester

Le fichier de test contient également les bonus cas

$ cat curlytestcases.txt
{}
{};
{};;
{};;;
{;;}
{{;};};
{{{{;}}};}
0
1
2
3
4
17
96
{};;;;;
42{;} ;;;;
c{u;r;l}y;!
{{;;;;};;}

$ cat curlytestcases.txt |perl -p curlies.pl
0
1
2
3
8
21
260
{}
{};
{};;
{};;;
{;}
{{;}};
{{{;};;}}
5
8
9
72
LukStorms
la source
Ajout de la pénalité -1 pour -p. Le $ b = $ r <2? "{}": ""; a été ajouté à l'exception de 0 & 1. {} ;;; est l'entrée dans le test.
LukStorms
A eu besoin de temps pour le tester. C'est corrigé maintenant. :)
LukStorms
Je pense que la pénalité +1 vient après un bonus de -10%.
Erik the Outgolfer
Observation intéressante. Je ne sais pas si cela devrait être le cas à présent, mais c'est logique, alors je l'ai changé quand même. Pas que ça change le score final.
LukStorms
1

Retina , 69 64 octets

+`{(;*)}
$1$1$1$1
^\d+|^(;*)
$*;$.1
+`(;+)\1\1\1
{$1}
^;|^$
{}$&

Essayez la suite de tests


Explication

+`{(;*)}
$1$1$1$1

Décomposer les accolades les plus internes à juste ;s. Boucle jusqu'à ce qu'il n'y ait plus d'attelles.

^\d+|^(;*)
$*;$.1

Convertir entre décimal et unaire ;

+`(;+)\1\1\1
{$1}

Trouvez le plus long cycle ;qui soit multiple de 4 et emboîtez-vous dans des accolades, en boucle, jusqu'à ce qu'il n'y ait plus de cycle de 4+.

^;|^$
{}$&

Si le nombre bouclé résultant commence par ;ou est une chaîne vide, ajoutez-le {}devant.

TwiNight
la source
1

Python 2 , 157 octets -10% = 141,3

lambda n:'{}'*(int(n)<4)+g(int(n))if n.isdigit()else sum((v==';')*4**n.count('}',i)for i,v in enumerate(n))
g=lambda n:'{%s}'%g(n/4)+';'*(n%4)if n>3else';'*n

Essayez-le en ligne!

Une réponse Python 2 plus golfée qui gère les cas bonus. Je ne voulais pas necro dead posts avec ceci comme commentaire, alors le voici.

Cela fonctionne de l'intérieur sur les nombres bouclés, en ajoutant 4 ^ (le nombre d'accolades finales laissées dans la chaîne) à la somme de chaque point-virgule trouvé. Si la chaîne est un nombre, il crée alors le nombre bouclé de manière récursive de la même manière que la grammaire fournie.

Arnold Palmer
la source
C'est étrange. J'ai même eu des cas de test pour des nombres inférieurs à 2. Corrigé pour un total de +5 octets.
Arnold Palmer
@DLosc Je jure que normalement je ne suis pas si mauvais. Fixé, et golfé un peu pour le rendre un peu plus compétitif.
Arnold Palmer