(KevinC)三角DeciDigits序列


19

输入:

一个正整数n,它是1 <= n <= 25000

输出:

  1. 在此序列中,我们从十进制数字1 / n开始
  2. 然后我们将数字的总和取到逗号后的第n个数字(1索引);然后是数字总和,直到第(n -1)个,然后是(n -2)个,依此类推。继续直到n为1。
  3. 输出是所有这些总和的总和。

例如:

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

挑战规则:

  • 如果1 / n的小数点后的逗号后没有n位数字,则丢失的数字将计为0(即1/2 = 0.50 => (5+0) + (5) = 10)。
  • 您不带舍入的数字(即1/6are 166666和not 的数字166667

通用规则:

  • 标准规则适用于您的答案,因此允许您使用STDIN / STDOUT,具有正确参数的函数/方法,完整程序。你的来电。
  • 默认漏洞是禁止的。
  • 如果可能,请为您的代码添加一个带有测试的链接。
  • 另外,如有必要,请添加说明。

顺序中的前1-50:

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

顺序的最后24990-25000:

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

8
有人提到我的名字吗?
凯文(Kevin)

Answers:


6

果冻,9 个字节

R⁵*:%⁵+\S

有点慢,但很短。在线尝试!验证前50个测试用例

怎么运行的

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个字节

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

要么

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

要么

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

说明

以挑战规范为例。我们要计算:

  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

重新排列,这是:

  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)

哪里.是两个向量的标量积。

该解决方案几乎完成了所有工作。

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

这会让我们的第一N小数位数1/N(中#&@@提取结果的第一个元素,RealDigits因为它还会返回我们不在乎的第一个数字的偏移量)。

然后,我们使用或从N下到下获取列表,这两个列表都比1(#-Range@#+1)Range[#,1,-1]Reverse@Range@#,并采用标量积。

相反,替代解决方案Accumulate用于计算所有前缀和的列表,然后将这些前缀和与Tr

由于即使对于大型输入来说,这确实是非常快的,因此以下是该序列的散点图N = 100,000(尽管将它们全部绘制并绘制了一段时间):

在此处输入图片说明
点击查看大图。

蓝线是的天真上限9 N (N+1) / 2(如果所有十进制数字均为9),而橙线恰好是其一半。毫不奇怪,这正好位于图的主分支内,因为从统计上讲,我们希望平均位数为4.5。

您可以在主分支下看到的细线图点是以结尾的分数...3333...,因为它们都非常靠近3 N (N+1) / 2


很好的答案,我喜欢图表!不幸的是,这不是最短的,我不能接受。:)如果我没有忘记,我可能会在两天之内得到一笔小小的悬赏,因为他回答的内容远远超过我给我的简单任务。
凯文·克鲁伊森

1
@KevinCruijssen谢谢!:)
Martin Ender

6

05AB1E12 11字节

Di<ë°¹÷.pSO

在线尝试! 或前50个数字的测试套件

说明

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

在TIO上尝试大量数字的更有效版本

与较短版本的区别在于,此处我们将数字的乘积与它们从1开始的索引的反转求和,而不是对前缀中的数字求和。

Di<ë°¹÷SDgLR*O

在线尝试!


5

爪哇8,181个 169 166 153 142字节

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

说明:

在这里尝试。

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字节

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

根据这个答案改编(也是由我本人改编而成):数字划分不多,JörgHülsermann建议对其进行编辑。使用方式如下:

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

编辑:更正了1个字节的错误,并将$ a的赋值折叠为$ argv [1]的-2个字节,净减少了1个字节。


3

Scala,84个字节

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

取消高尔夫:

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

说明:

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

我可以利用编译器标记化的方式节省一些字节:通过调用参数&,可以编写1 to&map而不是1 to n map。相同的规则适用于def?


3

果冻,11 字节

’aµR⁵*:µDFS

TryItOnline
前50名

对于大型测试用例来说太慢了。

怎么样?

’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
我认为我从未见过Jelly的答案,其中的解释是一条直线;-)
ETHproductions 16-10-14

我几乎把R⁵*等值线从左到右等了,但然后看到了一条漂亮的直线:)
乔纳森·艾伦

3

PHP,76字节

(编辑-1个字节-感谢user59178-您的解决方案更好)

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

您可以通过将其$c=blah移至for(;;)
user59178 '16

2

MATL,19个字节

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

在线尝试!

说明

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字节

这比我预期的要少,并且基于我在这里的回答:

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

说明

1.0g -使用BigDecimal表示法。

.divide(n, n, 1)+"" -以n精度除以n(仅BigDecimal函数),然后转换为str。

(...)[2..x+1].getChars() -将当前迭代的子字符串作为char数组获取。

.sum()-48*(x)-对字符的ASCII值求和,并对每个元素减少48。这会将值从ASCII数字转换为Integer,实际上将字节保存为*.toInteger()

(1..n).collect{...}.sum() -遍历除法中的每个数字,执行此功能,将它们全部合并在一个数组中并求和。

节省2个字节并牺牲了效率...

这是一个更有效的版本,不会在每次迭代时重新计算BigDecimal。

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

2

J,27个字节

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

用法

输入是扩展整数。

   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

性能很好,对于大型测试用例只需要大约3秒钟即可计算。

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

说明

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

果冻,10 字节

⁵*:⁸D+\_ỊS

不是最短的方法,而是相当有效的。在线尝试!验证所有测试用例

怎么运行的

⁵*:⁸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个字节

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

这不是很漂亮,但是可以通过浮点除法然后转换为字符串,然后迭代选择字符串索引来获得数字的三角形,然后执行列表理解并将每个char转换为int并最终将它们全部求和来完成。


1

JavaScript(ES6),47个字节

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

怎么运行的

此答案演示了一种计算a / b的c个十进制数字的技术:

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

这将为应对这一挑战提供一个极好的起点。首先,我们可以对其稍加更改,以便通过重新排序参数并设置默认值来计算b的十进制数字1 / b

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

接下来,我们可以更改它,以便它计算前b个十进制数字的总和,而不是将它们串联(这消除了d参数):

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

我们快要解决了;现在我们只需要使每个数字乘以c + 1即可

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

嗯,这似乎有点长。如果我们将c加1开始怎么办?

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

这样可以节省一个字节。这是保存更多内容的一种方法:

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

现在我们有了答案。f(7)是103,f(11)是270,f(1)是... 2?哦,我们忘记考虑第一次迭代中a / b为1(即b为1)的情况。让我们对此做些事情:

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

1 mod b始终为1,除非b1,在这种情况下它将为0。现在,我们的程序对于所有输入都是正确的,为47个字节



0

C,53字节

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

下面主要针对做一下测试...

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

3
正如其他人对您的其他答案提出的评论一样,编写代码的重点是使代码尽可能短,但您却没有充分理由继续包含一堆宏。f(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;}只有53个字节长。
丹尼斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.