区間分割法(スクリプト)

 2015-09-07 区間分割法

を when_exe Gem に実装した際のスクリプトは、ブログの方では紹介したことがなかったようです。
最近 AI との壁打ちで話題にしたので書いておくことにします。

| (1) 連続する冬至月の間隔は中11か月の場合と中12か月の場合がある
 …
| (2) その中12か月の区間を夏至月で分割すると必ず中5か月と中6か月に分かれる
 …
| (3) その中6か月の区間を春分月または秋分月で分割すると必ず中2か月と中3か月に分かれる

この↑部分のロジックは、実は3回記述するのではなく、再帰メソッドで実装ました↓。

lib/when_exe/region/chinese.rb の 980行目あたりから[1]

 # 天正冬至月から1年分の閏月のパターンの取得
 #
 # @param [Numeric] y 年
 # @param [Numeric] n 区間の長さ (12->6->3)
 #
 # @return [Array<Boolean>] f 閏判定表
 #  [ true - 閏月である ]
 #  [ false - 閏月でない ]
 #
 def _intercalary_pattern(y, n)
  m0 = _base_month(y)
  m1 = _base_month(y + n/12.0)
  return Array.new(n, false) if m1-m0 == n
  return _intercalary_pattern(y, n/2) +
      _intercalary_pattern(y + n/24.0, n/2) if n > @intercalary_span
  return _flags(m0, n)
 end

| (4) その中3か月の区間の真ん中の月に着目すると

この↑部分は、時憲暦との共通化を図るため順番に確認するロジックを採用しました↓。

 # 閏判定表(最初を選択)
 #
 # @param [Numeric] m 最初の通月
 # @param [Numeric] n 区間の長さ
 #
 # @return [Array<Boolean>] f 閏判定表
 #
 def _flags(m,n)
  flags = Array.new(n+1, false)
  n.times do |i|
   m += 1
   if _intercalary?(m)
    flags[i+1] = true
    return flags
   end
  end
 end

余分な条件判断がない綺麗なコードでロジックが実現できているように思います。

[1] 読みやすさのため、一部コードを端折りました。


この記事へのコメント