Fizz Buzz to Text


29

Вступ

Я особливо не знаю, звідки взялася тенденція кайфу. Це може бути просто мем чи щось таке, але воно дещо популярне.

Виклик

Ваше завдання сьогодні - перетворити Fizz Buzz у двійковий (0, 1) відповідно та перетворити цей двійковий текст у текст. Досить стандартні речі.

Як це працює?

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz перекладається на 01101000 01101001, то це перекладається на "привіт"

Обмеження

  • Вхід - Fizz Buzz у бінарній точці зору (див. Приклади нижче).
  • Вихід повинен бути текстовим.
  • Ви можете припустити, що вхід FizzBuzz правильний.
  • Це , найкоротший виграш байтів.

Вхідні дані

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz FizzFizzBuzzFizzFizzFizzFizzBuzz

Вихід

"Привіт!"


15
Меме? Це початкова (початкова) шкільна гра
бета-розпад

2
Чи не можемо ми не брати пробіли у вході?
HyperNeutrino

2
Невже ми не можемо зайняти цей простір? Я можу зберегти три байти, якщо мені не доведеться вводити цей простір.
HyperNeutrino


8
@dmckee - "черговий блог", на який посилається Джоел, - Джефф Етвуд, інший засновник "Стакковерф".
pilsetnieks

Відповіді:


55

C, 59 байт

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

Чарівні числа, чарівні числа скрізь!

(Також C коротше, ніж Python, JS, PHP та Ruby? Нечувано!)

Це функція, яка приймає рядок як вхід і виводить в STDOUT.

Покрокова інструкція

Основна структура:

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

Тут «речі всередині» - це купа коду, за яким ,*s++оператор з комами повертає лише значення другого аргументу. Отже, це буде проходити через рядок і встановлюватись *sдля кожного символу, включаючи кінцевий байт NUL (оскільки постфікс ++повертає попереднє значення) перед виходом.

Давайте подивимось на решту:

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

Знімаючи трійку і коротке замикання ||, це можна розширити до

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

Звідки беруться ці магічні числа? Ось двійкові зображення всіх залучених персонажів:

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

Спочатку нам потрібно відокремити простір та NUL від решти символів. Як працює цей алгоритм, він зберігає акумулятор "поточного" числа і друкує його щоразу, коли він досягає пробілу або кінця рядка (тобто '\0'). Зауваживши, що ' 'і '\0'є єдиними символами, які не мають жодного з двох найменш значущих бітів, ми можемо побітовим І символом з, 0b11щоб отримати нуль, якщо символ є пробілом або NUL, а не нульовим значенням є інше.

Копаючи глибше, у першій «якщо» гілці, тепер у нас є персонаж, який є одним із FBizu. Я вибрав лише оновлення акумулятора на Fs і Bs, тому мені знадобився якийсь спосіб відфільтрувати izus. Зручно, Fі Bобидва мають лише другий, третій чи сьомий найменш значущі біти, а всі інші числа мають принаймні один інший біт. Насправді всі вони мають або перший, або четвертий найменш значущий біт. Отже, ми можемо побіжно AND з 0b00001001, що дорівнює 9, що дасть 0 для Fі, Bа не нульове значення в іншому випадку.

Як тільки ми визначимо, що у нас є Fабо B, ми можемо відобразити їх відповідно 0і 1, взявши їх модуль 5, тому що Fє 70і Bє 66. Потім фрагмент

i += i + *s % 5;

- це просто грізний спосіб сказати

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

що також можна виразити як

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

який вставляє новий біт принаймні значущому положенні та зміщує все інше на 1.

"Але чекай!" ви можете протестувати. "Коли ви надрукуєте i, коли це колись повернеться до 0?" Що ж, putcharприводить свій аргумент до unsigned charвеличини, яка так само буває, що має 8 біт. Це означає, що все, що минуло восьмий найменш значущий біт (тобто мотлох від попередніх ітерацій), викидається, і нам не потрібно про це турбуватися.

Завдяки @ETHproductions для пропонуючи замінити 57з 9, зберігаючи байт!


Хороший трюк з путчаром.
Computronium

Це reeeeeally дивовижно. C зробив правильно!
Густаво Масель

13
Якщо говорити про те, щоб зробити все правильно, на мою не дуже скромну думку, як слід робити відповідь на кодекс-гольф. Ви публікуєте розумне проникливе рішення, супроводжуване повним, добре написаним поясненням, яке насправді навчає людей чогось про мову, яка може бути корисною в інших, більш практичних обставинах.
Коді Грей

3
@CodyGray Саме так. Однією з причин того, що Code Golf не перебуває на вершині мого SE, що я часто відвідую, це те, що багато відповідей - це просто "ось код". Хоча це здорово для людей, які дуже добре знають мови, мені це просто схоже на шум. Мені подобається бачити пояснення, як тут, тому що він розкриває метод , який, я думаю, більшості людей здається набагато цікавішим, ніж сам код. Всього два мої центи ...
Кріс Сірефіс

Дуже приємний битхак, але ви рахуєте свої біти від MSB (зліва) до LSB (праворуч)? IMO - єдиний розумний спосіб підрахунку бітів у 8-бітовому байті (або 128-бітному SIMD-векторі, або будь-якому іншому) - від LSB = біт 0 до MSB = біт 7.
Пітер Кордес

10

Желе , 9 байт

Ḳm€4O%5ḄỌ

Спробуйте в Інтернеті!


О, розумне, сплющування це було непотрібне. Приємно.
HyperNeutrino

@HyperNeutrino Зверніть увагу на коментар, який я зробив щодо вашого, я використав трохи інший алгоритм, щоб уникнути копіювання (хоча технічно дозволено мені це не подобається).
Ерік Аутгольфер

@downvoter: чи ви протестували це взагалі перед тим, як переходити по каналу?
Ерік Аутгольфер


9

Пітон 3 , 169 101 93 91 85 81 байт

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

Спробуйте в Інтернеті!

Пояснення:

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
    )

Це було швидко. +1
HyperNeutrino

Я щось подібне до цього робив. Це було лише питання копіювання-вставки та змінити його на FizzBuzz: P
Мармісти

1
О, це пояснює. : P Але ти здолав; _;
HyperNeutrino


1
Уопс, зробив це знову , 85 байт цього разу з lambdaфункцією
містер Xcoder

8

JavaScript (ES6), 80 79 байт

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


Дуже хороша. Я спробував і не зміг придумати - то більш коротким, хоча є кілька альтернативних рішень 80 байт з використанням .replace(/..zz/g,, '0b'+і т.д.
ETHproductions

@ETHproductions Позбавлення nдозволяє досягти 79. На жаль, для введення даних потрібно додати додатковий простір. Звідси досить затратна `${s} ` .
Арнольд

7

Japt , 26 24 19 17 байт

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

Спробуйте в Інтернеті!

Збережено 2 байти завдяки @Shaggy & 2 байти завдяки @ETHproductions

Пояснення

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
Ви можете замінити 2 })на Ã. Напевно, є більше, щоб врятувати, ніж це, але я не можу цілком примусити його працювати на своєму телефоні.
Кудлатий

1
Дуже приємно, дякую за використання Japt! Ви можете зберегти пару байтів, замінивши ò4...q n2на ë4...n2( ë4робить те саме, що ò4, крім повернення лише першого елемента; як не дивно, це не здається документально зафіксовано)
ETHproductions

1
@ETHproductions Дякуємо, що зробили Japt!
Пуельс

6

Рубі, 65 63 60 байт

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

Це анонімний додаток, який приймає введення та видає вихід у вигляді рядка.

->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 байт

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

Спробуй це

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>


Я вважаю, +це коротше, ніжparseInt
Kritixi Lithos

2
Думаю, +(m[0]<"F")можна скоротити доm<"F"|0
ETHproductions

5

Perl 5, 33 байт

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

Замінює "F" і "B" на вході відповідно 0 і 1 та видаляє інші символи. Потім він використовує packфункцію perl, щоб перетворити цю бітову рядок у символи ASCII.


Нічого, це полегшене приблизно до половини розміру моєї спроби Perl 5. Кудос.
Девід Конрад

1
Я вважаю, що ви можете зробити це значно коротше, скориставшись -p0командою командного рядка (що дозволить вам врятувати<>=~r для введення, і дозволяють використовувати $_=замість print()). Залежно від того, як ви хочете обробляти нові рядки, вони можуть вам навіть не знадобитися 0. (Навіть якщо ви хочете уникнути штрафних санкцій для командного рядка, sayце коротше, ніж print.)

@Chris Не моє, faubiguy's. Але спасибі ;)
Девід Конрад

@DavidConrad Мій поганий ха-ха.
Кріс

1
Вам також точно не потрібні 0. Просто використовуйте прапор -p і $_=pack'B*',y/FB -z/01/drдля вашої програми знижується оцінка до 26 байт.
Кріс

5

Python 2 , 90 83 82 81 байт

-1 байт завдяки абсолютно нелюдським
-1 байт завдяки мармістам
-1 байт завдяки Джонатану Фреху

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

Спробуйте в Інтернеті!



ви можете зберегти байт, перетворившись *1 forна*1for
мармісти

Так як ви використовуєте *1для перетворення з булева в ціле число, ви можете зберегти байти за допомогою +: (l<'D')*1forможе бути +(l<'D')for.
Джонатан Фрех

3

Пробіл, 123 байти

Видиме представлення:

SSNNSSNSNSSSNSNSTNTSTTTSSSTSSSSSNTSSTSNSNTSSNSSSTSSTTSNTSSTNTSTNSSSTNTSSSNSSTNSSNSNSSNSTNTSTNTSTNTSTSSSNSNNNSSSNSNTTNSSNSNN

Невимушена програма:

    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

Немає нічого особливо дивного в реалізації, єдиний справжній гольф - це в деякому дивному повторному використанні тимчасових споруд, а також не піклуючись про необмежений ріст стека, щоб зменшити ще кілька байт.


3

Октава , 59 57 53 байти

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

Це не працює в TIO, оскільки панель інструментів зв’язку не реалізована. Це добре працює, якщо ви скопіюєте його та вставте в Octave-он-лайн . У MATLAB навіть не працює робочий код.

Вдалося зберегти два байти, перемістивши матрицю після її перегортання, а не навпаки.

Пояснення:

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

Почнемо з середини <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]

Назвемо результуючий булевий (бінарний) вектор для 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 байт + 4 байти для прапорів = 32 байти

Біжи з прапорами -040pE

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

-040 встановлює роздільник записів на пробіл, щоб perl бачив кожну групу FizzBuzzes як окремий рядок, потім циклічно перетинав ці рядки, змінюючи F на 0, B на 1, видаляючи все інше, потім перетворюючи на бінарний і звідти в ascii.


2

Желе , 9 байт

Ḳm€4=”BḄỌ

Спробуйте в Інтернеті!

Ḳm€4=”BḄỌ  Main Link
Ḳ          Split on spaces
  €        Map
 m 4       Take every fourth letter (F and B)
    =”B    Check if each letter is equal to B (gives the binary representation)
       Ḅ   Binary -> Integer
        Ọ  Unord; gives chr(i)

-3 байти завдяки Еріку Переможнику




2

Мозок-Флак , 107 байт

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

Спробуйте в Інтернеті!

+3 байти для -c прапора.

Пояснення

{                                        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 байт

Рішення:

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

Приклад:

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

Пояснення:

Розділіть рядок введення на, " "щоб надати окремі списки FizzBuzz..., індексувати у кожному з цих списків перший символ (тобто 0 4 8 ... 28). Повернення булевого списку визначається тим, чи є кожен символ "B"(ASCII 66). Перетворіть ці списки в основу 10, а потім переведіть результат у рядок.

{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 байти

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

Спробуйте в Інтернеті!

Як це працює

            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 байт

занадто багато байтів, але принаймні читабельні

Визначена як функція - це 98 байт

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

тест:

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

Пояснення:

/(F)|(B)|./

Відповідає буквам F і B і будь-що інше як Групи

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

- це функція, яка захоплює групи, повертає 0 для F і 1 для B, або ""

c - символи, відповідні
F і B тепер Параметри!
3-й . Група опущена як параметр

F і B - це, undefinedколи 3-я група відповідає
B, undefinedколи група F відповідає

Отриманий рядок 0100 .. тощо

ріжеться скибочками по 8 байт

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

і обробляється як 0b двійковий рядок


2
Ласкаво просимо до PPCG! Завданням цього завдання є створення програми або функції, що перекладає довільні рядки FizzBuzz. Я не знаю дуже багато JavaScript, але можливе подання функції s=>s.replace( .... Також будь ласка, включіть кількість байтів у заголовку вашої відповіді.
Лайконі

Я очистив частину форматування вашого коду для вас. Крім того, вам не потрібні letанонімні функції, прийнятні.
Кудлатий

1

shortC , 35 байт

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

Конверсії в цій програмі:

  • A - int main(int argc, char **argv){
  • W - while(
  • @ - argv
  • P - putchar(
  • Автоматично вставлено );}

Сильно спираючись на відповідь Дорноба.




0

Google Таблиці, 94 байти

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

Я не знайомий з бінарними файлами FizzBuzz, але здається, що вони розмежовані пробілами, тому ця формула спирається на це. Логіка досить проста:

  • Замініть Fizzна 0і Buzzз1
  • Розбийте результат на масив, використовуючи пробіл як роздільник
  • Перетворити кожен елемент з двійкового в десятковий
  • Замініть кожен елемент його еквівалентом ASCII
  • Приєднуйтесь до кожного елемента без роздільника

0

Java 8, 117 115 байт

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

Я сумніваюся , що ви можете зробити багато химерні регулярні вирази заміни в Java , як і більшість інших відповідей, в основному тому , що ви не можете нічого з захопленим захопленням групами в Java-регулярні виразах робити .. (Тобто "$1".charAt(...)або"$1".replace(...) неможливо, наприклад.)

Пояснення:

Спробуйте тут.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.