Introducción
Así que he estado perdiendo mi tiempo nuevamente investigando algoritmos de clasificación de sufijos, evaluando nuevas ideas a mano y en código. ¡Pero siempre me cuesta recordar el tipo de mis sufijos! ¿Me puede decir de qué tipo son mis sufijos?
¿Qué más a la izquierda?
Una gran cantidad de algoritmos de clasificación de sufijos (SAIS, KA, mi propio software daware) agrupan los sufijos en diferentes tipos para ordenarlos. Hay dos tipos básicos: de tipo S y tipo L sufijos. Los sufijos tipo S son sufijos que son lexicográficamente menos ( S menor) que el siguiente sufijo y tipo L si es lexicográficamente mayor ( L arger). Un tipo S más a la izquierda ( tipo LMS ) es solo eso: un sufijo de tipo S precedido por un sufijo de tipo L.
¡Lo especial de estos sufijos de tipo LMS es que una vez que los ordenamos, podemos ordenar todos los demás sufijos en tiempo lineal! ¿No es asombroso?
El reto
Dada una cadena, suponga que está terminada por un carácter especial que es menor que cualquier otro carácter en esa cadena (por ejemplo, más pequeño que incluso el byte nulo). Salida de un tipo de corrosponding char para cada sufijo.
Se puede elegir libremente qué char a utilizar para el tipo, pero yo preferiría L, S and *
para L-, S- and LMS-type
siempre y cuando todos ellos son imprimibles ( 0x20 - 0x7E
).
Ejemplo
Dado el mmiissiissiippi
resultado de la cadena (cuando se usa L, S and *
):
LL*SLL*SLL*SLLL
Por ejemplo, el primero L
se debe al hecho de que mmiissiissiippi$
es lexicográficamente mayor que miissiissiippi$
( $
representa el carácter mínimo agregado):
L - mmiissiissiippi$ > miissiissiippi$
L - miissiissiippi$ > iissiissiippi$
* - iissiissiippi$ < issiissiippi and preceeded by L
S - issiissiippi$ < ssiissiippi$
L - ssiissiippi$ > siissiippi$
L - siissiippi$ > iissiippi$
* - iissiippi$ < issiippi$ and preceeded by L
S - issiippi$ < ssiippi$
L - ssiippi$ > siippi$
L - siippi$ > iippi$
* - iippi$ < ippi$ and preceeded by L
S - ippi$ < ppi$
L - ppi$ > pi$
L - pi$ > i$
L - i$ > $
Algunos ejemplos más:
"hello world" -> "L*SSL*L*LLL"
"Hello World" -> "SSSSL*SSLLL"
"53Ab§%5qS" -> "L*SSL*SLL"
Objetivo
No estoy aquí para molestar a Peter Cordes (voy a hacer esto en stackoverflow en algún momento); Soy muy vago, así que, por supuesto, ¡esto es código golf ! La respuesta más corta en bytes gana.
Editar: el orden de los caracteres viene dado por su valor de byte. Eso significa que se comparan deben ser como C de strcmp
.
Edit2: como se indica en la salida de comentarios, debe haber un solo carácter para cada carácter de entrada. Si bien supuse que se entendería como "devolver una cadena", parece que al menos 1 respuesta devuelve una lista de caracteres individuales. Para no invalidar las respuestas existentes, le permitiré devolver una lista de caracteres individuales (o enteros que, cuando se imprimen, dan como resultado solo 1 carácter).
Consejos para tiempo lineal:
- Se puede hacer en 2 iteraciones paralelas hacia adelante o en una única iteración hacia atrás.
- El estado de cada sufijo depende solo de los primeros 2 caracteres y del tipo del segundo.
- Al escanear la entrada en dirección inversa, puede determinar L o S de esta manera:
$t=$c<=>$d?:$t
(PHP 7), donde$c
está el carácter actual$d
del tipo anterior y$t
anterior. - Ver mi respuesta PHP . Mañana otorgaré la recompensa.
c++
cadenas de estilo. Piense en ello como datos binarios.*
significa*
significa que el sufijo correspondiente es de tipoleft most s-type
.A S-type suffix that is preceeded by a L-type suffix.
.Respuestas:
Haskell ,
64534842 bytesPruébalo en línea!
Sin golf, con en
Char
lugar deInt
:fuente
z=
se pueden eliminar.go
función toma dos argumentos. El primero es el personaje que representa lo que debe usarse para describir laS
situación. El segundo es una cadena. Pasa por esa cadena de forma recursiva, eliminando el primer carácter en cada paso (eso es lo quetail
hace). El truco es que el primer argumento se establece en*
cuando el resultado anterior fue aL
, o de loS
contrario. De esa manera, en el caso en que se debe usar an*
o anS
, ese primer argumento se puede usar directamente. Espero que tenga sentido.Jalea ,
25 23 21 2019 bytesUn programa completo que imprime la lista de caracteres, usando:
(Como enlace, devuelve una lista donde todos los elementos son caracteres excepto el último, que es un cero).
Pruébalo en línea! o vea el conjunto de pruebas (con conversión a
LS*
).¿Cómo?
fuente
+
en las cadenas parece vectorize pero los resultados subyacentes no esté jalea iterables pero las cadenas (por ejemplo, tratar (!)+@/L€
O+@/L€€
, o ...)+
produce una cadena real. Esta es una característica no documentada, o lo que llamas error.Python 3,
9287746965 bytesUsos
0
paraL
,1
paraS
y2
para*
. Envuelva la cadena de entrada entre comillas; Creo que esto está permitido por convención.Pruébalo en línea!
Ejemplo de uso:
ahorrado 5 bytes gracias a Leaky Nun, 4 bytes gracias a ovs
fuente
JavaScript (ES6),
5145 bytesGuardado 6 bytes gracias a @Neil.
Una solución recursiva para el ejercicio.
fuente
f=(c,d)=>c&&(d<(d=c<(c=c.slice(1))))+d+f(c,d)
JavaScript (ES6), 52 bytes
Puerto de la respuesta de @ L3viathan.
fuente
c=1
comoc=0
...C (clang) , 88 bytes
Pruébalo en línea!
fuente
Haskell ,
7775 bytes, tiempo linealPruébalo en línea!
Cómo funciona
Esto utiliza la recursión, quitando un carácter a la vez desde el comienzo de la cadena. (El tipo de cadena de Haskell es una lista de caracteres enlazados individualmente, por lo que cada uno de estos pasos es de tiempo constante).
fuente
S, L and *
?[1,1,2,0,1,1,2,0,1,1,2,0,1,1,1]
es una lista de números de un solo dígito, no una lista de caracteres únicos. En mi caso, creo que generar una lista de números no me ahorraría ningún byte.Python 2 ,
6555 bytesVersión recursiva, basada en la respuesta de L3viathan , usando
012
comoLS*
:Pruébalo en línea!
Python 3 ,
6559 bytesSolución recursiva usando
L
,S
y*
:Se ejecuta a través de la cadena desde el frente y reemplaza todas las instancias de
LS
conL*
Pruébalo en línea!
fuente
blah if s else''
→s and blah
guarda seis bytes. En Python 2,str(blah)
→`blah`
guarda otros tres bytes en la segunda solución.PHP, 82 bytes, tiempo lineal
Camina sobre la entrada de derecha a izquierda y reemplaza cada carácter con el tipo.
Calcula el tipo dado el carácter actual y el carácter anterior (-1 o 1). Si es igual, el tipo no cambia.
fuente
strtr
PHP , 70 bytes
L = 1, S = 0, * = 2
Se necesita soporte multibyte para el último caso de prueba con los
§
bytes +3 en sumb_substr
lugarsubstr
Pruébalo en línea!
PHP , 71 bytes
L = 1, S = 0, * = 2
Pruébalo en línea!
PHP , 74 bytes
Pruébalo en línea!
fuente
$s=&$argn
muy inteligente ! Sin embargo, estoy bastante seguro de que hay una mejor respuesta;) Espero que alguien se le ocurra :)mb_substr
lugar desubstr
si la entrada no está en el rango simple de ascii. ¿Es necesario soportar el último caso de prueba?§