Sequência DeciDigits Triangular (de KevinC)


19

Entrada:

Um número inteiro positivo n que é 1 <= n <= 25000.

Resultado:

  1. Nesta sequência, começamos com o número decimal 1 / n .
  2. Em seguida, tomar a soma dos dígitos até o n 'th dígitos depois da vírgula (1-indexado); seguido pela soma dos dígitos até ( n -1) 'ª, depois ( n -2)' ª, etc. Continue até n ser 1.
  3. A saída é a soma de tudo isso combinado.

Por exemplo:

n = 7
1/7 = 0.1428571428...
7th digit-sum = 1+4+2+8+5+7+1 = 28
6th digit-sum = 1+4+2+8+5+7 = 27
5th digit-sum = 1+4+2+8+5 = 20
4th digit-sum = 1+4+2+8 = 15
3rd digit-sum = 1+4+2 = 7
2nd digit-sum = 1+4 = 5
1st digit     = 1
Output = 28+27+20+15+7+5+1 = 103

Regras do desafio:

  • Se o decimal de 1 / n não tiver n dígitos após a vírgula, os que faltam serão contados como 0 (ou seja 1/2 = 0.50 => (5+0) + (5) = 10).
  • Você pega os dígitos sem arredondar (ou seja, os dígitos de 1/6são 166666e não 166667)

Regras gerais:

  • Aplicam-se regras padrão à sua resposta, para que você possa usar STDIN / STDOUT, funções / método com os parâmetros adequados, programas completos. Sua chamada.
  • As brechas padrão são proibidas.
  • Se possível, adicione um link com um teste para o seu código.
  • Além disso, adicione uma explicação, se necessário.

Primeiro 1 - 50 na sequência:

0, 10, 18, 23, 10, 96, 103, 52, 45, 10, 270, 253, 402, 403, 630, 183, 660, 765, 819, 95, 975, 1034, 1221, 1500, 96, 1479, 1197, 1658, 1953, 1305, 1674, 321, 816, 2490, 2704, 4235, 2022, 3242, 2295, 268, 2944, 3787, 3874, 4097, 1980, 4380, 4968, 3424, 4854, 98

Últimos 24990 - 25000 na sequência:

1405098782, 1417995426, 1364392256, 1404501980, 1408005544, 1377273489, 1395684561, 1405849947, 1406216741, 1142066735, 99984

8
Alguém mencionou meu nome?
Kevin

Respostas:


6

Geléia , 9 bytes

R⁵*:%⁵+\S

Um pouco lento, mas curto. Experimente online! ou verifique os 50 primeiros casos de teste .

Como funciona

R⁵*:%⁵+\S  Main link. Argument: n

R          Range; yield [1, ..., n].
 ⁵*        10 power; yield [10**1, ..., 10**n].
   :       Divide each power by n.
    %⁵     Take each quotient modulo 10.
           This yields all desired decimal digits.
      +\   Take the cumulative sum of the digits.
        S  Take the sum.

15

Mathematica, 42 bytes

#&@@RealDigits[1/#,10,#,-1].(#-Range@#+1)&

ou

#&@@RealDigits[1/#,10,#,-1].Range[#,1,-1]&

ou

Tr@Accumulate@#&@@RealDigits[1/#,10,#,-1]&

Explicação

Veja o exemplo da especificação do desafio. Queremos calcular:

  1+4+2+8+5+7+1
+ 1+4+2+8+5+7
+ 1+4+2+8+5
+ 1+4+2+8
+ 1+4+2
+ 1+4
+ 1

Reorganizando, isto é:

  1*7 + 4*6 + 2*5 + 8*4 + 5*3 + 7*2 + 1*1
= (1, 4, 2, 8, 5, 7, 1) . (7, 6, 5, 4, 3, 2, 1)

onde .é o produto escalar de dois vetores.

Isso é praticamente toda a solução.

#&@@RealDigits[1/#,10,#,-1]

Isso nos fornece os primeiros Ndígitos decimais de 1/N( #&@@extrai o primeiro elemento doRealDigits resultado, porque isso também retorna o deslocamento do primeiro dígito com o qual não nos importamos).

Em seguida, reduzimos a lista Npara 1usar (#-Range@#+1)ou Range[#,1,-1], que são mais curtos que Reverse@Range@#, e utilizamos o produto escalar.

Em vez disso, a solução alternativa usa Accumulatepara calcular uma lista de todas as somas de prefixo e, em seguida, adiciona essas somas de prefixo Tr.

Como isso é realmente rápido, mesmo para entradas grandes, aqui está um gráfico de dispersão da sequência até N = 100,000(fazer todas elas e plotá-las levou um tempo):

insira a descrição da imagem aqui
Clique para uma versão maior.

A linha azul é o limite superior ingênuo de 9 N (N+1) / 2(se todos os dígitos decimais forem9 ) e a linha laranja é exatamente a metade disso. Sem surpresa, isso está dentro do ramo principal do gráfico, pois, estatisticamente, esperamos que o dígito médio seja 4,5.

A fina linha de pontos de plotagem que você pode ver abaixo do ramo principal são frações que terminam ...3333..., pois estão todas muito próximas 3 N (N+1) / 2.


Resposta muito boa, e eu amo o gráfico! É quase lamentável que não seja o mais curto e não posso aceitá-lo como resposta. :) Se eu não esquecer, posso fazer uma pequena recompensa em dois dias por responder muito mais do que a simples tarefa que dei.
Kevin Cruijssen 14/10

11
@KevinCruijssen Thanks! :)
Martin Ender

6

05AB1E , 12 11 bytes

Di<ë°¹÷.pSO

Experimente online! ou um conjunto de testes para os 50 primeiros números.

Explicação

              # implicit input n
Di<           # if n == 1 then 0
   ë          # else
    °¹÷       # 10^n // n
       .p     # get prefixes
         SO   # sum digits

Uma versão mais eficiente para experimentar grandes números no TIO

A diferença para a versão mais curta é que aqui somamos o produto dos dígitos e a reversão de seu índice baseado em 1 em vez de somar dígitos em prefixos.

Di<ë°¹÷SDgLR*O

Experimente online!


5

Java 8, 181 169 166 153 142 bytes

import java.math.*;n->{int m=n+2,r=0,i;for(;m>2;)for(i=m--;i-->2;r+=(BigDecimal.ONE.divide(new BigDecimal(n),n,3)+"").charAt(i)-48);return r;}

Explicação:

Experimente aqui.

import java.math.*;   // Required import for BigDecimal

n->{                  // Method with integer as both parameter and return-type
  int m=n+2,          //  Copy of the input-integer plus 2
      r=0,            //  Result-integer, starting at 0
      i;              //  Index-integer
  for(;m>2;)          //  Loop (1) as long as `m` is larger than 2
    for(i=m--;        //   Set index `i` to `m`, and decrease `m` by one afterwards
        i-->2;        //   Inner loop (2) from `m` down to 2 (inclusive)
      r+=             //    Add to the result-sum:
         (BigDecimal.ONE.divide(
                      //     1 divided by,
           new BigDecimal(n),
                      //     the input
           n,3)       //     With the minimal required precision
          +"")        //     Convert this to a String
          .charAt(i)  //     Take the character of this String at index `i`
          -48         //     And convert it to a number
     );               //   End of inner loop (2)
                      //  End of loop (1) (implicit / single-line body)
  return r;           //  Return result
}                     // End of method

4

PHP, 66 65 bytes

for($b=$c=$argv[$a=1];$c;)$o+=$c--*(($a=10*($a%$b))/$b^0);echo$o;

Adaptado desta resposta (também por mim): Divisão de números não tão pequenos e a edição sugerida por Jörg Hülsermann. Use como:

php -r "for($b=$c=$argv[$a=1];$c;)$o+=$c--*(($a=10*($a%$b))/$b^0);echo$o;" 7

edit: corrigiu um bug para +1 bytes e dobrou a atribuição de $ a em $ argv [1] para -2 bytes para uma rede de 1 byte a menos.


3

Scala, 84 bytes

val b=BigDecimal
def?(& :Int)=1 to&map(x=>(""+b(1)/b(&))slice(2,x+2)map(_-48)sum)sum

Ungolfed:

def f(n: Int)={
  val digits = ""+BigDecimal(1)/BigDecimal(n)
  (1 to n).map( x=>
    digits.slice(2, x+2).map(d => d - 48).sum
  ).sum

Explicação:

val b=BigDecimal   //define an alias for BigDecimal
def?(& :Int)=      //define a method called ? with an integer & as a parameter
  1 to &           //create a range from 1 to &
  map(x=>          //for each number x...
    (""+b(1)/b(&))   //calculate the fraction
    slice(2,x+2)     //and take the slice starting from the third element,
                     //(dropping the "1.") and containing x elements
    map(_-48)        //for each char, subtract 48 to get the integer value
    sum              //and sum them
  )sum             //and take the sum

Eu poderia salvar alguns bytes explorando a maneira como o compilador tokeniza: Ao chamar o argumento &, você pode escrever em 1 to&mapvez de 1 to n map. A mesma regra se aplica a def?.


3

Gelatina , 11 bytes

’aµR⁵*:µDFS

TryItOnline
Primeiros 50

Muito lento para os grandes casos de teste.

Quão?

’aµR⁵*:µDFS - Main link: n
’           - decrement
 a          - and (to handle special case where n=1, to return 0 rather than 10)
  µ         - monadic chain separation
   R        - range: [1,2,...n]
    ⁵       - literal 10
     *      - exponentiation: [10,100,...,10^n]
      :     - integer division: [10//n,100//n,...,10^n//n]
       µ    - monadic chain separation
        D   - cast to a decimal list [[digits of 10//n],[digits of 100//n],...]
         F  - flatten into one list
          S - sum

2
Eu não acho que eu já visto antes uma resposta Jelly onde a explicação é uma linha reta ;-)
ETHproductions

Eu tinha quase colocou o R⁵*quanto a esquerda para o equivalente certo, mas, em seguida, viu a bela linha reta :)
Jonathan Allan

3

PHP, 76 bytes

(Editar -1 byte - Obrigado user59178 - sua solução é ainda melhor)

for($c=substr(bcdiv(1,$a=$argv[1],$a),2);$i<$a;)$s+=($a-$i)*$c[$i++];echo$s;

você poderia salvar um byte (um ponto e vírgula), movendo o $c=blahpara a primeira parte dofor(;;)
user59178

2

MATL, 19 bytes

li/GEY$4LQ)!UYsG:)s

Experimente Online!

Explicação

l       % Push a 1 literal to the stack
i/      % Grab the input (n) and compute 1/n
GE      % Grab the input again and multiply by 2 (2n)
Y$      % Compute the first 2n digits of 1/n after the decimal
4LQ)    % Get only the digits past the decimal point
!U      % Convert to numbers
Ys      % Compute the cumulative sum
G:)     % Get the first n terms
s       % Sum the result and implicitly display

2

Groovy, 87 bytes

Isso foi menos doloroso do que eu previa e é baseado na minha resposta aqui :

{n->(1..n).collect{x->(1.0g.divide(n, n, 1)+"")[2..x+1].getChars().sum()-48*(x)}.sum()}

Explicação

1.0g - Use a notação BigDecimal para esse.

.divide(n, n, 1)+"" - Divida por n com n precisão (somente na função BigDecimal) e converta para str.

(...)[2..x+1].getChars() - Obtenha a substring da iteração atual como uma matriz de caracteres.

.sum()-48*(x)- Soma os valores ASCII dos caracteres e reduza em 48 para cada elemento. Isso transforma o valor de um dígito ASCII em um número inteiro essencialmente salvando bytes *.toInteger().

(1..n).collect{...}.sum() - Itere sobre cada um dos dígitos da divisão, executando esta função, obtenha todos em uma única matriz e soma.

Economizou 2 bytes e eficiência sacrificada ...

Esta é uma versão mais eficiente que não recalcula o BigDecimal a cada iteração.

{n->i=1.0g.divide(n, n, 1)+"";(1..n).collect{x->i[2..x+1].getChars().sum()-48*(x)}.sum()}

2

J, 27 bytes

1#.[:+/\-{.10#.inv%<.@*10^]

Uso

A entrada é um número inteiro estendido.

   f =: 1#.[:+/\-{.10#.inv%<.@*10^]
   (,.f"0) (>: i. 50x) , 24990x + i. 11
    1          0
    2         10
    3         18
    4         23
    5         10
    6         96
    7        103
    8         52
    9         45
   10         10
   11        270
   12        253
   13        402
   14        403
   15        630
   16        183
   17        660
   18        765
   19        819
   20         95
   21        975
   22       1034
   23       1221
   24       1500
   25         96
   26       1479
   27       1197
   28       1658
   29       1953
   30       1305
   31       1674
   32        321
   33        816
   34       2490
   35       2704
   36       4235
   37       2022
   38       3242
   39       2295
   40        268
   41       2944
   42       3787
   43       3874
   44       4097
   45       1980
   46       4380
   47       4968
   48       3424
   49       4854
   50         98
24990 1405098782
24991 1417995426
24992 1364392256
24993 1404501980
24994 1408005544
24995 1377273489
24996 1395684561
24997 1405849947
24998 1406216741
24999 1142066735
25000      99984

O desempenho é bom e requer apenas cerca de 3 segundos para calcular os grandes casos de teste.

   timex 'f 7x'
0.000119
   timex 'f 24999x'
3.8823
   timex 'f 25000x'
3.14903

Explicação

1#.[:+/\-{.10#.inv%<.@*10^]  Input: n
                          ]  Get n
                       10^   Raise 10 to the nth power
                  %          Get the reciprocal of n
                      *      Multiply (1/n) with (10^n)
                   <.@       Floor it
           10#.inv           Convert it to a list of base 10 digits
        -                    Negate n
         {.                  Take the last n values from the list of digits
                             (This is to handle the case for n = 1)
   [:  \                     For each prefix of the list of digits
     +/                        Reduce it using addition to get the sum
1#.                          Convert those sums as base 1 digits and return
                             (This is equivalent to taking the sum)

2

Gelatina , 10 bytes

⁵*:⁸D+\_ỊS

Não é a abordagem mais curta , mas é bastante eficiente. Experimente online! ou verifique todos os casos de teste .

Como funciona

⁵*:⁸D+\_ỊS  Main link. Argument: n (integer)

⁵*          Yield 10**n.
  :⁸        Divide 10**n by n (integer division).
    D       Convert the quotient to base 10.
     +\     Take the cumulative sum of the digits.
        Ị   Insignificant; yield (abs(n) <= 1).
       _    Subtract the resulting Boolean from each decimal digit.
            This takes care of edge case n = 1, which would return 2 otherwise.
         S  Take the sum.

1

Python 2, 90 bytes

lambda o:sum([sum([int(i)for i in s])for s in map(lambda x:str(1.0/o)[2:x],range(3,3+o))])

Não é bonito, mas feito através da divisão de float, convertendo em uma string e, em seguida, selecionando iterativamente o índice de strings para obter o triângulo de números, depois realize a compreensão da lista e converta cada caractere em um int e, finalmente, somando todos eles.


1

JavaScript (ES6), 47 bytes

f=(b,a=1%b,c=b+1)=>c&&(a/b|0)*c+f(b,a%b*10,c-1)

Como funciona

Esta resposta demonstra uma técnica para calcular c dígitos decimais de a / b :

f=(a,b,c,d=".")=>~c?(a/b|0)+d+f(a%b*10,b,c-1,""):d

Isso será um excelente ponto de partida para esse desafio. Primeiro, podemos alterá-lo levemente para calcular b dígitos decimais de 1 / b , reordenando os parâmetros e definindo os padrões:

f=(b,a=1,c=b,d=".")=>~c?(a/b|0)+d+f(b,a%b*10,c-1,""):d

Em seguida, podemos alterar isso para que calcule a soma dos primeiros b dígitos decimais, em vez de concatená-los (isso acaba com o dparâmetro):

f=(b,a=1,c=b)=>~c?(a/b|0)+f(b,a%b*10,c-1):0

Estamos quase em uma solução; Agora, basta multiplicar cada dígito por c + 1 :

f=(b,a=1,c=b)=>~c?(a/b|0)*-~c+f(b,a%b*10,c-1):0

Hmm, isso parece um pouco longo. E se incrementássemos c por 1 para começar?

f=(b,a=1,c=b+1)=>c?(a/b|0)*c+f(b,a%b*10,c-1):0

Isso economiza um byte. E aqui está uma maneira de salvar mais uma:

f=(b,a=1,c=b+1)=>c&&(a/b|0)*c+f(b,a%b*10,c-1)

E agora temos a nossa resposta. f(7)é 103, f(11)é 270, f(1)é ... 2? Ah, esquecemos de explicar o caso em que a / b é 1 na primeira iteração (ou seja, b é 1). Vamos fazer algo sobre isso:

f=(b,a=1%b,c=b+1)=>c&&(a/b|0)*c+f(b,a%b*10,c-1)

1 mod b é sempre 1 , a menos que b seja 1 ; nesse caso, será 0 . Nosso programa agora está correto para todas as entradas, em 47 bytes .


1

Python 2, 49 bytes

lambda n:sum(10**-~k/n%10*(n-k)for k in range(n))

Teste em Ideone .


0

C, 53 bytes

f(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;}

Abaixo o principal para fazer algum teste ...

//44,79
#define R return
#define F for
#define U unsigned
#define N int
#define B break
#define I if
#define L(i) for(;i-->0;)
#define J(a,b)  if(a)goto b
#define G goto
#define P printf
#define D double
#define C unsigned char
#define A getchar()
#define O putchar
#define M main
#define Y malloc
#define Z free
#define S sizeof
#define T struct
#define E else
#define Q static
#define X continue  
main()
{N  k, a=0, b=0, i;

 F(i=1;i<50;++i) 
       P("f(%u)=%u |", i, f(i,i,1,0));
 P("\n");
 F(i=24990;i<=25000;++i) 
       P("f(%u)=%u |", i, f(i,i,1,0));
 P("\n");
 R 0;
}

/*
f(1)=0 |f(2)=10 |f(3)=18 |f(4)=23 |f(5)=10 |f(6)=96 |f(7)=103 |f(8)=52 |f(9)=45
f(10)=10 |f(11)=270 |f(12)=253 |f(13)=402 |f(14)=403 |f(15)=630 |f(16)=183 |f(17)=660 
f(18)=765 |f(19)=819 |f(20)=95 |f(21)=975 |f(22)=1034 |f(23)=1221 |f(24)=1500
f(25)=96 |f(26)=1479 |f(27)=1197 |f(28)=1658 |f(29)=1953 |f(30)=1305 |f(31)=1674
f(32)=321 |f(33)=816 |f(34)=2490 |f(35)=2704 |f(36)=4235 |f(37)=2022 |f(38)=3242
f(39)=2295 |f(40)=268 |f(41)=2944 |f(42)=3787 |f(43)=3874 |f(44)=4097 |f(45)=1980
f(46)=4380 |f(47)=4968 |f(48)=3424 |f(49)=4854 |
f(24990)=1405098782 |f(24991)=1417995426 |f(24992)=1364392256 |f(24993)=1404501980
f(24994)=1408005544 |f(24995)=1377273489 |f(24996)=1395684561 |f(24997)=1405849947 
f(24998)=1406216741 |f(24999)=1142066735 |f(25000)=99984 
*/

Por que alguém vota isso? é porque algum bug? é porque eu não encontro o mínimo certo para ele ou ela? Para mim, esse número de carvão são suficiente e ok sensação livre para cacel esta resposta também como o outro onde eu não posso falar
RosLuP

3
Como outros comentaram outras respostas suas, o objetivo do código de golfe é tornar o código o mais curto possível , mas você continua a incluir várias macros sem um bom motivo. f(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;}tem apenas 53 bytes.
Dennis
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.