ルーレットの最大値:「プログラマ脳を鍛える数学パズル」Q10の答え
問題
この問題もCodeIQで見つからなかったので書籍版オリジナル問題と思われる。
ルーレットの目の配列にはヨーロピアンスタイルとアメリカンスタイルがある。連続するn個の目の和の最大値がヨーロピアンスタイル<アメリカンスタイルとなるような2以上36以下のnはいくつあるか?と言う問題。
わたしの考え方
- 任意の目から順にn個のルーレットの目を合算する関数を定義する
- n個の目の数の和の最大値を求める関数を定義する
- さいごにヨーロピアンスタイルとアメリカンスタイルで比較する
わたしのオリジナル解答
European = [0,32,15,19,4,21,2,25,17,34,6,27,13,36,11,30,8,23,10,5,24,16,33,1,20,14,31,9,22,18,29,7,28,12,35,3,26] American = [0,28,9,26,30,11,7,20,32,17,5,22,34,15,3,24,36,13,1,00,27,10,25,29,12,8,19,31,18,6,21,33,16,4,23,35,14,2] def European_Sum(m, n): Sum = 0 for s in range (m, m + n): if s >= 37: s -= 37 Sum += European[s] return Sum def European_Max(n): Max_sum = 0 for m in range(0,37): if Max_sum < European_Sum(m, n): Max_sum = European_Sum(m, n) return Max_sum def American_Sum(m, n): Sum = 0 for s in range (m, m + n): if s >= 38: s -= 38 Sum += American[s] return Sum def American_Max(n): Max_sum = 0 for m in range(0,38): if Max_sum < American_Sum(m, n): Max_sum = American_Sum(m, n) return Max_sum cnt = 0 for n in range(2,36): if European_Max(n) < American_Max(n): cnt += 1 print cnt
模範解答のミソ
- 模範解答ではn個の目の数の和の最大値を求める関数を直接定義している
- どんな配列でも利用できるような汎用性の高いコードになっているので、コード自体がすっきりしている。
修正されたわたしの解答
European = [0,32,15,19,4,21,2,25,17,34,6,27,13,36,11,30,8,23,10,5,24,16,33,1,20,14,31,9,22,18,29,7,28,12,35,3,26] American = [0,28,9,26,30,11,7,20,32,17,5,22,34,15,3,24,36,13,1,00,27,10,25,29,12,8,19,31,18,6,21,33,16,4,23,35,14,2] def Sum_Max(roulette, n): Max_sum = 0 for i in range(0,len(roulette)): Sum = 0 for s in range(i, i + n): if s >= len(roulette): s -= len(roulette) Sum += roulette[s] if Max_sum < Sum: Max_sum = Sum return Max_sum cnt = 0 for n in range(2,36): if Sum_Max(European, n) < Sum_Max(American, n): cnt += 1 print cnt
気づき・反省点
- オリジナル解答ではn個の目の和を計算する関数と、和の最大値を求める関数を分けて書いたので冗長になっている。
- さらにヨーロピアンスタイルとアメリカンスタイルも別々に書いたので4倍冗長。
- 両者のスタイルで目の数が違う(ヨーロピアンは37、アメリカンは38)のだが、どんな場合でも対応できるような汎用性の高いコーディングを心がけるべき。
参考にしたサイト
プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問
- 作者: 増井敏克
- 出版社/メーカー: 翔泳社
- 発売日: 2015/10/16
- メディア: Kindle版
- この商品を含むブログ (5件) を見る