Fizz Buzz su testo


29

introduzione

Non so in particolare da dove provenga la tendenza alla moda. Potrebbe essere solo un meme o qualcosa del genere, ma è in qualche modo popolare.

Sfida

Il tuo lavoro oggi è convertire Fizz Buzz in binario (0, 1) rispettivamente e convertire quel binario in testo. Roba abbastanza standard.

Come funziona?

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz si tradurrebbe in 01101000 01101001 che poi si tradurrebbe in "ciao"

vincoli

  • L'input è Fizz Buzz in un punto di vista binario (vedi esempi di seguito).
  • L'output deve essere di testo.
  • Puoi presumere che l'ingresso FizzBuzz sia corretto.
  • Questo è , vincono i byte più brevi.

Ingresso

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBizzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzBizzBuzz

Produzione

"Ciao!"


15
Meme? Questo è un gioco scolastico primario (elementare)
Beta Decay del

2
Non possiamo prendere spazi nell'input?
HyperNeutrino,

2
Non possiamo prendere quello spazio però? Posso salvare tre byte se non devo inserire quello spazio.
HyperNeutrino,

10
FizzBuzz gode di molta valuta su Stack Exchange in parte perché Joel (uno dei fondatori) aveva un post sul blog che faceva riferimento a un altro blog che parlava di usarlo come un basso ostacolo al problema di ingresso per i candidati alla programmazione .
dmckee,

8
@dmckee l '"altro blog" a cui Joel fa riferimento è Jeff Atwood, l'altro fondatore di Stackoverflow.
pilsetnieks

Risposte:


55

C, 59 byte

i;f(char*s){while(*s&3?*s&9||(i+=i+*s%5):putchar(i),*s++);}

Numeri magici, numeri magici ovunque!

(Inoltre, C più corto di Python, JS, PHP e Ruby? Inaudito!)

Questa è una funzione che accetta una stringa come input e output su STDOUT.

Procedura dettagliata

La struttura di base è:

i;           // initialize an integer i to 0
f(char*s){
while(...);  // run the stuff inside until it becomes 0
}

Qui, "stuff inside" è un gruppo di codice seguito da ,*s++, in cui l'operatore virgola restituisce solo il valore del suo secondo argomento. Quindi, questo verrà eseguito attraverso la stringa e impostato *ssu ogni carattere, incluso il byte NUL finale (poiché postfix ++restituisce il valore precedente), prima di uscire.

Diamo un'occhiata al resto:

*s&3?*s&9||(i+=i+*s%5):putchar(i)

Staccando il ternario e il corto circuito ||, questo può essere espanso

if (*s & 3) {
    if (!(*s & 9)) {
        i += i + *s % 5;
    }
} else {
    putchar(i);
}

Da dove vengono questi numeri magici? Ecco le rappresentazioni binarie di tutti i personaggi coinvolti:

F  70  01000110
B  66  01000010
i  105 01101001
z  122 01111010
u  117 01110101
   32  00100000
\0 0   00000000

Innanzitutto, dobbiamo separare lo spazio e NUL dal resto dei personaggi. Il modo in cui funziona questo algoritmo mantiene un accumulatore del numero "corrente" e lo stampa ogni volta che raggiunge uno spazio o la fine della stringa (cioè '\0'). Notando che ' 'e '\0'sono gli unici caratteri a non avere nessuno dei due bit meno significativi impostati, possiamo bit a bit E il carattere con 0b11ottenere zero se il carattere è spazio o NUL e diverso da zero.

Scavando più a fondo, nel primo ramo "if", ora abbiamo un personaggio di cui è uno FBizu. Ho scelto solo di aggiornare l'accumulatore su Fs e Bs, quindi avevo bisogno di un modo per filtrare izus. Convenientemente, Fed Bentrambi hanno solo il secondo, il terzo o il settimo bit meno significativo impostato, e tutti gli altri numeri hanno almeno un altro bit impostato. In effetti, tutti hanno il primo o il quarto bit meno significativo. Quindi, possiamo bit a bit AND con 0b00001001, che è 9, che produrrà 0 per Fe Be diverso da zero.

Una volta stabilito che abbiamo un Fo B, possiamo mapparli 0e 1rispettivamente prendendo il loro modulo 5, perché Fè 70ed Bè 66. Quindi lo snippet

i += i + *s % 5;

è solo un modo di dire golfy

i = (i * 2) + (*s % 5);

che può anche essere espresso come

i = (i << 1) | (*s % 5);

che inserisce il nuovo bit nella posizione meno significativa e sposta tutto il resto su 1.

"Ma aspetta!" potresti protestare. "Dopo la stampa i, quando viene ripristinato su 0?" Bene, putcharlancia il suo argomento a un unsigned char, che in questo caso ha una dimensione di 8 bit. Ciò significa che tutto ciò che è passato dall'ottavo bit meno significativo (ovvero la spazzatura delle precedenti iterazioni) viene eliminato e non dobbiamo preoccuparci.

Grazie a @ETHproductions per aver suggerito di sostituire 57con 9, salvando un byte!


Bel trucco con il putchar.
Computronio

Questo è davvero fantastico. C ha fatto bene!
Gustavo Maciel,

13
Parlando di fare le cose bene, questo è, secondo la mia opinione non così modesta, come dovrebbe essere fatta una risposta da golf di codice. Pubblica una soluzione intelligente e approfondita, accompagnata da una spiegazione completa e ben scritta che in realtà insegna alle persone qualcosa sulla lingua che potrebbe essere utile in altre circostanze più pratiche.
Cody Gray,

3
@CodyGray Esattamente questo. Uno dei motivi per cui Code Golf non è in cima alla mia SE che visito frequentemente è perché molte risposte sono solo "ecco il codice". Sebbene sia interessante per le persone che hanno molta familiarità con le lingue, mi sembra solo rumore. Mi piace vedere le spiegazioni come qui perché rivela il metodo , che penso che la maggior parte delle persone trova molto più interessante del codice stesso. Solo i miei due centesimi ...
Chris Cirefice,

Bithack molto bello, ma conti i tuoi bit da MSB (a sinistra) a LSB (a destra)? L'IMO è l'unico modo sano per contare i bit in un byte a 8 bit (o un vettore SIMD a 128 bit o qualsiasi altra cosa) è da LSB = bit 0 a MSB = bit 7.
Peter Cordes,



9

Python 3 , 169 101 93 91 85 81 byte

lambda s,j="".join:j(chr(int(j('01'[b<"C"])for b in c[::4]),2))for c in s.split())

Provalo online!

Spiegazione:

lambda s,j="".join:  # Create a lambda function
    j(  # call "".join, adds characters together with nothing in between
        chr(  # character by int
            int(  # string to int
                j(  # "".join again
                    '01'[b<"C"]  # 1 or 0, based on what character we get
                    for b in c[::4]  # For every first of 4 characters
                ),
                2)  # Base 2
        )
        for c in s.split()  # for every group of Fizz and Buzz with any whitespace character after it
    )

È stato veloce. +1
HyperNeutrino,

Ho fatto qualcosa di simile a questo un po 'di tempo fa, era solo una questione di copia-incolla e lo cambiavo in FizzBuzz: P
Martmists,

1
Oh questo spiega. : P Ma sei stato superato: _;
HyperNeutrino,


1
Whoops, lo ha fatto di nuovo , questa volta 85 byte con una lambdafunzione
Mr. Xcoder

8

JavaScript (ES6), 80 79 byte

let f =

s=>`${s} `.replace(/.{4} ?/g,m=>m[s=s*2|m<'F',4]?String.fromCharCode(s&255):'')

console.log(f("FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzBuzz"))


Molto bella. Ho provato e fallito a venire con qualcosa di più breve, anche se ci sono diverse alternative soluzioni 80-byte che utilizzano .replace(/..zz/g,, '0b'+e così via
ETHproductions

@ETHproductions Sbarazzarsi di npermette di raggiungere 79. Purtroppo, questo richiede uno spazio extra da aggiungere all'input. Da qui il piuttosto costoso `${s} ` .
Arnauld,

7

Japt , 26 24 19 17 byte

¸®ë4 ®c u5Ãn2 dÃq

Provalo online!

Salvato 2 byte grazie a @Shaggy e 2 byte grazie a @ETHproductions

Spiegazione

input: "FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzBuzz"

¸®                // ["FizzBuzzBuzzFizzBuzzFizzFizzFizz","FizzBuzzBuzzFizzBuzzFizzFizzBuzz","FizzFizzBuzzFizzFizzFizzFizzBuzz"]
  ë4              // ["FBBFBFFF","FBBFBFFB","FFBFFFFB"]
     ®c           // [[70,66,66,70,66,70,70,70],[70,66,66,70,66,70,70,66],[70,70,66,70,70,70,70,66]]
        u5Ã       // ["01101000","01101001","00100001"]
           n2     // [104,105,33]
              d   // ["h","i","!"]
               Ãq // "hi!"

1
È possibile sostituire il 2 })con Ã. C'è sicuramente molto altro da salvare, ma non riesco a farlo funzionare sul mio telefono.
Shaggy,

1
Molto bello, grazie per aver usato Japt! È possibile salvare un paio di byte sostituendoli ò4...q n2con ë4...n2( ë4fa la stessa cosa ò4, tranne restituire solo il primo elemento; stranamente, non sembra essere documentato)
ETHproductions

1
@ETHproductions Grazie per aver reso Japt!
Powelles,

6

Rubino, 65 63 60 byte

->s{s.split.map{|x|x.gsub(/..../){$&.ord%5}.to_i(2).chr}*''}

Questo è un proc anonimo che accetta input e fornisce output come stringa.

->s{
s.split            # split on whitespace
.map{|x|           # for each word as x,
  x.gsub(/..../){  # replace each sequence of four characters with
    $&.ord%5       # the ASCII value of the first character, mod 5
                   # F is 70, B is 66, so this yields 0 for Fizz and 1 for Buzz
  }.to_i(2)        # interpret as a binary number
  .chr             # the character with this ASCII value
}*''               # join on empty string
}

6

JavaScript (ES6), 95 88 85 81 byte

s=>s.replace(/..zz/g,m=>m<"F"|0).replace(/\d+ ?/g,m=>String.fromCharCode("0b"+m))

Provalo

f=
s=>s.replace(/..zz/g,m=>m<"F"|0).replace(/\d+ ?/g,m=>String.fromCharCode("0b"+m))
oninput=_=>o.innerText=f(i.value)
o.innerText=f(i.value="FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzBuzz")
*{font-family:sans-serif}
<input id=i><p id=o>


Credo che +sia più breve diparseInt
Kritixi Lithos

2
Penso che +(m[0]<"F")potrebbe essere abbreviato inm<"F"|0
ETHproductions

5

Perl 5, 33 byte

print(pack'B*',<>=~y/FB -z/01/dr)

Sostituisce 'F' e 'B' nell'input rispettivamente con 0 e 1 ed elimina gli altri caratteri. Quindi utilizza la packfunzione di perl per trasformare questa stringa di bit in caratteri ASCII.


Wow, questo è ridotto a circa la metà del mio tentativo di Perl 5. Complimenti.
David Conrad,

1
Credo che potresti renderlo notevolmente più breve usando l' -p0opzione della riga di comando (che ti salverebbe <>=~rper l'input e ti permetterebbe di usare $_=piuttosto che print()). A seconda di come si desidera gestire le nuove righe, potrebbe non essere nemmeno necessario 0. (Anche se si desidera evitare penalità delle opzioni della riga di comando, sayè più breve di print.)

@Chris Non mio, faubiguy. Ma grazie. ;)
David Conrad,

@DavidConrad My bad haha.
Chris,

1
Sicuramente non hai nemmeno bisogno dello 0. Usa il flag -p e $_=pack'B*',y/FB -z/01/drper il tuo programma abbassa il tuo punteggio a 26 byte.
Chris,


3

Spazio bianco, 123 byte

Rappresentazione visibile:

SSNNSSNSNSSSNSNSTNTSTTTSSSTSSSSSNTSSTSNSNTSSNSSSTSSTTSNTSSTNTSTNSSSTNTSSSNSSTNSSNSNSSNSTNTSTNTSTNTSTSSSNSNNNSSSNSNTTNSSNSNN

Programma non filtrato:

    push  0
loop:
    dup
    push  0
    dup
    ichr
    get
    push  32
    sub
    dup
    jz    space
    push  38
    sub
    jz    fizz
    push  1
    add
fizz:
    push  0
    dup
    dup
    ichr
    ichr
    ichr
    add
    jmp   loop
space:
    swap
    pchr
    jmp   loop

Non c'è nulla di particolarmente strano nell'implementazione, l'unico vero golfing è in uno strano riutilizzo dei provvisori oltre a non preoccuparsi della crescita illimitata dello stack per sfogliare qualche byte in più.


3

Ottava , 59 57 53 byte

@(s)['',bi2de(flip(reshape(s(65<s&s<71)<70,8,[]))')']

Questo non funziona su TIO, poiché la casella degli strumenti di comunicazione non è implementata. Funziona bene se lo copi e lo incolli su Octave-online . Non è nemmeno vicino al codice di lavoro in MATLAB.

Riuscito a salvare due byte trasponendo la matrice dopo averla capovolta, anziché viceversa.

Spiegazione:

@(s)             % Anonymous function that takes a string as input
    ['',<code>]  % Implicitly convert the result of <code> to its ASCII-characters

Cominciamo nel mezzo di <code>:

s(65<s&s<71)      % Takes the elements of the input string that are between 66 and 70 (B and F)
                  % This gives a string FBBFFBBFBBBFFFBF...
s(65<s&s<71)<70   % Converts the resulting string into true and false, where F becomes false.
                  % Transformation: FBBFFB -> [0, 1, 1, 0, 0, 1]

Chiamiamo il vettore booleano (binario) risultante per t.

reshape(t,8,[])       % Convert the list of 1 and 0 into a matrix with 8 rows, one for each bit
flip(reshape(t,8,[])) % Flip the matrix vertically, since bi2de reads the bits from the wrong end
flip(reshape(t,8,[]))' % Transpose it, so that we have 8 columns, and one row per character
bi2de(.....)'          % Convert the result decimal values and transpose it so that it's horizontal

3

Perl 5, 28 byte + 4 byte per flag = 32 byte

Corri con le bandiere -040pE

$_=chr oct"0b".y/FB -z/01/dr

-040 imposta il separatore di record su uno spazio in modo che perl veda ogni gruppo di FizzBuzzes come una linea separata, quindi passa su quelle linee, cambiando F in 0, B in 1, eliminando tutto il resto, quindi convertendo in binario e da lì in ascii.




2

Brain-Flak , 107 byte

{(((((()()()()){}){}){})({}[{}])()())((){[()](<{}>)}{}<>)<>{(<{}{}{}{}>)<>({}({}){})<>}{}}<>{({}<>)<>}<>

Provalo online!

+3 byte per la -cbandiera.

Spiegazione

{                                        For each character in input:
 (((((()()()()){}){}){})({}[{}])()())    Push 32-n and 66-n
 ((){[()](<{}>)}{}<>)<>                  If character is B, push 1 on second stack.  Otherwise, push 0
 {                                       If character is not space:
  (<{}{}{}{}>)                           Burn 3 additional characters
  <>({}({}){})<>                         Multiply current byte by 2 and add previously pushed bit
 }                                       (otherwise, the pushed 0 becomes the new current byte)
 {}                                      Remove character from input
}
<>{({}<>)<>}<>                           Reverse stack for output

2

q / kdb +, 41 40 37 33 byte

Soluzione:

{10h$0b sv'66=vs[" ";x][;4*(!)8]}

Esempio:

q){10h$0b sv'66=vs[" ";x][;4*(!)8]}"FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzBuzz"
"hi!"

Spiegazione:

Dividi la stringa di input su " "per dare distinti elenchi di FizzBuzz..., indice in ciascuna di queste liste al primo carattere (cioè 0 4 8 ... 28). Restituisce l'elenco booleano determinato dalla presenza di ciascun carattere "B"(ASCII 66). Convertire questi elenchi in base 10, quindi eseguire il cast del risultato in stringa.

{10h$0b sv'66=vs[" ";x][;4*til 8]} / ungolfed solution
{                                } / lambda function with x as implicit input
              vs[" ";x]            / split (vs) input (x) on space (" ")
                           til 8   / til 8, the range 0..7 inclusive
                         4*        / vectorised multiplication, 0 1 2 3 => 0 4 8 12
                       [;       ]  / index the 2nd level at these indices (0, 4, 8 ... 28)
           66=                     / 66 is ASCII B, 66="FBBFBFFF" -> 01101000b
     0b sv'                        / join (sv) each row back with 0b (converts from binary)
 10h$                              / cast to ASCII (0x686921 -> "hi!")

1

Haskell, 72 byte

(>>= \w->toEnum(foldl1((+).(2*))[mod(fromEnum c)5|c<-w,c<'a']):"").words

Provalo online!

Come funziona

            words      -- split input string into words at spaces
(>>=      )            -- map the function to each word and flatten the resulting
                       -- list of strings into a single string
   \w->                -- for each word w
       [  |c<-w,c<'a'] -- take chars c that are less than 'a' (i.e. B and F)
     mod(fromEnum c)5  -- take ascii value of c modulus 5, i.e. convert to bit value
    foldl1((+).(2*))   -- convert list of bit to int
  toEnum(   ):""       -- convert ascii to char.  :"" forces toEnum to be of type String
                       -- now we have a list of single char strings, e.g. ["h","i","!"]        

1

JavaScript ES6 - 98 byte

troppi byte, ma almeno leggibili

Definito come funzione è di 98 byte

let s=>s.replace(/(F)|(B)|./g,(c,F,B)=>B?1:F?0:'').replace(/.{8}/g,v=>String.fromCharCode('0b'+v))

test:

"FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzBuzz"
.replace(/(F)|(B)|./g,(c,F,B)=>F?0:B?1:'').replace(/.{8}/g,v=>String.fromCharCode('0b'+v))

Spiegazione:

/(F)|(B)|./

Abbina le lettere F e B e qualsiasi altra cosa come gruppi

(c,F,B)=>F?0:B?1:''

è una funzione che acquisisce i gruppi, restituisce 0 per F e 1 per B o ''

c è il carattere abbinato
F e B ora sono Parametri!
il 3o . il gruppo viene omesso come parametro

F e B sono undefinedquando il 3 ° gruppo è abbinato
B è undefinedquando il gruppo F è abbinato

La stringa risultante 0100 .. etc

viene tagliato a fette di 8 byte

.replace(/.{8}/g,v=>String.fromCharCode('0b'+v))

ed elaborato come stringa binaria 0b


2
Benvenuti in PPCG! L'obiettivo di questa sfida è fornire un programma o una funzione che traduca stringhe FizzBuzz arbitrarie. Non conosco molto JavaScript, ma potrebbe essere valida l'invio di una funzione s=>s.replace( .... Includi anche un conteggio di byte nell'intestazione della tua risposta.
Laikoni,

Ho ripulito parte della tua formattazione del codice per te. Inoltre, non sono necessarie le letfunzioni anonime accettabili.
Shaggy,

1

shortC , 35 byte

i;AW*@&3?*@&9||(i+=i+*s%5):Pi),*s++

Conversioni in questo programma:

  • A - int main(int argc, char **argv){
  • W - while(
  • @ - argv
  • P - putchar(
  • Auto-inserito );}

Fortemente basato sulla risposta di Doorknob.


1

APL (Dyalog Classic) , 17 byte

{82DR'B'=⍵∩'BF'}

Spiegazione

           ⍵∩'BF'    cut, removes all but 'BF' from 
       'B'=          equals 'B' turns it into binary stream   
 82DR              converts into character stream

Provalo online!



0

Fogli Google, 94 byte

=ArrayFormula(JOIN("",CHAR(BIN2DEC(SPLIT(SUBSTITUTE(SUBSTITUTE(A1,"Fizz",0),"Buzz",1)," ")))))

Non ho familiarità con il binario FizzBuzz, ma sembra che siano delineati da spazi, quindi questa formula si basa su questo. La logica è piuttosto semplice:

  • Sostituisci Fizzcon 0e Buzzcon1
  • Dividi il risultato in un array usando uno spazio come delimitatore
  • Converti ogni elemento da binario a decimale
  • Sostituisci ogni elemento con il suo equivalente ASCII
  • Unisci ogni elemento senza un delimitatore

0

Java 8, 117 115 byte

s->{for(String x:s.split(" "))System.out.print((char)Long.parseLong(x.replace("Fizz","0").replace("Buzz","1"),2));}

Dubito che tu possa fare molte delle fantasiose sostituzioni di regex in Java come la maggior parte delle altre risposte, principalmente perché non puoi fare nulla con i gruppi di acquisizione catturati in regex Java ... (Ad esempio "$1".charAt(...)o "$1".replace(...)non è possibile, ad esempio.)

Spiegazione:

Provalo qui.

s->{                          // Method with String parameter and no return-type
  for(String x:s.split(" "))  //  Loop over the input split by spaces:
    System.out.print(         //   Print:
     (char)                   //    Each character
     Long.parseLong(          //    after we've converted each binary-String to a long
      x.replace("Fizz","0").replace("Buzz","1")
                              //    after we've replaced the Fizz/Buzz to 0/1
     ,2));
}                             // End of method

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.