{Numeri ricci};


33

Nel linguaggio di programmazione esoterico Ricci, i programmi consistono esclusivamente di parentesi graffe {}e punti e virgola ;. Nonostante questo umile set di strumenti, Curly ha letterali che possono rappresentare qualsiasi numero intero non negativo. Il formato è un po 'difficile da leggere per chi non lo sapesse, quindi scriviamo del codice per fare la conversione per noi.

Formato dei numeri

I numeri ricci sono strutturati secondo le seguenti regole:

  1. L'aggiunta di un punto e virgola aggiunge uno al numero.
  2. Un numero racchiuso tra parentesi graffe viene moltiplicato per quattro.
  3. I gruppi di parentesi graffe possono essere nidificati ma non concatenati. Le parentesi graffe devono corrispondere correttamente.
  4. I punti e virgola all'esterno di una serie di parentesi graffe devono venire dopo, non prima.
  5. Per evitare ambiguità nell'analisi, un numero deve sempre iniziare con una parentesi graffa.

Qualche esempio:

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

(Nota che la regola 5 indica che i numeri da 0 a 3 devono iniziare con una coppia vuota di parentesi graffe.)

E alcuni esempi non validi:

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

Ecco una grammatica BNF per i numeri ricci:

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

Numeri come {;;;;}(più di 3 punti e virgola di seguito) o {{};}(inutili gruppi di parentesi graffe vuote) sono chiamati numeri ricci impropri . Obbediscono alla grammatica sopra e possono essere valutati nel solito modo, ma sono anche capaci di rappresentazioni più brevi (per gli esempi sopra {{;}}e {;}rispettivamente).

La sfida

Scrivi un programma o una funzione che inserisce / riceve una stringa. Se la stringa è un numero intero decimale non negativo, visualizza / restituisce la rappresentazione riccia corretta (ovvero il più breve possibile) per quel numero intero. Se la stringa è un numero riccio, emette / restituisce la sua rappresentazione decimale.

L'ingresso può essere ricevuto tramite STDIN, argomento della riga di comando o parametro della funzione. Essa deve essere una stringa; vale a dire, non è possibile scrivere una funzione che accetta stringhe per numeri ricci ma numeri interi per numeri decimali.

L'output può essere stampato su STDOUT o restituito dalla funzione. Una funzione può restituire un numero intero quando appropriato, oppure può restituire stringhe in tutte le situazioni.

Il vostro programma non ha bisogno di gestire input non validi (numeri ricci che infrangono le regole di formattazione, numeri in virgola mobile, numeri interi negativi, testo casuale), ed è non necessario per gestire i numeri Curly improprie (ma vedi sotto). L'input consisterà solo di caratteri ASCII stampabili.

punteggio

Vince il codice più breve in byte. Se il tuo programma può eseguire entrambe le seguenti operazioni:

  1. gestire correttamente i numeri ricci impropri e
  2. quando viene assegnato un numero Ricci, ignora eventuali caratteri extra che non lo sono {};

quindi sottrai il 10% dal tuo punteggio. (L'input intero non avrà mai caratteri estranei, nemmeno per il bonus.)

Casi test

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

Per il bonus:

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

Nota: Curly non è ancora implementato. Ma se questa domanda va bene, posso svilupparla ulteriormente.


come dovrebbe gestire il caso se non si ha il numero di parentesi corrispondente? o devo supporre che non accadrà mai?
user902383

@ user902383 Si può presumere che parentesi graffe non corrispondenti non accadranno mai.
DLosc,

2
Stavo per fare una soluzione Retina, ma dopo averlo fatto gestire una stringa Curly (solo 20 byte), mi sono reso conto che doveva anche gestire numeri interi positivi -> Curly, quindi ho rinunciato.
mbomb007,

@DLosc Sì, non vincerebbe, quindi non ho intenzione di passare il tempo.
mbomb007,

@ mbomb007 Intendevo specificamente su questa domanda, in cui la soluzione Pyth è già del 22% più corta della soluzione CJam più corta e si qualifica per il bonus. Comunque, era una domanda retorica che tentava di dire: "No, ma potrebbe essere comunque divertente e raccogliere alcuni voti". Se non sei d'accordo con la parte "divertente", va bene.
DLosc,

Risposte:


15

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

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

Provalo online: Dimostrazione o Test Suite

modifica: Come ho scoperto, posso accidentalmente anche gestire numeri ricci non corretti. Non è stato pianificato affatto. ;-)

Spiegazione:

Esistono due espressioni nel codice. Il primo converte un numero in un numero di ricci e il secondo converte un numero di ricci in un numero normale. .xmaniglie, quale espressione viene stampata. Proverà a stampare la prima espressione. Se nell'input sono presenti cifre non numeriche, la prima espressione ha esito negativo (tramite Eccezione). .xcattura l'eccezione e stampa la seconda.

.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

2
La pistola più veloce in Occidente :( Avevo questa soluzione esatta, tranne che avevo dimenticato che .[Z2era necessaria.
Orlp

12

CJam, 51 47 44 41 byte

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

Provalo online: esempio di esecuzione | suite di test

Come funziona

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#

7

Python 2, 167 byte - 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("}")])

In questa implementazione, cè la funzione che soddisfa i requisiti. Restituisce una stringa se viene fornito un numero intero non negativo come input o un numero intero se viene fornito un numero riccio come input.


6

Python 266 byte - 10% = 1268,1 326,7 239,4 byte

Il ragazzo non sono io un codice golfista ancora = /, ma che il 10% ha aiutato me fuori un sacco quando il mio punteggio era ancora più di 1000!

Ho una versione completa (e dettagliata) di questo codice qui. Riconoscerà la validità dei numeri ricci e fornirà un'interfaccia ad anello per inserire i numeri per il test.

(Commenti solo per chiarimenti)

Vedi questo codice in azione

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)                         # 

Grazie a Erik Konstantopoulos per un'importante riduzione di byte! Potresti dire ... ha davvero preso un ... byte ... dal mio codice ... * self five *


4
Benvenuti in PPCG! Il codice contiene molte printistruzioni non necessarie e un commento, i nomi delle variabili sono troppo lunghi e alcuni spazi bianchi possono essere eliminati. Consiglio anche di leggere Suggerimenti per giocare a golf a Pyrhon .
Dennis,

Grande risorsa, grazie! Apporterò le modifiche appropriate a questo codice e vedrò fino a che punto mi arriva. Looks come se voglio essere chiunque su questo sito, ho neanche bisogno di imparare CJam o Pyth, o scrivere il mio proprio linguaggio lol.
Taylor Lopez,

3
@iAmMortos Non necessariamente . Se lo trovi divertente, oppure segui Python in caso contrario. :)
DLosc,

2
Di solito, il golf si svolge in tre passaggi: 1) rendi il tuo programma come faresti normalmente, il più minimamente possibile (ovvero, nessuna istruzione di debug, nessuna necessità di gestire input non validi, output minimo) 2) rimuovere il più possibile : spazi bianchi , rinominare le variabili ( valuein vetc), 3) fare cose golf intelligenti : questo è il punto in cui è necessario guardare il link di Dennis. Sono curioso di vedere quanto puoi ridurre questo!
Sanchises,

1
Non ho mai ricevuto un caloroso benvenuto in una comunità. lol, penso che mi piaccia qui.
Taylor Lopez,

4

CJam, punteggio 87,1 80 byte (89 byte - bonus del 10%)

Aggiorna la versione qualificata per il bonus mentre cresce di 2 byte:

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

Provalo online

La prima volta che ho usato la ricorsione in CJam! Il tutto può sembrare un po 'lungo, ma le due conversioni completamente separate si sommano.

Ho usato un caso completamente separato per convertire i numeri inferiori a 4 in Curly. Probabilmente è possibile evitarlo, ma piegare la gestione dei casi speciali nella funzione ricorsiva non sarebbe del tutto banale. E l'aggiunta di un extra {}come fase di post-elaborazione non ha davvero un aspetto migliore, anche se dovrei riprovare se potrebbe essere leggermente più breve.


Il tuo punteggio non sarebbe 80.1?
PurkkaKoodari,

4
@ Pietu1998 Grazie. Non solo le mie soluzioni sono troppo lunghe, a quanto pare fallisco anche nell'aritmetica di base ...
Reto Koradi

3

C #, 173-10% = 155.7 171.0, 177.3

Questo non convalida e cerca solo ;e }caratteri. Presuppone che tutti i {personaggi precedano qualsiasi ;personaggio. La cosa più difficile che ho trovato è stata quella di non inserire a {}nel mezzo di un numero Ricci.

Interruzioni di riga e rientri per maggiore chiarezza:

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

È possibile salvare un byte utilizzando var anziché char nei loop foreach.
raznagul,

@DLosc, scusa, sono stato confuso dal bonus n. 1. Ho pensato che si applicava all'output piuttosto che all'input.
Hand-E-Food,

2

Java 326 byte - 10% = 294 byte

È un programma completo scritto in 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));}}}

Sono sicuro che può essere molto più breve ma non posso avere molto tempo ora per ottimizzarlo


@DLosc dannazione, giusto, e ho pensato di poter avere un bel risultato con java :(
user902383

inoltre: l'ottimizzazione comune su Java è di evitare la public lezione precedente
masterX244

sostituisci public static void main(String[]c){constatic{
das_j il

2

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

(Ne ho aggiunto uno per l'uso -rprima di richiedere il bonus del 10%; spero sia corretto)

/;/{
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 versione completa mostra che la maggior parte di quanto sopra è la conversione tra decimale e unario:

#!/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

Sfortunatamente, questa domanda dice esplicitamente che è richiesto il decimale, motivo per cui ho disturbato la conversione.
Toby Speight,

Hai ragione, il che è un po 'sorprendente per me dal momento che escludere unario non era la mia intenzione. Vabbè, suppongo che sia troppo tardi per cambiare la domanda ora. Ribadisco il mio +1, signore.
DLosc,

2

Perl, 183 177

Questa potrebbe non essere la risposta Perl più breve, ma penso che sia abbastanza interessante pubblicare (input in $_, output come valore di ritorno):

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

Osserviamo che Curly è semplicemente notazione quaternaria (base-4). Siamo leggermente ostacolati dalla mancanza di supporto nativo da parte di Perl per il quaternario, ma fortunatamente ogni quaternit ha due bit in binario e possiamo leggere e scrivere binario. Quindi abbiamo il seguente:

  1. Ricci in decimali: converti ogni cifra Riccia in 2 cifre binarie, concatena e converti in decimale
  2. Da decimale a riccio: stampa il numero in binario (forzando un numero pari di cifre), quindi converti ogni coppia di bit in riccio.

Versione estesa

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 $_ <= {};;;
    }
}

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

Prova a eseguire lo snippet di seguito

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>


Potresti per favore pubblicare il tuo codice attuale? Inoltre, il tuo punteggio è 94,5.
Erik the Outgolfer,

@ErikKonstantopoulos il mio codice effettivo è stato pubblicato nella parte superiore dello snippet di test. Ora è anche in cima alla risposta. Per quanto riguarda il punteggio (che dovrebbe essere in byte), mi sento sempre divertente misurare metà (o meno) byte e preferisco il rouniding up
edc65

edc65: Sì, ma arrotondare fa male! 94,5 <95 quindi punteggio più piccolo, il che significa che probabilmente batte più contributi. Inoltre, la "parte superiore dello snippet" non è il luogo in cui mostrare il codice.
Erik the Outgolfer,

1

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

Utilizza la ricorsione per convertire i decimali in forma riccia. Rimuovere il segno di spunta per ignorare i personaggi al di fuori di /[;{}]/aumenta il punteggio 0.4al momento.

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

Ora è riparato. Grazie per aver segnalato il bug; il punteggio è stato aggiornato.
Value Ink

1

Perl 5, 154 ( 185 170 byte - 10% + 1 penalità)

$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 risolvono i ricci.
La generazione dei ricci è fatta in modo diverso.

Test

Il file di test contiene anche i casi bonus

$ 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

Aggiunta la penalità -1 per -p. $ B = $ r <2? "{}": ""; è stato aggiunto ad eccezione di 0 & 1. {} ;;; è l'ingresso nel test.
LukStorms,

Ci è voluto del tempo per testarlo. Ora è riparato. :)
LukStorms,

Penso che la penalità +1 arrivi dopo il bonus del -10%.
Erik the Outgolfer,

Osservazione interessante Non sono sicuro che ora dovrebbe essere, ma ha senso, quindi l'ho cambiato comunque. Non che cambi il punteggio finale.
LukStorms,

1

Retina , 69 64 byte

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

Prova Test Suite


Spiegazione

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

Decomporre le parentesi più interne in solo ;s. Ciclo fino a quando non ci sono più parentesi graffe.

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

Converti tra decimale e unario ;

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

Trova la corsa più lunga di ;questo è un multiplo di 4 e annida tra parentesi graffe, esegui il ciclo fino a quando non esistono più corse di 4+.

^;|^$
{}$&

Se il numero di ricci risultante inizia con ;o è una stringa vuota, aggiungi {}in primo piano.


1

Python 2 , 157 byte -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

Provalo online!

Una risposta Python 2 più giocosa che gestisce i casi bonus. Non volevo necro post morti con questo come commento, quindi eccolo qui.

Funziona dall'interno in numeri ricci, aggiungendo 4 ^ (il numero di parentesi graffe finali rimaste nella stringa) alla somma per ogni punto e virgola trovato. Se la stringa è un numero, crea ricorsivamente il numero riccio allo stesso modo della grammatica fornita.


Questo e'imbarazzante. Ho anche avuto casi di test lì per numeri inferiori a 2. Risolto per +5 byte in totale.
Arnold Palmer,

@DLosc Giuro che di solito non sono così male. Risolto e giocato a golf un po 'per renderlo un po' più competitivo.
Arnold Palmer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.