String.prototype.isRepeated

41

ACTUALIZACIÓN : ¡la presentación Pyth de isaacg es la ganadora!


Muchos de ustedes deben haber escuchado que hay una versión más fresca de JavaScript en la ciudad (lea ES6) que tiene un método String.prototype.repeatpara que puedan hacer

"Hello, World!".repeat(3)

y obten

"Hello, World!Hello, World!Hello, World!"

como la salida

Su trabajo es escribir una función o un programa en un idioma de su elección que detecte si una cadena se ha transformado.

es decir, la cadena de entrada se puede representar como una nrepetición de tiempos exactos de una cadena más pequeña. La salida (como la declaración de retorno de la función o STDOUT) debe ser veraz si la cadena puede ser o falsa si la cadena no se puede representar como una repetición de una cadena más pequeña.

Alguna entrada de muestra:

"asdfasdfasdf"  // true
"asdfasdfa"     // false
"ĴĴĴĴĴĴĴĴĴ"     // true
"ĴĴĴ123ĴĴĴ123"  // true
"abcdefgh"      // false

Tenga en cuenta que la última entrada es falsa, por lo tanto, ndebe ser mayor que1

Reglas completas

  • Escriba una función / programa en cualquier idioma para ingresar (mediante argumento de función / línea de comando args / STDIN) una cadena
  • Devuelve / Imprime un valor verdadero si la cadena dada se forma a través de una repetición exacta de una cadena más pequeña, repitiéndose al menos dos veces.
  • El tamaño máximo de la cadena de entrada es idealmente Infinito
  • La cadena puede tener todos los caracteres ASCII posibles
  • Este es un por lo que gana el código más pequeño en caracteres.
Optimizador
fuente
¿Qué debería "" - la cadena vacía - regresar? (Contiene un número infinito de copias de la cadena vacía.)
billpg
@billpg valor Falsy
Optimizador
¿Estás rompiendo empates por votos? La práctica común es la sumisión anterior, creo (bueno, la primera que se redujo al puntaje de empate). Pero no estoy seguro de que esté escrito como el desempate predeterminado en ningún lado, así que, en última instancia, depende de usted.
Martin Ender
El tiempo entre su publicación es de solo 30 minutos. No consideraré que eso sea suficiente para ganar :). Dado que ese momento no cambiará ahora, pero los votos pueden, fui con los votos
Optimizer
Esta pregunta debe cambiarse a xnor :) ¡Él es el hombre!
Silviu Burcea

Respuestas:

16

Pyth , 9

/:+zz1_1z

O

}z:+zz1_1

Ambas son traducciones cercanas de la respuesta de Python de @ xnor, excepto que toman información de STDIN y la imprimen. El primero es equivalente a:

z = input()
print((z+z)[1:-1].count(z))

0 para falso, 1 para verdadero.

La segunda línea es equivalente a:

z = input()
print(z in (z+z)[1:-1])

Falso por Falso, Verdadero por Verdadero.

El compilador oficial de Pyth tenía un error relacionado con el segundo, que acabo de reparar, así que el primero es mi presentación oficial.

isaacg
fuente
Estaba buscando una manera de informarle sobre ese error (el booleano no se imprime). No pensé en el primero y el uso xfue demasiado largo ...
Dennis
Sí, el error ya está solucionado. Además, si desea informar de errores, una buena manera podría ser abrir un problema en el sitio de github, aquí: github.com/isaacg1/pyth/issues
isaacg
Ah, ahí está. No conozco GitHub, y nunca noté el panel de navegación a la derecha ...
Dennis
81

Pitón (24)

lambda s:s in(s+s)[1:-1]

Comprueba si la cadena es una subcadena de sí misma concatenada dos veces, eliminando el primer y el último carácter para evitar coincidencias triviales. Si es así, debe ser una permutación cíclica no trivial de sí mismo y, por lo tanto, la suma de segmentos repetidos.

xnor
fuente
8
Una traducción trivial en Golfscript produce 10 caracteres:..+);(;\?)
Justin
3
No entiendo cómo funciona esto. ¿Puede dar un ejemplo explicado manualmente de cómo esto manejaría una cadena?
Nzall
8
Toma @NateKerkhofs abcabc. s+slo convierte en abcabcabcabc. las [1:-1]chuletas de los dos extremos para ceder bcabcabcabcab. y luego s in ...trata de encontrar abcabccomo una subcadena de eso. Esta subcadena no se puede encontrar en ninguna de la mitad original, porque ambas se han acortado, por lo que debe abarcar ambas mitades. En particular, debe tener su propio fin antes de su inicio, lo que implica que debe estar formado por subcadenas idénticas (repetidas).
Martin Ender
66
Lo cortas después de doblarlo. abse ababconvierte se convierte ba, por lo que devuelve falso, mientras que aase aaaaconvierte en aa, que devuelve verdadero
histocrat
1
@SargeBorsch Funciona igual: qweqweqween weqweqweqweqweqwes True.
xnor
30

Regex (sabor ECMAScript), 11 bytes

Suena como un trabajo para expresiones regulares!

^([^]+)\1+$

Pruébalo aquí.

Elegí ECMAScript, porque es el único sabor (lo sé) en el que [^]coincide con cualquier personaje. En todos los demás, necesitaría una bandera para cambiar el comportamiento .o usar [\s\S]tres caracteres más largos.

Dependiendo de cómo contamos la bandera, eso podría ser, por supuesto, un byte más corto. Por ejemplo, si estamos contando patrón + banderas (por ejemplo, ignorando delimitadores), el equivalente de PCRE / Perl sería

/^(.+)\1+$/s

Que es de 10 bytes, ignorando los delimitadores.

Pruébalo aquí.

Esto solo coincide con cadenas que consisten en al menos dos repeticiones de alguna subcadena.

Aquí hay una función ES6 completa de 26 bytes, pero mantengo que los envíos de expresiones regulares son generalmente válidos:

f=s->/^([^]+)\1+$/.test(s)
Martin Ender
fuente
^(.+)\1+$funciona para mí, que es de 9 bytes. ¿No te funciona?
Optimizador
@Optimizer Pruebe una cadena con saltos de línea.
Martin Ender
Probé asd\nasd\nasd\n. Funciona
Optimizer
@Optimizer refiddle.com/refiddles/5417fb2475622d4df7e70a00 no parece funcionar para mí (y no debería)
Martin Ender
Sí, eso no funciona. Tal vez se escapa el \ cuando escribo \nmanualmente
Optimizador
12

CJam, 9

q__+)@+#)

Similar a la idea de xnor.

q      " Read input. ";
__+    " Duplicate twice and concatenate them together. ";
)      " Remove the last character of the longer string. ";
@+     " Insert that character at the beginning of the shorter string. ";
#)     " Find the shorter string in the longer string, and increase by one. ";
jimmy23013
fuente
+1 obligado a votar esto antes de mi propia respuesta de CJam
Digital Trauma
¿Por qué la necesidad de la final )? Creo que es razonable tener -1 significa FALSO y> = 0 significa VERDADERO
Trauma digital
@ DigitalTrauma Creo que 0 es falso en CJam ... para operadores como gy ?.
jimmy23013
@DigitalTrauma: si se necesita en última instancia depende del OP, pero estrictamente hablando, solo cero se considera falso en CJam.
Dennis
@ user23013 @Dennis ¿Pero qué pasa con el #operador de búsqueda? ¿Seguramente el resultado de eso también es "verdadero" desde la perspectiva de éxito versus fracaso?
Trauma digital
7

APL, 11

2<+/x⍷,⍨x←⍞

La explicación
toma la entrada de la cadena desde las asignaciones de la pantalla
x←a la variable x
,⍨concatena la cadena con la propia
x⍷búsqueda xen la cadena resultante. Devuelve una matriz que consta de 1 en la posición inicial de una coincidencia y 0 en otro lugar.
+/suma la
2<verificación de la matriz si la suma es mayor que 2 (ya que habrá 2 coincidencias triviales)

TwiNight
fuente
7

CJam, 10 bytes

Capté el error de CJam. Mi primera respuesta, por lo que probablemente pueda jugar un poco más:

q__+(;);\#

Salidas -1 para FALSO y un número> = 0 para VERDADERO

Trauma digital
fuente
55
¡Bienvenido al club!
Dennis
5

GolfScript, 10 bytes

..+(;);\?)

Otra implementación más de la inteligente idea de xnor.

Dennis
fuente
Jajaja, acabo de publicar esto hace un minuto: codegolf.stackexchange.com/questions/37851/… . Pensé en publicarlo como respuesta, pero pensé que las traducciones triviales no son interesantes.
Justin
Incluso busqué nuevas respuestas esta vez, pero no para nuevos comentarios ... Sin )embargo, su código falta ; cuando no hay coincidencia, se imprimirá -1. Si va a publicar eso como respuesta, con mucho gusto eliminaré el mío.
Dennis
Agregué )justo antes de que publicaras tu respuesta (edité el comentario)
Justin
1
Versión mejorada (en Cjam): q__+)@+#). No funciona en GolfScript.
jimmy23013
1
@ user23013: No otra vez. ¡Estaba a punto de publicar eso! Ya hay demasiados CJammers por ahí ...: P
Dennis
3

Python - 59 57

lambda s:any([s*n==s[:n]*len(s)for n in range(2,len(s))])
Falko
fuente
3

Bash puro, 30 bytes

Puerto simple de la respuesta inteligente de @xnor :

[[ ${1:1}${1:0: -1} =~ "$1" ]]

El código de salida es 0 para VERDADERO y 1 para FALSO:

$ for s in 'Hello, World!Hello, World!Hello, World!' 'asdfasdfasdf' 'asdfasdfa' 'ĴĴĴĴĴĴĴĴĴ' 'ĴĴĴ123ĴĴĴ123' 'abcdefgh'; do echo "./isrepeated.sh "\"$s\"" returns $(./isrepeated.sh "$s"; echo $?)"; done
./isrepeated.sh "Hello, World!Hello, World!Hello, World!" returns 0
./isrepeated.sh "asdfasdfasdf" returns 0
./isrepeated.sh "asdfasdfa" returns 1
./isrepeated.sh "ĴĴĴĴĴĴĴĴĴ" returns 0
./isrepeated.sh "ĴĴĴ123ĴĴĴ123" returns 0
./isrepeated.sh "abcdefgh" returns 1
$ 

Nota =~dentro [[ ... ]]es el operador de expresiones regulares en bash . Sin embargo, "se puede citar cualquier parte del patrón para forzarlo a que coincida como una cadena" . Entonces, como a menudo es el caso con bash, es muy importante hacer una cita correcta: aquí solo queremos verificar si hay una subcoincidencia de cadenas y no una coincidencia de expresiones regulares.

Trauma digital
fuente
3

TI-BASIC - 32

Pensé en probar un lenguaje tokenizado. Ejecutar con la cadena en Ans, devuelve 0 si es falso y la longitud de la cadena repetida si es verdadero.

inString(sub(Ans+Ans,1,2length(Ans)-1),sub(Ans,length(Ans),1)+Ans

Increíble cómo es una línea.

Josiah Winslow
fuente
Pero ... pero ... iba a usar TI-BASIC: P +1
Timtech
@Timtech Bueno, tenga en cuenta a cualquiera que intente la manipulación de cadenas en TI-BASIC: No intente la manipulación de cadenas en TI-BASIC. : P Eso fue muy difícil de hacer y optimizar.
Josiah Winslow
Buena idea. La manipulación de cuerdas es una de las cosas más difíciles de hacer. Sin embargo, he publicado varias respuestas como esta, así que supongo que ahora tienes un competidor;)
Timtech
¡Dale! : P
Josiah Winslow
3

ECMAScript 6 (189)

(function(){var S=String.prototype,r=S.repeat;S.isRepeated=function(){return!1};S.repeat=function(c){var s=new String(r.call(this,c));if(c>1)s.isRepeated=function(){return!0};return s}}());

 

< console.log("abc".isRepeated(),"abc".repeat(10).isRepeated());
> false true

¿Seguramente esta es la única solución válida? Por ejemplo, la palabra (cadena) nanano se crea necesariamente a partir de"na".repeat(2)

Mardoxx
fuente
"nana"no lo es, pero la pregunta no es probar si .repeatse usó o no. Más bien, si la cadena es repetida o no
Optimizer
Lo sé, solo estaba tratando de ser un asno inteligente: P
Mardoxx
2

ECMAScript 6 (34 36 )

Otra respuesta de ES6, pero sin usar repeaty usar el truco de xnor :

f=i=>(i+i).slice(1,-1).contains(i)

Debe ejecutarse en la consola de un navegador compatible con ES6 como Firefox.

Ingo Bürk
fuente
2

C 85

l,d;f(s){return l=strlen(s),strstr(d,strcpy(strcpy(d=alloca(l*2+1),s)+l,s)-1)-d-l+1;}

Resultó ser bastante largo, pero las funciones externas siempre son así. Se me ocurrió que podía reescribir cada función de cadena reemplazándolas por un bucle o una recursiva. Pero en mi experiencia, sería más largo y, francamente, no quiero probar eso.

Después de investigar un poco, vi soluciones de alto rendimiento pero no tan inteligentes (y cortas) como las de xnor. solo para ser original ... reescribí la misma idea en c.

explicación:

int length, 
    duplicate;
int is_repetition(char *input)
{
    // length = "abc" -> 3
    length = strlen(input);
    // alloca because the function name is as long as "malloc" 
    // but you don't have to call free() because it uses the stack
    // to allocate memory
    // duplicate = x x x x x x + x
    duplicate = alloca(length*2 + 1);
    // duplicate = a b c 0 x x + x
    strcpy(duplicate, input);
    // duplicate = a b c a b c + 0
    strcpy(duplicate + length, input);
    if (strstr(duplicate,duplicate + length - 1) != duplicate + length - 1)
        // repetition
        // e.g. abab -> abababab -> aba[babab]
        // -> first occurence of [babab] is not aba[babab]
        // but a[babab]ab -> this is a repetition
        return 1;
    else
        // not repetition
        // e.g. abc -> abcabc -> ab[cabc]
        // -> first occurence of [cabc] is ab[cabc]
        // it matches the last "cabc"
        return 0;
}
bebe
fuente
1

ECMAScript 6 (59 62 67 73 )

No es un ganador, pero parece que al menos debería haber una respuesta en ES6 para esta pregunta que realmente use la repeatfunción:

f=i=>[...i].some((_,j)=>i.slice(0,j).repeat(i.length/j)==i)

Debe ejecutarse en la consola de un navegador compatible con ES6 como Firefox.

Hace muchas iteraciones innecesarias, pero ¿por qué alargarlo solo para evitar eso, verdad?

  • Edición n. ° 1: guardado unos pocos bytes al convertirlo en una función. Gracias a Optimizer!
  • Edición n. ° 2: ¡ Gracias a hsl por el truco del operador de propagación para guardar más bytes!
  • Edición # 3: ¡ Y gracias a Rob W. por otros 3 bytes!
Ingo Bürk
fuente
Puede convertirlo en una función para guardar más bytes allí
Optimizer
@Optimizer Cierto, supongo que no tiene que ser "stdin". Su vida a su nombre :)
Ingo Bürk
No he probado esto, pero deberías poder usar el operador de propagación en [...i]lugar dei.split('')
NinjaBearMonkey
1
@hsl Crazy, eso funciona. No sabía que el operador de propagación funciona así. Originalmente intenté usarlo desesperadamente para crear una matriz con el rango 0..N. ¡Gracias!
Ingo Bürk
1
.slice(0,j)es un personaje más corto que .substr(0,j). Además, la conversión a un entero parece innecesaria |0puede eliminarse (el uso en |0realidad reduce la utilidad del método porque fallará en repeticiones que excedan 2 ^ 31).
Rob W
0

Java 8, 28 bytes

s->s.matches("(?s)(.+)\\1+")

Pruébalo en línea.

Explicación:

Comprueba si la cadena de entrada coincide con la expresión regular, donde se String#matchesagrega implícitamente ^...$para que coincida con la cadena completa.
Explicación de la expresión regular en sí:

^(s?)(.+)\1+$
^                Begin of the string
 (s?)            Enable DOTALL-mode, where `.` also matches new-lines
     (           Open capture group 1
      .+          One or more characters
        )        Close capture group 1
         \1+     Plus the match of the capture group 1, one or more times
            $    End of the string

Por lo tanto, básicamente verifica si una subcadena se repite dos o más veces (admite nuevas líneas).

Kevin Cruijssen
fuente