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.