(KevinC's)三角DeciDigitsシーケンス


19

入力:

正の整数Nです1 <= n <= 25000

出力:

  1. このシーケンスでは、10進数の1 / nから始めます。
  2. 次に、コンマ(1インデックス)の後のn番目の桁までの桁の合計を取得します。その後に(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/6166666andでありません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
誰かが私の名前に言及しましたか?
ケビン

回答:



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)

どこ.2つのベクトルの内積です。

それはほとんどすべてのソリューションが行います。

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

これにより、最初のN10進数が得られます1/N(結果の#&@@最初の要素が抽出されRealDigitsます。これは、気にしない最初の数字のオフセットも返すためです)。

次に、を使用Nして1(#-Range@#+1)またはのいずれかRange[#,1,-1]より短いリストを取得しReverse@Range@#、スカラー積を取得します。

代わりのソリューションではAccumulate、代わりにすべてのプレフィックスの合計のリストを計算し、それらのプレフィックスの合計をで加算しTrます。

これは大規模な入力でも非常に高速であるため、ここまでのシーケンスの散布図を示しますN = 100,000すべてを実行し、プロットに時間がかかりました)。

ここに画像の説明を入力してください
拡大版をクリックしてください。

青い線は9 N (N+1) / 2(すべての10進数がの場合)の単純な上限で9あり、オレンジの線はその半分です。統計的には、平均桁が4.5になると予想されるため、当然ながら、これはプロットのメインブランチ内にあります。

あなたが主枝の下に見ることができるプロットポイントの細いラインは...3333...それらがすべて非常に近くにあるので終わる端数3 N (N+1) / 2です。


非常に良い答えで、グラフプロットが大好きです!残念ながら、これが最短ではなく、答えとして受け入れることはできません。:)忘れないなら、私が与えた単純な課題よりもはるかに多くのことに答えて、2日間で小さな賞金をかけるかもしれません。
ケビンCruijssen

1
@KevinCruijssenありがとう!:)
マーティンエンダー

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バイトのバグを修正し、1バイト少ないネットに対して-2バイトの$ aの割り当てを$ argv [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&map1 to n mapdef?


3

ゼリー、11 バイト

’aµR⁵*:µDFS

TryItOnline
First 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
説明が直線であるゼリーの答えを見たことがないと思います
;

私はほぼ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

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ケタから整数に本質的にバイトを節約します*.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))])

きれいではありませんが、フロート分割を行ってから文字列に変換し、文字列インデックスを繰り返し選択して数字の三角形を取得し、リスト内包を実行して各文字を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の 10進数のcを計算する手法を示しています。

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

これは、この課題の優れた出発点となります。最初に、パラメーターを並べ替えてデフォルトを設定することにより、1 / bの 10進数bを計算するようにわずかに変更できます。

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

次に、これを変更して、最初のbの 10進数を連結するのではなく、合計を計算するようにできます(これにより、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

1バイト節約できます。そして、もう1つ保存する方法を次に示します。

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

なぜ誰かがこれに反対投票するのですか?バグがあるからですか?それは私が彼または彼女にとって適切な分を見つけられなかったからでしょうか?私は話すことができないところ私にとってのcharの数があまりにも他としてこの回答cacelのための十分な空きし、[OK]を感じていること
RosLuP

3
他の人があなたの他の答えについてコメントしているように、コードゴルフのポイントはコードをできるだけ短くすることですが、正当な理由がないのにたくさんのマクロを含め続けます。長さf(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;}53バイトのみです。
デニス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.