Encuentra el patrón óptimo

33

Dada una cadena s compuesta de letras minúsculas, como

aabaaababbbbaaba

y un entero positivo n , tal como 4, genera una longitud n cadena t tal que cuando t se repite a la longitud de s , tienen tantos caracteres en común como sea posible. Para el ejemplo dado, la salida óptima sería aaba, porque tiene trece caracteres en común con la cadena de destino:

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

y no es posible t tiene más. Sin embargo, para aaaaaab, hay dos salidas posibles: aaaay aaba, cada una de las cuales tiene 6 caracteres en común con la cadena de destino:

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

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

Cualquiera aaaao aabapuede ser emitido, o ambos si lo desea. Tenga en cuenta que s nunca se repite; el final aen ambos valores repetidos de t simplemente se ignora.

Casos de prueba

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

Reglas

  • Puede suponer que la entrada solo será una cadena no vacía de letras minúsculas y un entero positivo no mayor que la longitud de la cadena.
  • Puede tomar las entradas en cualquier formato estándar y en cualquier orden.
  • Puede generar una sola cadena, o más de una en forma de matriz, separadas por nuevas líneas o espacios, etc.
  • Su código debe finalizar para cada caso de prueba en menos de 1 minuto en cualquier computadora bastante moderna.
  • Este es el , así que haga su código lo más corto posible.
ETHproducciones
fuente
2
Este desafío es de calidad Zgarb. ¡Buen trabajo!
Martin Ender
¿Asumo que solo se ignoran los caracteres finales? Por lo tanto, no puede ignorar los caracteres principales como este: 2 abb -> badonde se construye como (b)[ab]a: los elementos principales (b)se ignoran, [ab]coinciden.
Kevin Cruijssen
@KevinCruijssen Correcto, el patrón debe comenzar a repetirse desde el principio.
ETHproductions

Respuestas:

11

Jalea , 11 bytes

sZµṢŒrUṀṪµ€

Pruébalo en línea!

No esperaba vencer a Dennis en este caso, así que traté de FGITW (después de probar varias posibilidades; hay más de una forma de hacer 11). Llegué más corto, para mi sorpresa.

Toma la cadena y luego la cuenta como argumentos de línea de comandos. Salidas en stdout.

Explicación

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)

Esto utiliza la idea de que la letra en cada posición del patrón debe ser la letra más común correspondiente a esa posición. Podemos encontrar las letras correspondientes a un patrón particular dividiéndolo en grupos del tamaño de un patrón y transponiendo. La razón principal por la que esta solución es tan larga es que Jelly no parece tener un camino corto para encontrar el modo de una lista (hice varios intentos, pero todos tienen al menos seis bytes de longitud).

Jelly , 10 bytes, basado en la solución de @Dennis

⁸ċ$ÞṪ
sZÇ€

Pruébalo en línea!

Esta es una combinación de la solución de @Dennis y la mía; había un modo de cinco bytes en esa solución, que robé para esta solución. (Ya tenía soluciones basadas en ⁸ċ, pero no podía obtener menos de seis bytes; no había pensado en usarlas Þ).

Explicación

µ…µ€y Ç€(con el de la línea anterior) tienen una longitud de tres bytes (este último necesita una nueva línea) y equivalentes. Normalmente uso el primero, pero el último es más flexible, ya que te permite usar para mencionar el argumento.

Esto hace posible ordenar ( Þ) por el número de ocurrencias en ( ⁸ċ), luego tomar el último elemento ( ), para encontrar el modo en solo cinco caracteres.


fuente
55
¡Buen trabajo superando a Dennis con su propio idioma! : P
HyperNeutrino
10

Mathematica, 51 bytes

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

La entrada y la salida son listas de caracteres.

También se basa en los modos de las líneas de la transposición. Creo que llamaron al modo incorporado de una lista Commonest únicamente para molestar a los golfistas de código.

Martin Ender
fuente
Al menos es un byte más corto que MostCommon...
ETHproductions
7

Python 3, 99, 73 61 bytes

-12, gracias a @Rod

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

La misma idea, pero la reescribió para eliminar la declaración de importación.

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

Explicación:

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
fuente
puede cambiar a python2.7 y soltar ''.join()para devolver una lista de cadenas
Rod
@Rod Dropping ''.join(...)lo haría devolver un generador, no estoy seguro de si eso es salida permitida.
L3viathan
@ L3viathan que necesita ser python2.7 para funcionar, agregado al otro comentario
Rod
¿Puedes escribir alguna explicación de cómo funciona esto?
Dead Possum
2
@ Rod Una lista de cadenas solo está permitida en la pregunta si devuelve todas las soluciones posibles. Eso es lo que entendí.
mbomb007
5

Pitón 2, 106

¡Ahora es una respuesta diferente! Estaba pensando en un (casi) revestimiento desde el principio. Ahora incluso más corto, basado en el uso de zip por @Rod.

Gracias a @ L3viathan y @Rod por aclarar sobre el uso de lambdas como respuesta

Pruébalo en línea

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*

Explicación:

combinations(S,N) crea todas las combinaciones de longitud N a partir de caracteres de S

max()tener un argumento keyque toma como función de entrada para usar para comparar elementos

lambda s:sum(x==y for x,y in zip(S,s*len(S))) pasado como tal función

Esta lambda cuenta el número de caracteres coincidentes en la lista de tuplas, producida por zip(S,s*len(S))

s- una de las combinaciones y se multiplica por lo len(S)que crea una cadena que está garantizada por más tiempo que S

zipcrea tuplas de caracteres de cada cadena Se s*len(S)ignora todos los caracteres que no pueden coincidir (en el caso de una cadena más larga que otra)

Entonces maxelige la combinación, que produce la suma máxima

Zarigüeya muerta
fuente
1
no necesita usar []en la lista la comprensión dentro de las funciones, también lo está usando 1 for ... if <cond>, puede usarlo directamente, <cond> for ...ya que se usará en sum, python tomará Trueas 1y Falseas0
Rod
@ Rod ¡Gracias! Si cuadrara mi respuesta más, se transformaría en tu respuesta, el enfoque es el mismo: D Así que estoy intentando algo diferente ahora mismo
Dead Possum
Sí, solo digo que puedes usarlo en tus futuras respuestas: 3
Rod
1
Cambiar a una lambda ahorrará 7 bytes.
L3viathan
1
@DeadPossum Se refería a esto (tenga en cuenta el pie de página y el encabezado) y sí, una función es una respuesta válida , si es una lambda ni siquiera necesitaf= (a menos que sea 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)

Guardado 3 bytes dos veces gracias a @Arnauld. Solución de 97 bytes que funciona con todos los caracteres que no son de nueva línea:

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

La solución anterior de 104 bytes también funciona con caracteres de nueva línea:

(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
fuente
Muy agradable. Pensé en una solución de referencia al agregar casos de prueba y obtuve 122 bytes, recorriendo cada carácter, guardando los recuentos en una matriz de objetos y luego construyendo la cadena a partir de esa matriz.
ETHproductions
En lugar de inicializar oa un nuevo objeto, ¿podría simplemente reutilizar la matriz a la que se pasó maputilizando su tercer parámetro?
Arnauld
@Arnauld Hmm, supongo que eso funciona porque la pregunta garantiza letras minúsculas, por lo que no confundiré los elementos de la matriz con los recuentos ...
Neil
Creo 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:'')debería guardar 3 bytes más. (O 4 bytes usando la sintaxis curry.)
Arnauld
@Arnauld No está mal, pero eliminé otros dos bytes. (Y también arregló mis conteos de bytes; una nueva línea final los estaba descartando).
Neil
3

Jalea , 12 11 bytes

s@ZċþZMḢ$€ị

Pruébalo en línea!

Cómo 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
fuente
¿Jelly tiene comentarios?
caird coinheringaahing
No, no lo hace.
Dennis
2

Pyth, 11 bytes

meo/dNd.TcF

Toma entradas como s,ny salidas como una lista de caracteres.

Explicación

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.

fuente
2

Japt , 16 15 bytes

Guardado 1 byte gracias a @obarakon

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

14 bytes de código + 1 byte para la -Pbandera. Pruébalo en línea!

Sin golfos y explicación

 Ç   =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.
ETHproducciones
fuente
Creo que se puede sustituir gJcono
Oliver
@obarakon Eso es genial, ¡gracias!
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

Pruébalo en línea!

Barra
fuente
1

05AB1E , 17 bytes

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

Pruébalo en línea!

Explicación

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
fuente
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));

Versión en línea

Descompostura

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

Haskell, 84 bytes

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

Ejemplo de uso:

f 10 "bbbbacacbcedecdbbbdebdaedcecdabcebddbdcecebbeeaacdebdbebaebcecddadeeedbbdbbaeaaeebbedbeeaeedadeecbcd"
"ebbbdbeece"

Divida la cadena de entrada en trozos de longitud n, transponga y encuentre para cada sublista el elemento más frecuente.

nimi
fuente
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}_}

Pruébalo en línea!

Es una función que imprime la salida sin arrastrar la nueva línea.

Esto fue inspirado por esta respuesta .

fergusq
fuente