Fizz Buzz para texto


29

Introdução

Eu particularmente não sei de onde veio a tendência do fizz buzz. Pode ser apenas um meme ou algo assim, mas é um pouco popular.

Desafio

Sua tarefa hoje é converter o Fizz Buzz em binário (0, 1), respectivamente, e converter esse binário em texto. Material bastante padrão.

Como isso funciona?

O FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz se traduziria em 01101000 01101001 e, em seguida, se traduziria em "oi"

Restrições

  • A entrada é o Fizz Buzz do ponto de vista binário (veja os exemplos abaixo).
  • A saída deve ser texto.
  • Você pode assumir que a entrada do FizzBuzz está correta.
  • Isso é , os bytes mais curtos vencem.

Entrada

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzFizzFizzBuzz

Saída

"Oi!"


15
Meme? Esta é uma (elementar) jogo de escola primária
Beta Decay

2
Não podemos ocupar espaços na entrada?
HyperNeutrino 29/05

2
Mas não podemos ocupar esse espaço? Eu posso salvar três bytes se não precisar inserir esse espaço.
HyperNeutrino

10
O FizzBuzz desfruta de bastante dinheiro no Stack Exchange, em parte porque Joel (um dos fundadores) teve um post de um blog referenciando outro blog que falava sobre usá-lo como uma baixa barreira ao problema de entrada para candidatos de programação .
dmckee

8
@dmckee o "outro blog" ao qual Joel se refere é Jeff Atwood, o outro fundador do Stackoverflow.
Pilsetnieks # 30/17

Respostas:


55

C, 59 bytes

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

Números mágicos, números mágicos em todos os lugares!

(Além disso, C menor que Python, JS, PHP e Ruby? Inédito!)

Esta é uma função que recebe uma string como entrada e sai para STDOUT.

Passo a passo

A estrutura básica é:

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

Aqui, o "material interno" é um monte de código seguido por ,*s++, em que o operador de vírgula retorna apenas o valor do seu segundo argumento. Portanto, isso percorrerá a cadeia e definirá *stodos os caracteres, incluindo o byte NUL à direita (já que o postfix ++retorna o valor anterior), antes de sair.

Vamos dar uma olhada no resto:

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

Retirando o circuito ternário e curto-circuito ||, isso pode ser expandido para

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

De onde vêm esses números mágicos? Aqui estão as representações binárias de todos os personagens envolvidos:

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

Primeiro, precisamos separar espaço e NUL do resto dos personagens. Da maneira como esse algoritmo funciona, ele mantém um acumulador do número "atual" e o imprime sempre que atinge um espaço ou o final da string (ou seja '\0'). Ao perceber que ' 'e '\0'são os únicos caracteres que não possuem nenhum dos dois bits menos significativos definidos, podemos AND bit a bit e 0b11obter o zero se o caractere for espaço ou NUL e diferente de zero.

Indo mais fundo, no primeiro ramo "se", agora temos um personagem que é um deles FBizu. Eu escolhi apenas atualizar o acumulador em Fs e Bs, então eu precisava de uma maneira de filtrar os izus. Convenientemente, Fe Bambos têm apenas o segundo, terceiro ou sétimo bits menos significativos definidos, e todos os outros números têm pelo menos um outro conjunto de bits. De fato, todos eles têm o primeiro ou o quarto bit menos significativo. Assim, podemos bit a bit E com 0b00001001, o qual é 9, o que vai originar 0 para Fe Be diferente de zero em contrário.

Depois de determinarmos que temos um Fou B, podemos mapeá-los para 0e 1respectivamente, tomando seu módulo 5, porque Fé 70e Bé 66. Então o trecho

i += i + *s % 5;

é apenas uma maneira de dizer golfe

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

que também pode ser expresso como

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

que insere o novo bit na posição menos significativa e muda todo o resto em 1.

"Mas espere!" você pode protestar. "Depois de imprimir i, quando é que ele é redefinido para 0?" Bem, putcharlança seu argumento para an unsigned char, que por acaso tem 8 bits de tamanho. Isso significa que tudo que passou do oitavo bit menos significativo (ou seja, o lixo das iterações anteriores) é jogado fora, e não precisamos nos preocupar com isso.

Agradecemos a @ETHproductions por sugerir a substituição 57por 9, salvando um byte!


Bom truque com o putchar.
Computronium

Isso é realmente incrível. C fez certo!
Gustavo Maciel

13
Falando em fazer as coisas da maneira certa, é assim, na minha opinião não tão humilde, que uma resposta ao código-golfe deve ser feita. Você publica uma solução inteligente e perspicaz, acompanhada de uma explicação completa e bem escrita que ensina às pessoas algo sobre o idioma que pode ser útil em outras circunstâncias mais práticas.
Cody Grey

3
@CodyGray Exatamente isso. Uma das razões pelas quais o Code Golf não está no topo do meu SE que eu visito frequentemente é porque muitas respostas são apenas "aqui está o código". Embora isso seja legal para pessoas que estão muito familiarizadas com os idiomas, parece apenas um barulho para mim. Eu gosto de ver as explicações como aqui, porque revela o método , que eu acho que a maioria das pessoas acha muito mais interessante que o próprio código. Apenas meus dois centavos ...
Chris Cirefice

Bithack muito bom, mas você conta seus bits de MSB (esquerda) a LSB (direita)? IMO a única maneira sã para contar bits em um byte de 8 bits (ou um vector de SIMD de 128 bits, ou qualquer outro) é de LSB = bit 0 para o MSB = mordeu 7.
Pedro Cordes



9

Python 3 , 169 101 93 91 85 81 bytes

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

Experimente online!

Explicação:

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
    )

Isso foi rápido. +1
HyperNeutrino

Eu fiz algo semelhante a isto um tempo atrás, era apenas uma questão de copiar e colar e alterá-lo para FizzBuzz: P
Martmists

11
Oh, isso explica. : P Mas você foi derrotado; _;
HyperNeutrino


11
Whoops, fiz isso de novo , 85 bytes desta vez com uma lambdafunção
Mr. Xcoder

8

JavaScript (ES6), 80 79 bytes

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


Muito agradável. Eu tentei e não conseguiu chegar a algo mais curto, apesar de existirem várias alternativas soluções 80 bytes usando .replace(/..zz/g,, '0b'+etc.
ETHproductions

Livrar-se do @ETHproductions npermite chegar a 79. Infelizmente, isso requer um espaço extra a ser adicionado à entrada. Daí o bastante caro `${s} ` .
Arnauld 30/05

7

Japt , 26 24 19 17 bytes

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

Experimente online!

Economizou 2 bytes graças a @Shaggy & 2 bytes graças a @ETHproductions

Explicação

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

11
Você pode substituir o 2 })por Ã. Definitivamente, há mais a ser salvo do que isso, mas não consigo fazê-lo funcionar no meu telefone.
Shaggy

11
Muito bom, obrigado por usar o Japt! Você pode salvar um par de bytes, substituindo ò4...q n2com ë4...n2( ë4não a mesma coisa que ò4, exceto retornar apenas o primeiro item; estranhamente, ele não parece ser documentado)
ETHproductions

11
@ETHproductions Obrigado por fazer o Japt!
powelles

6

Ruby, 65 63 60 bytes

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

Este é um processo anônimo que recebe entrada e fornece saída como uma string.

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

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

Tente

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>


Eu acredito que +é mais curto queparseInt
Kritixi Lithos 29/05

2
Eu acho que +(m[0]<"F")poderia ser reduzido param<"F"|0
ETHproductions

5

Perl 5, 33 bytes

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

Substitui 'F' e 'B' na entrada por 0 e 1 respectivamente e exclui os outros caracteres. Ele então usa a packfunção perl para transformar essa sequência de bits em caracteres ASCII.


Uau, isso é jogado até a metade do tamanho da minha tentativa de Perl 5. Parabéns.
David Conrad

11
Eu acredito que você poderia fazer isso consideravelmente mais curto usando a -p0opção de linha de comando (que iria salvá-lo <>=~rpara a entrada, e permitem que você use $_=em vez de print()). Dependendo de como você deseja lidar com novas linhas, talvez você nem precise do 0. (Mesmo que você queira evitar multas por opção de linha de comando, sayé menor que print.) #

@ Chris Não é meu, faubiguy. Mas obrigada. ;)
David Conrad

@DavidConrad My bad haha.
315 Chris

11
Você definitivamente não precisa do 0 também. Basta usar o sinalizador -p e, $_=pack'B*',y/FB -z/01/drpara o seu programa, sua pontuação é reduzida para 26 bytes.
315 Chris

5

Python 2 , 90 83 82 81 bytes

-1 byte graças ao totalmente humano
-1 byte graças ao Martmists
-1 byte graças a Jonathan Frech

lambda x:''.join(chr(int(`[+(l<'D')for l in b[::4]]`[1::3],2))for b in x.split())

Experimente online!



você pode salvar um byte girando *1 forem*1for
Martmists

Como você usa *1a conversão de booleano para inteiro, você pode salvar um byte usando a +: (l<'D')*1forcan be +(l<'D')for.
Jonathan Frech

3

Espaço em branco, 123 bytes

Representação visível:

SSNNSSNSNSSSNSNSTNTSTTTSSSTSSSSSNTSSTSNSNTSSNSSSTSSTTSNTSSTNTSTNSSSTNTSSSNSSTNSSNSNSSNSTNTSTNTSTNTSTSSSNSNNNSSSNSNTTNSSNSNN

Programa não ofuscado:

    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

Não há nada de particularmente estranho na implementação, o único golfe real está em uma reutilização estranha de temporários, além de não se importar com o crescimento ilimitado da pilha para reduzir mais alguns bytes.


3

Oitava , 59 57 53 bytes

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

Isso não funciona no TIO, pois a caixa de ferramentas de comunicação não está implementada. Funciona bem se você copiar e colar no Octave-online . Não é nem perto de estar trabalhando com código no MATLAB.

Conseguiu salvar dois bytes transpondo a matriz depois de lançá-la, e não o contrário.

Explicação:

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

Vamos começar no meio de <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]

Vamos chamar o vetor booleano (binário) resultante para 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 bytes + 4 bytes para sinalizadores = 32 bytes

Corra com as bandeiras -040pE

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

-040 define o separador de registros como um espaço para que o perl veja cada grupo de FizzBuzzes como uma linha separada, em seguida, faça um loop sobre essas linhas, alterando F para 0, B para 1, excluindo tudo o resto, convertendo para binário e daí para ascii.




2

Flak cerebral , 107 bytes

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

Experimente online!

+3 bytes para o -csinalizador.

Explicação

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

Solução:

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

Exemplo:

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

Explicação:

Divida a sequência de entrada " "para fornecer listas distintas de FizzBuzz..., indexe em cada uma dessas listas no primeiro caractere (ie 0 4 8 ... 28). Retornar lista booleana determinada por cada caractere "B"(ASCII 66). Converta essas listas na base 10 e depois converta o resultado em sequência.

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

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

Experimente online!

Como funciona

            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 bytes

muitos bytes, mas pelo menos legível

Definido como função, é 98 bytes

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

teste:

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

Explicação:

/(F)|(B)|./

Corresponde às letras F e B e qualquer outra coisa como Grupos

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

é uma função que captura os grupos, retorna 0 para F e 1 para B ou ''

c é o caractere correspondente
F e B agora são Parâmetros!
o terceiro . grupo é omitido como parâmetro

F e B são undefinedquando o terceiro grupo é correspondido
B é undefinedquando o grupo F é correspondido

A sequência 0100 .. etc resultante

é cortado em fatias de 8 bytes

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

e processado como cadeia binária 0b


2
Bem-vindo ao PPCG! O objetivo deste desafio é fornecer um programa ou função traduzindo seqüências arbitrárias do FizzBuzz. Eu não sei muito JavaScript, mas pode ser um envio de função válido s=>s.replace( .... Além disso, inclua uma contagem de bytes no cabeçalho da sua resposta.
Laikoni

Limpei parte da sua formatação de código para você. Além disso, você não precisa das letfunções anônimas são aceitáveis.
Shaggy

1

shortC , 35 bytes

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

Conversões neste programa:

  • A - int main(int argc, char **argv){
  • W - while(
  • @ - argv
  • P - putchar(
  • Inserção automática );}

Fortemente baseado na resposta da maçaneta da porta.




0

Planilhas Google, 94 bytes

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

Eu não estou familiarizado com o binário do FizzBuzz, mas parece que eles são delineados por espaços, então essa fórmula depende disso. A lógica é bem simples:

  • Substitua Fizzpor 0e Buzzcom1
  • Divida o resultado em uma matriz usando um espaço como delimitador
  • Converta cada elemento de binário em decimal
  • Substitua cada elemento pelo seu equivalente ASCII
  • Una cada elemento sem um delimitador

0

Java 8, 117 115 bytes

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

Duvido que você possa fazer muitas substituições sofisticadas de regex em Java, como a maioria das outras respostas, principalmente porque você não pode fazer nada com os grupos de captura capturados em Java-regexes .. ( "$1".charAt(...)Ou seja, ou "$1".replace(...)não são possíveis, por exemplo).

Explicação:

Experimente aqui.

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.