Fizz Buzz na tekst


29

Wprowadzenie

Nie wiem szczególnie , skąd wziął się ten trend. To może być tylko mem lub coś takiego, ale jest dość popularny.

Wyzwanie

Twoim dzisiejszym zadaniem jest konwersja Fizz Buzz na odpowiednio binarne (0, 1) i konwersja tego binarnego na tekst. Całkiem standardowe rzeczy.

Jak to działa?

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz można przetłumaczyć na 01101000 01101001, a to znaczy „cześć”

Ograniczenia

  • Dane wejściowe to Fizz Buzz z binarnego punktu widzenia (patrz przykłady poniżej).
  • Dane wyjściowe muszą być tekstem.
  • Możesz założyć, że wejście FizzBuzz jest prawidłowe.
  • To jest , najkrótsze bajty wygrywają.

Wkład

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzBuzz

Wydajność

"cześć!"


15
Ja ja? To jest podstawowa (podstawowa) gra szkolna
Beta Decay

2
Czy nie możemy wstawiać spacji na wejściu?
HyperNeutrino

2
Czy nie możemy jednak zająć tej przestrzeni? Mogę zapisać trzy bajty, jeśli nie będę musiał wprowadzać tego miejsca.
HyperNeutrino

10
FizzBuzz cieszy się dużą ilością pieniędzy na Stack Exchange po części dlatego, że Joel (jeden z założycieli) miał post na blogu odnoszący się do innego bloga, który mówił o używaniu go jako niskiej bariery wejścia na rynek dla programistów .
dmckee

8
@dmckee „innym blogiem”, do którego odwołuje się Joel, jest Jeff Atwood, drugi założyciel Stackoverflow.
pilsetnieks

Odpowiedzi:


55

C, 59 bajtów

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

Magiczne liczby, magiczne liczby wszędzie!

(Również C jest krótszy niż Python, JS, PHP i Ruby? Niespotykane!)

Jest to funkcja, która pobiera ciąg jako dane wejściowe i wyjściowe do STDOUT.

Przewodnik

Podstawowa struktura to:

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

Tutaj „rzeczy w środku” to wiązka kodu, po ,*s++której operator przecinka zwraca tylko wartość drugiego argumentu. Dlatego też przejdzie przez ciąg i ustawi *skażdy znak, w tym końcowy bajt NUL (ponieważ postfix ++zwraca poprzednią wartość) przed wyjściem.

Rzućmy okiem na resztę:

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

Odrywając trójskładnikowe i zwarciowe ||, można to rozszerzyć do

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

Skąd pochodzą te magiczne liczby? Oto reprezentacje binarne wszystkich zaangażowanych postaci:

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

Najpierw musimy oddzielić spację i NUL od reszty postaci. Sposób działania tego algorytmu utrzymuje akumulator o numerze „bieżącym” i wypisuje go, gdy tylko dojdzie do spacji lub końca łańcucha (tj '\0'.). Zauważając to ' 'i '\0'jesteśmy jedynymi znakami, które nie mają ustawionego żadnego z dwóch najmniej znaczących bitów, możemy bitowo ORAZ znak za pomocą, 0b11aby uzyskać zero, jeśli znak jest spacją lub NUL i w przeciwnym razie jest niezerowy.

Kopiąc głębiej, w pierwszej gałęzi „jeśli” mamy teraz jedną z postaci FBizu. Zdecydowałem się tylko zaktualizować akumulator na Fsi Bs, więc potrzebowałem jakiegoś sposobu, aby odfiltrować izus. Dogodnie Fi Boba mają tylko drugi, trzeci lub siódmy najmniej znaczący zestaw bitów, a wszystkie pozostałe liczby mają co najmniej jeden inny zestaw bitów. W rzeczywistości wszystkie mają pierwszy lub czwarty najmniej znaczący bit. Stąd możemy bitowo ORAZ z 0b00001001, która wynosi 9, co da 0 dla Fi, w Bprzeciwnym razie, zero.

Po ustaleniu, że mamy Flub B, możemy zmapować je odpowiednio na 0i 1, biorąc ich moduł 5, ponieważ Fjest 70i Bjest 66. Następnie fragment kodu

i += i + *s % 5;

to po prostu golfowy sposób na powiedzenie

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

co można również wyrazić jako

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

który wstawia nowy bit w co najmniej znaczącej pozycji i przesuwa wszystko inne o 1.

"Ale poczekaj!" możesz protestować. „Po wydrukowaniu i, kiedy w ogóle resetuje się do 0?” Cóż, putcharrzuca swój argument na an unsigned char, który akurat ma 8 bitów. Oznacza to, że wszystko po 8. najmniej znaczącym bicie (tj. Śmieci z poprzednich iteracji) jest wyrzucane i nie musimy się tym martwić.

Dzięki @ETHproductions za sugerowanie zastąpić 57z 9, oszczędzając bajt!


Niezła sztuczka z putcharem.
Computronium

To jest naprawdę niesamowite. C zrobił dobrze!
Gustavo Maciel

13
Mówiąc o robieniu rzeczy, moim zdaniem, nie tak skromnie, jak należy odpowiedzieć na golfa. Zamieszczasz sprytne, wnikliwe rozwiązanie, któremu towarzyszy pełne, dobrze napisane wyjaśnienie, które faktycznie uczy ludzi czegoś o języku, który może być przydatny w innych, bardziej praktycznych okolicznościach.
Cody Gray

3
@CodyGray Dokładnie to. Jednym z powodów, dla których Code Golf nie jest na szczycie mojej SE, którą często odwiedzam, jest to, że wiele odpowiedzi to po prostu „oto kod”. To fajne dla ludzi, którzy znają języki, ale dla mnie to wygląda na hałas. Lubię widzieć wyjaśnienia takie jak tutaj, ponieważ ujawniają one metodę , która moim zdaniem dla większości ludzi jest o wiele bardziej interesująca niż sam kod. Tylko moje dwa centy ...
Chris Cirefice

Bardzo fajny bithack, ale liczysz swoje bity od MSB (po lewej) do LSB (po prawej)? IMO jedynym rozsądnym sposobem zliczania bitów w 8-bitowym bajcie (lub 128-bitowym wektorze SIMD lub czymkolwiek innym) jest od LSB = bit 0 do MSB = bit 7.
Peter Cordes



9

Python 3 , 169 101 93 91 85 81 bajtów

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

Wypróbuj online!

Wyjaśnienie:

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
    )

To było szybkie. +1
HyperNeutrino

Zrobiłem coś podobnego jakiś czas temu, wystarczyło skopiować i wkleić i zmienić na FizzBuzz: P
Martmists

1
Och, to wyjaśnia. : P Ale wygraliście; _;
HyperNeutrino


1
Ups, zrobiłem to ponownie , tym razem 85 bajtów z lambdafunkcją
Mr. Xcoder

8

JavaScript (ES6), 80 79 bajtów

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


Bardzo dobrze. Próbowałem i nie udało się wymyślić coś krótszego, choć istnieje kilka alternatywnych rozwiązań 80-bajtowych użyciem .replace(/..zz/g,, '0b'+itp
ETHproductions

@ETHproductions Pozbycie się npozwala osiągnąć 79. Niestety wymaga to dodatkowego miejsca do dodania. Stąd raczej kosztowne `${s} ` .
Arnauld

7

Japt , 26 24 19 17 bajtów

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

Wypróbuj online!

Zaoszczędzono 2 bajty dzięki @Shaggy i 2 bajty dzięki @ETHproductions

Wyjaśnienie

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
Można wymienić 2 })z Ã. Zdecydowanie jest o wiele więcej do uratowania, ale nie do końca mogę go uruchomić na telefonie.
Kudłaty

1
Bardzo miło, dziękuję za skorzystanie z Japt! Można zaoszczędzić kilka bajtów zastępując ò4...q n2z ë4...n2( ë4nie to samo, co ò4, z wyjątkiem zwrotu tylko pierwsza pozycja; dziwnie, to nie wydaje się być udokumentowane)
ETHproductions

1
@ETHproductions Dziękujemy za dokonanie Japt!
powelles

6

Rubinowy, 65 63 60 bajtów

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

Jest to anonimowy proc, który pobiera dane wejściowe i podaje dane wyjściowe jako ciąg znaków.

->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 bajtów

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

Spróbuj

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>


Uważam, że +jest krótszy niżparseInt
Kritixi Lithos

2
Myślę, że +(m[0]<"F")można go skrócić dom<"F"|0
ETHprodukcje

5

Perl 5, 33 bajtów

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

Zamienia „F” i „B” na wejściu odpowiednio na 0 i 1 oraz usuwa inne znaki. Następnie używa packfunkcji perla, aby przekształcić ten ciąg bitów w znaki ASCII.


Wow, to gra w golfa do połowy wielkości mojej próby Perla 5. Sława.
David Conrad

1
Wierzę, że możesz to znacznie skrócić, używając -p0opcji wiersza poleceń (co zaoszczędziłoby ci czasu <>=~rna wprowadzanie danych i pozwoliłoby na użycie $_=zamiast print()). W zależności od tego, jak chcesz obsługiwać nowe wiersze, możesz nawet nie potrzebować 0. (Nawet jeśli chcesz uniknąć kar za opcje wiersza poleceń, sayjest on krótszy niż print.)

@Chris Not mine, faubiguy's. Ale dzięki. ;)
David Conrad

@DavidConrad My bad haha.
Chris

1
Zdecydowanie nie potrzebujesz też 0. Wystarczy użyć flagi -p, a $_=pack'B*',y/FB -z/01/drprogram obniży Twój wynik do 26 bajtów.
Chris

5

Python 2 , 90 83 82 81 bajtów

-1 bajt dzięki totalnie ludzkiemu
-1 bajt dzięki Martmistom
-1 bajt dzięki Jonathanowi Frechowi

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

Wypróbuj online!



możesz uratować bajt, zamieniając się *1 forw*1for
Martmists

Ponieważ używasz *1do konwersji z wartości logicznej na liczbę całkowitą, możesz zapisać bajt za pomocą +: (l<'D')*1formoże być +(l<'D')for.
Jonathan Frech

3

Biała spacja, 123 bajty

Widoczne przedstawienie:

SSNNSSNSNSSSNSNSTNTSTTTSSSTSSSSSNTSSTSNSNTSSNSSSTSSTTSNTSSTNTSTNSSSTNTSSSNSSTNSSNSNSSNSTNTSTNTSTNTSTSSSNSNNNSSSNSNTTNSSNSNN

Nieobrobiony program:

    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

W implementacji nie ma nic szczególnie dziwnego, jedyne prawdziwe gra w golfa polega na jakimś dziwnym ponownym wykorzystaniu tymczasowości, a także nie dbanie o nieograniczony wzrost stosu, aby przesunąć więcej bajtów.


3

Oktawa , 59 57 53 bajtów

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

To nie działa w TIO, ponieważ zestaw narzędzi komunikacyjnych nie jest zaimplementowany. Działa dobrze, jeśli skopiujesz i wkleisz go do Octave-online . Nie jest nawet blisko działającego kodu w MATLAB.

Udało się zaoszczędzić dwa bajty, transponując matrycę po odwróceniu, zamiast na odwrót.

Wyjaśnienie:

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

Zacznijmy w środku <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]

Nazwijmy wynikowy wektor boolowski (binarny) dla 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 bajtów + 4 bajty dla flag = 32 bajty

Uruchom z flagami -040pE

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

-040 ustawia separator rekordów na spację, dzięki czemu perl widzi każdą grupę FizzBuzzów jako osobną linię, a następnie zapętla te linie, zmieniając F na 0, B na 1, usuwając wszystko inne, a następnie konwertując na binarne, a stamtąd na ascii.




2

Brain-Flak , 107 bajtów

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

Wypróbuj online!

+3 bajty dla -cflagi.

Wyjaśnienie

{                                        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 bajtów

Rozwiązanie:

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

Przykład:

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

Wyjaśnienie:

Podziel ciąg wejściowy na, " "aby uzyskać odrębne listy FizzBuzz..., indeks na każdej z tych list przy pierwszym znaku (tj 0 4 8 ... 28.). Zwraca listę boolowską określoną przez to, czy każdy znak to "B"(ASCII 66). Konwertuj te listy na bazę 10, a następnie rzutuj wynik na ciąg.

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

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

Wypróbuj online!

Jak to działa

            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 bajtów

za dużo bajtów, ale przynajmniej czytelne

Zdefiniowany jako funkcja ma 98 bajtów

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

Wyjaśnienie:

/(F)|(B)|./

Dopasowuje litery F i B i wszystko inne jako Grupy

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

to funkcja, która przechwytuje grupy, zwraca 0 dla F i 1 dla B lub ''

c jest znakiem dopasowanym
F i B są teraz parametrami!
3 . grupa jest odrzucana jako parametr

F i B występują, undefinedgdy dopasowana jest trzecia grupa.
B występuje, undefinedgdy dopasowana jest grupa F.

Wynikowy ciąg 0100 .. itd

jest pocięty na plasterki po 8 bajtów

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

i przetwarzany jako ciąg binarny 0b


2
Witamy w PPCG! Celem tego wyzwania jest zapewnienie programu lub funkcji tłumaczącej dowolne ciągi FizzBuzz. Nie znam dużo kodu JavaScript, ale może to być prawidłowe przesłanie funkcji s=>s.replace( .... Proszę również podać liczbę bajtów w nagłówku odpowiedzi.
Laikoni

Wyczyściłem dla ciebie część twojego formatowania kodu. Ponadto nie potrzebujesz let, anonimowe funkcje są dopuszczalne.
Kudłaty

1

shortC , 35 bajtów

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

Konwersje w tym programie:

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

Mocno oparty na odpowiedzi Doorknoba.




0

Arkusze Google, 94 bajty

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

Nie znam binarnego FizzBuzz, ale wygląda na to, że są one rozdzielone spacjami, więc ta formuła opiera się na tym. Logika jest dość prosta:

  • Wymień Fizzsię 0i Buzzze1
  • Podziel wynik na tablicę, używając spacji jako separatora
  • Konwertuj każdy element z binarnego na dziesiętny
  • Zastąp każdy element jego odpowiednikiem ASCII
  • Dołącz do każdego elementu bez ogranicznika

0

Java 8, 117 115 bajtów

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

Wątpię, można zrobić wiele zamienników fantazyjne regex w Javie jak większość innych odpowiedzi, głównie dlatego, że nie może nic z przechwyconych przechwytywania grup w Java-regexes zrobić .. (Ie "$1".charAt(...)lub"$1".replace(...) nie są możliwe.)

Wyjaśnienie:

Wypróbuj tutaj.

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.