FLYING

/* TODO: 気の利いた説明を書く */

“あなたのスキルで飯は食えるか?”の回答コード

makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) - ITmedia エンタープライズ

メンツには[XY][XZ](XYZ)[X](XX)[XX](XXX)の7パターンしかないことに気付いたので,それらのパターンを先頭から探索していく感じで実装してみた。ここまでに半日くらい費やしてるからプログラマとして飯が食えるかどうかには疑問符が付いてしかるべきだけれど,なるべくコードのコピペ部分を減らすように自分なりに頑張ってみたよ!

#!/usr/local/bin/ruby
# -*- encoding: utf-8 -*-

# パターンに合致する要素のインデクスを取得
# あとでdelete_atするのでreverseして返す
def get_positions(cards)
	positions = []
	array = $input.dup
	cards.each {|a|
		return nil unless array.include?(a)
		positions << array.index(a)
		array[positions.last] = 0
	}
	positions.reverse
end

# パターンを探索
def solve_sub(head, incomplete, member_head, member_incomplete)
	# 頭部分や待ち部分が既に存在するなら脱出
	return if (member_head && head) || (member_incomplete && incomplete)
	# パターンに合致する要素のインデクスを取得
	$input.sort!
	cards = yield
	positions = get_positions(cards)
	return unless positions
	# できあがったパターンをメンツに追加
	$members << "[" + cards.join('') + "]" if member_incomplete
	$members << "(" + cards.join('') + ")" if !member_incomplete
	# 手元からパターン牌を取り除く
	positions.each {|a|
		$input.delete_at(a)
	}
	# 次のパターンを探索
	solve(member_head || head, member_incomplete || incomplete)
	# パターン牌を手元に戻す
	$members.pop.split(//).each{|a|
		$input << a.to_i if a.to_i != 0
	}
end

# 探索
def solve(head, incomplete)
	# 待ち完成
	if $input.empty? then
		$answers << $members.sort
		return
	end
	# パターン定義
	conditions = [
		{	# [XY]パターン
			:head => nil,
			:incomplete => true,
			:cards => proc { [$input.first, $input.first + 1] }
		},
		{	# [XZ]パターン
			:head => nil,
			:incomplete => true,
			:cards => proc { [$input.first, $input.first + 2] }
		},
		{	# (XYZ)パターン
			:head => nil,
			:incomplete => nil,
			:cards => proc { [$input.first, $input.first + 1, $input.first + 2] }
		},
		{	# [X]パターン
			:head => true,
			:incomplete => true,
			:cards => proc { [$input.first] }
		},
		{	# (XX)パターン
			:head => true,
			:incomplete => nil,
			:cards => proc { [$input.first] * 2 }
		},
		{	# [XX]パターン
			:head => nil,
			:incomplete => true,
			:cards => proc { [$input.first] * 2 }
		},
		{	# (XXX)パターン
			:head => nil,
			:incomplete => nil,
			:cards => proc { [$input.first] * 3 }
		}
	]
	# 各パターンを探索
	conditions.each {|a|
		solve_sub(head, incomplete, a[:head], a[:incomplete], &a[:cards])
	}
end

# main
$input = gets.chomp.split(//).collect{|a| a.to_i }
$members = []
$answers = []
solve(nil, nil)
print $answers.uniq.collect{|a| a.join('') }.join("\n")

出力例。

$ ruby chinitsu.rb
1112224588899
(111)(222)(888)(99)[45]

$ ruby chinitsu.rb
1122335556799
(123)(123)(55)(567)[99]
(123)(123)(567)(99)[55]
(123)(123)(555)(99)[67]

$ ruby chinitsu.rb
1112223335559
(123)(123)(123)(555)[9]
(111)(222)(333)(555)[9]

$ ruby chinitsu.rb
1223344888999
(123)(44)(888)(999)[23]
(123)(234)(888)(999)[4]
(234)(234)(888)(999)[1]

$ ruby chinitsu.rb
1112345678999
(11)(345)(678)(999)[12]
(11)(123)(678)(999)[45]
(11)(123)(456)(999)[78]
(11)(123)(456)(789)[99]
(123)(456)(789)(99)[11]
(111)(456)(789)(99)[23]
(111)(234)(789)(99)[56]
(111)(234)(567)(99)[89]
(111)(234)(567)(999)[8]
(111)(234)(678)(999)[5]
(111)(345)(678)(999)[2]

バグを見つけたら教えてぬ。