我有一个子问题,其解决方案比我认为必要的解决方案更大。
问题定义如下
从组中ID为Y和Z或A和B之间的所有组中删除X
表示为伪查询,它看起来像Y,Z,A,B设置为0,1,3,4
remove(X,
[ period(0,1), period(3,4) ],
[
group(0, [ subgroup([_,_,X,_,_]), subgroup([X])]),
group(1, [ subgroup([X])]),
group(2, [ subgroup([_,_,X])]),
group(3, [ subgroup([_,X,_])]),
group(4, [ subgroup([X,_,_])])
], UpdatedGroups).
结果将是
UpdatedGroups = [
group(0, [ subgroup([_,_,_,_]), subgroup([])]),
group(1, [ subgroup([])]),
group(2, [ subgroup([_,_,X])]),
group(3, [ subgroup([_,_])]),
group(4, [ subgroup([_,_])])
]
所以,我的解决方案是:
当前期间的开始时间小于或等于当前期间的结束时,请在组中删除X,同时"递增"一天的开始。重复直到不再有句号
在组中删除X是通过"循环"所有组并检查它是否与句点匹配,如果它确实从子组中删除了用户,这又是通过"循环"来完成的。
这是一个非常乏味但直接的解决方案,现在我的问题是我经常发现自己正在做这样的事情,并且找不到以不那么全面的方式做到这一点的方法。
除了我的还有其他方法还没有覆盖50多行吗?
更新
非常感谢,代码变得如此清晰 - 它可能会更进一步,但现在可以实际发布在这里(这有点修改 - 但逻辑就在那里)
inPeriods(Day, [ period(Start,End) | _ ]) :- between(Start,End, Day).
inPeriods(Day, [ _ | RemainingPeriods ]) :- inPeriods(Day, RemainingPeriods).
ruleGroupsInPeriod(Periods, rulegroup(Day,_)) :- inPeriods(Day, Periods).
removeUserFromRelevantRuleGroups(UserId, Periods, RuleGroups, UpdatedRuleGroups) :-
include(ruleGroupsInPeriod(Periods), RuleGroups, IncludedRuleGroups).
exclude(ruleGroupsInPeriod(Periods), RuleGroups, ExcludedRuleGroups),
maplist(updateRuleGroup(UserId), IncludedRuleGroups, UpdatedIncludedRuleGroups)
append(UpdatedIncludedRuleGroups, ExcludedRuleGroups, UpdatedRuleGroups).
updateRuleGroup(UserId, rulegroup(X, RuleList), rulegroup(X, UpdatedRuleList)) :-
maplist(updateRule(UserId), RuleList, UpdatedRuleList).
updateRule(UserId, rule(X, UserList), rule(X, UpdatedUserList)) :-
delete(UserList, UserId, UpdatedUserList).
答案 0 :(得分:2)
是强>
您描述的模式非常常见,所有严肃的Prolog系统都附带强大的元谓词(即,其参数表示谓词的谓词),可以让您轻松地描述这个以及许多其他常见情况。灵活的方式,最多使用一些简单的附加定义来为您的具体关系。
Richard O'Keefe对An elementary Prolog Library的提议包含许多此类谓词的描述和实现,这些谓词在所有主要的Prolog实现和Prologue for Prolog中都越来越多。
特别是,你应该学习:
include/3
exclude/3
maplist/[2,3]
请注意,虽然许多描述的谓词都是不纯,因为它们会破坏代码的声明性属性。与真实关系相反,在保持逻辑健全性的同时,您将无法在所有方向上使用它们。
练习:上面提到的三个谓词中的哪一个(如果有的话)在其他一切都是纯粹的时候会保留logical-purity,哪些(如果有的话)不存在?