Più campanaccio ...!


42

Si sta fornendo il supporto tecnico per la Bruce Dickenson come egli produce una sessione di registrazione Blue Oyster Cult. Quando chiede altro campanaccio , puoi darglielo.

Il tuo compito

Scrivi un programma o una funzione che accetta come input una stringa (o equivalente nella tua lingua) e genera una stringa correlata contenente un altro campanaccio.

Quanti campanacci contiene una stringa?

Il numero di campanacci che una stringa contiene è uguale al numero massimo di copie distinte di "campanaccio" che possono essere ottenute permutando i caratteri della stringa. Ad esempio, "bbbccceeellllllooowwwwwwwww"contiene 3 campanacci, mentre "bbccceeellllllooowwwwwwwww"e "bbbccceeelllllooowwwwwwwww"ciascuno contiene 2 campanacci e "cowbel"contiene 0 campanacci.

Come dovrebbe essere correlato l'output all'input?

L'output dovrebbe consistere nella concatenazione, in questo ordine, della stringa di input e del prefisso più breve della stringa di input necessaria per aumentare il numero di campanacci.

Ad esempio, è "bbbccceeelllllooowwwwwwwww"necessario solo un ulteriore "l"per contenere 3 campanacci anziché 2; il prefisso più breve che contiene che "l"è "bbbccceeel". Pertanto, se l'input è "bbbccceeelllllooowwwwwwwww", allora dovrebbe essere l'output "bbbccceeelllllooowwwwwwwwwbbbccceeel".

Aspetti tecnici

  • Si può presumere che l'input contenga solo caratteri ASCII stampabili. Se ci sono uno o due caratteri che sono fastidiosi per l'elaborazione delle stringhe della tua lingua (come newline o \), puoi presumere che l'input non li contenga, basta menzionare questa limitazione.
  • Si può inoltre supporre che i caratteri alfabetici nell'input siano tutti minuscoli o maiuscoli. Se scegli di non assumere uno di questi, conta i campanacci senza distinzione tra maiuscole e minuscole.
  • Si può inoltre ipotizzare che l'input contiene almeno una copia di ciascuno dei personaggi b, c, e, l, o, e w. Ciò equivale ad assumere che un prefisso della stringa possa essere concatenato ad essa per produrre una stringa che contiene più campanaccio. (Notare che la stringa di input stessa non deve contenere un campanaccio.)
  • Se la tua lingua ha un builtin che risolve questo problema ... quindi usalo totalmente, sul serio, quanto è fantastico.

Pannolini dorati

Poiché il tempo di registrazione in studio è costoso, il codice deve essere il più breve possibile. La voce con il minor numero di byte è il vincitore!

Casi test

( link pastebin per facilitare la copia / incolla)

Ingresso di prova n. 1: "christopher walken begs for more cowbell!"

Uscita test n. 1: "christopher walken begs for more cowbell!christopher wal"

Ingresso di prova n. 2: "the quick brown fox jumps over the lazy dog"

Uscita test n. 2: "the quick brown fox jumps over the lazy dogthe quick brown fox jumps over the l"

Ingresso di prova n. 3: "cowbell"

Uscita test n. 3: "cowbellcowbell"

Test input # 4: "cowbell cowbell cowbell"

Uscita test n. 4: "cowbell cowbell cowbellcowbell"

Ingresso di prova n. 5: "cowbell cowbell cowbel"

Uscita test n. 5: "cowbell cowbell cowbelcowbel"

Test input # 6: "bcelow"

Uscita test n. 6: "bcelowbcel"

Test input # 7: "abcdefghijklmnopqrstuvwxyz"

Uscita test n. 7: "abcdefghijklmnopqrstuvwxyzabcdefghijkl"

Ingresso di prova n. 8: "cccowwwwbbeeeeelllll"

Uscita test n. 8: "cccowwwwbbeeeeelllllccco"

Ingresso di prova n. 9: "be well, programming puzzles & code golf"

Uscita test n. 9: "be well, programming puzzles & code golfbe well, programming puzzles & c"

Ingresso di prova n. 10: "lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. wow!"

Uscita test n. 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"

Test input # 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!
"

Uscita test n. 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
Chiunque risponda in COW guadagna dieci punti internet.
Pavel

3
Penso che sarebbe molto più facile per le persone gestire i casi di input / output se li formattassi in un singolo blocco di codice. Allo stato attuale, occupa molto spazio e non è molto adatto alla copia e incolla.
FryAmTheEggman,

Collegamento Pastebin aggiunto per copia / incolla. Se c'è un modo per nascondere / comprimere / mostrare i casi di test in questo post, risparmiando così spazio verticale, mi piacerebbe impararlo.
Greg Martin,

2
Bene, normalmente le persone usano test case -> resultun unico grande blocco di codice preformattato. È molto più bello esteticamente e più facile da copiare incolla.
FlipTack

1
@MatthewRoh A parte il fatto che ci sono due Ls nella parola, questo non è ciò che la sfida richiede.
Martin Ender,

Risposte:


13

Pip , 50 42 38 byte

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

Passare la stringa come argomento della riga di comando, citato se necessario. Provalo online!

Spiegazione

Lo spiegherò in due parti: la funzione campanaccio e il programma completo. Innanzitutto, ecco la funzione che calcola la quantità di campanaccio in una stringa:

MN{_NaM"lcowbe"}//^2

{...}definisce una funzione. Molti operatori Pip, quando applicati a una funzione, restituiscono un'altra funzione; per esempio, -{a+1}è uguale a {-(a+1)}. Quindi quanto sopra equivale a

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

che funziona come segue:

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

Ora che ce l'abbiamo, ecco il programma 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)

Sono entrato cowbell cowbell cowbeee l'output è stato cowbellcowbelcowbelma potrei usare l'IDE sbagliato (nuovo in PIP)
Albert Renshaw,

@AlbertRenshaw ottengo cowbell cowbell cowbeecowbell( provalo online ). Stai usando TIO o una copia locale?
DLosc

Oh bello! Lo stavo attaccando sotto il campo "input" non sotto l'argomento add. +1
Albert Renshaw,

Davvero di prima classe. L'ho portato su 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));}

Provalo online


Formato leggibile + spiegazione:

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)

}

Alcuni trucchi divertenti usati:

• Quando controllo i caratteri, digito 'w'per il carattere w che è di 3 byte, ma per i caratteri 'c'e 'b'posso digitare i loro valori ASCII 99 e 98 rispettivamente per salvare un byte ogni volta. (Modifica: grazie a @Titus lo so fare con tutte le lettere COWBELL usando solo l'input maiuscolo che sono tutti valori ascii numerici di 2 byte)

r=~-l/2sta r=(l-1)/2usando i bitshift

a[++i]Ricevo il carattere su index (i) e sto ripetendo l'indice allo stesso tempo. Ho appena iniziare ia i=-1invece di i=0(io lo faccio lo stesso con ze avviarlo come z=iper salvare un altro byte)


1
Salva 8 byte con l'input maiuscolo: tutti i codici ASCII inferiori a 100.
Titus

@Titus Brilliant! Grazie Tito, edito ora
Albert Renshaw il

1
Al momento abbiamo una domanda relativa alla tua affermazione "Il secondo int definito (in questo caso c) è sempre impostato su 1 [...]." Saremo lieti di avere la tua affermazione sul perché la pensi così laggiù perché sembra strano per alcuni di noi.
Cadaniluk,

@Albert potrebbe essere che il tuo programma si basi solo c,o,w,b,eper essere inizializzato sullo stesso valore, anziché su 1? Perché il tuo suggerimento n. 2 sembra non essere vero, non almeno per l'IC. Puoi chiarire? Domanda SO
Felix Dombek,

1
@FelixDombek grazie anche per averlo segnalato! È def. comportamento indefinito, l'ho appena simulato (in loop) su molti IDE e sembra sempre inizializzare l'int come 0. Probabilmente potrei lasciarlo dopo tutto, anche se la mia logica è stata progettata per averli tutti impostati su 1; il fatto che i casi di test stiano lavorando con esso a 0 è una coincidenza, penso. Acclamazioni
Albert Renshaw

5

Python 2, 125 113 112 byte

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 il numero di campanacci


-12 byte grazie a @Rod
-1 byte grazie a @Titus


non è necessario []per la comprensione dell'elenco quando è l'unico parametro, inoltre è possibile eliminare enumerate: min(s.count(c)/-~(c=='l')for c in"cowbel")dov'è -~(n=='l')un modo più breve di scrivere1+(n=='l')
Rod

1
Non >>sarebbe più breve di /-~?
Tito

@Titus hai ragione
ovs

Si è verificato un tentativo di modifica che avrebbe rimosso un byte sostituendo l'ultimo spazio di nuova riga con un solo punto e virgola.
Mago del grano

@ Möbius Non returnsarebbe nel ciclo while allora?
Ovs

5

Perl 6 , 91 byte

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

Presuppone input in lettere minuscole.

Come funziona

All'interno della lambda, un'altra lambda per contare il numero di campanacci in una stringa è definita come tale:

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.

Il resto del codice utilizza questa lambda interna &cper trovare il risultato, in questo modo:

                     [\,](.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 byte

1 byte di sconto grazie all'idea di @ DLosc di utilizzare la stringa di modello lcowbeanzichécowbel

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

I caratteri di input sono tutti in minuscolo. Se l'input contiene newline, il carattere newline deve essere inserito come suo codice ASCII concatenato con i caratteri normali (vedere l'ultimo input nel collegamento con tutti i casi di test).

Provalo online! Oppure verifica tutti i casi di test .


3

JavaScript (ES6), 106 107 113 126 141

Un porting su javascript della risposta Pip di @DLosc. Ho avuto bisogno di un po 'di tempo per capirlo appieno ed è geniale.

Modifica -15 byte seguendo il suggerimento di @Titus, aggiungendo direttamente i caratteri alla stringa di input aed evitando il ritorno anticipato (quindi no for/if)

Modifica 2 enumerando il valore 6 per la funzione Min salva altri 13 byte

Modifica 3 ha cambiato di nuovo la funzione c. Ho pensato al verboso lengthe splitsarebbe troppo lungo. Mi sbagliavo.

Supponendo un input in minuscolo

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

Meno golf

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

Test

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


Immagino che k[x]++fallirebbe a causa di undefined. Ma sono abbastanza sicuro che for(i=0;c(a)==c(a+=a[i++]);),afunzioni.
Tito

@Titus Non sono sicuro di capire. Ci proverò
edc65

@Titus wow 15 byte salvati, grazie
mille

>>!isalva 3 byte. Perché non usi c(a+=z)?
Tito

@Titus che uso c(a+=z). Non nella versione meno giocata , com'è, vedi, meno giocata. Usando si >>!isalva 1 byte (nella versione golfed). Grazie ancora
edc65,

2

Utilità Bash + Unix, 184 byte

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

Provalo online!

Grazie a @AlbertRenshaw per il golf 2 byte di sconto.


Questo può essere ulteriormente risolto, ad esempio rimuovendo gli spazi prima e dopo il!=
Albert Renshaw,

1
@AlbertRenshaw Grazie. Pensavo di averlo provato e di aver riscontrato un errore di sintassi, ma hai ragione. La parte awk può essere anche golfabile; Non ho molta familiarità con Awk.
Mitchell Spector,

Sì, ho ingenuamente provato a rimuovere altri spazi e interruzioni di riga nel codice e ho riscontrato errori di sintassi, ma su quello ha funzionato ¯ _ (ツ) _ / ¯
Albert Renshaw il

2

JavaScript (ES6), 124 114 byte

Grazie a Neil per aver salvato alcuni byte

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

Dato che questo è abbastanza diverso dalla risposta JavaScript già esistente e ho dedicato parecchio tempo a questo, ho deciso di creare una risposta da solo.

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

Produzione

"cowbellcowbell"

.sort()[0]è un'idea meravigliosa. evalè malvagio. : D
Tito

Grazie ;-) L'ho usato per la prima volta Math.min(), ma è costato molti personaggi e ho pensato che ci sarebbe stato un modo più breve. E sì, evalè davvero bello per il golf.
Luca

Se solo .sort()[0]funzionasse, costerebbe solo 10 byte, ma non lo è, e .sort((a,b)=>a-b)[0]costa 20 byte, ma Math.min(...)costa solo 13.
Neil

2

Ottava, 80 87 97 byte

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

Provalo online!


1
Questo non funziona quando abbiamo bisogno di due lsecondi per completare il campanaccio aggiuntivo. Ad esempio, sull'input cowbell, restituisce erroneamente cowbellcowbelanziché cowbellcowbell. (Spero che si può risolvere il problema, mi piace l'algoritmo atipico!)
Greg Martin

@GregMartin Grazie! Lo guarderò!
rahnema1,

2

CJam, 37

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

Provalo online

Se posso escludere i caratteri "e \, allora ...

35 byte

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

Provalo online

Spiegazione

Il codice accoda successivamente ogni carattere della stringa alla stringa iniziale (passando dall'originale al doppio), determina il numero di campanacci per ogni stringa (contando il numero di occorrenze di ciascun carattere in "cowbel" e dividendo quello per 'l' di 2, quindi prendendo il minimo), trova la posizione della prima stringa in cui il numero di campanacci aumenta di 1, quindi prende il prefisso corrispondente dell'input e lo inserisce dopo la stringa di input.

Per includere anche la stringa originale (senza carattere aggiunto), il codice antepone un carattere neutro alla stringa che viene ripetuta. La prima versione antepone uno spazio e la seconda versione utilizza la rappresentazione di stringa, ovvero la stringa tra virgolette doppie.

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

Sto bene escludendo i caratteri "e \!
Greg Martin, l'

1

PHP, 133 byte

una porta PHP della porta JavaScript di @ edc65 della risposta Pip di 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;

accetta l'input in minuscolo dall'argomento della riga di comando. Corri con -nr.

abbattersi

// 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.