(KevinC's) Triangular DeciDigits Sequence


19

Ingresso:

Un numero intero positivo n che è 1 <= n <= 25000.

Produzione:

  1. In questa sequenza iniziamo con il numero decimale 1 / n .
  2. Poi prendiamo la somma delle cifre fino al n 'th cifre dopo la virgola (1-indicizzati); seguito dalla somma delle cifre fino a ( n -1) 'th, quindi ( n -2)' th, ecc. Continua fino a n è 1.
  3. L'output è la somma di tutti questi combinati.

Per esempio:

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

Regole della sfida:

  • Se il decimale di 1 / n non ha n cifre dopo la virgola, quelle mancanti verranno conteggiate come 0 (cioè 1/2 = 0.50 => (5+0) + (5) = 10).
  • Prendi le cifre senza arrotondare (cioè le cifre di 1/6sono 166666e non 166667)

Regole generali:

  • Per la tua risposta valgono regole standard , quindi puoi usare STDIN / STDOUT, funzioni / metodo con i parametri corretti, programmi completi. La tua chiamata.
  • Sono vietate le scappatoie predefinite .
  • Se possibile, aggiungi un link con un test per il tuo codice.
  • Inoltre, si prega di aggiungere una spiegazione, se necessario.

Primi 1 - 50 nella sequenza:

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

Ultimi 24990 - 25000 nella sequenza:

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

8
Qualcuno ha menzionato il mio nome?
Kevin,

Risposte:


6

Gelatina , 9 byte

R⁵*:%⁵+\S

Piuttosto lento, ma corto. Provalo online! oppure verifica i primi 50 casi di test .

Come funziona

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 byte

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

o

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

o

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

Spiegazione

Prendi l'esempio dalle specifiche della sfida. Vogliamo calcolare:

  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

Riorganizzando, questo è:

  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)

dov'è .il prodotto scalare di due vettori.

È praticamente tutto ciò che la soluzione fa.

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

Questo ci dà le prime Ncifre decimali di 1/N( #&@@estrae il primo elemento del RealDigitsrisultato perché restituisce anche l'offset della prima cifra che non ci interessa).

Quindi otteniamo l'elenco dal Nbasso 1all'utilizzo (#-Range@#+1)o oppure Range[#,1,-1], entrambi più brevi di Reverse@Range@#, e prendiamo il prodotto scalare.

La soluzione alternativa invece utilizza Accumulateper calcolare un elenco di tutte le somme dei prefissi e quindi aggiunge quelle somme con Tr.

Dal momento che questo è davvero veloce anche per input di grandi dimensioni, ecco un diagramma a dispersione della sequenza fino a N = 100,000( eseguirli tutti e tracciarli ci è voluto un po 'di tempo):

inserisci qui la descrizione dell'immagine
Clicca per una versione più grande.

La linea blu è il limite superiore ingenuo di 9 N (N+1) / 2(se tutte le cifre decimali fossero 9) e la linea arancione ne rappresenta esattamente la metà. Non sorprende che questo sia proprio all'interno del ramo principale della trama poiché, statisticamente, ci aspetteremmo che la cifra media sia 4,5.

La sottile linea di punti della trama che puoi vedere sotto il ramo principale sono frazioni che finiscono ...3333..., poiché si trovano tutte molto vicine 3 N (N+1) / 2.


Risposta molto bella, e adoro la trama grafica! È quasi un peccato che questo non sia il più breve e non posso accettarlo come risposta. :) Se non dimentico, potrei fare una piccola ricompensa in due giorni per aver risposto molto più del semplice compito che ho dato.
Kevin Cruijssen,

1
@KevinCruijssen Grazie! :)
Martin Ender,

6

05AB1E , 12 11 byte

Di<ë°¹÷.pSO

Provalo online! o una suite di test per i primi 50 numeri.

Spiegazione

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

Una versione più efficiente per provare grandi numeri su TIO

La differenza con la versione più breve è che qui sommiamo il prodotto delle cifre e l'inversione del loro indice basato su 1 anziché sommare le cifre nei prefissi.

Di<ë°¹÷SDgLR*O

Provalo online!


5

Java 8, 181 169 166 153 142 byte

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

Spiegazione:

Provalo qui.

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 byte

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

Adattato da questa risposta (anche da me): divisione di numeri non così piccoli e proposta da Jörg Hülsermann di modificarlo. Usa come:

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

modifica: corretto un bug per +1 byte e piegato l'assegnazione di $ a in $ argv [1] per -2 byte per un netto inferiore di 1 byte.


3

Scala, 84 byte

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

Spiegazione:

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

Potrei salvare alcuni byte sfruttando il modo in cui il compilatore tokenizza: chiamando l'argomento &, è possibile scrivere 1 to&mapinvece di 1 to n map. La stessa regola si applica a def?.


3

Gelatina , 11 byte

’aµR⁵*:µDFS

TryItOnline
First 50

Troppo lento per i casi di test di grandi dimensioni.

Come?

’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
Non credo di aver mai visto una risposta Jelly in cui la spiegazione è una linea retta ;-)
ETHproductions

Ho quasi messo l' R⁵*equivalente da sinistra a destra, ma poi ho visto la bella linea retta :)
Jonathan Allan,

3

PHP, 76 byte

(Modifica -1 byte - Grazie user59178 - la tua soluzione è ancora migliore)

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

potresti salvare un byte (un punto e virgola) spostando il $c=blahnella prima parte difor(;;)
user59178

2

MATL, 19 byte

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

Provalo online!

Spiegazione

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 byte

Questo è stato meno doloroso di quanto mi aspettassi, e si basa sulla mia risposta qui :

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

Spiegazione

1.0g - Usa la notazione BigDecimal per quello.

.divide(n, n, 1)+"" - Dividi per n con n precisione (solo funzione BigDecimal) e converti in str.

(...)[2..x+1].getChars() - Ottieni la sottostringa dell'iterazione corrente come una matrice di caratteri.

.sum()-48*(x)- Sommare i valori ASCII dei caratteri e ridurli di 48 per ciascun elemento. Questo trasforma il valore da una cifra ASCII in un intero essenzialmente salvando i byte *.toInteger().

(1..n).collect{...}.sum() - Scorrere su ciascuna delle cifre della divisione, eseguendo questa funzione, inserendole tutte in un unico array e somma.

Salvato 2 byte ed efficienza sacrificata ...

Questa è una versione più efficiente che non ricalcola BigDecimal ad ogni iterazione.

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

2

J, 27 byte

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

uso

L'input è un numero intero esteso.

   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

Le prestazioni sono buone e richiedono solo circa 3 secondi per calcolare i casi di test di grandi dimensioni.

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

Spiegazione

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 byte

⁵*:⁸D+\_ỊS

Non l'approccio più breve , ma abbastanza efficiente. Provalo online! o verifica tutti i casi di test .

Come funziona

⁵*:⁸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 byte

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

Non carino, ma fatto attraverso la divisione float, quindi la conversione in una stringa e quindi la selezione dell'indice di stringa iterativa per ottenere il triangolo di numeri, quindi eseguire la comprensione dell'elenco e convertire ogni carattere in un int e infine sommarli tutti.


1

JavaScript (ES6), 47 byte

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

Come funziona

Questa risposta dimostra una tecnica per calcolare le cifre decimali c di a / b :

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

Ciò costituirà un eccellente punto di partenza per questa sfida. Innanzitutto possiamo cambiarlo leggermente in modo che calcoli b cifre decimali di 1 / b , riordinando i parametri e impostando i valori predefiniti:

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

Quindi possiamo cambiare questo in modo che calcoli la somma delle prime cifre decimali b , invece di concatenarle (questo elimina il dparametro):

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

Siamo quasi a una soluzione; ora dobbiamo solo moltiplicare ogni cifra per c + 1 :

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

Hmm, questo sembra un po 'lungo. Che cosa succede se abbiamo incrementato c da 1 per cominciare?

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

Ciò consente di risparmiare un byte. Ed ecco un modo per salvarne un altro:

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

E ora abbiamo la nostra risposta. f(7)è 103, f(11)è 270, f(1)è ... 2? Oh, abbiamo dimenticato di tenere conto del caso in cui a / b è 1 nella prima iterazione (ovvero b è 1). Facciamo qualcosa al riguardo:

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 meno che b sia 1 , nel qual caso sarà 0 . Il nostro programma è ora corretto per tutti gli input, a 47 byte .



0

C, 53 byte

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

Di seguito il principale per fare alcuni test ...

//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 
*/

Perché qualcuno vota questo? è perché qualche bug? è perché non trovo il minuto giusto per lui o lei? Per me quel numero di caratteri è sufficiente e ok sentiti libero per cacel anche questa risposta come l'altra dove non posso parlare
RosLuP

3
Come altri hanno commentato altre tue risposte, lo scopo del codice golf è di rendere il codice il più breve possibile , eppure continui a includere un mucchio di macro senza una buona ragione. f(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;}è lungo solo 53 byte.
Dennis,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.