Fix my FizzBuzz

FizzBuzz is where a range of positive integers is taken, and numbers divisible by 3 are replaced with "Fizz", divisible by 5 with "Buzz" and divisible by 15 with "FizzBuzz".

I've got some FizzBuzz output here. Unfortunately, it's been shuffled:

4
Fizz
Fizz
Buzz
2


A bit of logic shows us that this is 2, Fizz, 4, Buzz, Fizz shuffled.

Your challenge is to take a range of FizzBuzz, shuffled, and put it in any order such that it's valid FizzBuzz. For example, given Fizz, Fizz, Buzz, 11 we can work out that the correct order is Fizz, Buzz, 11, Fizz (corresponding to 9, 10, 11, 12)

Input will always be rearrangeable into valid FizzBuzz.

You may choose any values that cannot appear as integers to represent Fizz, Buzz and FizzBuzz.

This is , shortest wins!

Testcases

1, 2, Fizz, 4, Buzz -> 1, 2, Fizz, 4, Buzz
Fizz, 4, Buzz, 1, 2 -> 1, 2, Fizz, 4, Buzz
Fizz, Fizz, Buzz, 11 -> Fizz, Buzz, 11, Fizz
Fizz, Buzz, 8, Buzz, 7, Fizz -> Buzz, Fizz, 7, 8, Fizz, Buzz
Buzz, Fizz -> either way
29, 31, FizzBuzz -> 29, FizzBuzz, 31
28, Fizz, FizzBuzz, 29 -> Fizz, 28, 29, FizzBuzz
8, 7 -> 7, 8

• "that cannot appear as integers"... Is negative integers valid?
– tsh
Jun 28 at 3:03
• @tsh yes, as are 3, 5, 15 etc. Jun 28 at 3:06
• What about cases with more than one valid solution? E.g. 8, Fizz, 7, Buzz, which could be Buzz, Fizz, 7, 8 or 7, 8, Fizz, Buzz. Jun 28 at 17:16

Vyxal, 21 15 bytes

ṖÞ∞ƛ₍₃₅T∨;ÞS$↔h  Try it Online! Why use clever mathematics when you can just generate infinite FizzBuzz? -6 thanks to Steffan and emanresuA Explained ṖÞ∞ƛ₍₃₅T∨;ÞS$↔h
Ṗ                # All permutations of the input
Þ∞              # An infinite list of positive integers starting at 1
ƛ     ;       # To each number n:
₍₃₅          #   [n % 3 == 0, n % 5 == 0]
T         #   Truthy indices of that
∨        #   Logical or that with the number. This gets either the indices of where Fizz or Buzz would usually be or n
ÞS      # Sublists of the infinite fizzbuzz
\$↔    # Remove sublists which don't have everything from the input
h   # Get the first item of that


J, 54 bytes

(-:&(/:~)"1#])#]\1((,~{~0=])2-@#.0=5 3|])@+#i.@+9>.>./


Try it online!

_1, _2, _3 represent Fizz, Buzz, FizzBuzz.

• Generate all integers from 1 to <list length> + max(9, <max value>)
• Fizz Buzz them
• Sliding window across them of size <list len>
• Find ones which set equal the input

JavaScript (ES6), 82 bytes

Saved 2 bytes thanks to a suggestion by @emanresuA

Expects and returns -1 for Fizz, -2 for Buzz, -3 for FizzBuzz.

f=(a,i=k=0)=>[...b=a.sort().map(_=>-!(++i%3)-2*!(i%5)||i)].sort()+''==a?b:f(a,++k)


Try it online!

The underlying algorithm is the same as in my answer to the twin challenge.

• There's probably a way to use something like -!i%3*2-!i%5 (but precedence is annoying) Jun 29 at 0:05
• @emanresuA That's shorter indeed. Thank you! Jun 29 at 0:12
• On a completely uninteresting side note, I'm especially fond of 82-byte one-liners because that's the threshold to have the code rendered without a scroll bar on my OS/browser with the current version of Code Golf. :-p Jun 29 at 0:21
• I try to limit my side-by-side Charcoal explanations to 79 characters wide for a similar reason.
– Neil
Jun 30 at 7:23

Charcoal, 55 bytes

ＷＳ⊞υι⮌⊟ΦＥ⁷ＥＥυ⁻⁺⌈ＥυΣ⁺ψνκμ∨⁺⎇﹪λ³ωFizz⎇﹪λ⁵ωBuzzＩλ⬤ι⁼№ιλ№υλ


Try it online! Link is to verbose version of code. Explanation:

ＷＳ⊞υι


Input the shuffled range.

⌈ＥυΣ⁺ψν


Calculate the largest integer in the range.

Ｅυ⁻⁺...κμ


Calculate a descending range of integers starting with that integer, but also offset by the outer loop index (see below).

Ｅ...∨⁺⎇﹪λ³ωFizz⎇﹪λ⁵ωBuzzＩλ


Calculate the FizzBuzz output for that range.

⮌⊟ΦＥ⁷...⬤ι⁼№ιλ№υλ


Calculate 7 ranges sliding up by 1 each time, and output one which matches the input, reversing it to put it back into order. (7 is needed for the edge case of Buzz Fizz.)

37 bytes for a boring numeric version:

Ｉ⮌⊟ΦＥ⁷ＥＥθ⁻⁺⌈θκμ∨±⁺¬﹪λ³⊗¬﹪λ⁵λ⬤ι⁼№ιλ№θλ


Try it online! Link is to verbose version of code. Uses -1 for Fizz, -2 for Buzz and -3 for Fizzbuzz.

05AB1E, 28 bytes

∞εD35SÖƶ(O‚0Kθ}Ig„üÿ.V.Δ{I{Q


Explanation:

∞               # Push the infinite positive list: [1,2,3,...]
ε              # Map each value to:
D             #  Duplicate the current value
35S          #  Push pair [3,5]
Ö         #  Check if the value is divisible by 3 and/or 5
ƶ        #  Multiply the check by their 1-based index
(       #  Negate them
O      #  Sum them (-1 if only divisible by 3; -2 if only 5; -3 if both;
#  0 if neither)
‚     #  Pair it with the current value
0K   #  Remove all 0s
θ  #  Pop and keep the last value
}              # Close the map
Ig            # Push the length of the input-list
„üÿ         # Push string "ü<length>"
.V       # Evaluate and execute it as 05AB1E code,
# ün created overlapping lists of size n
.Δ     # Then find the first which is truthy for:
{    #  If it's sorted
Q #  is equal to
I{  #  the sorted input-list


Python 3.8 (pre-release), 149 bytes

lambda a,e=enumerate:{p for p in permutations(a)if all(j in(l:=k+i-n,-(l%3<1)-2*(l%5<1))for k,j in e(p)for n,i in e(p)if i>0)}
from itertools import*


Try it online!

Uses -1 for Fizz, -2 for Buzz and -3 for FizzBuzz.

Returns all possible options.

The idea is to try all permutations and then, for each permutation, find the first integer in the list and check if the rest of the list agrees with that one.

Python3, 276 bytes:

def v(r,l,k=[]):
if any([r,l])==0:yield k;return
for i,a in enumerate(l):
if a==r[0]or(type(a)==str and r[0]%{'Fizz':3,'Buzz':5,'FizzBuzz':15}[a]==0):yield from v(r[1:],l[:i]+l[i+1:],k+[a])
def f(l):
c=0
while(c:=c+1):
if(V:=next(v([*range(c,c+len(l))],l),0)):return V


Try it online!

• 191, using 3, 5, and 15 instead of Fizz, Buzz, and FizzBuzz Jun 28 at 16:48