解決策が必要と思われるものよりもはるかに大きい副問題があります。
問題は次のように定義されます
グループが 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).