I have a subproblem for which the solution is way larger than what I would suspect is necessary.
The problem is defined as follows
Remove X from all groups where group has id between Y and Z or A and B
expressed as a pseudo query it looks like this with Y,Z,A,B set to 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).
The result will be
UpdatedGroups = [
group(0, [ subgroup([_,_,_,_]), subgroup([])]),
group(1, [ subgroup([])]),
group(2, [ subgroup([_,_,X])]),
group(3, [ subgroup([_,_])]),
group(4, [ subgroup([_,_])])
]
So, my solution to this is:
While start of current period is less than or equal end of current period, do removal of X in groups, while "incrementing" start of day. Repeat until no more periods
The removal of X in groups is done by "looping" all groups and check if it matches the period, and if it does remove the user from subgroups, which again is done by "looping".
This is a very tedious but straight forward solution, now my problem is that I quite often find myself doing stuff like this, and cannot find approaches to do this in a less comprehensive way.
Are there other approaches than mine that does not cover 50+ lines?
Updated
Thanks a lot, the code became so much cleaner - it might go further, but now it is possible to actually post here (this is modified a bit - but the logic is there)
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).