お題
e (自然対数の底) の値で連続する10桁の数のうち, 最初の素数を ruby で求めよ.
ただし, e は200桁までで
2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190
である. これをテキストにコピーして読みこませよ.
ちなみにこれは, ここ (https://qiita.com/daddygongon/items/ba94b0f2a73990fc6a07) にある課題.
今回書いた code
とりあえず解説より先に, 今回書いた code を貼っとく.
def prime?(num)
warden = 0
i_max = Integer.sqrt(num)
[*2..i_max].each do |i|
warden = i
break if num % i == 0
end
warden == i_max # rubocop かけたらこうなった. return とかわざわざ書かんでいいらしい
end
def read_exp
exp1 = gets.to_s.chomp
end
def google_recruit
# e (自然対数の底) 読み込み
exp1 = read_exp
first = 2
last = exp1.size - 1 - 10
[*first..last].each do |i|
# e の値中の, 連続する10桁の整数 生成
target = exp1[i..i + 10 - 1].to_i
# 素数判定
if prime?(target)
puts target
break # 最初の連続する10桁の素数を見つけたら break
end
end
end
google_recruit if $PROGRAM_NAME == __FILE__
解説
解説は先程貼ったリンク先にあるので, 割愛する.(解説通りに code を書いたので特に言うことがない)
ちなみに,
warden == i_max
という部分は元々,
if warden == i_max
return true
else
return false
end
と書いていた.
これを rubocop にかけたら warden == i_max
になった.
類題
Congratulations. You've made it to level 2. Go to www.Linux.org and enter Bobsyouruncle as the login and the answer to this equation as the password.
f(1)=7182818284
f(2)=8182845904
f(3)=8747135266
f(4)=7427466391
f(5)=__________
この問題も, ここ (https://qiita.com/daddygongon/items/ba94b0f2a73990fc6a07) にある課題.
類題の解説
この問題は e (自然対数の底) の値で連続する10桁の数のうち, 各桁の数字の和が49のものを求めるというもの. (ここ (https://q.hatena.ne.jp/1169050304) 参照した.)
なので, 先程書いた code を少し修正したら良い.
修正した code はこんな感じ.
def sum_is49?(nums)
sum = 0
[*0..nums.size - 1].each do |k|
sum += nums[k]
end
sum == 49
end
def read_exp
exp1 = gets.to_s.chomp
end
######
# e (自然対数の底) の値で連続する10桁の数のうち, 各桁の数字の和が49のものを求める
# 和が49を求めなあかんってのは, 下記URLで発見した
# https://q.hatena.ne.jp/1169050304
######
def google_recruit2
# e (自然対数の底) 読み込み
exp1 = read_exp
first = 2
last = exp1.size - 1 - 10
[*first..last].each do |i|
nums = []
# e の値中の, 連続する10桁の整数グループ 生成
[*i..i + 10 - 1].each do |j|
nums.push(exp1[j].to_i)
end
# 和が49か判定
print "#{nums.join}\n" if sum_is49?(nums)
end
end
google_recruit2 if $PROGRAM_NAME == __FILE__
修正箇所はざっくりこんな感じ.
- 連続する10桁の数を, 各桁の数値を各要素にもつ配列にした.
- 関数
prime?
の代わりに, 配列の各要素の和が49であるか判定する関数sum_is49?
を新たにつくって, 用いた.
解説はこれ以上特に書くことない.
ちなみに, nums.join
は, 配列 nums
の各要素を結合した文字列を返してる.詳しくはリファレンスマニュアルのここを見れば良い.
リファクタリング
@scivola さんの指摘でリファクタリング. <2020-12-29 火>
リファクタリング後の code はこんな感じ.
# e (自然対数の底) の値で連続する10桁の数のうち, 各桁の数字の和が49のものを求める
def google_recruit2
# e (自然対数の底) 読み込み
exp1 = gets.to_s.chomp
# e の桁ごとの整数の配列を生成
char_nums = exp1.chars
integer_nums = char_nums.map { |n| n.to_i }
# e の値中の連続する10桁の整数グループ生成. そして和が49か判定し, 出力.
integer_nums.each_cons(10) do |nums|
puts nums.join if nums.sum == 49
end
end
google_recruit2 if $PROGRAM_NAME == __FILE__
とても綺麗. 良い感じ.
参考資料
- source ~/Lecture/multiscale_simulation/grad_members_20f/members/gagagagazelle/docs/google_recruit.org