(KevinC's) Triangular DeciDigits Sequence

19

2

Input:

A positive integer n which is 1 <= n <= 25000.

Output:

  1. In this sequence we start with the decimal number 1/n.
  2. Then we take the sum of digits up until the n'th digit after the comma (1-indexed); followed by the sum of digits up until the (n-1)'th, then (n-2)'th, etc. Continue until n is 1.
  3. The output is the sum of all these combined.

For example:

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

Challenge rules:

  • If the decimal of 1/n doesn't have n digits after the comma, the missing ones will be counted as 0 (i.e. 1/2 = 0.50 => (5+0) + (5) = 10).
  • You take the digits without rounding (i.e. the digits of 1/6 are 166666 and not 166667)

General rules:

  • Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code.
  • Also, please add an explanation if necessary.

First 1 - 50 in the sequence:

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

Last 24990 - 25000 in the sequence:

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

Kevin Cruijssen

Posted 2016-10-14T09:42:14.590

Reputation: 67 575

8Did somebody mention my name? – Kevin – 2016-10-14T13:46:52.780

Answers

6

Jelly, 9 bytes

R⁵*:%⁵+\S

Rather slow, but short. Try it online! or verify the first 50 test cases.

How it works

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.

Dennis

Posted 2016-10-14T09:42:14.590

Reputation: 196 637

15

Mathematica, 42 bytes

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

or

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

or

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

Explanation

Take the example from the challenge spec. We want to compute:

  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

Rearranging, this is:

  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)

where . is the scalar product of two vectors.

That's pretty much all the solution does.

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

This gets us the first N decimal digits of 1/N (the #&@@ extracts the first element of the RealDigits result because that also returns the offset of the first digit which we don't care about).

Then we get the list from N down to 1 either using (#-Range@#+1) or Range[#,1,-1], both of which are shorter than Reverse@Range@#, and take the scalar product.

The alternative solution instead uses Accumulate to compute a list of all prefix sums and then adds up those prefix sums with Tr.

Since this is really fast even for large inputs, here is a scatter plot of the sequence up to N = 100,000 (doing all of them and plotting them took a while though):

enter image description here
Click for larger version.

The blue line is the naive upper bound of 9 N (N+1) / 2 (if all the decimal digits were 9) and the orange line is exactly half of that. Unsurprisingly this is right inside the main branch of the plot since, statistically, we'd expect the average digit to be 4.5.

The thin line of plot points which you can see below the main branch are fractions which end in ...3333..., as they all lie very close to 3 N (N+1) / 2.

Martin Ender

Posted 2016-10-14T09:42:14.590

Reputation: 184 808

Very nice answer, and I love the graph-plot! It's almost unfortunate this isn't the shortest and I can't accept it as the answer. :) If I don't forget I might make a small bounty in two days for answering so much more than the simple assignment I gave. – Kevin Cruijssen – 2016-10-14T12:00:58.697

1@KevinCruijssen Thanks! :) – Martin Ender – 2016-10-19T11:22:01.920

6

05AB1E, 12 11 bytes

Di<ë°¹÷.pSO

Try it online! or a Test suite for the first 50 numbers.

Explanation

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

A more efficient version for trying big numbers on TIO

The difference to the shorter version is that here we sum the product of the digits and the reversal of their 1-based index instead of summing digits in prefixes.

Di<ë°¹÷SDgLR*O

Try it online!

Emigna

Posted 2016-10-14T09:42:14.590

Reputation: 50 798

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

Explanation:

Try it here.

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

Kevin Cruijssen

Posted 2016-10-14T09:42:14.590

Reputation: 67 575

4

PHP, 66 65 bytes

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

Adapted from this answer (also by me): Division of not so little numbers and Jörg Hülsermann's suggested edit to it. Use like:

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

edit: corrected a bug for +1 bytes and folded the assignment of $a into $argv[1] for -2 bytes for a net 1 byte less.

user59178

Posted 2016-10-14T09:42:14.590

Reputation: 1 007

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

Explanation:

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

I could save some bytes by exploiting the way the compiler tokenizes: By calling the argument &, you can write 1 to&map instead of 1 to n map. The same rule applies to def?.

corvus_192

Posted 2016-10-14T09:42:14.590

Reputation: 1 889

3

PHP, 76 bytes

(Edit -1 byte - Thanks user59178 - your solution is even better)

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

Crypto

Posted 2016-10-14T09:42:14.590

Reputation: 862

you could save a byte (a semicolon) by moving the $c=blah into the first part of the for(;;) – user59178 – 2016-10-14T16:43:59.610

3

Jelly, 11 bytes

’aµR⁵*:µDFS

TryItOnline
First 50

Too slow for the large test cases.

How?

’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

Jonathan Allan

Posted 2016-10-14T09:42:14.590

Reputation: 67 804

2I don't think I've ever before seen a Jelly answer where the explanation is a straight line ;-) – ETHproductions – 2016-10-14T19:30:30.047

I did nearly put the R⁵* as the left to right equivalent but then saw the nice straight line :) – Jonathan Allan – 2016-10-14T19:49:06.817

2

MATL, 19 bytes

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

Try it Online!

Explanation

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

Suever

Posted 2016-10-14T09:42:14.590

Reputation: 10 257

2

Groovy, 87 Bytes

This was less painful than I anticipated, and is based on my answer here:

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

Explanation

1.0g - Use BigDecimal notation for the one.

.divide(n, n, 1)+"" - Divide by n with n precision (BigDecimal function only) and convert to str.

(...)[2..x+1].getChars() - Get the substring of the current iteration as an array of char.

.sum()-48*(x) - Sum the ASCII values of the characters and reduce by 48 for each element. This turns the value from an ASCII digit to an Integer essentially saving bytes over *.toInteger().

(1..n).collect{...}.sum() - Iterate over each of the digits in the division, doing this function, get them all in a single array and sum.

Saved 2 Bytes and Sacrificed Efficiency...

This is a more efficient version that does not recalculate the BigDecimal each iteration.

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

Magic Octopus Urn

Posted 2016-10-14T09:42:14.590

Reputation: 19 422

2

J, 27 bytes

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

Usage

The input is an extended integer.

   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

The performance is good and only requires about 3 seconds to compute for the large test cases.

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

Explanation

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)

miles

Posted 2016-10-14T09:42:14.590

Reputation: 15 654

2

Jelly, 10 bytes

⁵*:⁸D+\_ỊS

Not the shortest approach, but fairly efficient. Try it online! or verify all test cases.

How it works

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

Dennis

Posted 2016-10-14T09:42:14.590

Reputation: 196 637

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

Not pretty, but done through float dividing then converting to a string and then iterative string index selection to get the triangle of numbers, then perform list comprehension and convert each char to an int and finally summing them all.

Zoo Zoo

Posted 2016-10-14T09:42:14.590

Reputation: 151

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)

How it works

This answer demonstrates a technique for calculating c decimal digits of a/b:

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

This will make an excellent starting point for this challenge. First we can change it slightly so that it calculates b decimal digits of 1/b, by reordering the parameters and setting defaults:

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

Next we can change this so that it calculates the sum of of the first b decimal digits, instead of concatenating them (this does away with the d parameter):

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

We're almost to a solution; now we just need to make it multiply each digit by c+1:

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

Hmm, this seems a little long. What if we incremented c by 1 to begin with?

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

That saves one byte. And here's a way to save one more:

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

And now we have our answer. f(7) is 103, f(11) is 270, f(1) is... 2? Oh, we forgot to account for the case where a/b is 1 on the first iteration (i.e. b is 1). Let's do something about this:

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

1 mod b is always 1, unless b is 1, in which case it will be 0. Our program is now correct for all inputs, at 47 bytes.

ETHproductions

Posted 2016-10-14T09:42:14.590

Reputation: 47 880

1

Python 2, 49 bytes

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

Test it on Ideone.

Dennis

Posted 2016-10-14T09:42:14.590

Reputation: 196 637

0

C, 53 bytes

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

Below the main for to do some 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 
*/

RosLuP

Posted 2016-10-14T09:42:14.590

Reputation: 3 036

Why someone down vote this? is it because some bug? is it because I not find the right min for him or her? For me that number of char are enough and ok feel free for cacel this answer too as the other where I can not speak – RosLuP – 2016-10-20T16:45:40.530

3As others have commented on other answers of yours, the point of code golf is to make the code as short as possible, yet you continue to include a bunch of macros for no good reason. f(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;} is only 53 bytes long. – Dennis – 2016-10-20T18:07:02.323