13
\$\begingroup\$

A simple FizzBuzz using strings.

Given

  • 1 word or phrase (string)
  • 2 unique characters

Output

The word or phrase with each occurrence of the first character replaced with fizz and each of the second character replaced with buzz

Rules

  • The first letter in both Fizz and Buzz must remain capitalized
  • For the rest of the words fizz and buzz, you must match the case of the replaced character (if no case then keep lowercase)
  • If given characters are not in the phrase, output the original phrase

Test Cases

Given: Hello, h, l
Output: FIZZeBuzzBuzzo

Given: test, a, b
Output: test

Given: PCG rocks!,  , !
PCGFizzrocksBuzz

Given: This
Is
SPARTA!, 
, S
Output: ThiBuzzFizzIBuzzFizzBUZZPARTA!

Given: FizzBuzz, a, b
Output: FizzBUZZuzz

This is code-golf so the shortest code, in bytes, wins!

Note

Technically handling the newline case (This Is SPARTA!) is a part of the challenge. However, I will not void an answer for not including it, as it is very challenging or even impossible in some languages.

\$\endgroup\$
7
  • 2
    \$\begingroup\$ you must match the case of the replaced character and Input is not case sensitive seem to contradict each other. \$\endgroup\$ Mar 19, 2017 at 7:37
  • \$\begingroup\$ @GregMartin ah thank you, i was trying to say that the 2 characters as input are case sensitive (ex. A means the same as a) \$\endgroup\$ Mar 19, 2017 at 7:51
  • 1
    \$\begingroup\$ ThiBuzzFizzIBuzzFizzBUZZPARTA is missing a final exclamation mark. \$\endgroup\$
    – Arnauld
    Mar 19, 2017 at 12:42
  • \$\begingroup\$ Are we supposed to support inputs such as aa, a, f? What would be the expected output? BUZZizzBUZZizz, FizzFizz, or both allowed at our option? \$\endgroup\$
    – Arnauld
    Mar 19, 2017 at 13:01
  • \$\begingroup\$ @Amauld Based on the last test case, I'd say it should output FizzFizz. \$\endgroup\$
    – anon
    Mar 19, 2017 at 15:15

11 Answers 11

6
\$\begingroup\$

Python 3, 180 174 168 160 152 bytes

from sys import*
J=''.join
L=str.lower
s,a,b=J(stdin).split(', ')
print(J('FBFBiuIUzzZZzzZZ'[L(k)==L(b)::2][k!=L(k)::2]*(L(k)in L(a+b))or k for k in s))

This is just a more golfed version of Stephen's answer, in Python 3. This chips away 42% of his bytes. Python 2 would save one byte on the print, but such is the price of progress. This handles newlines properly.

Thanks to Blckknight for saving 8 bytes on input.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ What is the fileinput modules used for? \$\endgroup\$ Mar 19, 2017 at 13:28
  • \$\begingroup\$ @ValyrioAccount, fileinput.input overrides the built-in input method. It enables inputs with newlines. \$\endgroup\$ Mar 19, 2017 at 20:57
  • 2
    \$\begingroup\$ How about from sys import* and s,a,b=J(stdin).split(', ') to save a few characters? \$\endgroup\$
    – Blckknght
    Mar 20, 2017 at 6:13
4
\$\begingroup\$

Python, 109 bytes

lambda s,w:"".join([c,"Fizz","Buzz","BUZZ","FIZZ"][-~w.lower().find(c.lower())*-~(-2*c.isupper())]for c in s)

Try it online!


Takes the two characters as a single string

Edit: Added testcase to TIO link, newline works too

\$\endgroup\$
0
2
\$\begingroup\$

Jelly, 34 bytes

Œl=€⁹Œl¤ȧ€"“¡Ṭ4“Ụp»o"/ȯ"Œu⁹Œln$T¤¦

Try it online!

How?

Œl=€⁹Œl¤ȧ€"“¡Ṭ4“Ụp»o"/ȯ"Œu⁹Œln$T¤¦ - Main link: characters, string
Œl                                 - lowercase the characters
       ¤                           - nilad followed by link(s) as a nilad:
    ⁹                              -     right argument, the string
     Œl                            -     lowercase
  =€                               - equals (vectorises) for €ach (a list of 2 lists that identify the indexes of the string matching the characters regardless of case)
           “¡Ṭ4“Ụp»                - dictionary strings ["Fizz", "Buzz"]
          "                        - zip with
        ȧ€                         -     logical and (non-vectorising) for €ach (replace the 1s with the words)
                     /             - reduce with:
                    "              -     zip with:
                   o               -         logical or (vectorises) (make one list of zeros and the words)
                                   - implicit right argument, string
                       "           - zip with:
                      ȯ            -     logical or (non-vectorising) (replace the zeros with the original characters from the string)
                                 ¦ - apply...
                        Œu         -     uppercase
                                   - ...to the indexes (the words at indexes):
                                ¤  -     nilad followed by link(s) as a nilad:
                          ⁹        -         right argument, the string
                              $    -         last two links as a monad (i.e. the string on both sides):
                           Œl      -             lowercase
                             n     -             not equals (vectorises)
                               T   -         truthy indexes (the indexes of the capital letters in the string)
                                 
\$\endgroup\$
1
  • \$\begingroup\$ +1, Thank you for using the newline case. That makes this the first entirely correct submission \$\endgroup\$ Mar 19, 2017 at 7:59
2
\$\begingroup\$

Python 2, 271, 261 bytes

import fileinput as f
a=''
for m in f.input():a+=m
a=a.split(', ')
l=L=list(a[0])
for i in range(0,len(a[0])):
 j,k=l[i].lower(),l[i].istitle()
 if j==a[1].lower():
  L[i]='FIZZ'if k else'Fizz'
 elif j==a[2].lower():
  L[i]='BUZZ'if k else'Buzz'
print''.join(L)

Try it online!

Wow this one was a doozie! It turns out python won't accept multi-line inputs so fileinput must be used.

edit: should pass all cases now :)

\$\endgroup\$
3
  • \$\begingroup\$ Definite +1 for handling the case with newlines! Not many are able to incorporate that \$\endgroup\$ Mar 19, 2017 at 7:57
  • \$\begingroup\$ You could save 3 bytes by doing something like import fileinput as f ... for m in f.input(): \$\endgroup\$ Mar 19, 2017 at 8:11
  • \$\begingroup\$ @Caleb Thanks for the suggestion! it should pass all tests now \$\endgroup\$
    – Stephen
    Mar 19, 2017 at 8:19
2
\$\begingroup\$

MATLAB/Octave, 106 102 111 bytes

@(a,b,c)regexprep(a,num2cell([lower([b c]) upper([b c]) '1234']),{'2','4','1','3','FIZZ','Fizz','BUZZ','Buzz'})

This could probably be optimised further.

It uses a simple Regex replacement. However an intermediate step is required by replacing the input characters with numbers first. This is so that if the second input replace letter was contained in Fizz that the Fizz doesn't then get replaced when the next regex is performed.

This of course assumes there are no numbers in the input. However given the question says the input is a word or phrase I feel that this is an acceptable assumption.

The code will handle new lines in the input correctly.

You can Try it online!

\$\endgroup\$
2
\$\begingroup\$

Bash 4.4 + GNU sed, 70 228 222 227 bytes

IFS=;alias e=echo;K=`sed $([[ $2 != '
' ]]&&e "s/${2,}/Fizz/g;s/${2^}/FIZZ/g"||:)$([[ $3 != '
' ]]&&e ";s/${3,}/Buzz/g;s/${3^}/BUZZ/g"||:)<<<"$1"`;[[ $2 = '
'||$3 = '
' ]]&&e ${K//$'\n'/`[[ $2 = '
' ]]&&e Fizz||e Buzz`}||e "$K"

Apparently alias e=echo throws an error if referenced in Bash 4.3 or below, the version TIO is apparently using. Therefore, the longer and equivalent Bash 4.3 code is given in the below TIO test suite for the sake of testing. This passes all of the test cases, so that is nice.

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ @thedarkwanderer Now it should. Sorry that it took a bit long to fix. \$\endgroup\$
    – R. Kap
    Mar 19, 2017 at 10:42
2
\$\begingroup\$

JavaScript (ES6), 92 bytes

Takes input as a string and an array of two characters. Supports newlines.

f=(s,[a,b],r='Fizz')=>a?f(s.replace(RegExp(a,'gi'),m=>m<'a'?r.toUpperCase():r),[b],'Buzz'):s

Test cases

f=(s,[a,b],r='Fizz')=>a?f(s.replace(RegExp(a,'gi'),m=>m<'a'?r.toUpperCase():r),[b],'Buzz'):s

console.log(f("Hello", ['h', 'l']))
console.log(f("test", ['a', 'b']))
console.log(f("PCG rocks!", [' ', '!']))
console.log(f(`This
Is
SPARTA!`, [`
`, 'S']))
console.log(f("FizzBuzz", ['a', 'b']))

\$\endgroup\$
2
\$\begingroup\$

GNU sed, 135 + 1(r flag) = 136 bytes

By default, a sed script is executed as many times as there are input lines. To handle multi-line input, I use a loop to append all possible remaining lines to the first, without starting a new cycle.

:r
$!N
$!br
s:, (.), (.):;\u\1FIZZ;\l\1Fizz;\u\2BUZZ;\l\2Buzz:
s:^:,:
:
s:,(.)(.*;\1)(...)(.):\3,\4\2\3\4:
s:,(.):\1,:
/,;.F/!t
s:,.*::

Try it online!

The replacement table used on line 4, needs to be in that exact order, i.e. 'Fizz' and 'Buzz' after their upper-case forms. This is because the sed regex .*, used during the table lookup, is greedy. If the current char needed to be replaced is not a letter (no case), then the lowercase string is needed (matched last).

Since sed has no data types, I use a character delimiter to iterate a string. It will mark my current position and in a loop I shift it from left to right. Fortunately, I can use , for this, since it is the input data delimiter.

Explanation:

:r                                                 # reading loop
$!N                                                # append next input line
$!br                                               # repeat till EOF
s:, (.), (.):;\u\1FIZZ;\l\1Fizz;\u\2BUZZ;\l\2Buzz: # create replacement table
s:^:,:                                             # append my string delimiter
:                                                  # main loop
s:,(.)(.*;\1)(...)(.):\3,\4\2\3\4:                 # apply char replacement, if any
s:,(.):\1,:                                        # shift delimiter to right
/,;.F/!t                                           # repeat till end of string
s:,.*::                                            # print only the final string
\$\endgroup\$
1
\$\begingroup\$

Pyth - 25 bytes

sXzsrBQ1scL2rB"FizzBuzz"1

Test Suite.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ A capital as one of the characters seems to cause problems - "Hl", Hello does not capitalise the output correctly and "hL", Hello does not substitute the ls. \$\endgroup\$ Mar 19, 2017 at 3:53
0
\$\begingroup\$

Haskell, 114 bytes

u=Data.Char.toUpper
p[f,b]x|f==u x="Fizz"|b==u x="Buzz"|2>1=[x]
q x y|u y<y=x|2>1=u<$>x
r x=concatMap$q=<<p(u<$>x)

r takes the fizz and buzz characters as a 2 element list as the first argument, and the input string as the second argument. Newlines and unicode should be handled appropriately, although the function is unfortunately not total (allowing for invalid inputs saved 5 bytes).

\$\endgroup\$
1
  • \$\begingroup\$ u=Data.Char.toUpper only works in ghci as far as I know. In standard Haskell you need the import. However you should be able to save some bytes by using =<< instead of concatMap. \$\endgroup\$
    – Laikoni
    Mar 20, 2017 at 22:49
0
\$\begingroup\$

Mathematica, 94 bytes

a=ToLowerCase;b=ToUpperCase;StringReplace@{a@#->"Fizz",b@#->"FIZZ",a@#2->"Buzz",b@#2->"BUZZ"}&

Anonymous function. Takes two strings as input and returns a function which takes a string as input and returns a string as output as output. It must be called in the format prog["c1", "c2"]["s"], where "s" is the target string and "c1" and "c2" are the two characters. Could probably be golfed further.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.