Nの約数の合計を見つける


20

ユーザーが1〜Nの範囲で入力した数値(1≤N≤100)の約数の合計を画面に表示するプログラムを作成します。

これはOEIS A000203です。


例:

入力:7

7 / 1 = 7
7 / 7 = 1

7 + 1 = 8

出力: 8


入力: 15

15 / 1 = 15
15 / 3 = 5
15 / 5 = 3
15 / 15 = 1

15 + 5 + 3 + 1 = 24

出力: 24


入力: 20

20 / 1 = 20
20 / 2 = 10
20 / 4 = 5
20 / 5 = 4
20 / 10 = 2
20 / 20 = 1

20 + 10 + 5 + 4 + 2 + 1 = 42

出力: 42


入力: 1

1 / 1 = 1

出力: 1


入力: 5

5 / 1 = 5
5 / 5 = 1

5 + 1 = 6

出力: 6


6
@ H.PWiz彼は「数Nの約数」を意味すると思う
ベンゼン

除数の合計、別名、シグマ関数を意味すると思いますか?
スティーブン

申し訳ありませんが、「Nの倍数の合計」という意味です。
ケビン・ハレー

@ H.PWizこれはそれらの合計なので、私は知らない
スティーブン

私には些細な変更のように思える@Stephen
H.PWiz

回答:



6

x86-64マシンコード、23バイト

89 F9 89 FE EB 0D 89 F8 99 F7 F1 85 D2 99 0F 44 D1 01 D6 E2 F1 96 C3

上記のコードのバイトは、単一の整数Nを受け入れ、その倍数の合計を結果として返す関数を定義します。

EDISystem V AMD64 ABI(* nixスタイルのシステムで使用される)と一致する単一のパラメーターがレジスターに渡されます。EAXすべてのx86呼び出し規約と同様に、結果はレジスタに返されます。

このアルゴリズムは非常に単純なものであり、他の言語での他の多くの提出物と同様です。モジュロを計算し、それを実行中の合計に追加するたびに、N回ループします。

非ゴルフアセンブリニーモニック:

; unsigned SumOfMultiples(unsigned N  /* (EDI) */)
    mov     ecx, edi      ; make copy of input N, to be used as our loop counter
    mov     esi, edi      ; make copy of input N, to be used as our accumulator
    jmp     CheckEnd      ; jump directly to 'CheckEnd'
AddModulo:
    mov     eax, edi      ; make copy of input N, to be used as input to DIV instruction
    cdq                   ; short way of setting EDX to 0, based on EAX
    div     ecx           ; divide EDX:EAX by ECX, placing remainder in EDX
    test    edx, edx      ; test remainder, and set ZF if it is zero
    cdq                   ; again, set EDX to 0, without clobbering flags
    cmovz   edx, ecx      ; set EDX to ECX only if remainder was zero (EDX = ZF ? 0 : ECX)
    add     esi, edx      ; add EDX to accumulator
CheckEnd:
    loop    AddModulo     ; decrement loop counter (ECX), and keep looping if it != 0
    xchg    eax, esi      ; move result from accumulator (ESI) into EAX
    ret                   ; return, with result in EAX

オンラインでお試しください!

確かにこれを短くする方法があるはずですが、私には見えません。x86でモジュロを計算するには、DIV(またはIDIV)命令を使用してそれを行うため、かなりのコードが必要です。また、どちらも固定入力レジスタ(EDXおよびEAX)を使用します。それぞれ商)。

ここでの唯一の本当のトリックは、かなり標準的なゴルフです。

  • LOOP基本的にDEC+ JNZECX暗黙的なオペランドとしてのレジスタの組み合わせであるCISCスタイルの命令を使用できるように、コードをやや珍しい方法で構造化しました。
  • オペランドの1 つがの場合、前者は特別な1バイトエンコーディングを持っているため、XCHG代わりに最後に使用しています。MOVEAX
  • 符号なし除算の場合、通常はaを使用してゼロにするだけですが、除算の準備ではCDQゼロを使用します。ただし、は常に2バイトですが、1バイトのみです。私は使用ゼロに再びループの二度目の内部を前に、命令。これが機能するのは、除算の商()が常に符号なしであることが保証されるためです。したがって、への符号拡張は0に設定されます。EDXXORXORCDQCDQEDXCMOVZEAXEDXEDX




3

Mathematica、14バイト

Tr@Divisors@#&   

または@Lokiによる回答

Mathematica、17バイト

DivisorSum[#,#&]&

@Jennymathyとても素敵です、ありがとう!同等で面白い書き方もあります:DivisorSum [#、#&]&
Rebel-Scum

@Jennymathyうーん、これはさらに良いです:Total @ Divisors @は15文字だけです!そして、それは機能します:例えば、Total @ Divisors @ 15は予想通り24を与えます。Mathematica FTW :)
Rebel-Scum

2
@LokiおよびTr@Divisors@#&さらに良い;-)
J42161217

1
@Lokiプログラムはf=入力f [x]を受け取る関数である必要があるため、このように表示します。PPCGへようこそ
J42161217

3
Tr@*Divisorsバイトを削るのに使用できます。
wchargin

3

C、C ++、C#、D、Java、65 62バイト

int d(int n){int s=0,i=1;for(;i<=n;++i)s+=n%i>0?0:i;return s;}

これは、類似性があるため、これらすべてのプログラミング言語で機能します。

C、C ++、およびDの最適化:62 60バイト

C ++およびDでは、整数は暗黙的にブール値に変換されます(ゼロ=> false、非ゼロ=> true)。したがって、 !=0

int d(int n){int s=0,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}

D最適化:ゴルフテンプレートシステム、55バイト

T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}

テストするコード

C:

printf("%d %d %d %d %d", d(7), d(15), d(20), d(1), d(5));

C ++:

std::cout << d(7) << ' ' << d(15) << ' ' << d(20) << ' ' << d(1) << ' ' << d(5);

C#:

class FindSum
{
    int d(int n) { int s = 0, i = 1; for (; i <= n; ++i) s += n % i > 0 ? 0 : i; return s; }

    static void Main(string[] args)
    {
        var f = new FindSum();
        Console.WriteLine(string.Format("{0}, {1}, {2}, {3}, {4}", f.d(7), f.d(15), f.d(20), f.d(1), f.d(5)));
    }
}

D

writeln(d(7));
writeln(d(15));
writeln(d(20));
writeln(d(1));
writeln(d(5));

Java:

public class FindSum {
    int d(int n){int s=0,i=1;for(;i<=n;++i)s+=n%i>0?0:i;return s;}

    public static void main(String[] args) {
        FindSum f = new FindSum();
        System.out.println(String.format("%d, %d, %d, %d, %d", f.d(7), f.d(15), f.d(20), f.d(1), f.d(5)));
    }
}

いくつかのこと:最初に、どの言語でもn%i/の周りに括弧は必要ないと思いますn%i!=0。第二に、最初のソリューションはのn%i>0代わりに持つことができるはずですn%i!=0。第三に、Dの解決策はT d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}、テンプレートシステムとデフォルト値を悪用することです。
ザカリー

3

Shnap44 43バイト

-1バイバイMr.

 $n return:{s=0for d:range(n+1)if n%d<1s+=d}

これは関数です($Shnapで関数を開始します)。

オンラインでお試しください!

説明:

$ n                        //Start function with parameter n
    return: {              //Technically, we are returning a scope-block, which evaluates to the last statement run
        s = 0              //Our result
        for d : range(n+1) //For each value in the iterator range(n+1)
            if n % d < 1  // If n is divisible by d
                s += d     // Add d to the sum
                           // Since (s += d) returns (s + d), and a scope-block returns the last run statement, this will be the last statement and equal to our result
    }

非競合、19バイト

多くの言語を更新した後、これをわずか19バイトに減らすことができます。

$n=>sum(factors(n))

オンラインでお試しください!


1
==0<143バイト
Xcoder氏17

@氏。Xcoder感謝...私はゴルフをしていなかった...自分の言語で...難解なxDでさえない
ソクラテスフェニックス

2

Python、44バイト

lambda k:sum(i*(k%i<1)for i in range(1,1+k))
  • スティーブンのおかげで、空白を削除して1バイト節約できます。
  • Jonathan Frechのおかげで、乗算するかどうかを変更してさらに1バイト節約できます。

2

J、23バイト

[:+/](([:=&0]|[)#])1+i.

オンラインでお試しください!

Jファンの場合、巧妙な13バイトのソリューションがあります。>:@#.~/.~&.q:があり。しかし、それは私の発明ではなかったので、公式の回答として投稿していません。

私自身のソリューションは、単に1..nをフィルタリングし、除数を見つけて、それらを合計します。それの核心は二項フォークです

](([:=&0]|[)#])

このコンテキストで]は1..nであり、[n自体であることに注意してください。したがって]|[、1..nの各要素をnに分割するときの剰余は、=&00に等しいかどうかを示します。


2
13バイトのためにこれは同等である必要があります:+1#.i.*0=i.|]
マイル

@マイル、それは本当にいいです。この部分はi.|]、私のアプローチを大きく改善したものです。しかし、この部分は完全には理解していません:+1#.i.-説明してもらえますか?
ジョナ

2
1#.はベース1変換で、これはと同等+/"1です。最初i.|]に剰余を取得し、次に0=0(除数)に等しいものを見つけてからi.*、範囲内の非除数をゼロにし、次にを使用して合計し1#.、排他的範囲な+のでそれ自体を追加しi.ます。
マイル




2

Javascript、54 44バイト

n=>[...Array(x=n)].reduce(y=>y+!(n%x)*x--,0)

Shaggyのおかげで10バイト節約

オンラインでお試しください!

const f = n=>[...Array(x=n)].reduce(y=>y+!(n%x)*x--,0)

console.log(f(7))
console.log(f(15))
console.log(f(20))
console.log(f(1))
console.log(f(5))


2

Brain-Flak、96バイト

((({})<>){<(([()]{})){<>(({})(<()>))<>{(({})){({}[()])<>}{}}{}<>([{}()]({})){((<{}{}>))}}{}>{}})

オンラインでお試しください!

説明:

改良により時代遅れになりました。

アルゴリズムの中心は次のとおりです。

({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]({})) turns |N, M...| into |N mod M, M...|
{((<{}{}>))} if the top of stack is not zero, replace it and the second with zero

それはmodの修正Mであり、それが要因であるかどうかNを示し0ます。完全なコードは次のとおりです。

((({})<>) place input, N on both stacks
{ Loop to find factors
 <
  (([()]{})) Decrement and Duplicate; get next factor to check
  { if not zero
   (<>({})<>) Copy N from other stack
   ({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]({})){((<{}{}>))} Code explained above
  }
  {} drop the zero
 >
 {} add the factor
}) push the sum

説明がありますか?
小麦ウィザード

@FunkyComputerMan今すぐ手に入れました!
メガトム

2

R31 26バイト

function(N)(x=1:N)%*%!N%%x

オンラインでお試しください!

1x1マトリックスを返します。

以下の!N%%xマップ要素dを計算します1:Nd->(1 if d divides N, 0 otherwise)

その後x%*%x!N%%xの行列積である1:Nの和でどの結果x場所!N%%xです1。きちんとした!技術的には、ルイスメンドーのオクターブ回答の移植版が、私はこのことを考えて初めてそれを見ました。

R +数字、14バイト

numbers::Sigma

オンラインでお試しください!


最初のもののためにあなたが2つのバイトを保存することができますN=scan();
gstats

@gstatsはい、ただしメタディスカッションごとに+4バイトを取得する必要があります。あなたが強い意見を持っているなら、Jarkoの答えを検討することができますが、誰も代替案を提案していないので、それは私の心の中にあります。
ジュゼッペ

2番目はそうではないnumbers::Sigma(N)でしょうか?このように、functionのソースコードを出力しますSigma
ルイバラダ

@RuiBarradas関数は完全に良い提出です。それをテストするには、最初の提出で行ったように、明らかにそれを呼び出す必要があります。
ジュゼッペ

1

JavaScript、31バイト

f=(n,i=n)=>i&&!(n%i)*i+f(n,i-1)



1

VBA(Excel)、73バイト

a=Cells(1,1)
x=1
While x<=a
If a Mod x = 0 Then b=b+x
x=x+1
Wend
MsgBox b

この回答は、スタンドのように単一のユニットとして実行できないスニペットのコレクションであるため無効です。これを有効にするには、これをサブルーチンまたは匿名VBEイミディエイトウィンドウ関数に変換する必要があります。
テイラースコット

私はあなたが言ったことにあまり詳しくありません。もう少し助けてもらえますか?
レモエル

この投稿を有効にするには、1-サブルーチン、2-関数、3-匿名VBEイミディエイトウィンドウ関数(イミディエイトウィンドウで実行できる1行)のいずれかの形式に変換する必要があります。あなたの実装では、これの最も簡単な実装では、とのラッピングによってサブルーチンに変換することですSub Y... End Sub85バイトソリューションを取得するSub y A=Cells(1,1) x=1 While x<=A If A Mod x=0 Then b=b+x x=x+1 Wend MsgBox b End Sub
テイラースコット

それはしかし、かなり頻繁にダウン72バイトのソリューションに最適化することができSub y While x<=[A1] x=x+1 If [A1]Mod x=0Then b=b+x Wend Debug.?b End Sub、それはきれいなモジュールで実行されていることを前提と(X =デフォルトのint型の値、0VBEイミディエイトウィンドウに)と出力(?オートフォーマットをするPrint
テイラー・スコット

これを超えて、ソリューションがサブルーチン呼び出しを介して入力を受け取らないことを認識すると、これは、50バイトのVBEイミディエイトウィンドウ関数に変換できます。これは、デフォルト値が0であり、VBEイミディエイトウィンドウに出力されるWhile x<=[A1]:x=x+1:b=IIf([A1]Mod x,b,b+x):Wend:?bことを前提とxbています(からVBEイミディエイトウィンドウ?Debug.Print )と同等です)
テイラースコット

1

Pyth、6バイト

s*M{yP

ここで試してみてください!

Pythには除数の組み込み機能がないため、これは合理的だと思います。

説明

s * M {yP-暗黙的な入力を伴う完全なプログラム。

     P-入力の素因数。
    y-その素因数のパワーセット。
   {-重複排除。
 * M-乗算を使用したマップ。
s-合計。
          -結果を暗黙的に表示します。

20たとえば、与えられた場合、これは私たちのプログラムが各命令の後に行うことです:

  • P[2, 2, 5]

  • y[[], [2], [2], [5], [2, 2], [2, 5], [2, 5], [2, 2, 5]]

  • {[[], [2], [5], [2, 2], [2, 5], [2, 2, 5]]

  • *M[1, 2, 5, 4, 10, 20]

  • s42



1

、5バイト

ṁΠuṖp

オンラインでお試しください!

どうやって?

ṁΠuṖp-完全なプログラム、暗黙的な入力。

     p-素因数。
    Ṗ-パワーセット。
   u-重複を削除します。
ṁΠ-各リストの積を取得し、合計し、暗黙的に出力します。

チャットで提案してくれたZgarbに感謝します!







0

QBIC、17バイト

[:|~b%a|\p=p+a}?p

説明

[:|      FOR a = 1; a <= b (read from cmd line); a++
~b%a|    IF b modulo a has a remainder THEN - empty block - 
\p=p+a   ELSE add divisor 'a' to running total 'p'
}        END IF, NEXT
?p       PRINT p

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.