プログラマ脳を鍛える数学パズル Q.3「カードを裏返せ」

More than 1 year has passed since last update.

前回記事に引き続き問題を解いていく。

問題はプログラマ脳を鍛える数学パズルより。


今回の問題


1~100までの番号が書かれた100枚のカードが順番に並べられています。最初、すべてのカードは裏返しの状態で置かれています。ある人が2番のカードが表を向くようになります。

次に、別の人が、3番のカードから2枚おきにカードを裏返していきます。また、別の人が、4番のカードから3番おきに、カードを裏返していきます。

このようにn番目のカードからn-1枚おきにカードを裏返す操作を、どのカードの向きも変わらなくなるまで続けたとします。

問題

カードの向きが変わらなくなったとき、裏向きになっているカードの番号をすべて求めてください。



実装手順

①1から100までのカードの配列を作成する。それぞれの番号に表裏の情報を付与する(今回はtrue, falseとする)。

②めくるカード(問題でいう「n」)のループ文を作成する。問題文の通り2から100までにする。

③実際にめくるカードを決めるループ文を作成する。

④めくるカードが表(true)の時は裏(false)に、裏の時は表にする条件文を書く

⑤結果を出力する


書いたPHPコードと出力結果


q03.php

<?php

$cards = [];

// ①表裏の情報を持つ1から100までのカード配列を作成する
for ($i = 1; $i <= 101; $i++) {
array_push($cards, 'false');
// 添字の番号とカード番号を合わせたいので、101枚作成して添字0のカードを削除する
unset($cards[0]);
}

// ②nをループさせる
for ($number = 2; $number <= 100; $number++) {
// ③nをn間隔でループさせてめくるカードを決める
for ($i = $number; $i <= 100; $i += $number) {
// ④めくるカードが表(true)の時は裏(false)に、裏の時は表にする
if ($cards[$i] === 'true') {
$cards[$i] = '';
// 参照渡しをする
$cards[$i] .= 'false';
} elseif ($cards[$i] === 'false') {
$cards[$i] = '';
$cards[$i] .= 'true';
}
}
}

// ⑤結果を出力する
foreach ($cards as $key => $value) {
if ($value === 'false') {
echo $key;
echo '<br/>';
}
}

// 結果
1
4
9
16
25
36
49
64
81
100


できた~~:joy:

平方数が並んでいるのが何か大きな力を感じます


今回の学び


  • ループ文の中で配列の値を置換し出力する際に手間取ったが、「参照渡し」という概念があることを知った。

  • カードの表裏の状態を、カードの値とは別に持っておくと操作しやすい