LoginSignup
4
0

More than 3 years have passed since last update.

Google recruit problem

Last updated at Posted at 2020-12-29

お題

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
4
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0