ReRegex , 294 275 bytes
Ahorró 19 bytes usando mejores definiciones de 'función'
Yo diría que esto es bastante bueno para un lenguaje único de Regex.
La base lib permite la conversión entre Unary y Decimal (que es necesario ya que la especificación de desafío declara explícitamente decimal), pero no admite Binary; Así que tuve que escribir eso como parte del script agregando 120 bytes.
#import base
b(\d*):(_*)\2_b/b1$1:$2b/b(\d*):(_+)\2b/b0$1:$2b/b(\d+):b/$1/b:b/0/B(_*):1/B$1$1_:/B(_*):0/B$1$1:/B(_*):B/$1/j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/j(\d*),\1\d{0,7}:,?(.*)/,$2,/,((_+)_+),(\2),/,$1,/,(_+),(\1_*),/,$2,/^,(_*),$/d<$1>/j,b:u<(?#input)>b:
Pruébalo en línea!
Por expresiones regulares individuales.
#import base
b(\d*):(_*)\2_b/b1$1:$2b/
b(\d*):(_+)\2b/b0$1:$2b/
b(\d+):b/$1/
b:b/0/
B(_*):1/B$1$1_:/
B(_*):0/B$1$1:/
B(_*):B/$1/
j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/
j(\d*),\1\d{0,7}:,?(.*)/,$2,/
,((_+)_+),(\2),/,$1,/
,(_+),(\1_*),/,$2,/
^,(_*),$/d<$1>/
j,b:u<(?#input)>b:
Pasos
En primer lugar, importamos la biblioteca 'base', que da dos expresiones regulares. Uno que se convierte u<numbers>
en unario. Y uno que convierte de d<unary_underlines>
nuevo a decimal. Esto se debe a que el desafío requiere IO en base10.
Luego definimos un puñado de expresiones regulares que convierten unario en binario.
b(\d*):(_*)\2_b/b1$1:$2b/
b(\d*):(_+)\2b/b0$1:$2b/
b(\d+):b/$1/
b:b/0/
El primero de ellos, b(\d*):(_*)\2_b/b1$1:$2b/
busca b
, opcionalmente seguido por algunos dígitos binarios, luego a :
, luego cualquier cantidad de subrayados, seguido de exactamente la misma cantidad de subrayados más uno, y finalmente otro b
.
Luego reemplazamos eso con b1
seguido de los dígitos binarios de antes :
, y solo la primera mitad de los guiones bajos, y finalmente la última b
.
Entonces esto verifica si el unario no es divisible por dos, y si es así, antepone 1 a sus dígitos binarios, luego lo divide menos uno por dos.
El segundo, b(\d*):(_+)\2b/b0$1:$2b/
es casi idéntico, sin embargo, no busca un extra _
, lo que significa que solo coincide si es divisible por dos, y en este caso antepone un 0
en su lugar.
El tercero verifica si no tenemos dígitos unarios, y si es así, quita el relleno para dejar solo los dígitos binarios.
El último verifica si nunca se proporcionaron dígitos binarios, y en ese caso simplemente se va 0
.
El siguiente grupo de expresiones regulares que definimos es convertir binario nuevamente en unario, y son un poco más simples.
B(_*):1/B$1$1_:/
B(_*):0/B$1$1:/
B(_*):B/$1/
El primero de este grupo, B(_*):1/B$1$1_:/
al igual que su antítesis, detecta a B
, seguido de cualquier cantidad de dígitos unarios :1
. En B
este caso, no comprueba la coincidencia , ya que solo busca un dígito a la vez. Si esto coincide, duplica la cantidad previamente coincidente de dígitos unarios y agrega uno, luego elimina el uno.
El segundo, B(_*):0/B$1$1:/
es casi idéntico al primero, excepto que coincide con a en 0
lugar de a 1
, y no agrega un dígito unario adicional.
El último de estos, B(_*):B/$1/
comprueba si no hay más dígitos binarios, y si es así, desenvuelve el unario. A diferencia de su antítesis, esto no necesita un caso especial 0.
A continuación definimos las j
expresiones regulares, que actúan como una función de división.
j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/
j(\d*),\1\d{0,7}:,?(.*)/,$2,/
El primero, j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/
hace la mayor parte del trabajo pesado. Busca j
, opcionalmente seguido por dígitos binarios que son el "incrementador", luego una coma seguida por el incrementador, luego exactamente 8 dígitos binarios seguidos por el resto del número binario, luego a :
. El primero de los 8 dígitos se agrega al incrementador, incrementándolo así, luego todo lo que no sean esos 8 dígitos de la entrada binaria se agrega después del :
siguiente a ,
. Entonces (si estuviéramos usando 2 dígitos en lugar de 8) j,1001:
sería j1:1001:,01
entonces j10:1001,01,11
. Además, los elementos de matriz adjuntos se envuelven en B
s, para convertirlos de nuevo a unario.
El otro, j(\d*),\1\d{0,7}:,?(.*)/,$2,/
verifica si quedan menos de 8 dígitos binarios para verificar después del incrementador, y si es así, elimina todo lo que no sea la matriz envuelta en ,
s. P.ej.,_,___,
Durante y después de la creación de la matriz, definimos las expresiones regulares de comparación.
,((_+)_+),(\2),/,$1,/
,(_+),(\1_*),/,$2,/
El primero de ellos, ,((_+)_+),(\2),/,$1,/
verifica una coma seguida de una cierta cantidad de guiones bajos, luego un poco más, seguida de una coma, luego la primera cantidad de guiones bajos, que una coma. Luego lo reemplaza con la cantidad total de guiones bajos en el primer elemento rodeado por ,
s.
El último, ,(_+),(\1_*),/,$2,/
busca una coma seguida de una cierta cantidad de guiones bajos seguidos de otra coma, luego la misma cantidad o más guiones bajos y una última coma. En su lugar, esto dejará el elemento correcto.
Finalmente, cuando queda un elemento que coincide ^,(_*),$
, eliminamos las comas circundantes y las convertimos a decimal a través de d<>
. Entonces no se pueden disparar más expresiones regulares y se presenta la salida.
La entrada se coloca inicialmente en la plantilla j,b:u<(?#input)>b:
, que primero convierte la entrada decimal en unario, por ejemplo 5
-> j,b:_____b:
, luego el unario resultante en binario, j,101:
luego divide el binario (que no funciona para el ejemplo), obtiene el elemento más grande, convierte volver al decimal, y listo.