Como eu acabei com este FizzBuzz?


21

O FizzBuzz é muito simples, aposto que você pode fazer isso ao contrário. Neste desafio, você receberá o comprimento da sequência do FizzBuzz e deverá fornecer o número inteiro positivo que produziu essa sequência.

Descrição

Para dividir isso, uma string do FizzBuzz para né gerada pelo seguinte algoritmo.

Comece com uma string vazia e, para cada i=1..n(inclusive):

  1. Se ié divisível por 3e por 5, acrescente FizzBuzzà sequência.
  2. Se ié apenas divisível por 3acréscimo Fizz.
  3. Se ié apenas divisível por 5acréscimo Buzz.
  4. Se não ié divisível por nenhum, acrescente a representação decimal de i.

Então, por exemplo, FizzBuzz(15)é o seguinte:

12Fizz4BuzzFizz78FizzBuzz11Fizz1314FizzBuzz

Você será dado Length(FizzBuzz(n))e deve determinar n. Você pode assumir que a entrada é positiva e sempre terá o comprimento de alguma string do FizzBuzz.

Regras

Sua solução pode ser um programa completo ou uma definição de função em qualquer idioma padrão aceitável. Seu programa / função pode receber argumentos e retornar respostas de qualquer maneira aceita de maneira padrão . As brechas padrão são proibidas.

Você pode assumir que a entrada é positiva e válida (descreve o comprimento de alguma string do FizzBuzz) e é menor que o maior número inteiro representável nativamente no seu idioma.

Este é o código de golfe, portanto, o menor número de bytes vence.

Exemplos

Aqui estão alguns exemplos de casos

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

Editar

Corrigido o último caso de teste. Obrigado @SteadyBox.


Argh! Eu tentei fazer recursão mas meus números eram muito grandes ...
0WJYxW9FMN


3
@Toto Como isso é uma duplicata?
AdmBorkBork 22/02

11
@Toto Isso não é uma duplicata. Talvez você devesse ler o que significa ser uma duplicata.
Mbomb007

Respostas:


8

Geléia ,  16  14 bytes

2 bytes salvos usando recursos de idioma mais recentes )para µ€e Äpara+\

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

Experimente online! ou veja os casos de teste .

Quão?

Cria uma lista dos comprimentos de cada item da 1entrada, reduz por adição e localiza o índice baseado em uma entrada na lista. (Isso também significa que uma entrada inválida resulta em 0"fora da lista").

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)

11

C, 81 78 bytes

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 bytes se você não se importa em converter para doublee voltar:

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

O "return i" é necessário, mesmo quando "i" é uma variável global? -) E você pode substituir a chamada snprintf longa por um log10 (i) +1, se isso compilar e for permitido ... gcc -lm
Rennex 23/02

@Rennex O return i;é necessário, porque essa é uma maneira aceita como padrão de saída no código golf, enquanto apenas a modificação de uma variável global não é. Pensei em usar log10(i)+1, mas achei que isso poderia causar alguns problemas devido à conversão para duplo e para trás (por exemplo, pow(i)não é confiável com números inteiros). Parece agora que funciona bem para todos os valores positivos que um intpode representar, então eu provavelmente poderia usá-lo. (Com valores maiores do que um simples intpode conter, às vezes falha, mas isso não importa aqui.)
Steadybox

Hmm, ok. Eu sou novo nesse código de golfe, mas observei o link de regras na pergunta e ele diz "Funções podem resultar modificando seus argumentos ou escrevendo para argumentos". Isso não significa que pelo menos um argumento de ponteiro de resultado possa ser usado?
Rennex

@Rennex Sim, acho que eu poderia usar o nponteiro como ponteiro e apenas modificar o valor para o qual está apontando no final, mas isso exigiria mais código no site da chamada para poder imprimir o valor, para que ele pareça um pouco como me traindo.
Steadybox

6

MATL , 31 28 27 bytes

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

Experimente online!

Explicação

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

4

Mathematica, 67 bytes

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

Isso é mais rápido e mais curto que minha solução inicial:

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

ou minha tentativa desesperada de encurtá-lo:

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

Explicação

ForLoop padrão que é incrementado naté que s := Length(FizzBuzz(n))seja pelo menos igual à entrada #. A única parte interessante é como eu calculo a duração do (n+1)-ésimo termo da sequência do 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

3

MATL, 31 30 28 bytes

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

Usa a mesma idéia que a solução Jelly de Jonathan Allen.

Experimente no matl.suever.net !


Até 28 agora! : -PI acho que nossas abordagens são mais semelhantes agora
Luis Mendo

Ah, bom trabalho! Sim, parece que :)
B. Mehta

3

Java 8, 100 97 bytes

Golfe:

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

Ungolfed:

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

Saída:

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

2

JavaScript (ES6), 62 57 bytes

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

Casos de teste


Expressão alternativa com o mesmo comprimento: (!(++k%3)+!(k%5)<<2||`${k}`.length).
Neil

2

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>


2

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

Função recursiva. Será necessário aumentar o limite de recursão para qualquer resultado acima de 1000.

Explicação:

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

1

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

1

k, 33 bytes

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

Breve explicação (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

Exemplo usando o 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

Bem-vindo à programação de quebra-cabeças e código de golfe! Para que você saiba, o voto negativo foi convertido automaticamente pelo usuário da Comunidade quando a resposta foi editada. Eu considero isso um bug .
Dennis


1

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}

Originalmente, eu estava evitando a monstruosidade do operador ternário aninhado e cheguei a 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}

1

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

Esta é a versão otimizada da resposta de @ Snowman


Isso retorna resultados incorretos para mim nos dois casos de teste finais: 75 em vez de 100 e 686 em vez de 1001. #

1

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

Principalmente o mesmo que a resposta de @ Snowman , mas usa algumas mágicas / diferenças do Groovy para reduzir a contagem de bytes.


0

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}

Experimente online!

Como funciona

{                                                  }  # 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.

0

Japonês , 20 bytes

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

Tente

@µ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



0

05AB1E , 17 bytes

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

Experimente online ou verifique todos os casos de teste .

Explicação:

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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.