Mais chocalho…!

42

Você está fornecendo suporte técnico para o Bruce Dickenson como ele produz uma sessão de gravação Blue Oyster Cult. Quando ele pede mais chocalho , você pode dar a ele.

Sua tarefa

Escreva um programa ou função que use uma string (ou equivalente no seu idioma) como entrada e emita uma string relacionada contendo mais um cowbell.

Quantos chocalhos contém uma corda?

O número de campainhas que uma string contém é igual ao número máximo de cópias distintas de "cowbell" que podem ser obtidas permutando os caracteres da string. Por exemplo, "bbbccceeellllllooowwwwwwwww"contém 3 cencerros, enquanto "bbccceeellllllooowwwwwwwww"e "bbbccceeelllllooowwwwwwwww"contêm cada um 2 cencerros, e "cowbel"contém 0 Tama.

Como a saída deve estar relacionada à entrada?

A saída deve consistir na concatenação, nessa ordem, da sequência de entrada e o prefixo mais curto da sequência de entrada necessária para aumentar o número de chocalhos.

Por exemplo, "bbbccceeelllllooowwwwwwwww"precisa apenas de um adicional "l"para conter 3 chocalhos em vez de 2; o prefixo curto que contém o "l"é "bbbccceeel". Portanto, se a entrada for "bbbccceeelllllooowwwwwwwww", a saída deve ser "bbbccceeelllllooowwwwwwwwwbbbccceeel".

Technicalities

  • Você pode assumir que a entrada contém apenas caracteres ASCII imprimíveis. Se houver um ou dois caracteres que são irritantes para o processamento de strings do seu idioma (como novas linhas ou \), você pode assumir que a entrada não os contém - apenas mencione esta restrição.
  • Você também pode assumir que os caracteres alfabéticos na entrada estão todos em minúsculas ou em maiúsculas. Se você optar por não assumir uma delas, conte os chocalhos sem diferenciar maiúsculas de minúsculas.
  • Você pode ainda assumir que a entrada contém pelo menos uma cópia de cada um dos personagens b, c, e, l, o, e w. Isso equivale a supor que algum prefixo da string possa ser concatenado para produzir uma string que contenha mais cowbell. (Observe que a própria string de entrada não precisa conter um chocalho.)
  • Se o seu idioma possui um built-in que resolve esse problema ... use-o totalmente, sério, o quão impressionante é isso.

Fraldas folheadas a ouro

Como o tempo de gravação do estúdio é caro, seu código deve ser o mais curto possível. A entrada com menos bytes é o vencedor!

Casos de teste

( link pastebin para facilitar a cópia / colar)

Entrada de teste nº 1: "christopher walken begs for more cowbell!"

Teste de saída 1: "christopher walken begs for more cowbell!christopher wal"

Entrada de teste nº 2: "the quick brown fox jumps over the lazy dog"

Teste de saída # 2: "the quick brown fox jumps over the lazy dogthe quick brown fox jumps over the l"

Entrada de teste nº 3: "cowbell"

Teste de saída # 3: "cowbellcowbell"

Entrada de teste # 4: "cowbell cowbell cowbell"

Teste de saída # 4: "cowbell cowbell cowbellcowbell"

Entrada de teste nº 5: "cowbell cowbell cowbel"

Teste de saída # 5: "cowbell cowbell cowbelcowbel"

Entrada de teste # 6: "bcelow"

Teste de saída # 6: "bcelowbcel"

Entrada de teste nº 7: "abcdefghijklmnopqrstuvwxyz"

Teste de saída 7: "abcdefghijklmnopqrstuvwxyzabcdefghijkl"

Entrada de teste nº 8: "cccowwwwbbeeeeelllll"

Teste de saída # 8: "cccowwwwbbeeeeelllllccco"

Entrada de teste nº 9: "be well, programming puzzles & code golf"

Teste de saída # 9: "be well, programming puzzles & code golfbe well, programming puzzles & c"

Entrada de teste nº 10: "lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. wow!"

Teste de saída # 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"

Entrada de teste # 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!
"

Resultado do teste # 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"
Greg Martin
fonte
23
Quem responde em COW ganha dez pontos na Internet.
Pavel
3
Eu acho que seria muito mais fácil para as pessoas lidar com os casos de entrada / saída se você os formatasse em um único bloco de código. Tal como está, ocupa muito espaço e não é muito fácil de copiar e colar.
FryAmTheEggman
Link Pastebin adicionado para copiar / colar. Se houver uma maneira de ocultar / recolher / mostrar os casos de teste nesta postagem, economizando espaço vertical, eu adoraria aprender.
Greg Martin
2
Bem, normalmente as pessoas usam test case -> resultem um grande bloco de código pré-formatado. É muito mais agradável esteticamente e mais fácil copiar e colar.
precisa saber é o seguinte
1
@ MatthewRoh Além do fato de haver dois Ls na palavra, não é isso que o desafio pede.
Martin Ender

Respostas:

13

Pip , 50 42 38 bytes

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

Passe a string como um argumento de linha de comando, citado se necessário. Experimente online!

Explicação

Vou explicar isso em duas partes: a função cowbell e o programa completo. Primeiro, aqui está a função que calcula a quantidade de cowbell em uma string:

MN{_NaM"lcowbe"}//^2

{...}define uma função. Muitos operadores Pip, quando aplicados a uma função, retornam outra função; por exemplo, -{a+1}é o mesmo que {-(a+1)}. Portanto, o acima é equivalente a

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

que funciona da seguinte maneira:

{                    }  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

Agora que temos isso, aqui está o programa completo:

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)
DLosc
fonte
Entrei cowbell cowbell cowbeee a saída era cowbellcowbelcowbel, mas eu poderia estar usando o errado IDE (novo para PIP)
Albert Renshaw
@AlbertRenshaw recebo cowbell cowbell cowbeecowbell( experimente online ). Você está usando o TIO ou uma cópia local?
DLosc 30/01
Ah legal! Eu estava colocando-o no campo "input" e não no argumento add. 1
Albert Renshaw
Realmente classe superior. Eu o carreguei para javascript.
edc65
6

C, 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));}

Experimente online


Formato legível + explicação:

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)

}

Alguns truques divertidos usados:

• Ao verificar os caracteres, digito 'w'o caractere w de 3 bytes, mas os caracteres 'c'e 'b'eu podemos digitar seus valores ASCII 99 e 98, respectivamente, para salvar um byte de cada vez. (Edit: Graças a @Titus, eu sei fazer isso com todas as letras COWBELL usando apenas entrada maiúscula, que são todos os valores ASCII numéricos de 2 bytes)

r=~-l/2está r=(l-1)/2usando bitshifts

a[++i]Estou obtendo o caractere no índice (i) e iterando o índice, tudo ao mesmo tempo. Eu apenas começo iem i=-1vez de i=0(faço o mesmo ze começo z=ia salvar outro byte)

Albert Renshaw
fonte
1
Salvar 8 bytes com entrada maiúscula: todos os códigos ASCII abaixo de 100.
Titus
@Titus Brilliant! Obrigado Titus, editando agora
Albert Renshaw
1
Atualmente, temos uma pergunta sobre sua afirmação "O segundo int definido (neste caso c) é sempre definido como 1 [...]". Ficaríamos felizes em ter sua declaração sobre o porquê de você pensar lá, porque isso parece estranho para alguns de nós.
precisa saber é
@ Albert, pode ser que o seu programa apenas c,o,w,b,eseja inicializado com o mesmo valor, em vez de 1? Como sua dica nº 2 parece não ser verdadeira, pelo menos para o IC, pelo menos. Você pode esclarecer? Pergunta SO
Felix Dombek
1
@FelixDombek, obrigado por apontar também! É def. comportamento indefinido, eu apenas o simulei (em loop) em muitos IDEs e parece sempre iniciar o int como 0. Eu provavelmente poderia deixá-lo, apesar de tudo, apesar de minha lógica ter sido projetada para ter todos eles definidos como 1; o fato de os casos de teste estarem trabalhando com 0 é coincidência, eu acho. Cheers
Albert Renshaw
5

Python 2, 125 113 112 bytes

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 conta o número de chocalhos


-12 bytes graças a @Rod
-1 byte graças a @Titus

ovs
fonte
Você não precisa []para a compreensão da lista quando é o único parâmetro, você também pode soltar enumerate: min(s.count(c)/-~(c=='l')for c in"cowbel")onde -~(n=='l')é um caminho mais curto para escrever1+(n=='l')
Rod
1
Não >>seria mais curto que /-~?
Titus
@Titus você está certo
ovs
Houve uma tentativa de edição que removeria um byte, substituindo o último espaço da nova linha por um único ponto e vírgula.
Assistente de trigo
@ Möbius Não returnseria o momento, então?
ovs 31/01
5

Perl 6 , 91 bytes

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

Pressupõe entrada em letras minúsculas.

Como funciona

Dentro do lambda, outro lambda para contar o número de chocalhos em uma string é definido da seguinte maneira:

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.

O restante do código usa essa lambda interna &cpara encontrar o resultado, assim:

                     [\,](.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.
smls
fonte
4

MATL , 38 37 bytes

1 byte de desconto, graças à idéia do @ DLosc de usar a string de modelo em lcowbevez decowbel

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

Os caracteres de entrada estão todos em minúsculas. Se a entrada contiver novas linhas, o caractere da nova linha precisará ser inserido como seu código ASCII concatenado com os caracteres normais (consulte a última entrada no link com todos os casos de teste).

Experimente online! Ou verifique todos os casos de teste .

Luis Mendo
fonte
3

JavaScript (ES6), 106 107 113 126 141

Uma portabilidade para javascript da resposta Pip feita por @DLosc. Eu precisava de algum tempo para entender completamente, e é genial.

Edite -15 bytes seguindo a dica de @Titus, anexando diretamente caracteres à string de entrada ae evitando retorno antecipado (portanto, não for/if)

Editar 2 enumerando o valor 6 para a função Min salva outros 13 bytes

A edição 3 mudou a função c novamente. Eu pensei que o detalhado lengthe splitseria muito demorado. Eu estava errado.

Assumindo entrada em minúsculas

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

Menos golfe

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

Teste

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

edc65
fonte
Eu acho que k[x]++isso falharia devido a undefined. Mas tenho certeza de que for(i=0;c(a)==c(a+=a[i++]);),afunciona.
Titus
@ Titus Não sei ao certo. Eu vou tentar
edc65
@Titus wow 15 bytes salvos, muito obrigado
edc65
>>!isalva 3 bytes. Por que você não usa c(a+=z)?
Titus
@Titus eu uso c(a+=z). Não na versão menos golfe , como é, você vê, menos golfe. O uso >>!isalva 1 byte (na versão em golf). Obrigado novamente
edc65 03/02
2

Utilitários Bash + Unix, 184 bytes

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}"

Experimente online!

Graças a @AlbertRenshaw por jogar fora 2 bytes.

Mitchell Spector
fonte
Isto pode ser golfed ainda mais, por exemplo, apenas removendo os espaços antes e depois da!=
Albert Renshaw
1
@ AlbertRenshaw Obrigado - pensei que tinha tentado isso e obtive um erro de sintaxe, mas você está certo. A parte awk também pode ser mais jogável; Eu não estou muito familiarizado com o awk.
precisa saber é o seguinte
Sim, eu ingenuamente tentou remover outros espaços e quebras de linha em seu código e estava recebendo erros de sintaxe, mas em que se trabalhou _ (ツ) _ / ¯
Albert Renshaw
2

JavaScript (ES6), 124 114 bytes

Agradecimentos a Neil por salvar alguns bytes

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

Como isso é bem diferente da resposta JavaScript já existente, e dediquei bastante tempo a isso, decidi criar uma resposta pessoalmente.

Uso

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

Saída

"cowbellcowbell"
Luke
fonte
.sort()[0]é uma ideia maravilhosa. evalé mau. : D
Tito
Obrigado ;-) Eu usei pela primeira vez Math.min(), mas isso custou muitos caracteres e achei que haveria uma maneira mais curta. E sim, evalé muito bom para jogar golfe.
Luke
Se apenas .sort()[0]trabalhou, ele só iria custar 10 bytes, mas isso não acontece, e .sort((a,b)=>a-b)[0]custa 20 bytes, mas Math.min(...)custa apenas 13.
Neil
2

Oitava, 80 87 97 bytes

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

Experimente Online!

rahnema1
fonte
1
Isso não funciona quando precisamos de dois ls para concluir o cowbell adicional. Por exemplo, na entrada cowbell, ele retorna incorretamente cowbellcowbele não cowbellcowbell. (Espero que você possa corrigi-lo-I como o algoritmo atípica!)
Greg Martin
@GregMartin Thanks! Eu vou mastigar!
precisa saber é o seguinte
2

CJam, 37

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

Experimente online

Se eu posso excluir os caracteres "e \, então…

35 bytes

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

Experimente online

Explicação

O código anexa sucessivamente cada caractere da string à string inicial (do original para o dobro), determina o número de campainhas para cada string (contando o número de ocorrências de cada caractere no "cowbel" e dividindo o caractere por 'l' por 2 e, em seguida, obtendo o mínimo), localiza a posição da primeira string em que o número de campainhas aumenta em 1, pega o prefixo correspondente da entrada e o coloca após a string de entrada.

Para incluir também a string original (sem nenhum caractere acrescentado), o código anexa um caractere neutro à string que está sendo iterada. A primeira versão precede um espaço e a segunda versão usa a representação de string, ou seja, a string entre aspas duplas.

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
aditsu
fonte
Estou bem com você, excluindo os caracteres "e \!"
Greg Martin
1

PHP, 133 bytes

uma porta PHP da porta JavaScript do @ edc65 da resposta Pip do DLosc.

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;

recebe entrada em minúscula do argumento da linha de comando. Corra com -nr.

demolir

// 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
Titus
fonte