How did I end up with this FizzBuzz?

FizzBuzz is so simple, bet you can do it backwards. In this challenge, you will be given the length of the FizzBuzz string and must give the positive integer that produced that string.

Description

To break this down, a FizzBuzz string for n is generated by the following algorithm.

Start with an empty string and, for every i=1..n (inclusive):

1. If i is divisible by 3 and by 5, append FizzBuzz to the string.
2. If i is just divisible by 3 append Fizz.
3. If i is just divisible by 5 append Buzz.
4. If i is divisible by neither, append the decimal representation of i.

So for example FizzBuzz(15) is the following:

12Fizz4BuzzFizz78FizzBuzz11Fizz1314FizzBuzz

You will be given Length(FizzBuzz(n)) and must determine n. You may assume that the input is positive and is always going to be the length of some FizzBuzz string.

Rules

Your solution may a complete program or a function definition in any standardly acceptable language. Your program/function may take in arguments and return answers in any standardly accepted way. Standard loopholes are forbidden.

You may assume that the input is positive and valid (describes the length of some FizzBuzz string) and is smaller than the largest integer representable natively in your language.

This is code golf, so shortest byte-count wins.

Examples

Here are some example cases

Length(FizzBuzz(n)) -> n
1                   -> 1
6                   -> 3
15                  -> 6
313                 -> 100
3677                -> 1001

Edit

Fixed last test case. Thanks @SteadyBox.

• Argh! I tried to do recursion but my numbers were too big... – 0WJYxW9FMN Feb 21 '17 at 21:09
• – Digital Trauma Feb 21 '17 at 21:19
• @Toto How is this a duplicate? – AdmBorkBork Feb 22 '17 at 13:30
• @Toto This is not at all a duplicate. Maybe you should read up on what being a duplicate means. – mbomb007 Feb 22 '17 at 14:34

Jelly,  16  14 bytes

2 bytes saved using more recent language features ) for µ€ and Ä for +\

3,5ḍS×4oDL$)Äi Try it online! or see the test cases. How? Builds a list of the lengths of every item from 1 to the input, reduces by addition and then finds the one-based index of the input in the list. (This also means an invalid input results in 0, "not in list"). 3,5ḍS×4oDL$)Äi - Main link: theLength
)    - perform the chain to the left for each (€) in
implicit range from 1 to the input and
pass the result into the monadic chain (µ) to the right
3,5            - 3 paired with 5: [3,5]
ḍ           - divides?  for a multiple of 15 [1,1]; sum = 2; times 4 = 8
S          - sum       for a multiple of  5 [0,1]; sum = 1; times 4 = 4
×4        - times 4   for a multiple of  3 [1,0]; sum = 1; times 4 = 4
for none of those    [0,0]; sum = 0; times 4 = 0

Test cases

f=(n,k=0)=>n?f(n-(++k%3?k%5?${k}.length:4:k%5?4:8),k):k console.log(f(1 )); // -> 1 console.log(f(6 )); // -> 3 console.log(f(15 )); // -> 6 console.log(f(313 )); // -> 100 console.log(f(3677)); // -> 1001 • Alternative expression with the same length: (!(++k%3)+!(k%5)<<2||${k}.length). – Neil Feb 22 '17 at 8:44

Javascript (ES6), 56 bytes

f=(x,s=i=0)=>s[x]?i:f(x,s+[++i%3?i%5?i:1e3:i%5?1e3:1e7])
<!-- snippet demo: -->
<input list=l oninput=console.log(f(this.value))>
<datalist id=l><option value=1><option value=6><option value=15><option value=313><option value=3677></datalist>

Python 3, 78 bytes

f=lambda i,n=1,s=0:~-n*(s==i)or f(i,n+1,s+(4*((n%3<1)+(n%5<1))or len(str(n))))

Recursive function. Will need the recursion limit increased for any result above 1000.

Explanation:

# i = length of final string
# n = current number in sequence, starting with 1
# s = length of current string, starting with 0
f=lambda i,n=1,s=0: \

# if s==1, this will evaluate to n+1, which is NOT 0, and will return
# else, it will evaluate to (n+1)*0, and trigger the second half of the OR clause
~-n*(s==i)or \

# recursively call the next iteration, with the next number in the sequence
f(i,n+1, \

# increase s by 4 if Fizz or Buzz, 8 if FizzBuzz, or len(n) if number
s+(4*((n%3<1)+(n%5<1))or len(str(n))))

Python, 93 bytes

def g(n,c=0,a=[4,0]):
while n:c+=1;s=a[c%3>0]+a[c%5>0];s+=(s<1)*len(str(c));n-=s
return c

k, 33 bytes

{1+&x=+\{(#$x;4;8)+/~3 5!'x}'1+!x} Brief (python-ish) explanation: { } / function(x): 1+!x / array from 1 to x, inclusive ' / for y in array: { } / function(y): (#$x;4;8)                 /       yield [ len(str(y), 4, 8 ][
+/~3 5!'x        /         sum([not(y mod 3), not(y mod 5)])
/       ]
+\                           /   cumulative sum of result of for loop
1+&x=                             /   get index of x in cumulative sum, add one

Example using kmac 2016.06.28:

f:{1+&x=+\{(#$x;4;8)+/~3 5!'x}'1+!x} ,/f'1 6 15 313 3677 1 3 6 100 1001 • Welcome to Programming Puzzles & Code Golf! Just so you know, the downvote was cast automatically by the Community user when the answer was edited. I consider this a bug. – Dennis Feb 22 '17 at 19:51 dc, 76 70 bytes ?sa0dsbsc[lc4+sc]sh[lbZ+sc]so[lcdlb1+ddsb3%0=h5%0=hlc=olcla!=y]dsyxlbp Try it online! Ruby, 69 66 bytes ->n{i=0;(i+=1;n-=i%3>0?i%5>0?i.to_s.size: 4:i%5>0?4:8)while n>0;i} Originally, I was avoiding the nested ternary operator monstrosity and got down to 69 bytes: ->n{i=0;(i+=1;n-=(x=[i%3,i%5].count 0)>0?4*x:i.to_s.size)while n>0;i} Java 8, 95 93 bytes l->{int j=0,i=0;for(;j<l;)j+=++i%15<1?8:i%3<1||i%5<1?4:Math.floor(Math.log10(i)+1);return i;} This is the optimized version of @Snowman's answer • This returns incorrect results for me on the final two test cases: 75 instead of 100, and 686 instead of 1001. – user18932 Feb 22 '17 at 19:09 Groovy, 76 bytes def f(n){i=0;for(s='';s.size()<n;)s+=++i%15<1?"1"*8:i%5<1||i%3<1?"1"*4:i;i;} Mostly the same as @Snowman's answer, but uses some Groovy magic/differences to cut down on the byte count. Perl 6, 55 52 bytes {1+first$_,:k,[\+] map {4*($_%%3+$_%%5)||.chars},1..*}

{(0,{my \i=++$;$_+(4*(i%%3+i%%5)||i.chars)}...$_)-1} Try it online! How it works { } # A lambda. 0 # Start with 0. ,{ } # Use the iteration formula... my \i=++$;                                       #   Fetch current index.
$_+( ) # Last element plus: 4*(i%%3+i%%5) # Fizz/Buzz/FizzBuzz length, ||i.chars # or number length. ...$_      # ...until the input is reached.
(                                              )-1   # Sequence length minus 1.

Japt, 20 bytes

@µ35ìx_XvZÃ*4ªXìÊ}f1

Try it

@µ35ìx_XvZÃ*4ªXìÊ}f1     :Implicit input of integer U
@                        :Function taking an integer X as argument
µ                       :  Decrement U by
35ì                    :    Digit array of 35
x                   :    Reduce by addition
_                  :    After passing each Z through the following function
XvZ               :      Is X divisible by Z?
Ã              :    End reduce
*4            :    Multiply by 4
ª           :    Logical OR with
Xì         :      Digit array of X
Ê        :      Length
}       :End function
f1     :First integer >=1 that returns a falsey value (i.e, 0) when passed through that function

Perl 5-p, 48 bytes

$\++;($_-=4*(!($\%3)+!($\%5))||length\$\)&&redo}{

Try it online!

C (gcc), 68 bytes, stdout-spamming

• Thanks to H.PWiz for this approach, saving six bytes.
f(n,j,r){for(r=j=0;!r;r=!n*j)n-=++j%3?j%5?printf("%d",j):4:j%5?4:8;}

Try it online!

C (gcc), 74 bytes

f(n,j,r){for(r=j=0;!r;r=!n*j)n-=++j%3?j%5?snprintf(0,0,"%d",j):4:j%5?4:8;}

Try it online!

05AB1E, 17 bytes

Lε35SÖ4*OygM}.¥sk

Explanation:

L          # Create a list in the range [1, (implicit) input]
#  i.e. 15 → [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
ε         # Map each value to:
35S      #  Push 35 as digit list: [3,5]
Ö     #  Check if the current value is divisible by these (1 if truthy; 0 if falsey)
4*   #  Multiply both by 4
O  #  And take the sum of that
#   i.e. 2 → [0,0] → [0,0] → 0
#   i.e. 9 → [1,0] → [4,0] → 4
#   i.e. 10 → [0,1] → [0,4] → 4
#   i.e. 15 → [1,1] → [4,4] → 8
yg       #  Push the current value again, and pop and push it's length
#   i.e. 2 → 1
#   i.e. 15 → 2
M        #  And then push the largest value on the stack
#   i.e. 0 and 1 → 1
#   i.e. 8 and 2 → 8
}.¥       # After the map: undelta the list (starting from 0)
#  i.e. [1,1,4,1,4,4,1,1,4,4,2,4,2,2,8]
#   → [0,1,2,6,7,11,15,16,17,21,25,27,31,33,35,43]
sk     # Swap to get the (implicit) input, and get its 0-based index in the list
#  i.e. 15 → 6
# (after which the result is output implicitly)