Найти оптимальный шаблон


33

Дана строка s, состоящая из строчных букв, таких как

aabaaababbbbaaba

и положительное целое число п , такие , как 4, выводить длина- п строка т таким образом, что , когда т повторяется до длины с , они имеют как много символов в часто , как это возможно. Для данного примера оптимальный результат будет aaba, потому что у него тринадцать общих знаков с целевой строкой:

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

и никакой возможности т больше. Тем не менее, для aaaaaab, есть два возможных выхода: aaaaи aaba, каждый из которых имеет 6 общих символов с целевой строкой:

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

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

Либо aaaaили aabaможет быть выведен, либо оба, если хотите. Обратите внимание, что s никогда не повторяется; трейлинг aв обоих повторяющихся значениях t просто игнорируется.

Контрольные примеры

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

Ответы:


11

Желе , 11 байт

sZµṢŒrUṀṪµ€

Попробуйте онлайн!

Не ожидал победить Денниса на этом, поэтому попытался FGITW (попробовав несколько вариантов; есть более одного способа сделать 11). Я пришел короче, к моему большому удивлению.

Принимает строку, а затем считать в качестве аргументов командной строки. Выходы на стандартный вывод.

объяснение

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, похоже, нет короткого способа найти режим списка (я сделал несколько попыток, но все они имеют длину не менее шести байтов).

Желе , 10 байт, на основе решения @Dennis

⁸ċ$ÞṪ
sZÇ€

Попробуйте онлайн!

Это комбинация решения @Dennis и моего; в этом решении был пятибайтовый режим, который я украл для этого решения. (У меня уже были решения, основанные на этом ⁸ċ, но я не мог получить меньше шести байт; я не думал об их использовании Þ.)

объяснение

µ…µ€и Ç€предыдущей строкой) имеют длину в три байта (последняя нуждается в новой строке) и эквивалентны. Обычно я использую первое, но второе более гибкое, так как позволяет вам упомянуть аргумент.

Это позволяет отсортировать ( Þ) по количеству вхождений в ( ⁸ċ), а затем взять последний элемент ( ), чтобы найти режим всего за пять символов.


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 для работы, добавлено в другой комментарий
Род

Можете ли вы написать какое-нибудь объяснение того, как это работает?
Мертвый Опоссум

2
@Rod Список строк разрешен только в том случае, если вы вернете все возможные решения. Вот что я понял.
mbomb007

5

Python 2, 106

Теперь это другой ответ! Я думал об одном (почти) лайнере с самого начала. Теперь еще короче, основанный на использовании почтового индекса @Rod.

Спасибо @ L3viathan и @Rod за разъяснения по поводу использования лямбд в качестве ответа

Попробуйте онлайн

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) создает все комбинации длиной N из символов S

max()есть аргумент, keyкоторый принимает в качестве входной функции для сравнения элементов

lambda s:sum(x==y for x,y in zip(S,s*len(S))) передается как такая функция

Эта лямбда подсчитывает количество совпадающих символов в списке кортежей, производится zip(S,s*len(S))

s- одна из комбинаций, умноженная на len(S)которую создает строка, которая гарантированно длиннее S

zipсоздает наборы символов каждой строки Sи s*len(S)игнорирует все символы, которые не могут быть сопоставлены (в случае, если одна строка длиннее другой)

Так maxвыбирает комбинацию, которая выдает максимальную сумму


1
вам не нужно использовать []для понимания списка внутри функции, также вы используете, 1 for ... if <cond>вы можете использовать напрямую, <cond> for ...так как он будет использоваться sum, Python будет принимать Trueкак 1и Falseкак0
Rod

@Rod Спасибо! Если бы я больше отвечал на мой ответ, он трансформировался бы в ваш ответ, подход тот же: D Так что я сейчас пробую что-то другое
Мертвый Опоссум

Да, просто говорю, чтобы вы могли использовать в своих будущих ответах: 3
Род

1
Переключение на лямбду сэкономит 7 байт.
L3viathan

1
@DeadPossum Он имел в виду это (обратите внимание на нижний колонтитул и верхний колонтитул), и да, функция является правильным ответом , если ее лямбда-выражение вам даже не нужноf= (если оно не рекурсивно)
Род

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)

Сэкономили 3 байта дважды благодаря @Arnauld. 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 Хмм, я думаю, это работает, потому что вопрос гарантирует строчные буквы, поэтому я не буду путать элементы массива с счетчиками ...
Нил

Я думаю, (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 байта. (Или 4 байта, используя синтаксис карри.)
Арно

@Arnauld Неплохо, но я сбрил еще два байта. (И также исправил мои подсчеты байтов; завершающий символ новой строки сбрасывал их.)
Нил

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 Coneheringaahing

Нет.
Денис

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

Japt , 16 15 байт

Сохранено 1 байт благодаря @obarakon

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

Я думаю, что вы можете заменить gJнаo
Оливер

@obarakon Это гений, спасибо!
ETHproductions


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"

Разбить входную строку на куски длины n, транспонировать и найти для каждого подсписка наиболее часто встречающийся элемент.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.