除数の削減


21

数値nの除数は、1とn自体を含め、nを均等に分割する任意の数値です。約数d(n)は、数に含まれる約数です。最初のカップルn のd(n)は次のとおりです。

n    divisors    d(n)
1    1           1
2    1, 2        2
3    1, 3        2
4    1, 2, 4     3
5    1, 5        2
6    1, 2, 3, 6  4

数から除数の数を繰り返し減算できます。例えば:

16                  = 16
16 - d(16) = 16 - 5 = 11
11 - d(11) = 11 - 2 = 9
 9 - d( 9) =  9 - 3 = 6
 6 - d( 6) =  6 - 4 = 2
 2 - d( 2) =  2 - 2 = 0

この場合、0になるまでに5つのステップが必要でした。


負でない数nを指定したプログラムまたは関数を作成すると、除数の減算を繰り返して0に減らすために必要なステップ数が返されます。

例:

0, 0
1, 1
6, 2
16, 5
100, 19
100000, 7534


回答:



6

Python、49バイト

f=lambda n:n and-~f(sum(n%~x<0for x in range(n)))

orlpはバイトの節約に役立ちました!Sp3000はさらに2つ節約しました。ありがとう!


1
移動して物事を短縮することができるはず-~にしn%-~kて、範囲の下限を取り除きます。
orlp

5

C、52バイト

g,o;l(f){for(g=o=f;o;f%o--||--g);return f?1+l(g):0;}

4

Pyth、10バイト

tl.ulf%NTS

テストスイート。

説明

tl.ulf%NTS
tl.ulf%NTSNQ  implicit variables at the end
           Q  obtain the input number
  .u      N   repeat the following until result no longer unique:
         S        generate range from 1 to N
     f            filter for:
      %NT             T in that range, which N%T is truthy (not zero)
    l             length of that list
                  that means, we found the number of "non-divisors" of N
tl            number of iterations, minus 1.

3

ジュリア、31バイト

f(n)=n<1?0:f(sum(n%(1:n).>0))+1

簡単な再帰的実装。



2

JavaScript(ES6)、64 51バイト

f=n=>n&&[...Array(m=n)].map((_,i)=>m-=n%++i<1)|f(m)+1

なぜ不必要に末尾再帰を使用していたのか聞かないでください。


2

Java、147 93

a->{int k,i,n=new Integer(a),l=0;for(;n!=0;n-=k)for(l+=k=i=1;i<n;)if(n%i++==0)++k;return l;}

3
なぜn=new Integer(100000)代わりにn=100000
user8397947

1

05AB1E、12 10バイト

コード:

[Ð>#Ñg-¼]¾

説明:

[           # start infinite loop
 Ð          # triplicate current number
  >#        # increase by 1 and break if true
    Ñg      # get number of divisors
      -     # subtract number of divisors from number
       ¼    # increase counter
        ]   # end loop
         ¾  # print counter

オンラインで試す

編集:2バイトが保存され、@ Adnanのおかげで入力0のバグが修正されました


非常に素晴らしい!私はそれを少しゴルフしようとしましたが、10バイトまで下げました[Ð>#Ñg-¼]¾。ただし、短くする方法が必要です
...-Adnan

@LuisMendoええ、それはD0Q#部品がカウンターの増分後だからです。[Ð>#Ñg-¼]¾コードは、のために働く必要があります0けれども:)。
アドナン

@Adnan:nまでのすべてのカウントを生成し、インデックスからインデックスの値に移動してカウントアップすることに基づいてバージョンを試しましたが、そのように短くすることはできませんでした。
エミグナ


1

Mathcad、[tbd]バイト

ここに画像の説明を入力してください


Mathcadのバイト等価スキームはまだ決定されていません。大まかなキーストロークの等価性を使用して、プログラムは約39 "バイト"を使用します。whileおよびプログラミングオペレーターは、入力(それぞれctl-]およびctl-shft-#)にそれぞれ1つのキーボード操作のみを使用することに注意してください。実際、キーボードからこの方法でしか入力できません。

表示されるのは、まさにMathcadワークシートに記載されているものです。Mathcadは方程式/プログラムを評価し、同じシートに出力を配置します(たとえば、「=」評価演算子の後またはプロット上)。


1

MATL、13バイト

tX`t:\ztt]Nq&

オンラインで試す

説明:

t               % Duplicate input
 X`      ]      % while loop, consumes 1 input
   t:\z         % calculates n-d(n), by counting number non-divisors
       tt       % dupe twice, for while loop condition, next iteration and to keep in stack
          Nq&   % get stack size, decrement, display that value

1

Mathematica、35バイト

If[#<1,0,#0[#-0~DivisorSigma~#]+1]&

古き良きを利用しますDivisorSigma。@MartinBüttnerは、次の代替案に注目しています。

If[#<1,0,#0[#-DivisorSum[#,1&]]+1]&
f@0=0;f@n_:=f[n-DivisorSum[n,1&]]+1

1

Hoon93 76バイト

|=
r/@
?~
r
0
+($(r (sub r (lent (skim (gulf 1^r) |=(@ =(0 (mod r +<))))))))

ゴルフをしていない:

|=  r/@
?~  r
  0
=+  (skim (gulf 1^r) |=(@ =(0 (mod r +<))))
+($(r (sub r (lent -))))

アトムを受け取る関数を返しますrr(メークリスト[1..n]のすべての除数を含む中間値を作成し、(mod ri)== 0の要素のみを保持します)。rがゼロの場合はゼロを返し、そうでない場合はrがr-(長さの除数)に等しい再帰の増分値を返します。

コードをそのまま使用すると、n = 100.000を評価するのに愚かな時間がかかります。これは、大きな数の除数を見つけると巨大なリストが作成され、その上にマップされるためです。除数をメモすると、n = 10.000の正しい出力が得られますが、100.000を待つ必要はありませんでした。


1

Haskell、43 40 39バイト

g 0=0;g n=1+g(sum$min 1.mod n<$>[1..n])

単純な再帰的アプローチ。使用例:g 16-> 5

編集:@Lynnは3 4バイトを節約しました。ありがとう!


どうg(sum$signum.mod n<$>[1..n])
リン

ああ、min 1実際にはより短い1バイトでsignumさえ、
リン

1

PowerShell v2 +、74 67バイト

param($n)for($o=0;$n-gt0){$a=0;1..$n|%{$a+=!($n%$_)};$n-=$a;$o++}$o

他の回答のいくつかと比較してかなり長いようです...

入力を受け取り$n、より大きいfor条件でループに入ります。ループを繰り返すたびにヘルパーを設定してから、最大数までのすべての数値をループします。各内部ループは、すべての数値をチェックして、それが除数かどうかを確認し、そうであればヘルパーをインクリメントします(ブール否定と暗黙のキャストto整数を使用)。次に、見つかった除数を減算し、counterをインクリメントします。最後に、出力します。$n0$a1$n$a$n-=$a$o++$o

受け取り長いことが重要なため、ループ構造なので、実行に時間を。たとえば、n = 10,000私のマシン(1年前のCore i5)で実行するには、ほぼ3分かかります。


1

ラケット-126バイトから98バイトまで 91バイト

非常に素朴な解決策-まともなアルゴリズムと私が知らないいくつかのLispトリックでおそらく大幅に削減できます

(define(g x[c 0][d 0][i 2])(cond[(= x 0)c][(= i x)(g d(+ 1 c))][(=(modulo x i)0)(g x c d(+ 1 i))][else(g x c(+ 1 d)(+ 1 i))]))

編集:リクエストによる説明。私が言ったように、これは非常に単純な再帰的な解決策であり、はるかに短くすることができます。

(define (g x [c 0] [d 0] [i 2]) ;g is the name of the function - arguments are x (input), c (counter for steps), d (non-divisor counter), i (iterator)
  (cond
    [(= x 0) c] ;once x gets to 0 c is outputted
    [(= i x) (g d (+ 1 c))] ;if iterator reaches x then we recurse with d as input and add 1 to c
    [(= (modulo x i) 0) (g x c d (+ 1 i))] ;checks if iterator is non divisor, then adds it to d and increments iterator
    [else(g x c (+ 1 d) (+ 1 i))])) ;otherwise just increments iterator

編集2:より愚かなアルゴリズムの98バイトバージョン(まだかなり愚かであり、より短くすることができます)

(define(g x)(if(< x 1)0(+ 1(g(length(filter(λ(y)(>(modulo x y)0))(cdr(build-list x values))))))))

説明:

(define (g x) ;function name g, input x
  (if (< x 1)
      0 ;returns 0 if x < 1 (base case)
      (+ 1 ;simple recursion - adds 1 to output for each time we're looping
         (g (length ;the input we're passing is the length of... 
              (filter (λ (y) (> (modulo x y) 0)) ;the list where all numbers which are 0 modulo x are 0 are filtered out from...
                             (cdr (build-list x values)))))))) ;the list of all integers up to x, not including 0

編集3:と交換(cdr(build-list x values))して7バイトを保存(build-list x add1)

(define(g x)(if(< x 1)0(+ 1(g(length(filter(λ(y)(>(modulo x y)0))(build-list x add1)))))))

こんにちは、PPCGへようこそ!素晴らしい投稿!解決策を説明してください。(PS私はLispが大好き!)
NoOneIsHere

@NoOneIsHere編集
-kronicmage

0

> <>、52 + 2 = 54バイト

入力番号は、プログラムの開始時にスタック上に存在する必要があるため、-vフラグには+2バイトがあります。オンラインでお試しください!

:0)?v~ln;>~$-]
03[}\::
@@:$<    v?=0:-1}+{~$?@@01%@:

アライメントの問題で無駄な4バイトが無駄になります。ああ。

これは、スタック上にシーケンスを構築するnこと0で機能します。0に達したら、それをポップし、残りのスタックの長さを出力します。

ところで、それはO(n^2)時間内に実行されるので、私はしようとしませんn = 100000...


-v2バイトではなく1バイトです。
-NoOneIsHere


0

ルビー、42バイト

f=->n{n<1?0:1+f[n-(1..n).count{|i|n%i<1}]}

最大のテストケース100000ではスタックオーバーフローエラーが発生するため、49バイト以内の反復バージョンがあります。ただし、O(N^2)複雑さを考慮すると少し時間がかかります。

->n{c=0;c+=1 while 0<n-=(1..n).count{|i|n%i<1};c}

0

Perl 5、40バイト

sub f{@_?(1,f((1)x grep@_%$_,1..@_)):()}

入力と出力は、の必要なコピー数のリストです1



0

実際には、17バイト

";╗R`╜%`░l;"£╬klD

オンラインでお試しください!(注:最後のテストケースはTIOでタイムアウトします)

説明:

";╗R`╜%`░l;"£╬klD
"          "£╬     while top of stack is truthy, call the function:
 ;╗                  push a copy of n to reg0
   R                 range(1,n+1) ([1,n])
    `  `░l             push the number of values where the following is truthy:
     ╜%                  k mod n
                       (this computes the number of non-divisors of n)
          ;            make a copy
              klD  push entire stack as list, count number of items, subtract 1
                   (the result is the number of times the function was called)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.