Jak skończyłem z tym FizzBuzz?

21

FizzBuzz jest tak prosty, że możesz to zrobić wstecz. W tym wyzwaniu otrzymasz długość ciągu FizzBuzz i musisz podać dodatnią liczbę całkowitą, która wytworzyła ten ciąg.

Opis

Aby to rozbić, ciąg FizzBuzz dla njest generowany przez następujący algorytm.

Zacznij od pustego ciągu i dla każdego i=1..n(włącznie):

  1. Jeśli ijest podzielna przez 3i 5dołącz FizzBuzzdo łańcucha.
  2. Jeśli ijest podzielne przez 3append Fizz.
  3. Jeśli ijest podzielne przez 5append Buzz.
  4. Jeśli nie imożna podzielić przez żadną, dołącz dziesiętną reprezentację i.

Na przykład FizzBuzz(15):

12Fizz4BuzzFizz78FizzBuzz11Fizz1314FizzBuzz

Otrzymasz Length(FizzBuzz(n))i musisz ustalić n. Możesz założyć, że dane wejściowe są dodatnie i zawsze będą miały długość niektórych ciągów FizzBuzz.

Zasady

Twoje rozwiązanie może zawierać pełną definicję programu lub funkcji w dowolnym standardowym języku. Twój program / funkcja może przyjmować argumenty i zwracać odpowiedzi w dowolny standardowy sposób . Standardowe luki są zabronione.

Możesz założyć, że dane wejściowe są dodatnie i prawidłowe (opisuje długość niektórych ciągów FizzBuzz) i są mniejsze niż największa liczba całkowita reprezentatywna dla twojego języka.

To jest golf golfowy, więc wygrywa najkrótsza liczba bajtów.

Przykłady

Oto kilka przykładowych przypadków

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

Edytować

Naprawiono ostatni przypadek testowy. Dzięki @SteadyBox.

walpen
źródło
Argh! Próbowałem wykonać rekursję, ale moje liczby były zbyt duże ...
0WJYxW9FMN
Związane . Związane .
Cyfrowa trauma
3
@Toto Jak to jest duplikat?
AdmBorkBork
1
@Toto To wcale nie jest duplikat. Może powinieneś przeczytać o tym, co oznacza bycie duplikatem.
mbomb007

Odpowiedzi:

8

Galaretka ,  16  14 bajtów

2 bajty zapisane przy użyciu nowszych funkcji językowych )dla µ€i Ädla+\

3,5ḍS×4oDL$)Äi

Wypróbuj online! lub zobacz przypadki testowe .

W jaki sposób?

Tworzy listę długości każdego elementu od 1wejścia, zmniejsza przez dodanie, a następnie znajduje na liście indeks oparty na jednym wejściu. (Oznacza to również, że nieprawidłowe dane wejściowe powodują 0„brak na liście”).

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
          $    - last two links as a monad
        D      -     to decimal digit list
         L     -     length - e.g. 313 -> [3,1,3] -> 3
       o       - logical or: replace a 0 with the decimal length, keep the 4s and 8s
            Ä  - reduce with addition: e.g. [1,1,4,1, 4, 4, 1, 1, 4, 4, 2, 4, 2 ,2, 8]
                                         -> [1,2,6,7,11,15,16,17,21,25,27,31,33,35,43]
             i - index of theLength in that list (e.g. 15 is at index 6)
Jonathan Allan
źródło
11

C, 81 78 bajtów

l,i;f(n){for(l=i=0;l<n;l+=++i%3?i%5?snprintf(0,0,"%d",i):4:i%5?4:8);return i;}

68 bajtów, jeśli nie masz nic przeciwko konwersji do doublei z powrotem:

l,i;f(n){for(l=i=0;l<n;l+=++i%3?i%5?log10(i)+1:4:i%5?4:8);return i;}
Steadybox
źródło
Czy „return i” jest nawet wymagane, gdy „i” jest zmienną globalną? -) I możesz zastąpić to długie wywołanie snprintf log10 (i) +1, jeśli to się kompiluje i jest dozwolone ... To działało dla mnie z gcc -lm
Rennex
@Rennex Jest return i;to potrzebne, ponieważ jest to powszechnie akceptowany sposób wyświetlania kodu w golfie, podczas gdy modyfikowanie tylko zmiennej globalnej nie jest. Zastanawiałem się nad użyciem log10(i)+1, ale pomyślałem, że może to powodować pewne problemy z powodu konwersji na podwójne i wstecz (np. pow(i)Nie jest wiarygodny z liczbami całkowitymi). Wydaje się jednak, że teraz działa dobrze dla wszystkich dodatnich wartości, które intmoże reprezentować, więc prawdopodobnie mógłbym go użyć. (Przy wartościach większych niż zwykła intmoże wytrzymać, czasami się nie udaje, ale to nie ma znaczenia tutaj.)
Steadybox
Hmm ok. Jestem nowy w tym kodzie golfowym, ale spojrzałem na link do reguł w pytaniu i mówi on: „Funkcje mogą generować, modyfikując swoje argumenty lub zapisując je na zewnątrz”. Czy to nie znaczy, że można użyć przynajmniej argumentu wskaźnika wyniku?
Rennex
@Rennex Tak, myślę, że mógłbym wziąć nwskaźnik jako wskaźnik, a następnie po prostu zmodyfikować wartość, na którą wskazuje na końcu, ale to wymagałoby więcej kodu w witrynie wywoływania, aby móc wydrukować wartość, więc czuję się trochę jak dla mnie oszustwo.
Steadybox
6

MATL , 31 28 27 bajtów

`@:tI5h!\XJA)VXznJ~z4*+G-}@

Wypróbuj online!

Wyjaśnienie

`        % Do...while
  @:     %   Push array [1 2 ...k], where k is iteration index
  t      %   Duplicate  
  I5h!   %   Push column vector [3; 5]
  \      %   Modulo, with broadcast. Gives 2 × k matrix
  XJ     %   Copy into clipboard J
  A      %   Row vector that contains true for columns that contain two nonzeros
  )      %   Index with that vector. This keeps numbers that are non-fizz/buzz
  V      %   Convert to string. This inserts spaces between numbers
  Xzn    %   Number of nonspace characters
  J      %   Push 2 × k matrix resulting from modulo operation again
  ~z     %   Number of zeros
  4*     %   Multiply by 4. Gives number of characters corresponding to fizz/buzz
  +      %   Add
  G-     %   Subtract input. This is the loop condition: exit if 0
}        % Finally (execute right before exiting loop)
  @      %   Push current iteration index
         % End (implicit)
         % Display (implicit)
Luis Mendo
źródło
4

Mathematica, 67 bajtów

(For[n=s=0,s<#,s+=Tr[4Boole[{3,5}∣++n]]/. 0:>IntegerLength@n];n)&

Jest to zarówno szybsze, jak i krótsze niż moje początkowe rozwiązanie:

1//.x_/;Sum[Tr[4Boole[{3,5}∣n]]/. 0:>IntegerLength@n,{n,x}]!=#:>x+1&

lub moja desperacka próba skrócenia:

(s=0;1)//.x_/;(s+=Tr[4Boole[{3,5}∣x]]/. 0:>IntegerLength@x)!=#:>x+1&

Wyjaśnienie

Standardowa Forpętla, której wartość rośnie ndo s := Length(FizzBuzz(n))co najmniej równej wartości wejściowej #. Jedynym interesującym bitem jest sposób, w jaki obliczam długość (n+1)-tego składnika sekwencji FizzBuzz

                ++n                           Preincrement n
          {3,5}∣                              Test for divisibility by 3 and 5 (returns a list)
    Boole[         ]                          Convert True to 1 and False to 0
   4                                          Multiply by 4
Tr[                 ]                         Sum
                     /.                       Replace
                        0                     0 (leading space is necessary or it thinks we are dividing by 0.0)
                         :>                   with
                           IntegerLength@n    the number of digits in n
ngenisis
źródło
3

MATL, 31 30 28 bajtów

:tI5h!\~s4*t~b10&YlkQ*+YsG=f

Używa tego samego pomysłu, co rozwiązanie galaretki Jonathana Allena.

Wypróbuj na matl.suever.net !

B. Mehta
źródło
Do 28 lat! : -Myślę, że nasze podejście jest teraz bardziej podobne
Luis Mendo
Dobra robota! Tak, wygląda na to :)
B. Mehta
3

Java 8, 100 97 bajtów

Gra w golfa:

l->{int i=0;for(String s="";s.length()<l;)s+=++i%15<1?"12345678":i%5<1||i%3<1?"1234":i;return i;}

Nie golfowany:

import java.util.function.*;

public class HowDidIEndUpWithThisFizzBuzz {

  public static void main(String[] args) {
    for (final int[] data : new int[][] { { 1, 1 }, { 6, 3 }, { 15, 6 },
        { 313, 100 }, { 3677, 1001 } }) {
      final int fizzBuzzLength = data[0];
      final int expected = data[1];
      final int actual = f(l -> {
        int i = 0;
        for (String s = ""; s.length() < l;) {
          s += (++i % 15 < 1 ? "12345678" : (i % 5 < 1 || i % 3 < 1 ? "1234" : i));
        }
        return i;
      } , fizzBuzzLength);
      System.out.println("Length(FizzBuzz(n)) -> " + fizzBuzzLength);
      System.out.println("Expected            -> " + expected);
      System.out.println("Actual              -> " + actual);
      System.out.println();
    }

  }

  private static int f(IntFunction<Integer> function, int fizzBuzzLength) {
    return function.apply(fizzBuzzLength);
  }
}

Wydajność:

Length(FizzBuzz(n)) -> 1
Expected            -> 1
Actual              -> 1

Length(FizzBuzz(n)) -> 6
Expected            -> 3
Actual              -> 3

Length(FizzBuzz(n)) -> 15
Expected            -> 6
Actual              -> 6

Length(FizzBuzz(n)) -> 313
Expected            -> 100
Actual              -> 100

Length(FizzBuzz(n)) -> 3677
Expected            -> 1001
Actual              -> 1001

źródło
2

JavaScript (ES6), 62 57 bajtów

f=(n,k=0)=>n?f(n-(++k%3?k%5?`${k}`.length:4:k%5?4:8),k):k

Przypadki testowe

Arnauld
źródło
Alternatywna ekspresja przy tej samej długości: (!(++k%3)+!(k%5)<<2||`${k}`.length).
Neil
2

JavaScript (ES6), 56 bajtów

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>

nderscore
źródło
2

Python 3, 78 bajtów

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))))

Funkcja rekurencyjna. Będzie wymagał zwiększenia limitu rekurencji dla każdego wyniku powyżej 1000.

Wyjaśnienie:

# 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))))
Triggernometria
źródło
1

Python, 93 bajty

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
użytkownik65823
źródło
1

k, 33 bajtów

{1+&x=+\{(#$x;4;8)+/~3 5!'x}'1+!x}

Krótkie wyjaśnienie (python-ish):

{                                } / 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

Przykład użycia 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
zgrep
źródło
Witamy w Programowaniu Puzzle i Code Golf! Właśnie dlatego wiesz, że głos głosowania został automatycznie przesłany przez użytkownika społeczności podczas edycji odpowiedzi. Uważam to za błąd .
Dennis
1

dc , 76 70 bajtów

?sa0dsbsc[lc4+sc]sh[lbZ+sc]so[lcdlb1+ddsb3%0=h5%0=hlc=olcla!=y]dsyxlbp

Wypróbuj online!

R. Kap
źródło
1

Rubinowy, 69 66 bajtów

->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}

Początkowo unikałem potworności zagnieżdżonego operatora potrójnego i zszedłem do 69 bajtów:

->n{i=0;(i+=1;n-=(x=[i%3,i%5].count 0)>0?4*x:i.to_s.size)while n>0;i}
Rennex
źródło
1

Java 8, 95 93 bajtów

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;}

To jest zoptymalizowana wersja odpowiedzi @ Snowman

Roman Gräf
źródło
Zwraca to nieprawidłowe wyniki dla mnie w dwóch ostatnich przypadkach testowych: 75 zamiast 100 i 686 zamiast 1001.
1

Groovy, 76 bajtów

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;}

Przeważnie to samo co odpowiedź @ Snowman , ale wykorzystuje trochę Groovy magii / różnic, aby zmniejszyć liczbę bajtów.

TheJizel
źródło
0

Perl 6 , 55 52 bajtów

{1+first $_,:k,[\+] map {4*($_%%3+$_%%5)||.chars},1..*}

{(0,{my \i=++$;$_+(4*(i%%3+i%%5)||i.chars)}...$_)-1}

Wypróbuj online!

Jak to działa

{                                                  }  # 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.
smls
źródło
0

Japt , 20 bajtów

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

Spróbuj

@µ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
Kudłaty
źródło
0

Perl 5 -p , 48 bajtów

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

Wypróbuj online!

Xcali
źródło
0

C (gcc) , 68 bajtów, stdoutspamowanie

  • Dzięki H.PWiz za to podejście, oszczędzając sześć bajtów.
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;}

Wypróbuj online!


C (gcc) , 74 bajty

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;}

Wypróbuj online!

Jonathan Frech
źródło
0

05AB1E , 17 bajtów

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

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

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)
Kevin Cruijssen
źródło