Pythonで解く数学パズル

「プログラマ脳を鍛える数学パズル」をPythonで解きます。

日付の2進数変換:「プログラマ脳を鍛える数学パズル」Q07の答え

問題

年月日をYYYYMMDDの8桁の整数で表したとき、これを2進数に変換して逆から並べ さらに10進数に戻したとき、元の日付と同じ日付になるものを探してください。
期間は、前回の東京オリンピック(1964年10月10日)から、次回の東京オリンピック(2020年7月24日予定)とします。

例)1966年7年13日の場合
● YYYYMMDDのフォーマット:
 19660713
● 2進数に変換:
 1001010111111111110101001
● 2進数を逆から並べる:
 1001010111111111110101001
● 逆から並べた2進数を10進数に戻す:
 19660713
 ↓
 1966年7月13日になる

元ネタ:
第2回「今週のアルゴリズム:日付の2進数変換」正解者発表|CodeIQ MAGAZINE

わたしの考え方

  • Pythonで日付を扱う場合はdatetimeモジュールをimportすればよい。
  • 日付の加算を行うにはtimedeltaを使う。
  • 2進数変換した時の回文判定はQ01を参考に。

pythonista.hateblo.jp

わたしのオリジナル解答

import datetime

def ispalindrome(x):
    y = x.year
    m = x.month
    d = x.day
    YMD = y * 10000 + m * 100 + d
    YMD = format(YMD, 'b')
    return str(YMD) == str(YMD)[::-1]

sDate = datetime.date(1964, 10, 10)
eDate = datetime.date(2020, 07, 24)

x = sDate

while x != eDate:
    if ispalindrome(x):
        print x
    x = x + datetime.timedelta(days=1)

模範解答のミソ

  • 模範解答も同じく対象の範囲の日付を順にループして検証している。
  • 別解答では、2進数の数値の側から回文になる値が対象範囲の日付になるかを判定している。こちらはPythonで実装するのが難しすぎて諦めた。

気づき・反省点

  • 結果を得ることが大事であって、その過程は幾通りかやり方を考えなければならない。最も効率の良いやり方を選ぶか、拡張性の高いやり方を選ぶかは、場合による。

参考にしたサイト

[Python] 日付や時間の扱い方に入門(datetimeモジュール) - YoheiM .NET
Pythonで2つのdatetimeオブジェクトの期間の1日ごとに処理をする - 雑記
日付の加算 減算 timedelta | Python Snippets