Google recruit problem



# お題

e (自然対数の底) の値で連続する10桁の数のうち, 最初の素数を ruby で求めよ.
ただし, e は200桁までで

```
2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190
```

である. これをテキストにコピーして読みこませよ. 

ちなみにこれは, ここ (<https://qiita.com/daddygongon/items/ba94b0f2a73990fc6a07>) にある課題.


# 今回書いた code

とりあえず解説より先に, 今回書いた code を貼っとく.

```ruby

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`
という部分は元々,

```ruby
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 はこんな感じ.

```ruby

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` の各要素を結合した文字列を返してる.詳しくは[リファレンスマニュアルのここ](https://docs.ruby-lang.org/ja/2.6.0/class/Array.html#I_JOIN)を見れば良い.


## リファクタリング

[@scivola](https://qiita.com/scivola) さんの指摘でリファクタリング. <span class="timestamp-wrapper"><span class="timestamp">&lt;2020-12-29 火&gt;    </span></span>  
リファクタリング後の code はこんな感じ.

```ruby

# 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__

```

とても綺麗. 良い感じ.


# 参考資料

-   [Google recruit problem, exp and prime](https://qiita.com/daddygongon/items/ba94b0f2a73990fc6a07)
-   [人力検索はてな](https://q.hatena.ne.jp/1169050304)
-   [Ruby 2.6.0 リファレンスマニュアル](https://docs.ruby-lang.org/ja/2.6.0/class/Array.html#I_JOIN)



------
 - **source** ~/Lecture/multiscale_simulation/grad_members_20f/members/gagagagazelle/docs/google_recruit.org