String.prototype.isRepeated

41

MISE À JOUR : La soumission isaacg de Pyth est la gagnante!


Beaucoup d’entre vous ont sûrement entendu dire qu’il existe une version plus fraîche de JavaScript en ville (lisez ES6), qui dispose d’une méthode String.prototype.repeatpermettant de le faire.

"Hello, World!".repeat(3)

et obtenir

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

comme sortie.

Votre travail consiste à écrire une fonction ou un programme dans la langue de votre choix afin de détecter si une chaîne a été transformée.

C'est-à-dire que la chaîne en entrée peut être représentée comme une nrépétition exacte de l' heure d'une chaîne plus petite. La sortie (en tant qu'instruction return ou STDOUT de la fonction) doit être true si la chaîne peut être ou falsy si la chaîne ne peut pas être représentée sous la forme d'une répétition de chaîne plus petite.

Quelques exemples d'entrées:

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

Notez que la dernière entrée est fausse, elle devrait donc nêtre supérieure à1

Règles complètes

  • Écrivez une fonction / un programme dans n’importe quelle langue pour saisir (via l’argument de la fonction / les arguments de la ligne de commande / STDIN) une chaîne
  • Renvoie / Imprime une valeur de vérité si la chaîne donnée est formée via la répétition exacte d'une chaîne plus petite, en répétant au moins deux fois.
  • La taille maximale de la chaîne d'entrée est idéalement Infinity
  • La chaîne peut avoir tous les caractères ASCII possibles
  • C'est un si le code le plus petit des personnages gagne.
Optimiseur
la source
Que devrait "" - la chaîne vide - retourner? (Il contient un nombre infini de copies de la chaîne vide.)
billpg
@billpg valeur de fausseté
Optimiseur
Êtes-vous décisif par des votes? La pratique courante est la soumission antérieure, je pense (enfin, le premier qui a été joué au golf jusqu'au score de égalité). Mais je ne suis pas sûr que ce soit le point de départ par défaut, donc c'est à vous de décider.
Martin Ender
Le temps entre leur affichage est seulement 30 minutes. Je ne considérerai pas cela suffisant pour gagner :). Depuis ce temps ne changera pas maintenant, mais les votes peuvent, je suis allé avec des votes
Optimizer
Cette question devrait être renommée en xnor :) C'est l'homme!
Silviu Burcea le

Réponses:

16

Pyth , 9

/:+zz1_1z

Ou

}z:+zz1_1

Ce sont deux traductions proches de la réponse python de @ xnor, à la différence près qu'elles prennent l'entrée de STDIN et l'impriment. Le premier est équivalent à:

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

0 pour faux, 1 pour vrai.

La deuxième ligne est équivalente à:

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

False pour False, True pour True.

Le compilateur officiel de Pyth avait un bogue lié au second, que je viens de corriger, le premier est donc ma soumission officielle.

isaacg
la source
Je cherchais simplement un moyen de vous informer sur ce bogue (le booléen n'est pas imprimé). Je n'ai pas pensé au premier et l'utilisation xétait trop longue ...
Dennis
Oui, le bogue est corrigé maintenant. De plus, si vous souhaitez signaler des bogues, un bon moyen peut-être d’ouvrir un problème sur le site github, ici: github.com/isaacg1/pyth/issues
isaacg le
Oh, ça y est. Je ne connais pas GitHub, et je n'ai jamais remarqué le panneau de navigation à droite ...
Dennis
81

Python (24)

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

Vérifie si la chaîne est une sous-chaîne d'elle-même concaténée deux fois, en éliminant les premier et dernier caractères pour éviter les correspondances triviales. Si c'est le cas, il doit s'agir d'une permutation cyclique non triviale d'elle-même, et donc de la somme de segments répétés.

Xnor
la source
8
Une traduction triviale dans Golfscript donne 10 caractères:..+);(;\?)
Justin
3
Je ne comprends pas très bien comment cela fonctionne. Pouvez-vous donner un exemple expliqué manuellement de la façon dont cela gérerait une chaîne?
Nzall
8
@NateKerkhofs prendre abcabc. s+sle transforme en abcabcabcabc. les [1:-1]côtelettes des deux bouts à céder bcabcabcabcab. et s in ...essaie ensuite de trouver abcabcune sous-chaîne de cela. Cette sous-chaîne ne peut être trouvée dans aucune des moitiés d'origine, car elles ont toutes les deux été raccourcies et doivent donc s'étendre sur les deux moitiés. En particulier, il doit avoir sa propre fin avant son début, ce qui implique qu'il doit être composé de sous-chaînes identiques (répétées).
Martin Ender
6
Vous le hachez après l'avoir doublé. abdevient ababdevient ba, donc il retourne faux, alors que aadevient aaaadevient aa, qui retourne vrai.
histocrat
1
@SargeBorsch Cela fonctionne exactement de la même manière: qweqweqwein weqweqweqweqweqwis True.
xnor
30

Regex (saveur ECMAScript), 11 octets

Cela ressemble à un travail pour regex!

^([^]+)\1+$

Testez-le ici.

J'ai choisi ECMAScript, car c'est la seule saveur (je sais) dans laquelle [^]correspond n'importe quel caractère. Dans tous les autres cas, il me faudrait un drapeau pour changer le comportement de .ou utiliser [\s\S]trois caractères de plus.

Selon la façon dont nous comptons le drapeau, cela pourrait bien sûr être un octet plus court. Par exemple, si nous comptons modèle + drapeaux (par exemple en ignorant les délimiteurs), l’équivalent PCRE / Perl serait

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

Ce qui correspond à 10 octets, en ignorant les délimiteurs.

Testez-le ici.

Cela correspond uniquement aux chaînes qui consistent en au moins deux répétitions de certaines sous-chaînes.

Voici une fonction ES6 complète de 26 octets, mais je maintiens que les soumissions d’expression régulière sont généralement valides:

f=s->/^([^]+)\1+$/.test(s)
Martin Ender
la source
^(.+)\1+$fonctionne pour moi, qui est de 9 octets. Ça ne marche pas pour toi?
Optimiseur
@Optimizer Essayez une chaîne avec des sauts de ligne.
Martin Ender
J'ai essayé asd\nasd\nasd\n. Cela fonctionne
Optimiseur
@Optimizer refiddle.com/refiddles/5417fb2475622d4df7e70a00 ne semble pas fonctionner pour moi (et cela ne devrait pas être le cas)
Martin Ender
Oui, ça ne marche pas. Peut-être que ça échappe au \ quand j'écris \nmanuellement
Optimiseur
12

CJam, 9

q__+)@+#)

Semblable à l'idée 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
la source
+1 obligé de revenir sur cette question avant ma propre réponse CJam
Digital Trauma
Pourquoi le besoin de la finale )? Je pense qu'il est raisonnable d'avoir -1 signifie FAUX et> = 0 signifie VRAI
Digital Trauma
@ DigitalTrauma Je pense que 0 est de la fausseté dans CJam ... pour les opérateurs comme get ?.
jimmy23013
@ DigitalTrauma: La nécessité ultime dépend du PO mais, à proprement parler, seul le zéro est considéré comme une fausseté dans CJam.
Dennis
@ user23013 @Dennis Mais qu'en est-il de l' #opérateur de recherche? Le résultat de cela est sûrement aussi la "vérité" du point de vue du succès vs de l'échec?
Digital Trauma
7

APL, 11

2<+/x⍷,⍨x←⍞

Explication
prend une chaîne de caractères à partir des
x←assignations d’ écran à une variable x
,⍨concatène la chaîne avec elle-même
x⍷recherche xdans la chaîne résultante. Retourne un tableau composé de 1 à la position de départ d'une correspondance et de 0 ailleurs.
+/somme la
2<vérification du tableau si la somme est supérieure à 2 (car il y aura 2 correspondances triviales)

TwiNight
la source
7

CJam, 10 octets

J'ai attrapé le virus CJam. Ma première réponse, donc peut probablement être joué au golf un peu plus:

q__+(;);\#

Sorties -1 pour FALSE et un nombre> = 0 pour TRUE

Trauma numérique
la source
5
Bienvenue au club!
Dennis
5

GolfScript, 10 octets

..+(;);\?)

Encore une autre implémentation de l’idée intelligente de xnor.

Dennis
la source
Hahaha, je viens de poster ceci il y a une minute: codegolf.stackexchange.com/questions/37851/… . J'ai pensé la poster comme réponse, mais je pensais que les traductions triviales sont sans intérêt.
Justin
J'ai même vérifié les nouvelles réponses cette fois-ci, mais pas les nouveaux commentaires ... Votre code manque )cependant; quand il n'y a pas de correspondance, ça va imprimer -1. Si vous voulez y répondre en guise de réponse, je supprimerai volontiers le mien.
Dennis
J'ai ajouté le )juste avant de poster votre réponse (j'ai modifié le commentaire)
Justin
1
Version améliorée (en CJAM): q__+)@+#). Cela ne fonctionne pas dans GolfScript.
jimmy23013
1
@ user23013: Pas encore. J'allais juste poster ça! Il y a trop de CJammers à ce jour ...: P
Dennis
3

Python - 59 57

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

Pure bash, 30 octets

Port simple de la réponse intelligente @ xnor :

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

Le code de sortie est 0 pour VRAI et 1 pour FAUX:

$ 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
$ 

La note en =~dedans [[ ... ]]est l'opérateur de regex dans bash . Cependant "Toute partie du motif peut être citée pour le forcer à correspondre sous forme de chaîne" . Comme c’est souvent le cas avec bash, il est très important d’obtenir des guillemets exacts. Ici, nous voulons simplement vérifier la présence d’une chaîne et non d’une correspondance regex.

Trauma numérique
la source
3

TI-BASIC - 32

Je pensais que j'essaierais un langage symbolique. Exécuter avec la chaîne dans Ans, renvoie 0 si faux et la longueur de la chaîne répétée si vrai.

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

Incroyable comme c'est un one-liner.

Josiah Winslow
la source
Mais ... mais ... j'allais utiliser TI-BASIC: P +1
Timtech le
@ Timtech Eh bien, remarquez ceux qui essaient de manipuler des chaînes dans TI-BASIC: N'essayez pas de manipuler des chaînes dans TI-BASIC. : P C'était si difficile à faire et à optimiser.
Josiah Winslow
Bonne idée. La manipulation des cordes est l’une des choses les plus difficiles à faire. Cependant, j'ai posté plusieurs réponses comme celle-ci, je suppose donc que vous avez maintenant un concurrent;)
Timtech le
L'amener sur! : 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

C’est sûrement la seule solution valable? Par exemple, le mot (chaîne) nanan'est pas nécessairement créé à partir de"na".repeat(2)

Mardoxx
la source
"nana"Ce n’est pas le cas, mais la question n’est pas de savoir s’il a .repeatété utilisé ou non. Plutôt, que la chaîne soit répétée ou non
Optimizer
Je sais, j'essayais juste d'être un imbécile: P
Mardoxx
2

ECMAScript 6 (34 36 )

Une autre réponse de ES6, mais sans utiliser repeatet utiliser le truc de xnor :

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

Doit être exécuté dans la console d'un navigateur compatible ES6 tel que Firefox.

Ingo Bürk
la source
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;}

Cela s'est avéré être assez long, mais les fonctions externes sont toujours comme ça. Il m'est venu à l'esprit que je pouvais réécrire chaque fonction de chaîne en les remplaçant par une boucle ou une récursive. Mais, selon mon expérience, les résultats seraient plus longs et, franchement, je ne veux pas essayer.

Après quelques recherches, j'ai trouvé des solutions hautes performances mais pas aussi intelligentes (et courtes) que celle de xnor. juste pour être original ... j'ai réécrit la même idée en c.

explication:

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
la source
1

ECMAScript 6 (59 62 67 73 )

Pas un gagnant, mais il semble qu'il devrait y avoir au moins une réponse dans ES6 pour cette question qui utilise réellement la repeatfonction:

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

Doit être exécuté dans la console d'un navigateur compatible ES6 tel que Firefox.

Il fait beaucoup d'itérations inutiles, mais pourquoi le prolonger pour éviter cela, non?

  • Edit # 1: Sauvegardé quelques octets en le convertissant en une fonction. Merci à Optimizer!
  • Edit # 2: Merci à hsl pour le truc de l’opérateur de propagation pour économiser plus d’octets!
  • Edit # 3: Et merci à Rob W. pour encore 3 octets!
Ingo Bürk
la source
Vous pouvez simplement le convertir en une fonction pour économiser davantage d'octets ici
Optimiseur
@Optimizer C'est vrai, je suppose que ça ne doit pas nécessairement être "stdin". Votre vie à votre nom :)
Ingo Bürk
Je n'ai pas testé cela, mais vous devriez pouvoir utiliser l' opérateur de diffusion pour [...i]au lieu dei.split('')
NinjaBearMonkey
1
@ hsl Crazy, ça marche. Je ne savais pas que l'opérateur de diffusion fonctionnait comme ça. Au départ, j'ai désespérément essayé de l'utiliser pour créer un tableau avec la plage 0..N. Merci!
Ingo Bürk
1
.slice(0,j)est un caractère plus court que .substr(0,j). En outre, la conversion en un entier semble inutile |0peut être supprimée (l’utilisation |0réduit en réalité l’utilité de la méthode car elle échouera pour les répétitions dépassant 2 ^ 31).
Rob W
0

Java 8, 28 octets

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

Essayez-le en ligne.

Explication:

Vérifie si la chaîne d'entrée correspond à l'expression régulière, où elle est String#matchesimplicitement ajoutée ^...$pour correspondre à la chaîne entière.
Explication de la regex elle-même:

^(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

Donc, il vérifie fondamentalement si une sous-chaîne est répétée deux fois ou plus (en prenant en charge les nouvelles lignes).

Kevin Cruijssen
la source