Problem:
連鎖

問題

次のようなゲームがある．

あるキャラクターが縦 1 列に N 個並んでいる．これらのキャラクターの色は赤，青，黄のいずれかであり，初期状態で同じ色のキャラクターが4つ以上連続して並んでいることはない．プレーヤーは，ある位置のキャラクターを選び他の色に変更することができる．この操作により同じ色のキャラクターが4つ以上連続して並ぶとそれらのキャラクターは消滅する．キャラクターが消滅することにより新たに同じ色のキャラクターが4つ以上連続して並ぶとそれらのキャラクターも消滅し，同じ色のキャラクターが4つ以上連続して並んでいる箇所がなくなるまでこの連鎖は続く．このゲームの目的は，消滅しないで残っているキャラクター数をなるべく少なくすることである．

例えば，下図の左端の状態で，上から6番目のキャラクターの色を黄色から青に変更すると，青のキャラクターが5つ連続するので消滅し，最終的に3つのキャラクターが消滅せずに残る．

初期状態における N 個のキャラクターの色の並びが与えられたとき， 1箇所だけキャラクターの色を変更した場合の，消滅しないで残っているキャラクター数の最小値 M を求めるプログラムを作成せよ．

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．

1行目はキャラクター数 N (1 ≤ N ≤ 10000) だけからなる．続く N 行には 1, 2, 3 のいずれか1つの整数が書かれており， i + 1 行目 (1 ≤ i ≤ N) は初期状態における上から i 番目のキャラクターの色を表す（1 は赤を，2 は青を，3は黄を表す）．

N が 0 のとき入力の終了を示す．データセットの数は 5 を超えない．

出力

データセットごとに, 消滅しないで残っているキャラクター数の最小値 M を１行に出力せよ．

入出力例

入力例

12
3
2
1
1
2
3
2
2
2
1
1
3
12
3
2
1
1
2
3
2
1
3
2
1
3
0

出力例

3
12

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in Ruby (judge verdict: Wrong Answer)

#
# Chain
#

while (n=gets.to_i)!=0

  queue=[]
  chain=[0]
  count=[0]

  n.times do
    char=gets.to_i
    if char==chain[-1]
      count[-1]+=1
    else
      chain<<char
      count<<1
    end
  end
  chain<<0
  count<<0

  # 色を変える候補
  2.upto(chain.size-2) do |i|
    if count[i]==1 && chain[i-1]==chain[i+1] && count[i-1]+count[i+1]>2
      queue<<[i, chain[i-1], -1]
    elsif count[i-1]>2
      queue<<[i, chain[i-1], -1]
    elsif count[i+1]>2
      queue<<[i, chain[i+1], 1]
    end
  end

  # 連鎖
  min=n
  while !queue.empty?

    _chain=chain.dup
    _count=count.dup

    idx, color, shift=queue.shift
    _chain[idx]=color

    if _count[idx]!=1
      if shift<0
      else
        _chain.insert(idx+1, color)
        _count.insert(idx+1, 1)
      end
    end

    idx+=shift

    while _chain[idx]==_chain[idx+1]
      _count[idx]+=_count[idx+1]
      _chain.delete_at(idx+1)
      _count.delete_at(idx+1)
      if _count[idx]>3
        _chain.delete_at(idx)
        _count.delete_at(idx)
      end
      if _chain[idx-1]==_chain[idx]
        idx-=1
      end
    end

    sum=0
    _count[1..-2].map { |c| sum+=c }
    min=sum if sum<min

  end

  puts min

end