1

我有一个子问题,其解决方案比我怀疑的要大得多。

问题定义如下

从 group 具有 Y 和 Z 或 A 和 B 之间 id 的所有组中删除 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).
4

1 回答 1

2

的。

您描述的模式非常常见,所有严肃的 Prolog 系统都带有强大的元谓词(即,其参数表示谓词的谓词),使您可以轻松地以灵活的方式描述这种情况和许多其他常见情况,最多使用几个简单的您的具体关系的附加定义。

Richard O'Keefe 的基本 Prolog 库提案包含许多此类谓词的描述和实现,这些谓词在所有主要 Prolog 实现以及 Prolog 的Prologue中变得越来越可用。

特别是,你应该学习:

  • include/3
  • exclude/3
  • maplist/[2,3]

请注意,尽管许多描述的谓词是不纯的,因为它们会破坏代码的声明性属性。与真正的关系相反,您将无法在所有方向上使用它们,同时保持逻辑上的合理性。

练习:上面提到的三个谓词中的哪一个,如果有的话,在其他一切都是纯粹的时候保持

于 2016-02-08T18:56:37.787 回答