Encontre o padrão ideal

33

Dada uma string s composta por letras minúsculas, como

aabaaababbbbaaba

e um número inteiro positivo n , tal como 4, a produção de um comprimento- n corda t de tal modo que, quando t é repetido para o comprimento de s , que têm como muitos caracteres em comum quanto possível. Para o exemplo dado, a saída ideal seria aaba, porque possui treze caracteres em comum com a cadeia de destino:

s: aabaaababbbbaaba
t: aabaaabaaabaaaba (aaba)
   ^^^^^^^^  ^ ^^^^

e não é possível t tem mais. No entanto, para aaaaaab, existem duas saídas possíveis: aaaae aaba, cada uma com 6 caracteres em comum com a sequência de destino:

s: aaaaaab
t: aaaaaaaa (aaaa)
   ^^^^^^ 

s: aaaaaab
t: aabaaaba (aaba)
   ^^ ^^^^

Um aaaaou aabapode ser produzido, ou ambos, se você desejar. Observe que s nunca é repetido; a trilha anos dois valores repetidos de t é simplesmente ignorada.

Casos de teste

Inputs -> Valid outputs
1 a -> a
1 aa -> a
2 aa -> aa
1 ab -> a b
2 ab -> ab
1 abb -> b
2 abb -> ab bb
2 ababa -> ab
2 abcba -> ab
2 aabbbbb -> bb  (ab is not a valid output here)
3 aababba -> aab abb
3 aababbaa -> aab
3 asdasfadf -> asf
3 asdasfadfsdf -> asf adf
2 abcdefghijklmnopqrstuvwxyzyx -> yx
2 supercalifragilisticexpialidocious -> ic ii
3 supercalifragilisticexpialidocious -> iri ili ioi
4 supercalifragilisticexpialidocious -> scii
5 supercalifragilisticexpialidocious -> iapic
2 eeeebaadbaecaebbbbbebbbbeecacebdccaecadbbbaceebedbbbddadebeddedbcedeaadcabdeccceccaeaadbbaecbbcbcbea -> bb be
10 bbbbacacbcedecdbbbdebdaedcecdabcebddbdcecebbeeaacdebdbebaebcecddadeeedbbdbbaeaaeebbedbeeaeedadeecbcd -> ebbbdbeece ebdbdbeece
20 aabbbaaabaaabaaaabbbbabbbbabbbabbbbbabbaaaababbbaababbbaababaaaabbaaabbaabbbabaaabbabbaaabbaaaaaaaba -> aabbbbaaabbabbbaabba

Regras

  • Você pode assumir que a entrada será apenas uma sequência não vazia de letras minúsculas e um número inteiro positivo não maior que o comprimento da sequência.
  • Você pode receber as entradas em qualquer formato padrão e em qualquer ordem.
  • Você pode gerar uma única sequência, ou mais de uma, na forma de uma matriz, separada por novas linhas ou espaços, etc.
  • Seu código deve terminar para cada caso de teste em menos de 1 minuto em qualquer computador razoavelmente moderno.
  • Isso é , então faça seu código o mais curto possível.
ETHproductions
fonte
2
Esse desafio é de qualidade Zgarb. Bom trabalho!
Martin Ender
Estou assumindo que apenas os caracteres finais são ignorados? Portanto, você não tem permissão para ignorar caracteres principais como este: 2 abb -> baonde é construído como (b)[ab]a: o líder (b)é ignorado, [ab]está correspondendo.
Kevin Cruijssen
@KevinCruijssen Certo, o padrão deve começar a se repetir no início.
ETHproductions

Respostas:

11

Gelatina , 11 bytes

sZµṢŒrUṀṪµ€

Experimente online!

Não esperava vencer Dennis neste, então tentei fazer o FGITW (depois de tentar várias possibilidades; há mais de uma maneira de fazer 11). Cheguei mais curto, para minha surpresa.

Leva a string e a contagem como argumentos da linha de comando. Saídas em stdout.

Explicação

sZµṢŒrUṀṪµ€
s            Split {the first input} into {the second input}-sized groups
 Z           Transpose
  µ      µ€  On each of the transposed groups:
   Ṣ           Sort it;
    Œr         Run-length encode it;
      U        Rearrange it to the form {count, letter};
       Ṁ       Take the largest element (i.e. largest count)
        Ṫ      Take the second element of the pair (i.e. just the letter)

Isso usa a percepção de que a letra em cada posição do padrão deve ser a letra mais comum correspondente a essa posição. Podemos encontrar as letras correspondentes a um padrão específico, dividindo-as em grupos de tamanho padrão e transpondo. A principal razão pela qual essa solução é tão longa é que o Jelly parece não ter um caminho curto para encontrar o modo de uma lista (fiz várias tentativas, mas todos têm pelo menos seis bytes).

Geléia , 10 bytes, com base na solução @Dennis '

⁸ċ$ÞṪ
sZÇ€

Experimente online!

Essa é uma combinação da solução @Dennis e a minha; havia um modo de cinco bytes nessa solução, que eu roubei para esta solução. (Eu já tinha soluções baseadas em ⁸ċ, mas não conseguia ficar com menos de seis bytes; não tinha pensado em usarÞ .)

Explicação

µ…µ€e Ç€(com o na linha anterior) têm três bytes de comprimento (o último precisa de uma nova linha) e equivalente. Normalmente eu uso o primeiro, mas o último é mais flexível, pois permite que você mencione o argumento.

Isso torna possível classificar ( Þ) pelo número de ocorrências em ( ⁸ċ) e pegar o último elemento ( ), para encontrar o modo em apenas cinco caracteres.


fonte
5
Bom trabalho superando Dennis com seu próprio idioma! : P
HyperNeutrino 22/03
10

Mathematica, 51 bytes

#&@@@Commonest/@(PadRight@Partition[#2,UpTo@#])&

Entrada e saída são listas de caracteres.

Também com base nos modos das linhas da transposição. Eu acredito que eles chamaram o built-in para o modo de uma lista Commonest apenas para ofender jogadores de código.

Martin Ender
fonte
Pelo menos é um byte menor do que MostCommon...
ETHproductions
7

Python 3, 99, 73 61 bytes

-12, thx para @Rod

lambda s,n:''.join(max(s,key=s[i::n].count)for i in range(n))

Mesma idéia, mas reescrevi-a para eliminar a declaração de importação.

lambda s,n:''.join(max(s,key=lambda c:s[i::n].count(c))for i in range(n))

Original

from collections import*
lambda s,n:''.join(Counter(s[i::n]).most_common(1)[0][0]for i in range(n))

Explicação:

s[i::n]                  a slice of every nth character of s, starting at position i

Counter(s[i::n])         counts the characters in the slice
  .most_common()         returns a list of (character, count) pairs, sorted by decreasing count
    [0][0]               grabs the letter from the first pair (i.e., the most common letter
      for i in range(n)  repeat for all starting positions

''.join                  combines the most common letters into a single string
RootTwo
fonte
você pode mudar para python2.7 e soltar o ''.join()para retornar uma lista de cadeias de caracteres
Rod
O @Rod Dropping ''.join(...)faria com que ele retornasse um gerador, sem ter certeza se isso é permitido.
L3viathan
@ L3viathan ele precisa ser python2.7 para funcionar, adicionado ao outro comentário #
Rod Rod
Você pode escrever uma explicação de como isso funciona?
Gambá morto
2
@ Rod Uma lista de strings só é permitida na pergunta, se você retornar todas as soluções possíveis. Foi isso que eu entendi.
mbomb007
5

Python 2, 106

Agora é uma resposta diferente! Eu estava pensando em um (quase) forro desde o início. Agora ainda mais curto, com base no uso de zip do @Rod.

Obrigado a @ L3viathan e @Rod por esclarecimentos sobre o uso de lambdas como resposta

Experimente online

lambda S,N:max(combinations(S,N),key=lambda s:sum(x==y for x,y in zip(S,s*len(S))))
from itertools import*

Explicação:

combinations(S,N) cria todas as combinações de comprimento N a partir de caracteres de S

max()tem argumento keyque toma como função de entrada usar para comparar elementos

lambda s:sum(x==y for x,y in zip(S,s*len(S))) passado como tal função

Este lambda conta o número de caracteres correspondentes na lista de tuplas, produzido por zip(S,s*len(S))

s- uma das combinações e é multiplicada pela len(S)qual cria uma sequência garantida por mais de S

zipcria tuplas de caracteres de cada string Se s*len(S)ignora todos os caracteres que não podem ser correspondidos (no caso de uma string maior que a outra)

Então maxescolhe a combinação que produz a soma máxima

Gambá morto
fonte
1
você não precisa usar []na compreensão da lista dentro de funções, também você está usando 1 for ... if <cond>você pode usar diretamente <cond> for ...uma vez que vai ser usado em sum, python terá Truecomo 1e Falsequanto0
Rod
@ Rod Obrigado! Se eu espremer minha resposta mais, ele vai se transformar em sua resposta, a abordagem é a mesma: D Então eu estou tentando algo diferente agora
Morto Possum
Sim, basta dizer para que você possa usar em suas respostas futuras: 3
Rod
1
Mudar para um lambda economizará 7 bytes.
L3viathan
1
@DeadPossum Ele quis dizer isso (nota de rodapé eo cabeçalho) e sim, uma função é uma resposta válida , se é um lambda que você não precisa mesmo de of= (a menos que seja recursiva)
Rod
5

JavaScript (ES6), 104 101 94 bytes

(n,s)=>s.replace(/./g,(_,i)=>[...s].map((c,j,a)=>j%n-i||(a[c]=-~a[c])>m&&(m++,r=c),m=r=``)&&r)

Salva 3 bytes duas vezes graças a @Arnauld. Solução de 97 bytes que funciona com todos os caracteres que não são de nova linha:

(n,s)=>s.replace(/./g,(_,i)=>[...s].map((c,j)=>j%n-i||(o[c]=-~o[c])>m&&(m++,r=c),m=r=``,o={})&&r)

A solução anterior de 104 bytes também funciona com caracteres de nova linha:

(n,s)=>[...Array(n)].map((_,i)=>[...s].map((c,j)=>j%n-i||(o[c]=-~o[c])>m&&(m++,r=c),m=0,o={})&&r).join``
Neil
fonte
Muito agradável. Criei uma solução para referência ao adicionar casos de teste e obtive 122 bytes, percorrendo cada caractere, salvando as contagens em uma matriz de objetos e construindo a string a partir dessa matriz.
ETHproductions
Em vez de inicializar opara um novo objeto, você poderia reutilizar a matriz transmitida mapusando seu terceiro parâmetro?
Arnauld 23/03
@Arnauld Hmm, eu acho que as obras porque a questão garantias letras minúsculas, por isso não vou confundir os elementos da matriz com as contagens ...
Neil
Eu acho que (n,s)=>s.replace(/./g,(_,i)=>i<n?[...s].map((c,j,a)=>j%n-i||(a[c]=-~a[c])>m&&(m++,r=c),m=0)&&r:'')deveria salvar mais 3 bytes. (Ou 4 bytes com a sintaxe de currying.)
Arnauld
@ Arnauld Nada mal, mas raspei mais dois bytes. (E também fixa minhas contagens de bytes; uma nova linha de fuga foi jogá-los fora.)
Neil
3

Geléia , 12 11 bytes

s@ZċþZMḢ$€ị

Experimente online!

Como funciona

s@ZċþZMḢ$€ị  Main link. Arguments: n (integer), s (string)

s@           Split swapped; split s into chunks of length n.
  Z          Zip/transpose, grouping characters that correspond to repetitions.
   ċþ        Count table; for each slice in the previous result, and each character
             in s, count the occurrences of the character in the group.
             This groups by character.
     Z       Zip/transpose to group by slice.
        $€   Map the two-link chain to the left over the groups.
      M        Find all maximal indices.
       Ḣ       Head; pick the first.
          ị  Index into s to retrieve the corresponding characters.
Dennis
fonte
Jelly tem comentários?
caird coinheringaahing
Não, não tem.
Dennis
2

Pitão, 11 bytes

meo/dNd.TcF

Aceita entrada como s,n e saídas como uma lista de caracteres.

Explicação

meo/dNd.TcF
         cFQ   Split s into chunks of length n.
       .T      Transpose.
m o/dNd        Sort characters in each string by frequency.
 e             Take the most common.

fonte
2

Japt , 16 15 bytes

Guardado 1 byte graças a @obarakon

Ç=VëUZ)¬ñ!èZ o

14 bytes de código + 1 byte para o -Psinalizador.Experimente online!

Ungolfed e explicação

 Ç   =VëUZ)¬ ñ!èZ o
UoZ{Z=VëUZ)q ñ!èZ o}
                          Implicit: U = input number, V = input string
Uo                        Create the range [0...U).
  Z{               }      Map each item Z by this function:
      VëUZ                  Take every U'th char of V, starting at index Z.
    Z=    )                 Call the result Z.
           q                Split the result into chars.
             ñ!èZ           Sort each char X by the number of occurrences of X in Z.
                  o         Pop; grab the last item (the most common char).
                      -P  Join the results (array of most common chars) into a string.
ETHproductions
fonte
Eu acho que você pode substituir gJporo
Oliver
@obarakon Isso é genial, obrigado!
ETHproductions
1

Python 2 , 132 bytes

from itertools import*
p,k=input()
b=l=len(p)
for i in combinations(p,k):
 x=sum(x!=y for x,y in zip(p,i*l))
 if x<b:b,o=x,i
print o

Experimente online!

Cajado
fonte
1

05AB1E , 17 bytes

Iôð«øvy{.¡é®èÙJðÜ

Experimente online!

Explicação

Iô                 # split 2nd input in chunks of 1st input size
  ð«               # append a space to each
    ø              # zip
     vy            # for each y in the zipped list
       {           # sort the string
        .¡         # group into chunks of consecutive equal elements
          é        # sort by length
           ®è      # pop the last element (the longest)
             Ù     # remove duplicate characters from the string
              J    # join the stack into one string
               ðÜ  # remove any trailing spaces
Emigna
fonte
1

PHP, 245 bytes

function p($c,$s,$r=""){global$a;if(($c-strlen($r)))foreach(str_split(count_chars($s,3))as$l)p($c,$s,$r.$l);else{for($v=str_pad("",$w=strlen($s),$r);$z<$w;)$t+=$v[$z]==$s[$z++];$a[$t][]=$r;}}p($argv[1],$argv[2]);ksort($a);echo join(" ",end($a));

Versão Online

Demolir

function p($c,$s,$r=""){
    global$a;
    if(($c-strlen($r)))  # make permutation
        foreach(str_split(count_chars($s,3))as$l)
            p($c,$s,$r.$l); #recursive
    else{
        for($v=str_pad("",$w=strlen($s),$r);$z<$w;) 
        $t+=$v[$z]==$s[$z++]; #compare strings
        $a[$t][]=$r; # insert value in array
    }
}
p($argv[1],$argv[2]); #start function with the input parameter
ksort($a); # sort result array 
echo join(" ",end($a)); #Output
Jörg Hülsermann
fonte
1

Haskell, 84 bytes

import Data.Lists
f n=map(argmax=<<(length.).flip(filter.(==))).transpose.chunksOf n

Exemplo de uso:

f 10 "bbbbacacbcedecdbbbdebdaedcecdabcebddbdcecebbeeaacdebdbebaebcecddadeeedbbdbbaeaaeebbedbeeaeedadeecbcd"
"ebbbdbeece"

Divida a string de entrada em pedaços de comprimento n, transponha e encontre para cada sublist o elemento mais frequente.

nimi
fonte
1

Röda , 68 bytes

f s,n{seq 0,n-1|{|i|sort s/"",key={|c|x=s[i::n]x~=c,"";[#x]}|head}_}

Experimente online!

É uma função que imprime a saída sem seguir a nova linha.

Isso foi inspirado por esta resposta .

fergusq
fonte