{Números rizados};

33

En el lenguaje de programación esotérico Curly, los programas consisten únicamente en llaves {}y puntos y comas ;. A pesar de este humilde conjunto de herramientas, Curly tiene literales que pueden representar cualquier número entero no negativo. Sin embargo, el formato es un poco difícil de leer para los no iniciados, así que escribamos un código para hacer la conversión por nosotros.

Formato de numeros

Los números rizados se estructuran de acuerdo con las siguientes reglas:

  1. Agregar un punto y coma agrega uno al número.
  2. Un número encerrado entre llaves se multiplica por cuatro.
  3. Los grupos de llaves pueden estar anidados pero no concatenados. Los frenos deben coincidir correctamente.
  4. Los puntos y comas fuera de un conjunto de llaves deben aparecer después, no antes.
  5. Para evitar la ambigüedad en el análisis, un número siempre debe comenzar con una llave.

Algunos ejemplos:

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

(Tenga en cuenta que la regla 5 significa que los números del 0 al 3 deben comenzar con un par vacío de llaves).

Y algunos ejemplos inválidos:

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

Aquí hay una gramática BNF para números rizados:

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

Los números como {;;;;}(más de 3 puntos y coma seguidos) o {{};}(grupos de llaves vacías innecesarias) se denominan números rizados incorrectos . Obedecen la gramática anterior y pueden evaluarse de la manera habitual, pero también son capaces de representaciones más cortas (para los ejemplos anteriores, {{;}}y {;}respectivamente).

El reto

Escriba un programa o función que ingrese / reciba una cadena. Si la cadena es un entero decimal no negativo, genera / devuelve la representación Curly adecuada (es decir, la más corta posible) para ese entero. Si la cadena es un número rizado, genera / devuelve su representación decimal.

La entrada se puede recibir a través de STDIN, argumento de línea de comando o parámetro de función. Se debe ser una cadena; es decir, no puede escribir una función que acepte cadenas para números Curly pero números enteros para números decimales.

La salida puede imprimirse en STDOUT o devolverse desde la función. Una función puede devolver un número entero cuando sea apropiado, o puede devolver cadenas en todas las situaciones.

Su programa no tiene que manejar mal de entrada (números de Curly que rompen las reglas de formato, números de punto flotante, enteros negativos, texto aleatorio), y se no se requiere para manejar números Curly indebidos (pero véase más adelante). La entrada consistirá solo en caracteres ASCII imprimibles.

Tanteo

El código más corto en bytes gana. Si su programa puede hacer tanto de lo siguiente:

  1. manejar correctamente los números rizados incorrectos, y
  2. cuando se le da un número Curly, ignore cualquier carácter adicional que no sea {};

luego reste el 10% de su puntaje. (La entrada entera nunca tendrá caracteres extraños, incluso para la bonificación).

Casos de prueba

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

Por el bono:

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

Nota: Curly aún no está implementado. Pero si esta pregunta funciona bien, puedo desarrollarla más.

DLosc
fuente
¿Cómo debería manejar el caso si no tiene un número de paréntesis coincidente? ¿o debo suponer que nunca sucederá?
user902383
@ user902383 Puede suponer que las llaves no coincidentes nunca sucederán.
DLosc
2
Iba a hacer una solución Retina, pero después de hacerla manejar una cadena Curly (solo 20 bytes), me di cuenta de que también necesita manejar enteros positivos -> Curly, así que me di por vencido.
mbomb007
@DLosc Sí, no ganaría, así que no voy a pasar el tiempo.
mbomb007
@ mbomb007 Me refería específicamente a esta pregunta, donde la solución Pyth ya es un 22% más corta que la solución CJam más corta y califica para la bonificación. De todos modos, era una pregunta retórica que intentaba decir: "No, pero aún así podría ser divertido y obtener algunos votos positivos". Sin embargo, si no está de acuerdo con la parte "divertida", está bien.
DLosc

Respuestas:

15

Pyth, 35 32 bytes - 10% = 28.8

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

Pruébelo en línea: demostración o conjunto de pruebas

editar: Resultó que accidentalmente también puedo manejar números rizados incorrectos. No fue planeado en absoluto. ;-)

Explicación:

Hay dos expresiones en el código. El primero convierte un número en un número rizado, y el segundo convierte un número rizado en un número regular. .xmanijas, cuya expresión se imprime. Intentará imprimir la primera expresión. Si no hay dígitos en la entrada, la primera expresión falla (a través de Exception). .xcaptura la excepción e imprime la segunda.

.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
fuente
2
La pistola más rápida en el oeste :( Tenía esta solución exacta, excepto que había olvidado que .[Z2era necesaria.
orlp
12

CJam, 51 47 44 41 bytes

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

Pruébelo en línea: ejecución de muestra |Banco de pruebas

Cómo funciona

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

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

En esta implementación, ces la función que satisface los requisitos. Devuelve una cadena si se le da un entero no negativo como entrada, o un entero si se le da un número rizado como entrada.

Greg Hewgill
fuente
6

Python 266 bytes - 10% = 1268.1 326.7 239.4 bytes

Chico, todavía no soy un jugador de código = /, pero ese 10% me ayudó a montón cuando mi puntaje fue todavía más de 1000!

Tengo una versión completamente desarrollada (y detallada) de este código aquí.Reconocerá la validez de los números rizados y proporcionará una interfaz en bucle para ingresar números para la prueba.

(Comentarios solo para aclaración)

Ver este código en acción

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

¡Gracias a Erik Konstantopoulos por una importante reducción de bytes! Se podría decir ... él realmente tomó un ... byte ... de mi código ... * self five *

Taylor Lopez
fuente
44
Bienvenido a PPCG! Su código contiene muchas printdeclaraciones no requeridas y un comentario, los nombres de sus variables son demasiado largos y se pueden eliminar algunos espacios en blanco. También recomiendo leer Consejos para jugar al golf en Pyrhon .
Dennis
Gran recurso, gracias! Haré los cambios apropiados a este código y veré cuán lejos me lleva. Parece que si quiero ser alguien en este sitio, necesito aprender CJam o Pyth, o escribir mi propio idioma jajaja.
Taylor Lopez
3
@iAmMortos No necesariamente . Hazlo si lo encuentras agradable, o quédate con Python si no. :)
DLosc
2
Por lo general, el golf se realiza en tres pasos: 1) haga su programa como lo haría normalmente, lo más mínimo posible (es decir, sin sentencias de depuración, sin necesidad de manejar entradas no válidas, salidas mínimas) 2) elimine lo más posible : espacios en blanco , cambie el nombre de las variables ( valuea vetc.), 3) haga cosas ingeniosas para jugar al golf : este es el punto donde necesita mirar el enlace de Dennis. ¡Tengo curiosidad por ver cuánto puedes reducir esto!
Sanchises
1
Nunca he recibido una bienvenida tan cálida en una comunidad. jajaja, creo que me gusta aquí.
Taylor Lopez
4

CJam, 87 bytes 80.1 puntaje (89 bytes - 10% de bonificación)

Versión de actualización que califica para la bonificación mientras crece en 2 bytes:

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

Pruébalo en línea

¡La primera vez que usé la recursión en CJam! Todo puede parecer un poco largo, pero las dos conversiones completamente separadas se suman.

Utilicé un caso completamente separado para convertir números menores de 4 a Curly. Probablemente sea posible evitar eso, pero plegar el manejo de casos especiales en la función recursiva no sería del todo trivial. Y agregar el extra {}como un paso de procesamiento posterior realmente no se veía mejor, aunque debería intentarlo nuevamente si pudiera ser un poco más corto.

Reto Koradi
fuente
¿No sería su puntaje 80.1?
PurkkaKoodari
44
@ Pietu1998 Gracias. No solo mis soluciones son demasiado largas, aparentemente también fallo en la aritmética básica ...
Reto Koradi
3

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

Esto no valida y solo busca ;y }caracteres. Se supone que todos los {personajes van antes que cualquier ;personaje. Lo más difícil que encontré fue no insertar un{} en medio de un número Curly.

Saltos de línea y guiones para mayor claridad:

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
fuente
Puede guardar un Byte usando var en lugar de char en los bucles foreach.
raznagul
@DLosc, lo siento, estaba confundido por el bono # 1. Pensé que se aplicaba a la salida en lugar de a la entrada.
Hand-E-Food
2

Java 326 bytes - 10% = 294 bytes

Es un programa completo escrito 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));}}}

Estoy seguro de que puede ser mucho más corto, pero ahora no puedo tener mucho tiempo para optimizarlo

usuario902383
fuente
@DLosc maldita sea, cierto, y pensé que podría tener un buen resultado con java :(
user902383
también: la optimización común en Java es evitar la public clase anterior
masterX244
reemplazar el public static void main(String[]c){constatic{
das_j
2

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

(Agregué uno para usar -rantes de reclamar el bono del 10%; espero que sea correcto)

/;/{
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 versión completa muestra que la mayor parte de lo anterior es la conversión entre decimal y 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
Toby Speight
fuente
Desafortunadamente, esta pregunta dice explícitamente que se requiere decimal, por lo que me molesté en convertir.
Toby Speight
Tienes razón, lo cual me sorprende un poco, ya que excluir a unario no era mi intención. Bueno, supongo que es demasiado tarde para cambiar la pregunta ahora. Reafirmo mi +1, señor.
DLosc
2

Perl, 183 177

Puede que esta no sea la respuesta Perl más corta, pero creo que es lo suficientemente interesante como para publicar (entrada $_, salida como valor de retorno):

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

Observamos que Curly es simplemente notación cuaternaria (base-4). Estamos un poco obstaculizados por la falta de soporte nativo de Perl para el cuaternario, pero afortunadamente, cada cuarto es dos bits en binario, y podemos leer y escribir binarios. Entonces tenemos lo siguiente:

  1. Rizado a decimal: convierta cada dígito rizado a 2 dígitos binarios, concatene y convierta a decimal
  2. Decimal a Curly: imprima el número en binario (forzando un número par de dígitos), luego convierta cada par de bits a Curly.

Versión ampliada

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

Prueba a ejecutar el fragmento a continuación

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
fuente
¿Podría por favor publicar su código real? Además, su puntaje es 94.5.
Erik the Outgolfer
@ErikKonstantopoulos mi código real se publicó en la parte superior del fragmento de prueba. Ahora está en la parte superior de la respuesta también. Sobre el puntaje (que debería estar en bytes), siempre me siento divertido midiendo la mitad (o menos) byte y prefiero redondear hacia arriba
edc65
edc65: Sí, ¡pero redondear es malo para ti! 94.5 <95, por lo tanto, un puntaje menor, lo que significa que probablemente supera más presentaciones Además, la "parte superior del fragmento" no es el lugar para mostrar su código.
Erik the Outgolfer
1

Rubí, 126.9 129.6 (144 - 10%)

Utiliza la recursividad para convertir el decimal en forma rizada. Quitar la /[;{}]/marca de verificación para ignorar caracteres fuera de aumenta la puntuación por 0.4el 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"})}
Tinta de valor
fuente
Ya está arreglado. Gracias por informar el error; La puntuación ha sido actualizada.
Value Ink el
1

Perl 5, 154 ( 185 170 Bytes - 10% + 1 Penalización)

$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 y eval resuelven los curlies.
La generación de los curlies se realiza de manera diferente.

Prueba

El archivo de prueba contiene también los casos de bonificación

$ 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
fuente
Se agregó la penalización de -1 para -p. El $ b = $ r <2? "{}": ""; se agregó con la excepción de 0 y 1. {} ;;; es la entrada en la prueba.
LukStorms
Necesitaba algo de tiempo para probarlo. Ya está arreglado. :)
LukStorms
Creo que la penalización de +1 viene después de un bono de -10%.
Erik the Outgolfer
Interesante observación. No estoy seguro de si es así, pero tiene sentido, así que lo cambié de todos modos. No es que cambie el puntaje final.
LukStorms
1

Retina , 69 64 bytes

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

Prueba Test Suite


Explicación

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

Descomponga los frenos internos en solo ;s. Haga un bucle hasta que no haya más aparatos.

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

Convertir entre decimal y unario ;

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

Encuentre la ejecución más larga de ;eso es un múltiplo de 4 y anide entre llaves, repita hasta que no existan más ejecuciones de 4+.

^;|^$
{}$&

Si el número rizado resultante comienza con ;o es una cadena vacía, agregue {}al frente.

TwiNight
fuente
1

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

Pruébalo en línea!

Una respuesta más desarrollada de Python 2 que maneja los casos de bonificación. No quería necro mensajes muertos con esto como un comentario, así que aquí está.

Funciona desde adentro hacia adentro en números rizados, agregando 4 ^ (el número de llaves finales que quedan en la cadena) a la suma de cada punto y coma encontrado. Si la cadena es un número, crea recursivamente el número rizado de la misma manera que la gramática proporcionada.

Arnold Palmer
fuente
Eso es incómodo. Incluso tuve casos de prueba allí para números menores que 2. Corregido por +5 bytes en total.
Arnold Palmer
@DLosc Juro que normalmente no soy tan malo. Se corrigió y jugó un poco para hacerlo más competitivo.
Arnold Palmer