質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

teratail

teratail(テラテイル)は、プログラミングに特化した日本語Q&Aサイトです。

Q&A

3回答

3211閲覧

1234567890の正の約数のうち、5000000以下のものを全て足し合わせたときの和を求めてください。

wagadayon

総合スコア0

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

teratail

teratail(テラテイル)は、プログラミングに特化した日本語Q&Aサイトです。

0グッド

0クリップ

投稿2021/08/30 06:19

編集2021/08/30 06:30

タイトルの答えを教えてください! 回答の方よろしくお願いします!
コードはこんなかんじで書きました!
ですが、答えが出てきません。

def divisor_sum(num, limit)
(1..limit).select{ |i| num % i == 0 }.sum
end

puts divisor_sum(1234567890, 50000000)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mather

2021/08/30 06:34

JavaScriptタグも関係ないので外してください。
m.ts10806

2021/08/30 07:02

何が出てくるんでしょうか。そして何が出てくる想定で組んだのでしょうか。 あと、コードはマークダウンのcodeを利用してご提示ください
m.ts10806

2021/08/30 07:35

タイムアウトしてますね。 数字がでかすぎるんじゃないかな 型とか要確認
guest

回答3

0

5000000以下のもの

puts divisor_sum(1234567890, 50000000)

桁を間違えています。Rubyではアンダースコア _ を挿入しても数値リテラルとして認識してくれるので、記述ミスを減らせます。

ruby

1# 5,000,000以下のもの 2puts divisor_sum(1_234_567_890, 5_000_000)

投稿2021/08/30 08:03

mather

総合スコア6759

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

アルゴリズムの改善案出しときますわ。

1以上limit以下のすべての整数について、numの約数かを調べる必要が常にあるか?といったら無いねんな。題意の和を計算するためには、1以上かつmin { √num を超えない最大の整数, limit } 以下の整数について、num を割り切るか調べれば十分ですわ。

たとえば、質問にあるように num が 1234567890 で、limit が 5000000 のとき、√num を超えない最大の整数は、35136 で、これは 5000000 よりも(かなり)小さく、num を割り切るかどうかのチェックは、1以上35136以下の数に対してだけやれば済むこっちゃ。

以下、考え方の説明します。話を簡単にするため、例えば、numが60、limitが18としますわ。

  • 60を割りきるか調べる数(1以上18以下の整数)を変数dとします。

  • また、求める合計をsum とします。sum の初期値はゼロです。

  • まず、d が 1 のとき、60を割り切るので、sum に 1 を加えます。

  • このとき、つまり、numd が割り切るとき、num ÷ d の商q num の約数やねんな。num が60でdが1のときは、商qは60で、60は18以下ではないので、この場合はsum には足しませんが、もし商qが 18 以下になっていれば、商も sum に加えます。

  • dを、1から順に1つずつ増やして、上記の操作をやっていくと、dが4のとき、qが15になり、初めて商のほうも18以下になりsum に加えることになる。

  • 引き続き、d が 5および6のとき、d自身とともに、それらで割った商q として得られる 12および10 も (18以下なので)sum に加えます。

  • このような操作によって sum に累積していくとき、dの上限としては、√60 (60の平方根: 7.74...)を超えない最大の整数である7まで調べればよい。(なぜなら、8以上の整数でsum に加算すべきものは、それまでのループの中で、既に商qとして出現しており、その中で limit以下のものは sumに加算済みだから。)

  • ただし、num が平方数の場合、たとえば100のとき、√100 は 10なので、d が 10 のとき、商qも 10 になり、limitがたとえば20のとき、上記の操作だと10を2回sumに足してしまうことになるので、重複して足さないようなロジック追加が必要

以上を実装した divisor_sum() のコード例が以下です。ワテ、Rubyは得意やないもんで、javascriptで書いたで。

javascript

1const divisor_sum = (num, limit) => { 2 3 let sum = 0; // 求める合計値 4 const sqrtNum = Math.sqrt(num); // num の平方根 5 6 for (let d = 1; d <= limit; ++ d) { 7 8 if (d > sqrtNum) // dがnumの平方根を超えたらループから抜ける 9 break; 10 11 if (num % d === 0) {  // d が num の約数である 12 sum += d;  // sum にdを加算 13 const q = num / d; // sum を d で割った商を求める(整数になる) 14 if (q <= limit && q !== d) { // qがlimit以下であり、かつ qとdが等しくない場合 15 sum += q;  // 商qもsumに加算 16 } 17 } 18 } 19 20 return sum; 21} 22 23 24// テスト実行 25console.log(divisor_sum(60, 18)); // => 58 (約数かどうかを調べるのは、7までで済む) 26console.log(divisor_sum(1234567890, 5000000));  // => 1734174 (約数かどうかを調べるのは、35136までで済む) 27console.log(divisor_sum(100, 30)); // => 67 (約数かどうかを調べるのは、10までで済む。100は10の2乗なので、10を2回足さないようにする。) 28console.log(divisor_sum(60, 5)); // => 15 (この場合は、5は√60より小さいので、1以上5以下の全ての整数について60の約数かどうかを調べる)

サンプル

一応、上のコードで // テスト実行 したテストケースは、質問にあるRubyの def divisor_sum(num, limit) でもやってみて、結果が一致したことは確認済みや。

ほなまた〜

投稿2021/08/30 12:59

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2021/08/30 15:59

> num を割り切るかどうかのチェックは、1以上35136以下の数に対してだけやれば済むこっちゃ。 36070 は 35136 より大きく 5000000 以下で 1234567890 の約数ですが、これを計算に入れなくていいということですか?
fana

2021/08/31 01:15

> ・このとき、つまり、numをd が割り切るとき…(中略)…商も sum に加えます で扱われる(:36070は,d=34227 でのチェックの時に商として出てくる)形でしょう.
Zuishin

2021/08/31 01:35

> で扱われる(:36070は,d=34227 でのチェックの時に商として出てくる)形でしょう. なるほど、割り切れるとわかった時だけ割ればいいので除算の回数が減るという意味の回答ですね。 質問は「答えが出てきません」で、回答が「アルゴリズムの改善案」になりますが、これは要するに質問のコードが間違っているので別の数値が出るコードにしたというわけではなく、質問のコードは効率が悪いために正しい答えは出るけどタイムアウトになっているという趣旨の回答でしょうか?
Zuishin

2021/08/31 01:36

なお、タイトルにある 5000000(この回答でも採用されている数値) で試したところ、質問のコードで 1 秒以内に正しい答えが出ました。
退会済みユーザー

退会済みユーザー

2021/09/01 01:42

Zuishin さん, fanaさん コメントありがとうございます。コメントいただいているご理解と、私がこの回答をした意図との間に齟齬はありません。
Zuishin

2021/09/01 02:08 編集

7 桁を採用するなら mather さんの回答の通り他に何も変えなくても正しい答えが出ますね。 8 桁は Ruby では厳しいようですが、JavaScript ならアルゴリズムを変えなくてもタイムアップにならないんじゃないかと思っています。
guest

0

残念ながら、ここではコード作成依頼は受け付けておりません。

まずはあなたなりにコードを書いてみましょう。
そのうえで、わからないことがあればそのコードとともに聞いていただければお答えできるかと思います

投稿2021/08/30 06:22

y_waiwai

総合スコア88024

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wagadayon

2021/08/30 06:26

このような感じでコードを書いたのですが答えが出てこないんですよね def divisor_sum(num, limit) (1..limit).select{ |i| num % i == 0 }.sum end puts divisor_sum(1234567890, 50000000)
y_waiwai

2021/08/30 06:29

質問文は編集できますんで、それを質問文の方に追記してください。 回答のコメントではあんまし見てくれません それと、そのコードでは具体的にどういう結果が出るのかを詳しく説明しましょう
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問