Aggregate solution over multiple facts

前端 未结 2 715
你的背包
你的背包 2021-01-26 11:38

Trying to create a predicate (timePeriod/2) that calculates the time period between two dates for a specific fact. I\'ve managed to do this by myself, but face issu

2条回答
  •  情话喂你
    2021-01-26 12:03

    You probably don't quite understand what foreach/3 does. I don't think I fully understand foreach/3 either. I know for sure that it is not the same as say:

    for each x in xs:
        do foo(x)
    

    Another thing: "tuples" in Prolog are not what you might expect, coming from a language like Python or Haskell. This: (a,b,c) is actually this: ','(a,','(b,c)). Much better is to use a flat term, the generic form would be triple(a,b,c). For a pair, the idiom is First-Second.

    So, you can simplify your call to bagof/3 to this:

    ?- bagof(From-To, pop_star(Name, Start, End), Ts).
    Name = 'Bowie',
    Ts = [2008-2010] ;
    Name = 'Jackson',
    Ts = [1987-1991, 1992-1996] ;
    Name = 'Michaels',
    Ts = [1996-2000] ;
    Name = 'Newcastle',
    Ts = [2000-2007].
    

    Once you have a list as above, you need to sum the differences, which would be maybe something like:

    periods_total(Ps, T) :-
        maplist(period_length, Ps, Ls),
        sum_list(Ls, T).
    
    period_length(From-To, Length) :-
        Length is To - From + 1.
    

    And then you can query like this:

    ?- bagof(From-To, pop_star('Jackson', From, To), Ps), periods_total(Ps, T).
    Ps = [1987-1991, 1992-1996],
    T = 10.
    
    ?- bagof(From-To, pop_star(Name, From, To), Ps), periods_total(Ps, T).
    Name = 'Bowie',
    Ps = [2008-2010],
    T = 3 ;
    Name = 'Jackson',
    Ps = [1987-1991, 1992-1996],
    T = 10 ;
    Name = 'Michaels',
    Ps = [1996-2000],
    T = 5 ;
    Name = 'Newcastle',
    Ps = [2000-2007],
    T = 8.
    

提交回复
热议问题