看到這么一個題目:
{3,2,2,6,7,8}排序輸出,7不在第二位,68不在一起。
這樣的題目似乎避免不了遍歷,關鍵還在于過濾條件的安排,怎么讓過濾的范圍盡量地小。通常的做法是循環遍歷,對于類似Prolog這樣的語言來說,由于內置了推理引擎,可以簡單地描述問題,讓引擎來幫你做遞歸遍歷,解決這類問題是非常簡單的。Prolog好久沒寫,以Ruby的amb操作符為例來解決這道題目:
#結果為hash,去重
$hash={}
amb=Amb.new
array=[3,2,2,6,7,8]
class << array
alias remove delete
def delete(*nums)
result=dup
nums.each do |n|
result.delete_at(result.index(n)) if result.index(n)
end
result
end
end
#從集合選元素
one=amb.choose(*array)
two=amb.choose(*(array.delete(one)))
three=amb.choose(*(array.delete(one,two)))
four=amb.choose(*(array.delete(one,two,three)))
five=amb.choose(*(array.delete(one,two,three,four)))
six=amb.choose(*(array.delete(one,two,three,four,five)))
#條件1:第二個位置不能是7
amb.require(two!=7)
#條件2:6跟8不能一起出現
def six_eight_not_join(a,b)
"#{a}#{b}"!="68"&&"#{a}#{b}"!="86"
end
amb.require(six_eight_not_join(one,two))
amb.require(six_eight_not_join(two,three))
amb.require(six_eight_not_join(three,four))
amb.require(six_eight_not_join(four,five))
amb.require(six_eight_not_join(five,six))
#條件3:不重復,利用全局hash判斷
def distinct?(one,two,three,four,five,six)
if $hash["#{one},#{two},#{three},#{four},#{five},#{six}"].nil?
$hash["#{one},#{two},#{three},#{four},#{five},#{six}"]=1 #記錄
true
else
false
end
end
amb.require(distinct?(one,two,three,four,five,six))
puts "#{one},#{two},#{three},#{four},#{five},#{six}"
amb.failure
三個條件的滿足通過amb.require來設置,這里安排的只是一種順序,可以根據實際測試結果來安排這些條件的順序以最大程度地提高效率。代碼注釋很清楚了,我就不多嘴了。Ruby amb的實現可以看
這里。什么是amb可以看
這個。