amb解决排列组合问题
2023-03-14 10:30:12 时间
看到这么一个题目:
{3,2,2,6,7,8}排序输出,7不在第二位,68不在一起。
这样的题目似乎避免不了遍历,关键还在于过滤条件的安排,怎么让过滤的范围尽量地小。通常的做法是循环遍历,对于类似Prolog这样的语言来说,由于内置了推理引擎,可以简单地描述问题,让引擎来帮你做递归遍历,解决这类问题是非常简单的。Prolog好久没写,以Ruby的amb操作符为例来解决这道题目:
{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
$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可以看这个。
文章转自庄周梦蝶 ,原文发布时间2009-10-19
相关文章
- 在 Go 里用 CGO?这 7 个问题你要关注!
- 9款优秀的去中心化通讯软件 Matrix 的客户端
- 求职数据分析,项目经验该怎么写
- 在OKR中,我看到了数据驱动业务的未来
- 火山引擎云原生大数据在金融行业的实践
- OpenHarmony富设备移植指南(二)—从postmarketOS获取移植资源
- 《数据成熟度指数》报告:64%的企业领袖认为大多数员工“不懂数据”
- OpenHarmony 小型系统兼容性测试指南
- 肯睿中国(Cloudera):2023年企业数字战略三大趋势预测
- 适用于 Linux 的十大命令行游戏
- GNOME 截图工具的新旧截图方式
- System76 即将推出的 COSMIC 桌面正在酝酿大变化
- 2GB 内存 8GB 存储即可流畅运行,Windows 11 极致精简版系统 Tiny11 发布
- 迎接 ecode:一个即将推出的具有全新图形用户界面框架的现代、轻量级代码编辑器
- loongarch架构介绍(三)—地址翻译
- Go 语言怎么解决编译器错误“err is shadowed during return”?
- 敏捷:可能被开发人员遗忘的部分
- Denodo预测2023年数据管理和分析的未来
- 利用数据推动可持续发展
- 在 Vue3 中实现 React 原生 Hooks(useState、useEffect),深入理解 React Hooks 的