Znajdź optymalny wzór

33

Biorąc pod uwagę ciąg y składa się z małych liter, takich jak

aabaaababbbbaaba

oraz dodatnia liczba całkowita n , taka jak 4, wypisuje ciąg n długości t taki, że gdy t jest powtarzane do długości s , mają one jak najwięcej wspólnych znaków. W podanym przykładzie optymalne wyjście byłoby aaba, ponieważ ma trzynaście znaków wspólnych z ciągiem docelowym:

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

i żaden możliwy t nie ma więcej. Istnieją jednak aaaaaabdwa możliwe wyniki: aaaai aaba, z których każdy ma 6 znaków wspólnych z ciągiem docelowym:

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

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

Albo aaaaalbo aabamoże być wyprowadzony, albo jedno i drugie, jeśli chcesz. Zauważ, że s nigdy się nie powtarza; końcowe aobie powtarzane wartości t są po prostu ignorowane.

Przypadki testowe

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

Zasady

  • Możesz założyć, że dane wejściowe będą zawsze niepustym ciągiem małych liter i dodatnią liczbą całkowitą nie większą niż długość łańcucha.
  • Możesz pobrać dane wejściowe w dowolnym standardowym formacie i w dowolnej kolejności.
  • Możesz wyprowadzić pojedynczy ciąg znaków lub więcej niż jeden w postaci tablicy oddzielonej znakami nowej linii lub spacjami itp.
  • Twój kod musi kończyć się dla każdego przypadku testowego w mniej niż 1 minutę na dowolnym dość nowoczesnym komputerze.
  • To jest , więc ustaw swój kod tak krótko, jak to możliwe.
ETHprodukcje
źródło
2
To wyzwanie ma jakość Zgarb. Dobra robota!
Martin Ender
Zakładam, że tylko końcowe znaki są ignorowane? Dlatego nie wolno ignorować wiodących postaci, takich jak to: 2 abb -> bajeśli jest budowane, ponieważ (b)[ab]a: wiodące (b)jest ignorowane, [ab]pasują.
Kevin Cruijssen
@KevinCruijssen Racja, wzorzec musi zacząć się powtarzać na początku.
ETHprodukcje

Odpowiedzi:

11

Galaretka , 11 bajtów

sZµṢŒrUṀṪµ€

Wypróbuj online!

Nie spodziewałem się pokonać Dennisa na tym, więc spróbowałem FGITW (po wypróbowaniu kilku możliwości; istnieje więcej niż jeden sposób na zdobycie 11). Ku mojemu zaskoczeniu przyjechałem krócej.

Bierze ciąg, a następnie liczy jako argumenty wiersza poleceń. Wyjścia na standardowym wyjściu.

Wyjaśnienie

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)

Wykorzystuje to wgląd, że litera w każdej pozycji wzoru musi być najczęstszą literą odpowiadającą tej pozycji. Możemy znaleźć litery odpowiadające danemu wzorowi, dzieląc je na grupy wielkości wzoru i transponując. Głównym powodem, dla którego to rozwiązanie jest tak długie, jest to, że Jelly nie wydaje się mieć krótkiej drogi do znalezienia trybu listy (podjąłem kilka prób, ale wszystkie mają co najmniej sześć bajtów długości).

Galaretka , 10 bajtów, w oparciu o rozwiązanie @Dennis

⁸ċ$ÞṪ
sZÇ€

Wypróbuj online!

Jest to połączenie rozwiązania @Dennis i mojego własnego; w tym rozwiązaniu był tryb pięciobajtowy, który ukradłem dla tego rozwiązania. (Miałem już oparte na tym rozwiązaniu ⁸ċ, ale nie mogłem zejść poniżej sześciu bajtów; nie myślałem o użyciu Þ).

Wyjaśnienie

µ…µ€i Ç€(z poprzednim wierszem) mają długość trzech bajtów (ta ostatnia wymaga nowej linii) i są równoważne. Zwykle używam tego pierwszego, ale ten drugi jest bardziej elastyczny, ponieważ pozwala na użycie argumentu.

Umożliwia to sortowanie ( Þ) według liczby wystąpień w ( ⁸ċ), a następnie pobranie ostatniego elementu ( ), aby znaleźć tryb w zaledwie pięciu znakach.


źródło
5
Dobra robota obezwładniająca Dennisa własnym językiem! : P
HyperNeutrino
10

Mathematica, 51 bajtów

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

Dane wejściowe i wyjściowe są listami znaków.

Również w oparciu o tryby linii transpozycji. Sądzę, że nazwali wbudowany tryb listy Commonest wyłącznie po to, by wkurzyć golfistów.

Martin Ender
źródło
Przynajmniej jest to bajt krótszy niż MostCommon...
ETHprodukcje
7

Python 3, 99, 73 61 bajtów

-12, dzięki za @Rod

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

Ten sam pomysł, ale przepisałem go w celu wyeliminowania instrukcji importu.

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

Oryginalny

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

Wyjaśnienie:

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
źródło
możesz przejść do python2.7 i upuścić, ''.join()aby zwrócić listę ciągów znaków
Rod
@Rod Dropping ''.join(...)sprawi, że zwróci generator, nie jestem pewien, czy to dozwolone wyjście.
L3viathan
@ L3viathan do pracy musi być python2.7, dodano do drugiego komentarza
Rod
Czy możesz napisać jakieś wyjaśnienie, jak to działa?
Dead Possum
2
@Rod Lista ciągów znaków jest dozwolona w pytaniu, jeśli zwrócisz wszystkie możliwe rozwiązania. Właśnie to miałam na myśli.
mbomb007
5

Python 2, 106

Teraz jest inna odpowiedź! Od samego początku myślałem o jednej (prawie) liniowej. Teraz jeszcze krótszy, w oparciu o użycie zip przez @Rod.

Podziękowania dla @ L3viathan i @Rod za wyjaśnienie na temat używania lambdas jako odpowiedzi

Wypróbuj 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*

Wyjaśnienie:

combinations(S,N) tworzy wszystkie kombinacje długości N ze znaków S

max()mają argument, keyktóry przyjmuje jako funkcję wejściową do porównywania elementów

lambda s:sum(x==y for x,y in zip(S,s*len(S))) przekazywane jako taka funkcja

Ta lambda liczy liczbę pasujących znaków na liście krotek, produkowanych przez zip(S,s*len(S))

s- jedna z kombinacji i jej wielokrotność, przez len(S)co powstaje ciąg znaków, który jest gwarantowany dłużej niż S.

ziptworzy krotki znaków każdego łańcucha Si s*len(S)ignoruje wszystkie znaki, których nie można dopasować (w przypadku jednego ciągu dłuższego niż drugiego)

maxWybiera więc kombinację, która daje maksymalną sumę

Dead Possum
źródło
1
nie musisz używać do []zrozumienia listy wewnątrz funkcji, również używasz 1 for ... if <cond>możesz używać bezpośrednio, <cond> for ...ponieważ będzie on używany sum, python będzie przyjmował Truejako 1i Falsejak0
Rod
@Rod Dziękuję! Gdybym jeszcze bardziej ścisnął moją odpowiedź, przekształci się ona w twoją odpowiedź, podejście jest takie samo: D Więc próbuję teraz czegoś innego
Dead Possum
Tak, tylko mówię, abyś mógł użyć swoich przyszłych odpowiedzi: 3
Rod
1
Przełączenie na lambda pozwoli zaoszczędzić 7 bajtów.
L3viathan
1
@DeadPossum Miał to na myśli (zwróć uwagę na stopkę i nagłówek) i tak, funkcja jest prawidłową odpowiedzią , jeśli to lambda nawet nie potrzebujeszf= (chyba że jest rekurencyjna)
Rod
5

JavaScript (ES6), 104 101 94 bajtów

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

Zaoszczędzono 3 bajty dwa razy dzięki @Arnauld. 97-bajtowe rozwiązanie, które działa ze wszystkimi znakami nieliniowymi:

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

Poprzednie 104-bajtowe rozwiązanie działa również ze znakami nowej linii:

(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
źródło
Bardzo dobrze. Dodałem przypadki testowe do gry w golfa i wymyśliłem 122 bajty, przechodząc przez każdy znak, zapisując liczby w tablicy obiektów, a następnie budując ciąg z tej tablicy.
ETHproductions
Czy zamiast zainicjować onowy obiekt, możesz po prostu ponownie użyć przekazanej tablicy map, używając jej trzeciego parametru?
Arnauld
@Arnauld Hmm, myślę, że to działa, ponieważ pytanie gwarantuje małe litery, więc nie pomylę elementów tablicy z liczbami ...
Neil
Myślę, że (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:'')powinien zaoszczędzić jeszcze 3 bajty. (Lub 4 bajty przy użyciu składni curry.)
Arnauld
@Arnauld Nieźle, ale ogoliłem kolejne dwa bajty. (A także naprawiłem liczbę moich bajtów; wyrzucanie ich przez nową linię).
Neil
3

Galaretka , 12 11 bajtów

s@ZċþZMḢ$€ị

Wypróbuj online!

Jak to działa

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
źródło
Czy Jelly ma komentarze?
caird coinheringaahing
Nie.
Dennis
2

Pyth, 11 bajtów

meo/dNd.TcF

Pobiera dane wejściowe s,ni wyjściowe jako listę znaków.

Wyjaśnienie

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.

źródło
2

Japt , 16 15 bajtów

Zapisano 1 bajt dzięki @obarakon

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

14 bajtów kodu + 1 bajt dla -Pflagi. Wypróbuj online!

Bez golfa i wyjaśnienia

 Ç   =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.
ETHprodukcje
źródło
Myślę, że można zastąpić gJzo
Oliver
@obarakon To genialne, dzięki!
ETHproductions
1

Python 2 , 132 bajty

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

Wypróbuj online!

Pręt
źródło
1

05AB1E , 17 bajtów

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

Wypróbuj online!

Wyjaśnienie

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
źródło
1

PHP, 245 bajtów

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

Wersja online

Awaria

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
źródło
1

Haskell, 84 bajty

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

Przykład użycia:

f 10 "bbbbacacbcedecdbbbdebdaedcecdabcebddbdcecebbeeaacdebdbebaebcecddadeeedbbdbbaeaaeebbedbeeaeedadeecbcd"
"ebbbdbeece"

Podziel ciąg wejściowy na kawałki długości n, transponuj i znajdź dla każdej podlisty najczęstszy element.

nimi
źródło
1

Röda , 68 bajtów

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

Wypróbuj online!

Jest to funkcja, która drukuje dane wyjściowe bez kończenia nowej linii.

To było zainspirowane tą odpowiedzią .

fergusq
źródło