LoginSignup
1
1

More than 5 years have passed since last update.

第23回オフラインリアルタイムどう書く「くねくね増加列」の実装例と若干の解題

Last updated at Posted at 2014-07-06

計算量の少ない実装の例

まずは、問題作成用に書いたもの。

# ruby 2.1.2p95
def solve(s)
  cells=["/"]*6+s.chars+["/"]*6 # "/" は番兵
  (?0..?9).each.with_object( {} ){ |digit, length|
    cells.size.times do |pos|
      next unless cells[pos]==digit
      neis=[-6,-1,1, 6]
        .map{ |d| d+pos }
        .flat_map{ |x|
          c=cells[x]
          /\d/===c && c < digit ? [length[x]] : []
        }
      length[pos] = ( neis + [0] ).max + 1
    end
  }.values.max.to_s
end

$stdout.sync=true
DATA.map do |line|
  num, src, exp = line.split(/\s+/)
  actual = solve( src )
  ok = actual==exp
  p [ num, src, exp, actual ] unless ok
  ok
end.all?{ |x| x }.tap{ |x| p x }

__END__
0 01224/82925/69076/32298/21065 6
1 03478/12569/03478/12569/03478 10
2 09900/28127/87036/76545/87650 10
50  02489/77571/84873/03879/84460 7

再帰しない動的計画法で、マス目の数字が小さいものから順に処理する。
cells=["/"]*6+s.chars+["/"]*6 # "/" は番兵
とある部分は邪悪な感じだけど

  • もともと入力にある / を左右の番兵として活かす。
  • 上下に番兵がいないので、["/"]*6 で追加する。

ということ。
each_with_index のなかの times のなかの flat_map のなかに 〜?〜:〜 があって、ちょっとよろしくない感じ。

計算量を気にしない実装の例

一方。
次にお見せするのは当日書いたもの。

# ruby 2.1.2p95
def max_len( s, pos )
  cur = s[pos]
  cx, cy = pos.divmod 5
  neipos = [[-1,0],[1,0],[0,-1],[0,1]].map{ |dx,dy|
    x = cx+dx
    y = cy+dy
    (0...5)===x && (0...5)===y ? x*5+y : nil
  }.select{ |x| x && cur<s[x] }
  1+( neipos.map{ |x| max_len( s, x ) }.max || 0 )
end

def solve(s0)
  s = s0.scan( /\w/ ).to_a
  25.times.map{ |pos|
    max_len(s,pos)
  }.max.to_s
end

$stdout.sync=true
DATA.map do |line|
  num, src, exp = line.split(/\s+/)
  actual = solve( src )
  ok = actual==exp
  p [ num, src, exp, actual ] unless ok
  ok
end.all?{ |x| x }.tap{ |x| p x }

__END__
0 01224/82925/69076/32298/21065 6
1 03478/12569/03478/12569/03478 10
2 09900/28127/87036/76545/87650 10
50  02489/77571/84873/03879/84460 7

こちらは再帰呼び出しによる深さ優先探索。
メモ化も何もせずに全探索。

計算量のオーダーとしてはひどいものだと思うけど、5×5 とわかっているのでこれでよい。

[ ].max は nil なので、
(array.max || 0) は、array が空っぽなら 0、array の中身があったら最大値。
という計算になる。|| は便利だね。

解題

前回( http://nabetani.sakura.ne.jp/hena/ord22irrpas/ )はメモ化つき再帰だったので、今回はメモ化つき再帰じゃない方の動的計画法 と思って出題したつもり。

今回の問題をメモ化つき再帰で書くことはできるし、前回の問題を メモ化つき再帰じゃない方の動的計画法 で書くこともできるけどね。

宣伝

CodeIQ にも、狭義単調増加列 にからめた問題を出してます。
https://codeiq.jp/ace/nabetani_takenori/q957
こちらもよろしく。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1