Fizz Buzz to Text


29

introduction

Je ne sais pas particulièrement d' où vient la tendance du fizz buzz. Ce pourrait être juste un mème ou quelque chose, mais il est quelque peu populaire.

Défi

Votre travail consiste aujourd'hui à convertir Fizz Buzz en binaire (0, 1) respectivement, et à convertir ce binaire en texte. Des trucs assez standard.

Comment ça marche?

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz se traduirait par 01101000 01101001 puis cela se traduirait par "salut"

Contraintes

  • L'entrée est Fizz Buzz d'un point de vue binaire (voir les exemples ci-dessous.)
  • La sortie doit être du texte.
  • Vous pouvez supposer que l'entrée FizzBuzz est correcte.
  • C'est le , la plus courte victoire en octets.

Contribution

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzBuzz

Sortie

"salut!"


15
Meme? Ceci est un jeu d'école primaire (élémentaire)
Beta Decay

2
Ne pouvons-nous pas prendre des espaces dans l'entrée?
HyperNeutrino

2
Ne pouvons-nous pas prendre cet espace cependant? Je peux économiser trois octets si je n'ai pas à entrer cet espace.
HyperNeutrino

10
FizzBuzz bénéficie de beaucoup de devises sur Stack Exchange en partie parce que Joel (l'un des fondateurs) avait un article de blog faisant référence à un autre blog qui parlait de l'utiliser comme un faible obstacle à l'entrée pour les candidats à la programmation .
dmckee

8
@dmckee «l'autre blog» auquel Joel fait référence est Jeff Atwood, l'autre fondateur de Stackoverflow.
pilsetnieks

Réponses:


55

C, 59 octets

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

Des nombres magiques, des nombres magiques partout!

(De plus, C plus court que Python, JS, PHP et Ruby? Du jamais vu!)

Il s'agit d'une fonction qui prend une chaîne en entrée et sort vers STDOUT.

Procédure pas à pas

La structure de base est:

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

Ici, le "stuff inside" est un tas de code suivi de ,*s++, où l'opérateur virgule ne renvoie que la valeur de son deuxième argument. Par conséquent, cela parcourra la chaîne et sera défini *ssur chaque caractère, y compris l'octet NUL de fin (puisque postfix ++renvoie la valeur précédente), avant de quitter.

Jetons un coup d'œil au reste:

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

Décoller le ternaire et les courts-circuits ||, cela peut être étendu à

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

D'où viennent ces nombres magiques? Voici les représentations binaires de tous les personnages impliqués:

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

Tout d'abord, nous devons séparer l'espace et NUL du reste des caractères. La façon dont cet algorithme fonctionne, il conserve un accumulateur du nombre "courant", et l'imprime chaque fois qu'il atteint un espace ou la fin de la chaîne (ie '\0'). En remarquant cela ' 'et '\0'étant les seuls caractères à n'avoir aucun des deux bits les moins significatifs définis, nous pouvons bit par bit ET le caractère avec 0b11pour obtenir zéro si le caractère est un espace ou NUL et non nul sinon.

En creusant plus profondément, dans la première branche "if", nous avons maintenant un personnage qui en fait partie FBizu. J'ai choisi uniquement de mettre à jour l'accumulateur sur Fs et Bs, donc j'avais besoin d'un moyen de filtrer les izus. Idéalement, Fet les Bdeux n'ont que le deuxième, le troisième ou le septième ensemble de bits de poids faible, et tous les autres nombres ont au moins un autre ensemble de bits. En fait, ils ont tous le premier ou le quatrième bit le moins significatif. Par conséquent, nous pouvons binaire ET avec 0b00001001, qui est 9, ce qui donnera 0 pour Fet Bet non nul sinon.

Une fois que nous avons déterminé que nous avons un Fou B, nous pouvons les mapper à 0et 1respectivement en prenant leur module 5, parce que Fest 70et Best 66. Puis l'extrait

i += i + *s % 5;

est juste une façon golfique de dire

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

qui peut également être exprimé comme

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

qui insère le nouveau bit à la position la moins significative et décale tout le reste sur 1.

"Mais attendez!" vous pourriez protester. "Après avoir imprimé i, quand est-il jamais remis à zéro?" Eh bien, putcharconvertit son argument en un unsigned char, qui se trouve être 8 bits. Cela signifie que tout ce qui dépasse le 8e bit le moins significatif (c'est-à-dire la jonque des itérations précédentes) est jeté, et nous n'avons pas à nous en soucier.

Merci à @ETHproductions d' avoir proposé de remplacer 57par 9, d'économiser un octet!


Belle astuce avec le putchar.
Computronium

C'est vraiment génial. C a bien fait!
Gustavo Maciel

13
En parlant de bien faire les choses, c'est, à mon avis pas si humble, comment une réponse de code-golf devrait être faite. Vous publiez une solution intelligente et perspicace, accompagnée d'une explication complète et bien écrite qui enseigne réellement aux gens quelque chose sur la langue qui pourrait être utile dans d'autres circonstances plus pratiques.
Cody Gray

3
@CodyGray Exactement cela. L'une des raisons pour lesquelles Code Golf n'est pas au sommet de mon SE que je visite fréquemment est parce que beaucoup de réponses sont simplement "voici le code". Bien que ce soit cool pour les gens qui connaissent très bien les langues, cela ressemble à du bruit pour moi. J'aime voir les explications comme ici car cela révèle la méthode , que je pense que la plupart des gens trouvent beaucoup plus intéressante que le code lui-même. Juste mes deux cents ...
Chris Cirefice

Très joli bithack, mais vous comptez vos bits de MSB (gauche) à LSB (droite)? IMO la seule façon saine de compter les bits dans un octet 8 bits (ou un vecteur SIMD 128 bits, ou autre) est de LSB = bit 0 à MSB = bit 7.
Peter Cordes



9

Python 3 , 169 101 93 91 85 81 octets

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

Essayez-le en ligne!

Explication:

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
    )

C'était rapide. +1
HyperNeutrino

J'ai fait quelque chose de similaire il y a quelque temps, c'était juste une question de copier-coller et de le changer en FizzBuzz: P
Martmists

1
Oh ça explique. : P Mais vous vous êtes fait golfer; _;
HyperNeutrino


1
Oups, encore une fois , 85 octets avec une lambdafonction
M. Xcoder

8

JavaScript (ES6), 80 79 octets

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


Très agréable. J'ai essayé et échoué à trouver quelque chose de plus court, mais il y a plusieurs solutions alternatives de 80 octets à l' aide .replace(/..zz/g,, '0b'+etc.
ETHproductions

@ETHproductions Se débarrasser de npermet d'atteindre 79. Malheureusement, cela nécessite un espace supplémentaire pour être ajouté à l'entrée. D'où le plutôt coûteux `${s} ` .
Arnauld

7

Japt , 26 24 19 17 octets

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

Essayez-le en ligne!

2 octets enregistrés grâce à @Shaggy et 2 octets grâce à @ETHproductions

Explication

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
Vous pouvez remplacer le 2 })par Ã. Il y a certainement plus à économiser que cela, mais je n'arrive pas à le faire fonctionner sur mon téléphone.
Shaggy

1
Très bien, merci d'utiliser Japt! Vous pouvez économiser quelques octets en remplaçant ò4...q n2par ë4...n2( ë4fait la même chose que ò4, sauf en renvoyant uniquement le premier élément; étrangement, il ne semble pas être documenté)
ETHproductions

1
@ETHproductions Merci d'avoir créé Japt!
powelles

6

Rubis, 65 63 60 octets

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

Il s'agit d'un proc anonyme qui prend l'entrée et donne la sortie sous forme de chaîne.

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

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

Essayez-le

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>


Je crois que +c'est plus court queparseInt
Kritixi Lithos

2
Je pense que cela +(m[0]<"F")pourrait être raccourci àm<"F"|0
ETHproductions

5

Perl 5, 33 octets

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

Remplace «F» et «B» dans l'entrée par 0 et 1 respectivement et supprime les autres caractères. Il utilise ensuite la packfonction de perl pour transformer cette chaîne de bits en caractères ASCII.


Wow, c'est environ la moitié de ma tentative de Perl 5. Gloire.
David Conrad

1
Je pense que vous pourriez raccourcir considérablement la durée en utilisant l' -p0option de ligne de commande (ce qui vous permettrait d'économiser <>=~rdes données et vous permettrait d'utiliser $_=plutôt que print()). Selon la façon dont vous souhaitez gérer les sauts de ligne, vous n'aurez peut-être même pas besoin de 0. (Même si vous voulez éviter les pénalités d'option de ligne de commande, sayest plus court que print.)

@Chris Pas le mien, faubiguy. Mais merci. ;)
David Conrad

@DavidConrad Mon mauvais haha.
Chris

1
Vous n'avez certainement pas besoin du 0 non plus. Utilisez simplement l'indicateur -p et $_=pack'B*',y/FB -z/01/drpour votre programme, votre score baisse à 26 octets.
Chris

5

Python 2 , 90 83 82 81 octets

-1 octet grâce à totalement humain
-1 octet grâce aux Martmistes
-1 octet grâce à Jonathan Frech

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

Essayez-le en ligne!



vous pouvez enregistrer un octet en tournant *1 fordans*1for
Martmists

Étant donné que vous utilisez *1pour convertir du booléen en entier, vous pouvez enregistrer un octet en utilisant un +: (l<'D')*1forpeut être +(l<'D')for.
Jonathan Frech

3

Espace, 123 octets

Représentation visible:

SSNNSSNSNSSSNSNSTNTSTTTSSSTSSSSSNTSSTSNSNTSSNSSSTSSTTSNTSSTNTSTNSSSTNTSSSNSSTNSSNSNSSNSTNTSTNTSTNTSTSSSNSNNNSSSNSNTTNSSNSNN

Programme non obscurci:

    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

L'implémentation n'a rien de particulièrement étrange, le seul vrai golf est dans une étrange réutilisation des temporaires ainsi que de ne pas se soucier de la croissance illimitée de la pile pour parcourir encore plus d'octets.


3

Octave , 59 57 53 octets

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

Cela ne fonctionne pas sur TIO, car la boîte à outils de communication n'est pas implémentée. Cela fonctionne très bien si vous le copiez-collez sur Octave-online . Ce n'est même pas près de fonctionner du code dans MATLAB.

Géré pour enregistrer deux octets en transposant la matrice après l'avoir retournée, au lieu de l'inverse.

Explication:

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

Commençons au milieu 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]

Appelons le vecteur booléen (binaire) résultant pour 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 octets + 4 octets pour les indicateurs = 32 octets

Courez avec les drapeaux -040pE

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

-040 définit le séparateur d'enregistrement sur un espace de sorte que perl voit chaque groupe de FizzBuzz comme une ligne distincte, puis passe en boucle sur ces lignes, change F à 0, B à 1, supprime tout le reste, puis convertit en binaire et de là en ascii.




2

Brain-Flak , 107 octets

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

Essayez-le en ligne!

+3 octets pour le -c indicateur.

Explication

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

Solution:

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

Exemple:

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

Explication:

Divisez la chaîne d'entrée sur " "pour donner des listes distinctes de FizzBuzz..., indexez dans chacune de ces listes au premier caractère (c'est-à-dire 0 4 8 ... 28). Renvoie une liste booléenne déterminée par si chaque caractère est "B"(ASCII 66). Convertissez ces listes en base 10, puis convertissez le résultat en chaîne.

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

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

Essayez-le en ligne!

Comment ça marche

            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 octets

trop d'octets, mais au moins lisible

Défini comme fonction, il est de 98 octets

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

tester:

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

Explication:

/(F)|(B)|./

Correspond aux lettres F et B et à tout le reste en tant que groupes

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

est une fonction qui capture les groupes, renvoie un 0 pour F et 1 pour B, ou ''

c est le caractère correspondant à
F et B sont maintenant des paramètres!
le 3 . le groupe est omis comme paramètre

F et B sont undefinedlorsque le 3e groupe est apparié
B est undefinedlorsque le groupe F est apparié

La chaîne 0100 .. etc résultante

est coupé en tranches de 8 octets

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

et traité comme une chaîne binaire 0b


2
Bienvenue chez PPCG! L'objectif de ce défi est de fournir un programme ou une fonction traduisant des chaînes FizzBuzz arbitraires. Je ne connais pas beaucoup de JavaScript, mais une soumission de fonction valide pourrait l'être s=>s.replace( .... Veuillez également inclure un nombre d'octets dans l'en-tête de votre réponse.
Laikoni

J'ai nettoyé une partie de la mise en forme de votre code pour vous. De plus, vous n'avez pas besoin letdes fonctions anonymes, sont acceptables.
Shaggy

1

shortC , 35 octets

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

Conversions dans ce programme:

  • A - int main(int argc, char **argv){
  • W - while(
  • @ - argv
  • P - putchar(
  • Inséré automatiquement );}

Fortement basé sur la réponse de Doorknob.




0

Google Sheets, 94 octets

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

Je ne suis pas familier avec le binaire FizzBuzz mais il semble qu'ils soient délimités par des espaces, donc cette formule s'appuie sur cela. La logique est assez simple:

  • Remplacer Fizzpar 0et Buzzpar1
  • Fractionner le résultat en un tableau en utilisant un espace comme délimiteur
  • Convertir chaque élément de binaire en décimal
  • Remplacez chaque élément par son équivalent ASCII
  • Rejoignez chaque élément sans délimiteur

0

Java 8, 117 115 octets

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

Je doute que vous puissiez faire beaucoup de remplacements de regex fantaisie en Java comme la plupart des autres réponses, principalement parce que vous ne pouvez rien faire avec les groupes de capture capturés dans Java-regexes .. (C'est-à-dire "$1".charAt(...)ou "$1".replace(...)n'est pas possible par exemple.)

Explication:

Essayez-le ici.

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.