読者です 読者をやめる 読者になる 読者になる

個人的自由ノート

ふと自分が気になった事を書いてます

数学パズルという参考書の問題をRubyで解いてみた Q03

問題 1-100までの番号が書かれた100枚のカードが順番に並べられています。最初、すべてのカードは裏返しの状態で置かれています。ある人が2番のカードから、1枚おきにカードを裏返していきます。すると、2,4,6…100番のカードが表を向くようになります。次に、別の人が、3番のカードから2枚おきにカードを裏返していきます。(裏向きのカードは表を向き、表を向いているカードは裏返されます)。 …中略… このようにn番目のカードからn - 1枚おきにカードを裏返す操作を、どのカードの向きも変わらなくなるまで続けたとします。

自力で解いてみようと思って、やってみたは良いものの、Rubyの文法を使いこなせていないせいか、苦戦してました。自分で作ったのは以下のプログラムになりますが、答えが間違ってます。

n = 2
card = Array.new

for num in n..100 do
  if num % n == 0 then
    card[num - 1] = num
  else
    card[num - 1] = 0
  end

  if num == 100 then
    n += 1
  end
end

for num in 1..100 do
  if card[num - 1] != 0 && card[num - 1] != nil then
    puts card[num - 1]
  end
end

こういう古典的な組み方をしてしまうので答えが求めにくい原因となるんですね。答えは以下のようになります。

n = 100
cards = Array.new(n, false)

(2..n).each{|i|
  j = i - 1
  while (j < cards.size) do
    cards[j] = !cards[j]
    j += i
  end
}

n.times{|i|
  puts i + 1 if !cards[i]
}

もっと簡単に書くと以下のようになります。

(1..100).each{|i|
  flag = false
  (1..100).each{|j|
    if i % j == 0 then
      flag = !flag
    end
  }
  puts i if flag
}

実行結果は以下のようになります。

> ruby q-3.rb
1
4
9
16
25
36
49
64
81
100

Ruby、もうちょっと使いこなしておこう。便利ですね。