寻找最佳模式


33

给定由小写字母组成的字符串s,例如

aabaaababbbbaaba

而正整数n(例如4)输出长度为n的字符串t,使得当t重复到s的长度时,它们具有尽可能多的共同字符。对于给定的示例,最佳输出为aaba,因为它与目标字符串共有13个字符:

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

没有可能牛逼有更多。但是,对于aaaaaab,有两个可能的输出:aaaaaaba,每个输出与目标字符串共有6个字符:

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

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

无论是aaaaaaba可以输出,或者如果两个你想。注意,s永远不会重复;t的a两个重复值中的尾部将被忽略。

测试用例

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

规则

  • 您可以假定输入将永远是一个非空的小写字母字符串,并且是一个不大于字符串长度的正整数。
  • 您可以采用任何标准格式和任意顺序输入。
  • 您可以输出单个字符串,也可以以数组形式输出多个字符串,并以换行符或空格等分隔。
  • 在任何相当现代的计算机上,每个测试用例的代码必须在不到1分钟的时间内完成。
  • 这是,因此请使代码尽可能短。

2
挑战在于Zgarb的品质。干得好!
马丁·恩德

我假设只有结尾字符会被忽略?因此,您不可以忽略这样的前导字符:2 abb -> ba它的构建方式是(b)[ab]a(b)忽略前导,[ab]是匹配的。
凯文·克鲁伊森

@KevinCruijssen对,模式必须从头开始重复。
ETHproductions

Answers:


11

果冻,11字节

sZµṢŒrUṀṪµ€

在线尝试!

没想到会在这方面击败丹尼斯,所以尝试了FGITW(尝试了几种可能性后,有11种方法可以实现多种选择)。我进来矮了,令我惊讶的是。

将字符串然后计数作为命令行参数。在stdout上输出。

说明

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)

这利用了以下洞察力:模式每个位置的字母必须是与该位置相对应的最常见的字母。我们可以通过分成图案大小的组并进行转置来找到与特定图案相对应的字母。该解决方案之所以这么长,主要是因为Jelly似乎没有找到列表模式的捷径(我做了几次尝试,但它们都至少有六个字节长)。

Jelly,10个字节,基于@Dennis的解决方案

⁸ċ$ÞṪ
sZÇ€

在线尝试!

这是@Dennis解决方案和我自己的解决方案的结合;在该解决方案中有一个五字节模式,我偷了这个解决方案。(我已经有基于的解决方案⁸ċ,但是无法使用少于6个字节的内容;我没有想到要使用Þ。)

说明

µ…µ€Ç€前一行带有)均为三个字节长(后者需要换行),并且等效。通常,我使用前者,但后者则更灵活,因为它允许您使用提及参数。

这使得有可能进行排序(Þ按出现的次数)⁸ċ),然后取最后一个元素(),发现在短短的五个字符模式。


5
用丹尼斯的语言胜过丹尼斯,做得很好!:P
HyperNeutrino

10

Mathematica,51个字节

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

输入和输出是字符列表。

也基于转置线的模式。我相信他们Commonest 为打高尔夫球的人打了电话,而将列表模式称为内置模式。


至少比MostCommon... 短一个字节
ETHproductions

7

Python 3、99、73 61字节

-12,谢谢@Rod

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

想法相同,但重新编写以消除导入语句。

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

原版的

from collections import*
lambda s,n:''.join(Counter(s[i::n]).most_common(1)[0][0]for i in range(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

您可以切换到python2.7并放下''.join()以返回字符串列表
Rod

@Rod Dropping ''.join(...)将使其返回生成器,不确定是否允许输出。
L3viathan

@ L3viathan它需要是python2.7才能工作,并添加到其他评论中
Rod

您能写一些关于它如何工作的解释吗?
死负鼠

2
@Rod仅在问题中允许使用字符串列表,以便返回所有可能的解决方案。这就是我的意思。
mbomb007 '17

5

蟒蛇2,106

现在是一个不同的答案!我从一开始就在考虑一个(几乎)班轮。现在更短了,基于@Rod的zip用法。

感谢@ L3viathan和@Rod关于使用lambda作为答案的说明

在线尝试

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*

说明:

combinations(S,N) 根据S的字符创建长度为N的所有组合

max()具有key作为输入函数的参数,用于比较元素

lambda s:sum(x==y for x,y in zip(S,s*len(S))) 通过这样的功能

此lambda计算元组列表中匹配字符的数量,由 zip(S,s*len(S))

s-组合之一,并且与之相乘以len(S)创建保证比S长的字符串

zip创建每个字符串的字符的元组Ss*len(S)并忽略不能匹配的所有字符(在一个字符串的情况下,比另一个更长)

所以max选择组合,产生最大的和


1
你不需要使用[]里面的功能列表理解,也使用的是1 for ... if <cond>你可以直接使用<cond> for ...,因为它会被用在sum,蟒蛇将True作为1False作为0

@Rod谢谢!如果我再压缩我的答案,它将转化为您的答案,方法是相同的:D所以,我现在正在尝试不同的方法
Dead Possum

是的,只是说,这样您就可以使用自己的未来答案了:3
Rod Rod

1
切换到lambda将节省7个字节。
L3viathan

1
@DeadPossum 他的意思是(请注意页脚和页眉),是的,一个函数是一个有效的答案,如果它是lambda,则您甚至不需要f=(除非是递归的)
Rod

5

的JavaScript(ES6),104个 101 94字节

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

感谢@Arnauld,两次节省了3个字节。97字节的解决方案,适用于所有非换行符:

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

先前的104字节解决方案也适用于换行符:

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

非常好。添加测试用例时,我提供了一个解决方案供参考,它的大小为122字节,遍历每个字符,将计数保存在对象数组中,然后从该数组构建字符串。
ETHproductions

除了初始化o为新对象,您还可以仅map使用第三个参数重用传递给它的数组吗?
Arnauld

@Arnauld Hmm,我猜这行得通,因为该问题保证小写字母,因此我不会将数组元素与计数混淆……
Neil

我认为(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:'')应该再保存3个字节。(或者使用currying语法获取4个字节。)
Arnauld

@Arnauld还不错,但是我又削了两个字节。(并且还修复了我的字节数;尾随换行符将它们扔掉了。)
尼尔(Neil

3

果冻12 11字节

s@ZċþZMḢ$€ị

在线尝试!

怎么运行的

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.

果冻有评论吗?
caird coinheringaahing

不,不是的。
丹尼斯,

2

Pyth,11个字节

meo/dNd.TcF

将输入作为s,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.

2

Japt16 15字节

@obarakon节省了1个字节

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

14个字节的代码+ 1个字节的-P标志。在线尝试!

脱节和解释

 Ç   =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.

我认为您可以替换gJo
奥利弗·奥利弗(Oliver)

@obarakon天才,谢谢!
ETHproductions

1

Python 2,132字节

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

在线尝试!


1

05AB1E,17个字节

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

在线尝试!

说明

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

1

PHP,245字节

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

在线版本

分解

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

1

Haskell,84个字节

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

用法示例:

f 10 "bbbbacacbcedecdbbbdebdaedcecdabcebddbdcecebbeeaacdebdbebaebcecddadeeedbbdbbaeaaeebbedbeeaeedadeecbcd"
"ebbbdbeece"

将输入字符串拆分为length块,n为每个子列表最频繁的元素转置和查找。


1

Röda,68位元组

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

在线尝试!

此函数可打印输出而不会在末尾加上换行符。

这是受此答案启发的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.