Fizz Buzz to Text


29

Введение

Я не особенно знаю, откуда взялась эта тенденция. Это может быть просто мем или что-то, но это несколько популярно.

Вызов

Ваша задача сегодня - преобразовать Fizz Buzz в двоичный файл (0, 1) соответственно и преобразовать этот двоичный файл в текстовый. Довольно стандартные вещи.

Как это работает?

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzBuzzFizzBuzzFizzFizzBuzz будет переводить в 01101000 01101001, а затем переводится в "привет"

Ограничения

  • Вводом является Fizz Buzz в двоичной точке зрения (см. Примеры ниже.)
  • Вывод должен быть текстом.
  • Вы можете предположить, что вход FizzBuzz правильный.
  • Это , выигрывают короткие байты.

вход

FizzBuzzBuzzFizzBuzzFizzFizzFizz FizzBuzzzBuzzFizzBuzzFizzFizzBuzz FizzФиззБуззФизФизФизСерзФиззБизз

Выход

"Здравствуй!"


15
Meme? Это игра для начальной (начальной) школы
— Beta Decay

2
Разве мы не можем взять пробелы на входе?
— HyperNeutrino

2
Разве мы не можем занять это место, хотя? Я могу сохранить три байта, если мне не нужно вводить это пространство.
— HyperNeutrino


8
@dmckee "еще один блог", на который ссылается Джоэл, - это Джефф Этвуд, другой основатель Stackoverflow.
— 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 (поскольку postfix ++возвращает предыдущее значение), перед выходом.

Давайте посмотрим на остальное:

*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приведем свой аргумент к an unsigned char, который просто так получается размером 8 бит. Это означает, что все, что осталось за восьмым младшим значащим битом (т.е. мусор из предыдущих итераций), отброшено, и нам не нужно об этом беспокоиться.

Спасибо @ETHproductions за предложение заменить 57на 9, сохраняя байт!


Хороший трюк с путчаром.
— КОМПЬЮТРОНИУМ

Это потрясающе. С правильно сделал!
— Густаво

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

3
@CodyGray Именно это. Одна из причин, по которой Code Golf не входит в число моих SE, которые я часто посещаю, заключается в том, что многие ответы - это просто «вот код». Хотя это здорово для людей, которые хорошо знакомы с языками, для меня это просто шум. Мне нравится видеть объяснения, подобные здесь, потому что они раскрывают метод , который, я думаю, большинство людей находят гораздо более интересным, чем сам код. Просто мои два цента ...
— Крис Cirefice

Очень хороший битхак, но вы считаете свои биты от MSB (слева) до LSB (справа)? IMO единственный разумный способ подсчета битов в 8-битном байте (или 128-битном векторе SIMD, или что-то еще) - от LSB = бит 0 до MSB = бит 7.
— Питер Кордес

10

Желе , 9 байт

Ḳm€4O%5ḄỌ

Попробуйте онлайн!


О, умный, сплющивать было ненужно. Ницца.
— HyperNeutrino

@HyperNeutrino Обратите внимание на мой комментарий, я использовал немного другой алгоритм, чтобы избежать дублирования (хотя технически это разрешено, но мне это не нравится).
— Эрик Outgolfer

@ downvoter: ты проверял это вообще до даун-голосования?
— Эрик Outgolfer


9

Python 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
— Martmists

1
О, это объясняет. : P Но ты переиграл; _;
— HyperNeutrino


1
Ой, сделал это снова , 85 байтов на этот раз с lambdaфункцией
— Mr. 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.)

@ Крис Не мое, фобигуи. Но спасибо. ;)
— Дэвид Конрад

@DavidConrad Мой плохой ха-ха.
— Крис

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

5

Python 2 , 90 83 82 81 байт

-1 байт благодаря полностью человеческому
-1 байт благодаря Martmists
-1 байт благодаря Джонатану Фреху

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

Попробуйте онлайн!



Вы можете сохранить байт, превратившись *1 forв*1for
— Martmists

Поскольку вы используете *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-online . Это даже не близко, чтобы работать код в 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

Brain-Flak , 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анонимные функции.
— Лохматый




0

Google Sheets, 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.