String.prototype.isRepeated

41

ATUALIZAÇÃO : O envio de Pyth de isaacg é o vencedor!


Muitos de vocês devem ter ouvido falar que existe uma versão mais legal do JavaScript na cidade (leia ES6), que possui um método String.prototype.repeatpara que você possa fazer

"Hello, World!".repeat(3)

e pegue

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

como a saída.

Seu trabalho é escrever uma função ou um programa em um idioma de sua escolha, que detecta se uma string foi submetida a essa transformação.

ou seja, a sequência de entrada pode ser representada como uma nrepetição exata de uma sequência menor. A saída (como instrução de retorno da função ou STDOUT) deve ser verdadeira se a sequência puder ser ou falsificada se a sequência não puder ser representada como uma repetição de uma sequência menor.

Alguma amostra de entrada:

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

Observe que a última entrada é falsa, portanto ndeve ser maior que1

Regras completas

  • Escreva uma função / programa em qualquer idioma para inserir (via argumento da função / linha de comando args / STDIN) uma string
  • Retorne / imprima o valor da verdade se a sequência especificada for formada através de uma repetição exata de uma sequência menor, repetindo pelo menos duas vezes.
  • O tamanho máximo da sequência de entrada é idealmente Infinito
  • A cadeia pode ter todos os caracteres ASCII possíveis
  • Este é um pelo que o menor código em caracteres vence.
Optimizer
fonte
O que deve "" - a string vazia - retornar? (Ele contém um número infinito de cópias da cadeia vazio.)
billpg
@billpg valor falsy
Otimizador
Você está empatando por votos? A prática comum é a submissão anterior, eu acho (bem, a primeira que jogou golfe até a pontuação do empate). Mas não tenho certeza de que isso seja anotado como o desempate padrão em qualquer lugar; portanto, depende de você.
Martin Ender
O tempo entre a publicação é de apenas 30 minutos. Não considerarei isso suficiente para ganhar :). Desde que o tempo não vai mudar agora, mas os votos podem, fui com votos
Optimizer
Esta questão deve ser renomeada para xnor :) Ele é o cara!
Silviu Burcea

Respostas:

16

Pitão , 9

/:+zz1_1z

Ou

}z:+zz1_1

Ambas são traduções aproximadas da resposta python do @ xnor, exceto que elas recebem a entrada do STDIN e a imprimem. O primeiro é equivalente a:

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

0 para Falso, 1 para Verdadeiro.

A segunda linha é equivalente a:

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

Falso para Falso, Verdadeiro para Verdadeiro.

O compilador oficial do Pyth tinha um bug relacionado ao segundo, que acabei de corrigir, então o primeiro é o meu envio oficial.

isaacg
fonte
Eu estava apenas procurando uma maneira de informá-lo sobre esse bug (o booleano não é impresso). Não pensar na primeira e usando xera muito longo ...
Dennis
Sim, o bug está corrigido agora. Além disso, se você deseja relatar erros, uma boa maneira é abrir um problema no site do github, aqui: github.com/isaacg1/pyth/issues
isaacg
Ah, está. Eu não conheço o GitHub e nunca notei o painel de navegação à direita ...
Dennis
81

Python (24)

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

Verifica se a cadeia de caracteres é uma subcadeia de si concatenada duas vezes, eliminando o primeiro e o último caracteres para evitar correspondências triviais. Se for, deve ser uma permutação cíclica não trivial de si mesma e, portanto, a soma de segmentos repetidos.

xnor
fonte
8
Uma tradução trivial em Golfscript produz 10 caracteres:..+);(;\?)
Justin
3
Eu não entendo direito como isso funciona. Você pode dar um exemplo explicado manualmente de como isso lidaria com uma string?
Nzall # 16/14
8
@NateKerkhofs take abcabc. s+stransforma isso abcabcabcabc. as [1:-1]costeletas dos dois terminam bcabcabcabcab. e, em seguida, s in ...tenta encontrar abcabccomo uma substring disso. Essa substring não pode ser encontrada em nenhuma das metades originais, porque ambas foram reduzidas e, portanto, deve abranger as duas metades. Em particular, ele deve ter seu próprio fim antes do início, o que implica que deve ser composto de substrings idênticos (repetidos).
Martin Ender
6
Você corta depois de dobrar. abtorna- ababse torna- se ba, então retorna falso, enquanto aatorna- aaaase torna- se aa, que retorna verdadeiro.
histocrat 16/09/14
11
@SargeBorsch Funciona da mesma forma: qweqweqwein weqweqweqweqweqwis True.
xnor
30

Regex (sabor ECMAScript), 11 bytes

Parece um trabalho para regex!

^([^]+)\1+$

Teste aqui.

Eu escolhi o ECMAScript, porque é o único sabor (eu sei) que [^]corresponde a qualquer caractere. Em todos os outros, eu precisaria de um sinalizador para alterar o comportamento .ou usar [\s\S]três caracteres a mais.

Dependendo de como contamos a bandeira, é claro que isso pode ser um byte mais curto. Por exemplo, se estivermos contando padrão + sinalizadores (por exemplo, ignorando delimitadores), o equivalente PCRE / Perl será

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

Qual é 10 bytes, ignorando os delimitadores.

Teste aqui.

Isso corresponde apenas às seqüências de caracteres que consistem em pelo menos duas repetições de alguma substring.

Aqui está uma função ES6 completa de 26 bytes, mas afirmo que os envios de expressões regulares geralmente são válidos:

f=s->/^([^]+)\1+$/.test(s)
Martin Ender
fonte
^(.+)\1+$funciona para mim, que é de 9 bytes. Isso não funciona para você?
Optimizer
@Optimizer Tente uma string com quebras de linha.
Martin Ender
Eu tentei asd\nasd\nasd\n. Funciona
Optimizer
@Optimizer refiddle.com/refiddles/5417fb2475622d4df7e70a00 não parece trabalhar para mim (e não deve)
Martin Ender
Sim, isso não funciona. Talvez ele escapa a \ quando eu escrever \nmanualmente
Optimizer
12

CJam, 9

q__+)@+#)

Semelhante à idéia 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
fonte
+1 obrigado a upvote esta à frente da minha própria resposta CJam
Digital Trauma
Por que a necessidade da final )? Eu acho que é razoável ter -1 significa FALSO e> = 0 significa VERDADEIRO
Digital Trauma
@DigitalTrauma Eu acho que 0 é falso no CJam ... para operadores como ge ?.
precisa saber é o seguinte
@DigitalTrauma: Se é necessário, em última análise, depende do OP, mas, estritamente falando, apenas zero é considerado falso no CJam.
Dennis
@ user23013 @Dennis Mas e o #operador de localização? Certamente o resultado disso também é "verdadeiro" do ponto de vista do sucesso versus do fracasso?
Digital Trauma
7

APL, 11

2<+/x⍷,⍨x←⍞

A explicação
utiliza a entrada de seqüência de caracteres da tela
x←atribuída à variável x
,⍨concatena a seqüência de caracteres que ela
x⍷procura xna sequência resultante. Retorna uma matriz que consiste em 1 na posição inicial de uma partida e 0 em outro lugar.
+/soma a matriz,
2<verifique se a soma é maior que 2 (pois haverá 2 correspondências triviais)

TwiNight
fonte
7

CJam, 10 bytes

Eu peguei o bug CJam. Minha primeira resposta, então provavelmente pode ser jogado um pouco mais:

q__+(;);\#

Saídas -1 para FALSE e um número> = 0 para TRUE

Trauma Digital
fonte
5
Bem-vindo ao clube!
Dennis
5

GolfScript, 10 bytes

..+(;);\?)

Mais uma implementação da idéia inteligente do xnor.

Dennis
fonte
Hahaha, acabei de postar isso um minuto atrás: codegolf.stackexchange.com/questions/37851/… . Pensei em publicá-lo como uma resposta, mas achei que traduções triviais não eram interessantes.
Justin
Até chequei novas respostas dessa vez, mas não novos comentários ... Seu código está ausente ); quando não houver correspondência, ela será impressa -1. Se você postar isso como resposta, excluirei o meu com prazer.
Dennis
Eu adicionei o )logo antes que você postou sua resposta (I editou o comentário)
Justin
11
Versão melhorada (em CJam): q__+)@+#). Não funciona no GolfScript.
precisa saber é o seguinte
11
@ user23013: De novo não. Eu ia postar isso! Existem muitos CJammers por aí agora ...: P
Dennis
3

Python - 59 57

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

Festa pura, 30 bytes

Porta simples da resposta inteligente do @ xnor :

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

O código de saída é 0 para TRUE e 1 para FALSE:

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

Observe que =~dentro [[ ... ]]é o operador regex no bash . No entanto, "qualquer parte do padrão pode ser citada para forçá-lo a corresponder como uma sequência" . Então, como geralmente acontece com o bash, é muito importante fazer uma citação correta - aqui, queremos apenas verificar se há uma sub-correspondência de string e não uma correspondência de regex.

Trauma Digital
fonte
3

TI-BASIC - 32

Eu pensei em experimentar uma linguagem tokenizada. Execute com a string em Ans, retornará 0 se false e o comprimento da string repetida se true.

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

Incrível como é uma linha.

Josiah Winslow
fonte
Mas ... mas ... eu usaria o TI-BASIC: P +1
Timtech
@ Timtech Bem, repare em quem está tentando manipular as cordas no TI-BASIC: Não tente manipular as cordas no TI-BASIC. : P Isso foi tão difícil de criar e otimizar.
Josiah Winslow
Boa ideia. A manipulação de strings é uma das coisas mais difíceis de fazer. No entanto, eu postei várias respostas como esta, então eu acho que agora você tem um concorrente;)
Timtech
Pode vir! : 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

Certamente esta é a única solução válida? Por exemplo, a palavra (string) nananão é necessariamente criada a partir de"na".repeat(2)

Mardoxx
fonte
"nana"não é, mas a questão não está testando se .repeatfoi usada ou não. Em vez disso, se a cadeia é um repetida uma ou não
Optimizer
Eu sei, eu estava apenas tentando ser um espertinho: P
Mardoxx
2

ECMAScript 6 (34 36 )

Outra resposta do ES6, mas sem usar repeate usar o truque do xnor :

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

Deve ser executado no console de um navegador compatível com ES6, como o Firefox.

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

Acabou sendo bastante longo, mas as funções externas são sempre assim. Me ocorreu que eu poderia reescrever todas as funções de string substituindo-as por um loop ou por uma recursiva. Mas na minha experiência, ficaria mais tempo e, francamente, não quero tentar isso.

Após algumas pesquisas, vi soluções de alto desempenho, mas não tão inteligentes (e curtas) quanto as do xnor. apenas para ser original ... reescrevi a mesma idéia em c.

explicação:

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
fonte
1

ECMAScript 6 (59 62 67 73 )

Não é um vencedor, mas parece que deveria haver pelo menos uma resposta realmente no ES6 para esta pergunta que realmente usa a repeatfunção:

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

Deve ser executado no console de um navegador compatível com ES6, como o Firefox.

Faz muitas iterações desnecessárias, mas por que prolongar apenas para evitar isso, certo?

  • Editar # 1: salvou alguns bytes convertendo-o em uma função. Graças ao Optimizer!
  • Edit # 2: Graças a hsl pelo truque do operador spread para economizar mais bytes!
  • Edit # 3: E obrigado a Rob W. por mais 3 bytes!
Ingo Bürk
fonte
Você pode simplesmente convertê-lo em uma função para salvar mais bytes lá
Optimizer
@ Optimizer Verdadeiro, acho que não precisa ser "stdin". Você vive de acordo com o seu nome :)
Ingo Bürk
Eu não testei isso, mas você deve ser capaz de usar o operador de propagação para [...i], em vez dei.split('')
NinjaBearMonkey
11
@hsl Louco, isso funciona. Eu não sabia que o operador de propagação funciona assim. Originalmente, tentei desesperadamente usá-lo para criar uma matriz com o intervalo 0..N. Obrigado!
Ingo Bürk
11
.slice(0,j)é um caractere menor que .substr(0,j). Além disso, a conversão para um número inteiro parece desnecessária e |0pode ser removida (o uso |0na verdade reduz a utilidade do método, pois falhará em repetições que excedam 2 ^ 31).
Rob W
0

Java 8, 28 bytes

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

Experimente online.

Explicação:

Verifica se a String de entrada corresponde ao regex, onde é String#matchesincluído implicitamente ^...$para corresponder à String inteira.
Explicação do próprio regex:

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

Portanto, basicamente verifica se uma substring é repetida duas ou mais vezes (suportando novas linhas).

Kevin Cruijssen
fonte