Debido a que no puedo concentrarme en ninguna tarea durante más de 5 segundos, a menudo me encuentro separando palabras en subcadenas, cada una de las cuales tiene una longitud diferente y no contiene caracteres repetidos. Por ejemplo, la palabra "pasta" podría estar dividida en "pasado" y "a", "pas" y "ta", o "pa" y "sta" y obtendrá la imagen.
Sin embargo, debido a que recordar todas las combinaciones es difícil, generalmente solo selecciono una, y me gusta seleccionar la más agradable. Consideramos que la mejor manera de ser la que tiene la "puntuación" más baja. Su tarea será, dada una palabra, imprimir su puntaje, dadas las siguientes reglas complicadas.
Puntuación
Descripción de cómo calificar una palabra:
Una palabra es una cadena de caracteres latinos, las letras mayúsculas deben reemplazarse por 2 de la misma letra minúscula (por lo que "Box" se convierte en "bbox")
Un segmento es una subcadena contigua (estricta) de una palabra y no debe contener ningún carácter dos veces ("ella", "re", "h" son todos segmentos válidos de "Aquí" ("aquí"), pero "hh" y "ere" no lo son)
Una segmentación es un conjunto de segmentos de diferentes longitudes que, cuando se unen, forman la palabra original ("tre" y "e" hacen "árbol"), y que no pueden segmentarse más dentro de la segmentación (es decir, "ba" tiene una sola segmentación, "ba", y "alp" y "habet" no es una segmentación válida de "alfabeto", porque cualquiera de estos podría segmentarse aún más (por ejemplo, en "a" & "lp" y "habet", que ahora es una segmentación válida ("habet" no se puede segmentar sin formar un segmento de longitud 2 o 1))).
El puntaje de una segmentación es la suma de los puntajes de cada carácter distinto que aparece en la palabra original (una vez que se han reemplazado las mayúsculas)
La puntuación de los personajes se explica a continuación.
El puntaje de una palabra es el puntaje de su mejor segmentación posible (con el puntaje más bajo)
Si no existen segmentaciones válidas para una palabra (por ejemplo, "Brass" ("bbrass"), que no se puede segmentar porque la primera "b" y la última "s" tendrían que estar en sus propios segmentos, lo que resultaría en dos segmentos de la misma longitud), entonces debe mostrar el texto "mal", de lo contrario, debe mostrar la puntuación de la palabra.
Puntuación de personaje
La puntuación de los caracteres se basa en cuántas veces aparece el carácter y las ponderaciones de los segmentos en los que aparece. Las ponderaciones de los segmentos dependen de las longitudes del segmento y del múltiplo común más bajo de las longitudes de todos los segmentos en La segmentación.
segment weighting = lowest common multiple of lengths segments / length of segment
Considere la palabra "oliva", que podría segmentarse como "ol" y "ive", y visualizarse como 2 cajas de la misma área, una de "ol" con peso 3 y una de "ive" con peso 2 (LCM de 6).
ol
ol ive
ol ive
Esto está destinado a representar las dos cajas, una hecha de 3 "ol" y otra hecha de 2 "ive" s. Alternativamente, podría ser "o" y "en vivo" (MCM de 4)
o
o
o
o live
El puntaje de cada carácter es la suma de los pesos de los segmentos en los que aparece, multiplicado por el número de veces que aparece después de reemplazar las mayúsculas (por lo que si aparece dos veces, se le cobrará el doble por cada vez que tenga que decirlo). )
character score = character count * sum(segment weights in which character appears)
Ejemplo de puntaje
Tomamos la palabra "caer", solo se puede segmentar en "fal" y "l". El mínimo común múltiplo de 3 y 1 es 3, por lo que "fal" tiene peso 1 y "l" tiene peso 3.
l
l
fal l
Pasando por cada personaje ...
"f" aparece una vez, y está en el segmento "fal" con peso 1, por lo que tiene puntaje 1 * 1 = 1
"a" también aparece solo una vez, tiene una suma de pesos de 1, por lo que tiene una puntuación de 1 * 1 = 1
"l" aparece dos veces y aparece en "fal" (peso 1) y "l" (peso 3), por lo que tiene puntaje 2 * (1 + 3) = 8
La suma de estos es 10 (el puntaje de la segmentación y de la palabra, ya que esta es la mejor segmentación). Aquí está esto en el mismo formato que los ejemplos a continuación:
fall = fal l
2*1 [fa] + 2*(1+3) [ll] = 10
Calificaciones de ejemplo
Estos ejemplos de calificaciones pueden o no ayudar:
class -> clas s
3*1 [cla] + 2*(4+1) [ss] = 13
fish -> fis h
3*1 [fis] + 1*3 [h] = 6
eye -> e ye
1*1 [y] + 2*(1+2) [ee] = 7
treasure -> treas u re
3*2 [tas] + 2*2*(2+5) [rree] + 1*10 [u] = 44
Wolf -> w wolf
3*1 [olf] + 2*(1+4) = 13
book
evil
"libro" es una palabra malvada, por lo que no tiene puntaje.
Tenga en cuenta que el "tesoro" se puede segmentar de varias maneras, pero la segmentación mostrada se beneficia de tener las letras más frecuentes ("r" y "e") en los segmentos más largos, por lo que no tienen tanto peso. La segmentación "t" y "re" y "asure" darían el mismo resultado, mientras que "Treas" y "ur" y "e" sufrirían, con "e" con una puntuación de 2 * (1 + 10 + 2 ) = 24 por sí solo. Esta observación es realmente el espíritu de todo el ejercicio. Un ejemplo de una puntuación incorrecta de "tesoro" (incorrecta porque no se deriva de la puntuación de la mejor segmentación (que con la puntuación más baja)):
treasure = treas ur e
3*2 [tas] + 2*(2+5) [rr] + 1*5 [u] + 2*[2+10] = 49
Entrada
Una sola cadena que contiene solo caracteres latinos de cualquier caso ("caballo", "Caballo" y "hOrSe" son todas entradas válidas) que puede ser aceptada por STDIN, argumento de línea de comando, argumento de función o de otro modo si su idioma de elección no es compatible con ninguno de los mencionados anteriormente.
Salida
Debe generar el puntaje de la palabra, que es un número entero positivo mayor que 0, o "malvado" si no existe segmentación. La salida debe ser STDOUT o el argumento de retorno de una función, a menos que su idioma de elección no soporte ninguno de estos, en cuyo caso haga algo deportivo.
Ejemplos
No espero que imprima todo esto, todo lo que quiero es el puntaje de la palabra, o la salida "mal", por ejemplo (entrada seguida de salida)
eye
7
Eel
evil
a
1
Establishments
595
antidisestablishmentarianism
8557
No me preocupa el rendimiento, si puede anotar casi cualquier palabra de 15 letras (después de reemplazar las mayúsculas) en menos de un minuto en una máquina sensible (intencionalmente vaga), eso es suficiente para mí.
Este es el código de golf, que gane el código más corto.
Gracias a PeterTaylor, MartinBüttner y SP3000 por su ayuda con este desafío.
fuente
Respuestas:
Mathematica, 373 bytes
Esto es bastante largo ... y también bastante ingenuo. Define una función sin nombre que toma la cadena y devuelve la puntuación. Se tarda aproximadamente 1 segundo en manejar
"Establishments"
, por lo que está dentro del límite de tiempo. Tengo una versión un poco más corta que usaCombinatorica`SetPartitions
, pero ya lleva un minuto"Establishme"
.Aquí hay una versión con espacios en blanco:
Podría agregar una explicación más detallada más adelante. Este código usa la segunda solución de esta respuesta para obtener todas las particiones y esta solución para asegurarse de que todas estén segmentadas al máximo.
fuente
Java 8,
15101485 bytesEsto es así por mucho tiempo. La combinatoria nunca es fácil en Java. Definitivamente se puede acortar un poco. Llamada con
a(string)
. Esto utiliza un algoritmo exponencial de memoria y tiempo; así que no esperes que funcione para entradas largas. Tarda aproximadamente medio segundo en procesarseEstablishments
. Se bloquea con un error de falta de memoria paraantidisestablishmentarianism
.Intenta aquí
Sangrado con explicación:
Esto también abusa bastante de los genéricos para reducir el recuento de bytes. Estoy bastante sorprendido de haber podido compilarlo todo.
Gracias Ypnypn :)
fuente
i.put...
línea y el bucle while; Creo quewhile(d!=0)
puede serwhile(d>0)
; no hay necesidadnew ArrayList
al final ya queArrays.asList
da un deArrayList
todos modos; en el método final puedes definirlob
como un planoList
.Arrays.asList
devuelve un no modificableArrayList
, por lo que no puedo usar eso sin obtener unOperationNotSupportedException
.b
puede ser una lista simple, peroc
debe mantenerse aList<List<String>>
. Comprobaré siwhile(d>0)
funciona mañana.C # 679 bytes
Esta solución se basa más o menos en la estructura de mi implementación de prueba original, e inicialmente fue solo una reescritura de golf, pero luego incluí todas las funciones, y ahora es horrible. Es razonablemente rápido, resolviendo establecimientos en menos de un segundo. Es un programa completo que toma la palabra de entrada como un único parámetro de ARGV.
El
Main
método comienza creando una copia de la entrada con las mayúsculas reemplazadas. Luego llamaS
al "solucionador", que devuelve el puntaje de una segmentación dada (la primera segmentación es aquella con un solo segmento que es la palabra completa). Luego imprime "mal" o el puntaje, dependiendo del puntaje.El "solucionador" (
S
) hace todas las cosas interesantes, y originalmente se desglosó en 4 métodos, que se combinaron. Funciona primero puntuando la segmentación actual, tomando nota de si es inválida (y crucialmente, si es tan inválida que no deberíamos intentar segmentarla más (por rendimiento), omitiendo el resto del cálculo si lo es) . Luego, si no se ha omitido, divide cada segmento de la segmentación en todas partes donde se puede dividir, y encuentra la mejor puntuación de todos estos (llamadas recursivasS
). Finalmente, devuelve el mejor puntaje de las segmentaciones subordinadas, de lo contrario, es su propio puntaje o no es válido si su propia segmentación es inválida.Código con comentarios:
fuente