Compruebe si una cadena está hecha completamente de la misma subcadena

24

Esto se toma de esta pregunta (con permiso del curso). Citaré:

Cree una función que tome una cadena, y debería devolver verdadero o falso en función de si la entrada consiste solo en una secuencia de caracteres repetida. La longitud de la cadena dada siempre es mayor que 1 y la secuencia de caracteres debe tener al menos una repetición.

Algunos ejemplos:

'aa' //true
'aaa' //true
'abcabcabc' //true
'aba' //false
'ababa' //false
'weqweqweqweqweqw' // false

Específicamente, la comprobación de una cadena estrictamente compuesta de subcadenas repetidas ( Actualización ) puede generar cualquier representación verdadera o falsa, pero no se genera ningún error. Cuerdas estrictamente alfanuméricas. De lo contrario, el código estándar de las reglas de golf. Este es Code Golf, por lo que gana la respuesta más corta en bytes para cada idioma.

ouflak
fuente
44
Hm, iba a cerrar este desafío como un imbécil de ese , pero noté que el otro puntúa en el recuento de personajes. Entonces, tal vez deberíamos cerrar el otro (también tiene una respuesta aceptada) como un engañado de este.
Erik el Outgolfer
Continuemos esta discusión en el chat .
Erik the Outgolfer

Respuestas:

11

Brachylog , 4 3 bytes

ġ=Ṁ

Pruébalo en línea!

Explicación

ġ=Ṁ    Implicit input, say "abcabc"
ġ      Split into chunks of equal lengths (except maybe the last one): ["abc","abc"]
 =     Apply the constraint that all of the chunks are equal,
  Ṁ    and that there are multiple of them.

El programa imprime true.si se pueden satisfacer las restricciones, y false.si no.

Zgarb
fuente
Estaba luchando por tratar de conseguir algo ~j↙o =Ṁctrabajar antes de notar que publicaste esto hace una hora
Cadena no relacionada
44
Oh, sí, esto podría ser un byte más corto:ġ=Ṁ
Cadena no relacionada
( es una variable restringida a ser una lista de dos o más elementos)
Cadena no relacionada
1
@UnrelatedString Genial, gracias! No pensé en consultar la página wiki de variables.
Zgarb
1
Muchas respuestas geniales, y la respuesta LUA tiene un lugar especial en mi corazón. La respuesta de Arnauld es particularmente dulce ya que la pregunta original en la que basé esto (no el engaño) en realidad está etiquetada con Javascript. Principalmente seleccionando este solo porque parece ser el más corto en general para todos los idiomas y, como esta es mi primera pregunta, recibo una insignia.
ouflak
19

JavaScript (ES6), 22 bytes

Devuelve un valor booleano.

s=>/^(.*)\1+$/.test(s)

Pruébalo en línea!


Sin una expresión regular,  33  29 bytes

Devuelve null(falso) o un objeto (verdadero).

s=>(s+s).slice(1,-1).match(s)

Pruébalo en línea!

NB: Técnicamente, s se convierte en una expresión regular para match () , por lo que el título anterior es una mentira.

Arnauld
fuente
9

grep, 19

grep -qxE '(.+)\1+'

Prueba

while read; do 
  <<<"$REPLY" grep -qxE '(.+)\1+' && t="true" || t="false"
  echo "$REPLY: $t"
done < infile 

Salida:

aa: true
aaa: true
abcabcabc: true
aba: false
ababa: false
weqweqweqweqweqw: false
Thor
fuente
9

Japt , 6 bytes

²é ¤øU

Guardado un byte gracias a @Shaggy

Pruébalo en línea!

        Implicit input, stored in variable 'U'
²       U+U, "abcabc" -> "abcabcabcabc"
 é      Rotate 1 char to the right "abcabcabcabc" -> "cabcabcabcab"
   ¤    Remove first two chars, "cabcabcabcab" -> "bcabcabcab"
    øU  Check if U is in the above
Encarnación de la ignorancia
fuente
Nice one :) Puedes reemplazarlo p<space>por ²para guardar un byte.
Shaggy
9

Java, 25 24 bytes

-1 byte gracias a Olivier Grégoire!
Respuesta aburrida de la expresión regular

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

Pruébalo en línea!

Es solo 1 byte más largo que la respuesta de Python aaaaa estoy atado ahora :)

Benjamin Urquhart
fuente
3
Puede eliminar el final $ya que el matchesmétodo es una coincidencia exacta, no una coincidencia de subcadena de forma predeterminada.
Olivier Grégoire
Olvidé matchesagrega el suyo $a la expresión regular. ¡Gracias!
Benjamin Urquhart
7

Excel, 26 bytes

=FIND(A1,A1&A1,2)<=LEN(A1)

Entradas de A1, salidas a cualquier celda que ponga esta fórmula.

Sophia Lechner
fuente
Podría guardar 4 bytes si definió un nombre de rango de una sola letra (por ejemplo A) y lo configuró como su entrada.
i_saw_drones
@i_saw_drones: creo que eso no está permitido por las reglas estándar de E / S: aquí hay un enlace a la meta respuesta que se aplicaría a ese método; Actualmente está en -36 votos.
Sophia Lechner
Disculpas que no había visto esa publicación, aunque pensando en ello, ¿no es A1también una "variable" ya que contiene el valor de entrada? :)
i_saw_drones
1
Me sentiría así si estuviera haciendo algo especial con el hecho de que es A1 específicamente, como si confiara de alguna manera en que su ROW (_) es 1. Sin embargo, es la forma más natural de proporcionar una función de Excel con Una entrada arbitraria.
Sophia Lechner
7

R , 28 bytes

grepl("(.+)\\1+$",scan(,''))

Pruébalo en línea!

Versión simple de Regex. R es (a veces) muy similar a Python, por lo que es similar a la respuesta regex de Python 2 de TFeld, ¡aunque más corta!

Pregunta (si alguien sabe la respuesta)

Todavía estoy confundido por qué esto funciona, ya que la subcadena puede ser de cualquier longitud y siempre funcionará, y aún funciona cuando agrego una letra al frente de una cadena válida, como "cABABABABAB". Si personalmente leo la expresión regular, veo (.+), que captura cualquier grupo de cualquier longitud. Y entonces\\1+$ que repite el grupo capturado varias veces hasta el final.

Entonces, ¿por qué no captura solo "AB" y descubre que se repite hasta el final de la cadena, especialmente porque no hay ninguna restricción especificada sobre dónde puede comenzar la subcadena?

Sumner18
fuente
1
Interesante, esto parece ser un error en el motor regex de R. Agregar la opción perl=TRUEhace que coincida con cABABAB, como era de esperar. Ejecutar grep -E '(.*)\1+$'en bash también coincide con cABABAB, aunque grep -Eusa ERE, se supone que admite el mismo sabor regex R.
Grimmy
2
Supongo que esta es una optimización aplicada incorrectamente. Cambiar .+al comienzo de un patrón a ^.+es una optimización importante, pero si .+está dentro de capturar parens deja de ser válido.
Grimmy
6

Jalea ,  5  4 bytes

¡Ahora veo que la forma óptima es seguir el método de xnor !

Ḋ;Ṗw

Un enlace monádico que acepta una lista de caracteres y genera un número entero: la longitud más corta posible de un segmento repetido o cero si no existe ninguno. Tenga en cuenta que cero es falsey mientras que los números que no son cero son verdaderos en Jelly.

Pruébalo en línea!

¿Cómo?

Ḋ;Ṗw - Link: list of characters, S   e.g. "abcabcabc"   or "abababa"
Ḋ    - dequeue S                           "bcabcabc"       "bababa"
  Ṗ  - pop from S                         "abcabcab"       "ababab"
 ;   - concatenate                "bcabcabcabcabcab"       "bababaababab"
   w - first index of sublist     3  ^---here!             0  (not found)
Jonathan Allan
fuente
4

Wolfram Language (Mathematica) , 24 23 bytes

StringMatchQ[x__..~~x_]

Pruébalo en línea!

StringMatchQ[           (*a function that checks if its input (string) matches:*)
             x__..      (*a sequence of one or more characters, repeated one or more times*)
                  ~~x_] (*and one more time*)
attinat
fuente
3

PowerShell, 23 24 bytes

+1 byte para coincidir completamente con las reglas

"$args"-match"^(.+)\1+$"

Pruébalo en línea!

Bastante aburrido. Basado en las otras respuestas de Regex. ¡Afortunadamente, PowerShell no se usa \como personaje de escape!

Gabriel Mills
fuente
vuelve trueparaaabcabc
mazzy
1
@mazzy acaba de arreglar!
Gabriel Mills
3

C # (compilador interactivo de Visual C #) , 70 bytes

Adaptación descarada de xnor ( 46 bytes )

s=>(s+s).Substring(1,s.Length*2-2).Contains(s)

Mi solución no Regex:

s=>s.Select((x,y)=>y).Count(z=>s.Replace(s.Substring(0,z+1),"")=="")>1

Explicación:

Reemplace cada posible subcadena que comience en el índice 0 con una cadena vacía. Si el resultado es una cadena vacía, la cadena está hecha completamente de esa subcadena. Como esto incluye evaluar toda la cadena consigo mismo, la cantidad de resultados esperados debe ser mayor que 1.

Ejemplo: abcabc

Posibles subcadenas que comienzan en el índice 0:

'a', 'ab', 'abc', 'abca', 'abcab', 'abcabc'

Si los reemplazamos con cadenas vacías

Substring          Result

'a'         =>     'bcbc'
'ab'        =>     'cc'
'abc'       =>     ''
'abca'      =>     'bc'
'abcab'     =>     'c'
'abcabc'    =>     ''

Dado que hay una subcadena distinta de 'abcabc' que devuelve una cadena vacía, la cadena está hecha completamente de otra subcadena ('abc')

Pruébalo en línea!

Innat3
fuente
3

Python 3 , 62 60 56 54 bytes

-4 bytes gracias a ArBo

lambda s:s in(len(s)//l*s[:l]for l in range(1,len(s)))
  1. Iterar sobre todos los prefijos posibles en la cadena.
  2. Intenta construir la cadena fuera del prefijo.
  3. Devuelve si esto tiene éxito con algún prefijo.

Pruébalo en línea!

movatica
fuente
1
¡Buena respuesta! El f=puede ser dejado caer; Generalmente se permiten funciones anónimas. Además, al cambiar a Python 2 y verificar la membresía de una lista en lugar de la anyconstrucción, puede obtener 55 bytes
ArBo
1
Buena captura con la lista de miembros, gracias! No cambiaré a Python 2, ya que esto es como cambiar el idioma, que obviamente no es el punto aquí;) Además, ¿hay una manera conveniente de probar una función anónima en TIO, manteniendo el conteo de bytes?
movatica
1
@movatica En el encabezado, ponga `f =` (\ es el carácter de continuación de línea en python)
Artemisa apoya a Monica el
Molesto, \ es también un personaje de escape. Aquí, sin formato de código, es lo que debe poner en el encabezado: f = \
Artemis es compatible con Monica
2

Japt , 10 bytes

Devuelve un número positivo si es verdadero y 0 si es falso. Si desea una salida bool, simplemente agregue la bandera

å+ k@rXÃÊÉ

å+ k@rXÃÊÉ      Full program. Implicit input U.
                    e.g: U = "abcabcabc"
å+              Take all prefixes 
                         U = ["a","ab","abc","abca","abcab","abcabc","abcabca","abcabcab","abcabcabc"]
   k@           Filter U by:
     rXÃ        Values that return false (empty string)
                when replacing each prefix in U
                e.g: ["bcbcbc","ccc","","bcabc","cabc","abc","bc","c",""]
                                take ↑                             and ↑
                     U = ["abc","abcabcabc"]
         ÊÉ     Get U length and subtract 1. Then return the result

Pruébalo en línea!

Luis felipe De jesus Munoz
fuente
2

Casco , 6 bytes

Ṡ€ȯhtD

Pruébalo en línea!

Siento que este es un byte más que óptimo, pero no pude encontrar un arreglo que hiciera la composición explícita ȯ innecesaria la .

Explicación

Ṡ€      Find the argument in the result of applying the following function to the argument
  ȯhtD  Duplicate the argument, then remove the first and last elements.
Sophia Lechner
fuente
2
€htD¹evita el ȯ.
Zgarb
¡Eso es fantástico! Lo había pensado λ€htD¹pero no me di cuenta de que las lambdas se agregarían implícitamente
Sophia Lechner
2

Mathematica 11.x, 74 bytes

{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&

donde, en todo momento, #representa la cadena de entrada y

StringCases[#,<pattern>]

encuentra subcadenas de la cadena de entrada que coinciden con el patrón

StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="") 

Este patrón requiere coincidencias, xdebe comenzar al comienzo de la cadena y debe cumplir la condición de que (1) la coincidencia no sea la cadena de entrada completa y (2) si reemplazamos las ocurrencias de la coincidencia en la cadena de entrada con la cadena vacía obtenemos la cadena vacía. Finalmente, comparando la lista de coincidencias con la lista vacía,

{}!=

es Truesi la lista de coincidencias no está vacía yFalse si la lista de coincidencias está vacía.

Casos de prueba:

{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["aa"]
(*  True  *)
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["aaa"]
(*  True  *)
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["abcabc"]
(*  True  *)

y

{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["aba"]
(*  False  *)
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["ababa"]
(*  False  *)
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["weqweqweqweqweqw"]
(*  False  *)
Eric Towers
fuente
2

Python 3, 84 bytes

import textwrap
lambda s:any(len(set(textwrap.wrap(s,l)))<2 for l in range(1,len(s)))

Usa textwrap.wrap(gracias a esta respuesta ) para dividir la cadena en trozos de longitud npara probar cada posible longitud de subcadena repetida. Las piezas divididas se comparan entre sí agregándolas a un conjunto. Si todas las piezas son iguales, y el conjunto es de longitud 1, entonces la cadena debe ser una cadena repetitiva. Utilicé en <2lugar de ==1porque guarda un byte, y se garantizó que la longitud de la cadena de entrada sería mayor que cero.

Si no hay npara qué subcadenas repetidas de longitud ncomponen la cadena completa, entonces devuelve falso para toda la función.

Delya Erricson
fuente
2

05AB1E , 5 bytes

El método de xnor de la pregunta anterior también parece ser óptimo en 05AB1E.

«¦¨så

Pruébalo en línea! o como un conjunto de pruebas

Explicación

«       # append input to input
 ¦¨     # remove the first and last character of the resulting string
   så   # check if the input is in this string
Emigna
fuente
1
Por supuesto ... Estaba a punto de responder 05AB1E cuando vi que no había ninguna. Colega me hizo algunas preguntas y habló sobre sus vacaciones. Miro hacia atrás a la pantalla: una nueva respuesta. Tada, venció de nuevo XD
Kevin Cruijssen
@KevinCruijssen: Eso es típico. Me ha pasado
muchas
2

Limpio , 73 bytes

No usa expresiones regulares.

import StdEnv,Data.List
$s=or[isPrefixOf s(cycle t)\\t<-tl(tails s)|t>[]]

Pruébalo en línea!

Define $ :: [Char] -> Bool.
Comprueba si la cadena dada es un prefijo de la repetición de cualquier subcadena tomada desde el final.

Οurous
fuente
2

C ++ (gcc) , 36 bytes

#define f(x)(x+x).find(x,1)<x.size()

Pruébalo en línea!

Otro puerto de la solución de xnor. Utiliza una macro para expandir el argumento en la expresión. Se supone que el argumento es de tipo std::string.

jxh
fuente
1

QlikView Variable, 27 bytes

Esto debe definirse como una variable, que luego le permite pasar parámetros, por ejemplo, $1como su valor de entrada.

Devuelve 0o -1(equivalente a la TRUE()función de QlikView ).

=substringcount($1&$1,$1)>2
i_saw_drones
fuente
1

Rápido, 196 bytes

func r(s:String)->Bool{guard let k=s.dropFirst().firstIndex(where:{$0==s.first}) else{return false};let v=s[...k].dropLast();var w=v;while s.hasPrefix(w) && s.count>=(w+v).count{w+=v};return s==w}

Pruébalo en línea!

onnoweb
fuente
No uso Swift, pero estoy seguro de que se pueden eliminar espacios en blanco adicionales
Benjamin Urquhart
193 bytes usando la sugerencia de @benjamin.
Artemisa apoya a Mónica el
@ArtemisFowl o incluso 123 bytes
Roman Podymov
1

Rojo , 72 bytes

func[s][repeat i length? s[parse s[copy t i skip some t end(return 1)]]]

Pruébalo en línea!

Devoluciones 1paraTrue

Galen Ivanov
fuente
1

T-SQL, 47 bytes

Usando el método de @ Xnor :

DECLARE @ varchar(max)='ababab'

PRINT sign(charindex(@,left(@+@,len(@)*2-1),2))

Mantener la respuesta anterior, ya que contiene un buen golf (67 bytes)

DECLARE @y varchar(max)='abababa'

,@ INT=0WHILE
replace(@y,left(@y,@),'')>''SET
@+=1PRINT @/len(@y)^1

Explicación: Este script intenta repetidamente reemplazar la entrada '@y' con los primeros caracteres '@' de la entrada '@y' con nada, mientras aumenta '@'.

si reemplaza 'ab' en 'ababab' con nada, tiene una cadena vacía

Finalmente, el resultado estará vacío. Si esto sucede cuando la variable del bucle es igual a la longitud del varchar, el criterio es falso / 0 porque '@' = len (@y) (no hubo varchar repetido).

iif(@=len(@y),0,1)

se puede jugar golf en esto

@/len(@y)^1

porque la longitud de '@y' no puede ser 0 y '@' nunca excederá la longitud de @y.

Pruébalo en línea

t-clausen.dk
fuente