Больше колокольчика ...!


42

Вы обеспечиваете техническую поддержку в Брюс Dickenson , как он производит запись сеанса Blue Oyster Cult. Когда он просит еще колокольчика , вы можете дать его ему.

Твое задание

Напишите программу или функцию, которая принимает строку (или эквивалент на вашем языке) в качестве входных данных и выводит связанную строку, содержащую еще один колокольчик.

Сколько колокольчиков содержит строка?

Количество колокольчиков в строке равно максимальному количеству отдельных копий «колокольчика», которое можно получить путем перестановки символов строки. Например, "bbbccceeellllllooowwwwwwwww"содержит 3 колокольчика, в то время как "bbccceeellllllooowwwwwwwww"и "bbbccceeelllllooowwwwwwwww"каждый содержит 2 колокольчика, и "cowbel"содержит 0 колокольчиков.

Как выход должен быть связан с входом?

Выходные данные должны состоять из объединения в указанном порядке входной строки и кратчайшего префикса входной строки, необходимого для увеличения числа колокольчиков.

Например, "bbbccceeelllllooowwwwwwwww"нужен только один дополнительный, "l"чтобы содержать 3 колокольчика вместо 2; самый короткий префикс , который содержит , что "l"это "bbbccceeel". Поэтому, если вход есть "bbbccceeelllllooowwwwwwwww", то выход должен быть "bbbccceeelllllooowwwwwwwwwbbbccceeel".

Технические детали

  • Вы можете предположить, что ввод содержит только печатные символы ASCII. Если есть один или два символа, которые раздражают для обработки строки вашего языка (например, перевод строки или \), вы можете предположить, что входные данные не содержат их - просто упомяните это ограничение.
  • Кроме того, вы можете предположить, что буквенные символы на входе являются строчными или прописными. Если вы решите не принимать одно из них, считайте колокольчики без учета регистра.
  • Далее Вы можете предположить , что ввод содержит , по меньшей мере , одну копию каждого из персонажей b, c, e, l, o, и w. Это эквивалентно предположению, что некоторый префикс строки может быть присоединен к нему для получения строки, содержащей больше колокольчика. (Обратите внимание, что сама входная строка не должна содержать колокольчик.)
  • Если у вашего языка есть встроенная функция, которая решает эту проблему ... тогда всерьез используйте ее, насколько это здорово.

Позолоченные подгузники

Поскольку время записи в студии дорого, ваш код должен быть максимально коротким. Запись с наименьшим количеством байтов является победителем!

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

( ссылка на вставку для более простого копирования / вставки)

Тестовый вход № 1: "christopher walken begs for more cowbell!"

Тестовый вывод № 1: "christopher walken begs for more cowbell!christopher wal"

Тестовый вход № 2: "the quick brown fox jumps over the lazy dog"

Тестовый вывод № 2: "the quick brown fox jumps over the lazy dogthe quick brown fox jumps over the l"

Тестовый вход № 3: "cowbell"

Тестовый вывод № 3: "cowbellcowbell"

Тестовый вход № 4: "cowbell cowbell cowbell"

Тестовый вывод № 4: "cowbell cowbell cowbellcowbell"

Тестовый вход № 5: "cowbell cowbell cowbel"

Тестовый вывод № 5: "cowbell cowbell cowbelcowbel"

Тестовый вход № 6: "bcelow"

Тестовый вывод № 6: "bcelowbcel"

Тестовый вход № 7: "abcdefghijklmnopqrstuvwxyz"

Тестовый вывод № 7: "abcdefghijklmnopqrstuvwxyzabcdefghijkl"

Тестовый вход № 8: "cccowwwwbbeeeeelllll"

Тестовый вывод № 8: "cccowwwwbbeeeeelllllccco"

Тестовый вход № 9: "be well, programming puzzles & code golf"

Тестовый вывод № 9: "be well, programming puzzles & code golfbe well, programming puzzles & c"

Тестовый вход № 10: "lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. wow!"

Тестовый вывод № 10: "lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. wow!lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut lab"

Тестовый вход № 11:

"c-c-b-c

i have a cow, i have a bell.
uh! bell-cow!
i have a cow, i have a cowbell.
uh! cowbell-cow!

bell-cow, cowbell-cow.
uh! cow-cowbell-bell-cow.
cow-cowbell-bell-cow!
"

Тестовый вывод № 11:

"c-c-b-c

i have a cow, i have a bell.
uh! bell-cow!
i have a cow, i have a cowbell.
uh! cowbell-cow!

bell-cow, cowbell-cow.
uh! cow-cowbell-bell-cow.
cow-cowbell-bell-cow!
c-c-b-c

i have a cow, i have a bell"

23
Любой, кто отвечает в COW, зарабатывает десять интернет-очков.
Павел

3
Я думаю, что людям было бы намного легче обрабатывать случаи ввода / вывода, если вы отформатировали их в одном блоке кода. В настоящее время он занимает много места и не очень удобен для копирования.
FryAmTheEggman

Добавлена ​​ссылка на Pastebin для копирования / вставки. Если в этом посте есть способ скрыть / свернуть / показать тестовые случаи, сэкономив при этом вертикальное пространство, я бы с удовольствием его изучил.
Грег Мартин

2
Ну обычно люди используют test case -> resultв одном большом предварительно отформатированном блоке кода. С эстетической точки зрения это намного приятнее и проще копировать.
FlipTack

1
@MatthewRoh Помимо того, что Lв этом слове есть две буквы , это не то, что требует задача.
Мартин Эндер

Ответы:


13

Пип , 50 42 38 байт

T$<(MN{_NaM"lcowbe"}//^2M[aYa@<i])++iy

Передайте строку в качестве аргумента командной строки, если необходимо, заключите в кавычки. Попробуйте онлайн!

объяснение

Я собираюсь объяснить это в двух частях: функция «колокольчик» и полная программа. Во-первых, вот функция, которая вычисляет количество ковбелл в строке:

MN{_NaM"lcowbe"}//^2

{...}определяет функцию. Многие операторы Pip при применении к функции возвращают другую функцию; например, так -{a+1}же, как {-(a+1)}. Таким образом, вышесказанное эквивалентно

{MN(_NaM"lcowbe")//^2}

который работает следующим образом:

{                    }  Function, in which a is the 1st argument (the string)
    _Na                 Lambda fn: returns number of times its argument occurs in a
       M"lcowbe"        Map that function to the characters of "lcowbe"
                   ^2   A devious way to get [2]: split the scalar 2 into characters
   (            )//     Int-divide the list of character counts by [2]
                        Since the lists are not the same length, this divides the first
                          element (# of l's) by 2 and leaves the others alone
 MN                     Take the min of the resulting list

Теперь, когда у нас это есть, вот полная программа:

T$<(MN{_NaM"lcowbe"}//^2M[aYa@<i])++iy
                                        a is 1st cmdline arg, i is 0 (implicit)
T                                       Loop till condition is true:
                            a@<i        Slice leftmost i characters of a
                           Y            Yank that into y variable
                         [a     ]       List containing a and that value
                        M               To that list, map...
    MN{_NaM"lcowbe"}//^2                ... the cowbell function
                                        Result: a list containing the amount of cowbell
                                        in the original string and the amount in the slice
 $<(                             )      Fold on less-than: true if the first element is
                                        less than the second, otherwise false
                                  ++i   In the loop, increment i
                                     y  Once the loop exits, print y (the latest slice)

Я вошел, cowbell cowbell cowbeeи вывод был, cowbellcowbelcowbelно я мог неправильно использовать IDE (новичок в PIP)
Альберт Реншоу

@AlbertRenshaw Я получаю cowbell cowbell cowbeecowbell( попробуйте онлайн ). Вы используете TIO или локальную копию?
DLosc

О, классно! Я вставил его в поле «вход», а не в аргумент «Добавить». +1
Альберт Реншоу

Действительно высший класс. Я перенес это на javascript.
edc65

6

С 511 488 474 470 463 454

void f(char*a){char*s;int i=-1,c,o,w,b,e=b=w=o=c=1,l=3,n,r,z=i;for(;s=a[++i];c+=s==67,o+=s==79,w+=s==87,b+=s==66,e+=s==69,l+=s==76);r=~-l/2;n=c<o?c:o;n=w<n?w:n;n=b<n?b:n;n=e<n?e:n;n=r<n?r:n;c=c==n;o=o==n;w=w==n;b=b==n;e=e==n;if(l=r==n?l:0)if(l%2)l=2;else l=1,c=o=w=b=e=0;else l+=l%2;n=c+o+w+b+e+l;for(printf("%s",a);s=n?a[++z]:0;s==67&&c?n--,c--:0,s==79&&o?n--,o--:0,s==87&&w?n--,w--:0,s==66&&b?n--,b--:0,s==69&&e?n--,e--:0,s==76&&l?n--,l--:0,putchar(s));}

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


Читаемый формат + объяснение:

void f(char*a){
//a = input

    char*s;

    int i=-1,c,o,w,b,e=b=w=o=c=1,l=3,n,r,z=i;//c,o,w,b,e all start at 1; L starts at 3

    for(;s=a[++i];c+=s==67,o+=s==79,w+=s==87,b+=s==66,e+=s==69,l+=s==76);
    //loop to obtain number of times each character C,O,W,B,E,L is found in string (using the ASCII numeric values of each letter)

    //to get an extra cowbell we need to increment C,O,W,B,E by 1 and L by 2 (two Ls in cowbell); except we don't have to because we already did that by starting them at c=1, o=1, w=1, b=1, e=1, L=3 when we declared them. 

    r=~-l/2;
    //r is half of (1 less the number of times L is in string (+ init value))

    n=c<o?c:o;n=w<n?w:n;n=b<n?b:n;n=e<n?e:n;n=r<n?r:n;
    //n is the number of times that the least occouring character appears in the string, (use R instead of L since cowbell has two L's in it and we just need ~-l/2)

    c=c==n;o=o==n;w=w==n;b=b==n;e=e==n;
    //convert c,o,w,b,e to BOOL of whether or not we need 1 more of that letter to create one more cowbell (logic for L handled below since it's trickier)

    if(l=r==n?l:0)//if L-1/2 is [or is tied for] least occurring character do below logic, else set l to 0 and skip to `else`
        if(l%2)//if l is divisible by 2 then we need 2 more Ls
            l=2;
        else //otherwise we just need 1 more l and no other letters
            l=1,c=o=w=b=e=0;
    else //add 1 to L if it's divisible by 2 (meaning just 1 more L is needed in addition to possibly other C,O,W,B,E letters) (*Note: L count started at 3, so a count of 4 would be divisible by 2 and there is only 1 L in the string)
        l+=l%2;

    n=c+o+w+b+e+l;
    //n = number of specific characters we need before we reach 1 more cowbell

    for(printf("%s",a);s=n?a[++z]:0;s==67&&c?n--,c--:0,s==79&&o?n--,o--:0,s==87&&w?n--,w--:0,s==66&&b?n--,b--:0,s==69&&e?n--,e--:0,s==76&&l?n--,l--:0,putchar(s));
    //loop starts by printing the original string, then starts printing it again one character at a time until the required number of C,O,W,B,E,L letters are reached, then break (s=n?a[++z]:0) will return 0 when n is 0. Each letter subtracts from n only when it still requires letters of its type (e.g. b?n--,b--:0)

}

Использованы некоторые забавные трюки:

• При проверке символов я печатаю 'w'для символа w, который составляет 3 байта, но для символов 'c'и 'b'я могу ввести их значения ASCII 99 и 98 соответственно, чтобы каждый раз сохранять байт. (Изменить: Благодаря @Titus, я знаю, сделать это со всеми буквами COWBELL, используя только ввод в верхнем регистре, которые представляют собой 2-байтовые числовые значения ascii)

r=~-l/2в r=(l-1)/2использовании bitshifts

a[++i]Я получаю символ по индексу (i) и повторяю индекс одновременно. Я просто начать iв i=-1вместо i=0(я сделать то же самое с zи начать его как z=iдля сохранения следующего байта)


1
Сохраните 8 байтов с вводом в верхнем регистре: все коды ASCII ниже 100.
Титус

@ Титус Блестящий! Спасибо Титус, редактирование сейчас
Альберт Реншоу

1
В настоящее время у нас есть вопрос относительно вашего утверждения: «Второе определенное значение int (в данном случае c) всегда устанавливается как 1 [...].» Мы были бы рады получить ваше заявление о том, почему вы так думаете, потому что некоторым это кажется странным.
cadaniluk

@ Альберт, возможно, ваша программа просто c,o,w,b,eинициализируется тем же значением, а не 1? Потому что ваш намек № 2, похоже, не соответствует действительности, по крайней мере, для CI знают. Вы можете уточнить? ТАК вопрос
Феликс Домбек

1
@FelixDombek спасибо за указание на это тоже! Это деф. неопределенное поведение, я просто имитировал (зацикливал) во многих IDE и, похоже, всегда инициализировал int как 0. Я, вероятно, мог бы все-таки оставить его, хотя моя логика была разработана, чтобы все они были установлены в 1; Я думаю, что совпадение тестов с нулевым значением - это совпадение. Приветствия
Альберт Реншоу

5

Python 2, 125 113 112 байтов

n=lambda s:min(s.count(c)>>(c=='l')for c in "cowbel")
def f(s,i=0):
 while n(s)==n(s+s[:i]):i+=1
 return s+s[:i]

n считает количество колокольчиков


-12 байт благодаря @Rod
-1 байт благодаря @Titus


вам не нужно []понимать список, когда он является единственным параметром, также вы можете пропустить enumerate: min(s.count(c)/-~(c=='l')for c in"cowbel")где -~(n=='l')более короткий способ записи1+(n=='l')
Rod

1
Не >>будет короче чем /-~?
Титус

@Titus вы правы
OVS

Была предпринята попытка редактирования, при котором байт был удален путем замены последнего пробела новой строки одной точкой с запятой.
Пшеничный волшебник

@ Мёбиус, разве тогда не было returnбы времени?
овс

5

Perl 6 , 91 байт

{my &c={.comb.Bag.&{|.<c o w b e>,.<l>div 2}.min}
first *.&c>.&c,($_ X~[\,](.comb)».join)}

Предполагает ввод строчных букв.

Как это работает

Внутри лямбды другая лямбда для подсчета количества колокольчиков в строке определяется так:

my &c={                                        }  # Lambda, assigned to a variable.
       .comb                                      # Split the string into characters.
            .Bag                                  # Create a Bag (maps items to counts).
                .&{                       }       # Transform it into:
                   |.<c o w b e>,                 #   The counts of those letters, and
                                 .<l>div 2        #   half the count of "l" rounded down.
                                           .min   # Take the minimum count.

Остальная часть кода использует эту внутреннюю лямбду, &cчтобы найти результат, например так:

                     [\,](.comb)».join   # All prefixes of the input,
               ($_ X~                 )  # each appended to the input.
first         ,                          # Return the first one for which:
      *.&c>                              #   The cowbell count is greater than
           .&c                           #   the cowbell count of the input.

4

MATL , 38 37 байт

1 байт благодаря идее @ DLosc об использовании строки шаблона lcowbeвместоcowbel

n`Gt@q:)hXK!'lcowbe'=s32BQ/kX<wy-Q]xK

Все вводимые символы строчные. Если входные данные содержат символы новой строки, символ новой строки необходимо вводить в виде его кода ASCII, объединенного с обычными символами (см. Последний ввод в ссылке со всеми тестовыми примерами).

Попробуйте онлайн! Или проверьте все тестовые случаи .


3

JavaScript (ES6), 106 107 113 126 141

Портирование на javascript ответа Pip от @DLosc. Мне нужно было время, чтобы полностью понять это, и это гений.

Отредактируйте -15 байт, следуя подсказке @Titus, напрямую добавляя символы к входной строке aи избегая досрочного возврата (поэтому нет for/if)

Редактирование 2, перечисляя значение 6 для функции Min, сохраняет другие 13 байтов.

Изменить 3 изменил функцию c снова. Я думал, что многословно lengthи splitбудет слишком долго. Я был неправ.

Предполагая ввод строчных букв

a=>[...a].some(z=>c(a+=z)>b,c=a=>Math.min(...[...'lcowbe'].map((c,i)=>~-a.split(c).length>>!i)),b=c(a))&&a

Меньше гольфа

a=>{
  c=a=>{ // cowbell functions - count cowbells
    k = [... 'lcowbe'].map((c,i) => 
          (a.split(c).length - 1) // count occurrences of c in a
           / (!i + 1) // divide by 2 if first in list ('l')
    );
    return Math.min(...k);
  };
  b = c(a); // starting number of cowbells
  [...a].some(z => ( // iterate for all chars of a until true
    a += z,
    c(a) > b // exit when I have more cowbells
  ));
  return a;
}

Тест

f=
a=>[...a].some(z=>c(a+=z)>b,c=a=>Math.min(...[...'lcowbe'].map((c,i)=>~-a.split(c).length>>!i)),b=c(a))&&a

;["christopher walken begs for more cowbell!"
,"the quick brown fox jumps over the lazy dog"
,"cowbell"
,"cowbell cowbell cowbell"
,"cowbell cowbell cowbel"
,"bcelow"
,"abcdefghijklmnopqrstuvwxyz"
,"cccowwwwbbeeeeelllll"
,"be well, programming puzzles & code golf"
,"lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. wow!"
,`c-c-b-c
 
i have a cow, i have a bell.
uh! bell-cow!
i have a cow, i have a cowbell.
uh! cowbell-cow!
 
bell-cow, cowbell-cow.
uh! cow-cowbell-bell-cow.
cow-cowbell-bell-cow!
`].forEach(x=>console.log(x+'\n\n'+f(x)))


Я думаю, k[x]++что не получится из-за undefined. Но я уверен, что это for(i=0;c(a)==c(a+=a[i++]);),aработает.
Титус

@ Титус Я не уверен, чтобы понять. Я попробую
edc65

@ Титус вау 15 байт сохранено, большое спасибо
edc65

>>!iэкономит 3 байта. Почему вы не используете c(a+=z)?
Тит

@ Titus я использую c(a+=z). Не в менее гольфовой версии, как вы видите, менее гольфовой. Использование >>!iэкономит 1 байт (в версии для гольфа).
Еще

2

Утилиты Bash + Unix, 184 байта

f()(tr -cd cowbel<<<"$1"|sed 's/\(.\)/\1\
/g'|sort|uniq -c|awk '{print int($1/(($2=="l")?2:1))}'|sort -n|head -1)
for((m=1;`f "$1${1:0:m}"`!=$[`f "$1"`+1];m++)){ :;}
echo "$1${1:0:$m}"

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

Спасибо @AlbertRenshaw за игру в гольф на 2 байта.


Это может быть сделано в дальнейшем, например, просто удаляя пробелы до и после!=
Альберт Реншоу

1
@AlbertRenshaw Спасибо - я думал, что попробовал это и получил синтаксическую ошибку, но вы правы. Часть awk также может быть пригодна для игры в гольф; Я не очень знаком с awk.
Митчелл Спектор

Да, я наивно пытался удалить другие пробелы и разрывы строк в вашем коде и получал синтаксические ошибки, но на этом он работал ¯_ (ツ) _ / ¯
Альберт Реншоу

2

JavaScript (ES6), 124 114 байт

Спасибо Нейлу за сохранение нескольких байтов

a=>eval("for(c=0,d=a;(A=$=>Math.min([...'cowbel'].map(_=>($.split(_).length-1)>>(_=='l'))))(a)==A(d+=a[c++]););d")

Поскольку это сильно отличается от уже существующего ответа JavaScript, и я потратил немало времени на это, я решил создать ответ сам.

использование

f=a=>eval("for(c=0,d=a;(A=$=>Math.min([...'cowbel'].map(_=>($.split(_).length-1)>>(_=='l'))))(a)==A(d+=a[c++]););d")
f("cowbell")

Выход

"cowbellcowbell"

.sort()[0]это изумительная идея evalэто зло : D
Титус

Спасибо ;-) Я сначала использовал Math.min(), но это стоило много символов, и я подумал, что будет более короткий путь. И да, evalдействительно хорош для игры в гольф.
Люк

Если бы это .sort()[0]работало, это стоило бы всего 10 байтов, но это не так, и .sort((a,b)=>a-b)[0]стоило бы 20 байтов, а Math.min(...)стоило бы только 13.
Нил

2

Октава, 80 87 97 байт

s=input('');k=1;do;until(x=@(A)min(fix(sum('cowbel'==A')./('111112'-48))))(b=[s s(1:++k)])>x(s);b

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


1
Это не работает, когда нам нужно два lс, чтобы завершить дополнительный колокольчик. Например, при вводе cowbellон неверно возвращает, cowbellcowbelа не cowbellcowbell. (Я надеюсь, что вы можете это исправить - мне нравится нетипичный алгоритм!)
Грег Мартин

@GregMartin Спасибо! Я проверю это!
rahnema1

2

CJam, 37

q___S\+{+"cowbel"1$fe=)2/+:e<\}%()#)<

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

Если я могу исключить "и \символы, то ...

35 байт

q___`{+"cowbel"1$fe=)2/+:e<\}%()#)<

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

объяснение

Код последовательно добавляет каждый символ строки к исходной строке (переходя от исходного к удвоенному), определяет количество колокольчиков для каждой строки (подсчитывает количество вхождений каждого символа в «ковбеле» и делит один на «l»). на 2, затем беря минимум), находит позицию первой строки, где число колокольчиков увеличивается на 1, затем берет соответствующий префикс ввода и помещает его после строки ввода.

Чтобы также включить исходную строку (без добавления символа), в коде добавляется нейтральный символ к строке, которая повторяется. Первая версия добавляет пробел, а вторая версия использует строковое представление, то есть строку между двойными кавычками.

q___          read input and make 3 more copies: one for output, one for prefix,
               one for appending and one for iterating
S\+           prepend a space to the iterating string
              or
`             get the string representation
{…}%          map each character of the string
  +           append the character to the previous string
  "cowbel"    push this string
  1$          copy the appended string
  fe=         get the number of occurrences of each "cowbel" character
  )2/+        take out the last number, divide by 2 and put it back
  :e<         find the minimum
  \           swap with the appended string
(             take out the first number (cowbells in the initial string)
)#            increment and find the index of this value in the array
)             increment the index (compensating for taking out one element before)
<             get the corresponding prefix
              another copy of the input is still on the stack
              and they are both printed at the end

Я в порядке с вами, исключая символы "и \"!
Грег Мартин

1

PHP, 133 байта

порт PHP @ edc65, порт JavaScript ответа DLosc's Pip.

function f($s){for(;$c=lcowbe[$i];)$a[$c]=substr_count($s,$c)>>!$i++;return min($a);}for($s=$argv[1];f($s)==f($s.=$s[$i++]););echo$s;

принимает строчные данные из аргумента командной строки. Беги с -nr.

сломать

// function to count the cowbells:
function f($s)
{
    for(;$c=lcowbe[$i];)            # loop through "cowbel" characters
        $a[$c]=substr_count($s,$c)  # count occurences in $s
            >>!$i++;                # divide by 2 if character is "l" (first position)
        return min($a);             # return minimum value
}
for($s=$argv[1];    # copy input to $s, loop:
    f($s)               # 1. count cowbells in $s
    ==                  # 3. keep looping while cowbell counts are equal
    f($s.=$s[$i++])     # 2. append $i-th character of $s to $s, count cowbells
;);
echo$s;             # print $s
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.