Prolog循环计划主页和离开

时间:2017-04-05 01:43:50

标签: prolog

我目前正在尝试在Prolog中设定一个循环计划,并设法让所有球队互相比赛一次,我现在想要对其进行编程,以便所有球队互相比赛两次,无论是主场还是场外,例如[1,2]和[2,1]。我到目前为止的代码如下:

%table of allocated matches
:- dynamic(match_table/2).

%get all teams from 1 .. NumTeams
forTeams(T, T, X) :-
    T =< X.
forTeams(I, T, X) :-
    T < X,
    T1 is T + 1,
    forTeams(I, T1, X).

%teams represented by integers more than 1
check_num_input(T) :-
    integer(T),
    T > 1.

%resets the allocation table of matches
reset_allocations :-
    retractall(match_table(_, _)).

%check the match has not already been allocated
%empty list for once recursion is complete
check_not_allocated(_, []).
%recursively search through allocation list to see if team is allocated
check_not_allocated(T, [X | CurrentMatchesTail]) :-
    \+ match_table(T, X),
    \+ match_table(X, T),
    check_not_allocated(T, CurrentMatchesTail).

%recursively fetch match allocation
get_match_allocation(_, 0, CurrentMatches, CurrentMatches).
get_match_allocation(NumTeams, RemainingNumTeamsPerMatch, CurrentMatches, 
Matches) :-
    RemainingNumTeamsPerMatch > 0,
    forTeams(T, 1, NumTeams),
    \+ member(T, CurrentMatches),
    check_not_allocated(T, CurrentMatches),
    append(CurrentMatches, [T], NewMatches),
    Remaining1 is RemainingNumTeamsPerMatch - 1,
    get_match_allocation(NumTeams, Remaining1, NewMatches, Matches).

%recursively store/ add matches into allocation list
store_allocation_1(_, []).
store_allocation_1(T, [X | MatchesTail]) :-
    assertz(match_table(T, X)),
    store_allocation_1(T, MatchesTail).

%recursively store allocation from match list
store_allocation([_]).
store_allocation([T | MatchesTail]) :-
    store_allocation_1(T, MatchesTail),
    store_allocation(MatchesTail).

%recursively check all required matches are allocated
check_plays_all(_, []).
check_plays_all(T, [Team | TeamsTail]) :-
    %check head team from teams list plays next head team from remaining 
teams list
    (    match_table(T, Team)
    ;    match_table(Team, T)
    ),
    check_plays_all(T, TeamsTail).

check_all_play_all([_]).
%get head team of teams list
check_all_play_all([T | TeamsTail]) :-
    check_plays_all(T, TeamsTail),
    check_all_play_all(TeamsTail).

do_round_robin(NumTeams, _, T, []) :-
    T > NumTeams.
do_round_robin(NumTeams, NumTeamsPerMatch, T, [Matches | MatchesTail]) :-
    T =< NumTeams,
    get_match_allocation(NumTeams, NumTeamsPerMatch, [T], Matches),
    !,
    store_allocation(Matches),
    do_round_robin(NumTeams, NumTeamsPerMatch, T, MatchesTail).
do_round_robin(NumTeams, NumTeamsPerMatch, T, Matches) :-
    T =< NumTeams,
    T1 is T + 1,
    do_round_robin(NumTeams, NumTeamsPerMatch, T1, Matches).

round_robin(NumTeams, NumTeamsPerMatch, Matches) :-
    check_num_input(NumTeams),
    check_num_input(NumTeamsPerMatch),
    reset_allocations,
    NumTeamsPerMatch1 is NumTeamsPerMatch - 1, %1
    do_round_robin(NumTeams, NumTeamsPerMatch1, 1, Matches), %(NumTeams, 1, 
1, Matches_List)
    findall(T, forTeams(T, 1, NumTeams), Teams), %finds all teams from 1 .. 
NumTeams
    check_all_play_all(Teams),
    !,
    reset_allocations.
round_robin(_, _, _) :-
    reset_allocations,
    fail.

要输出两队参加一场比赛的赛程,查询为round_robin(6,2,Schedule)。其中6是团队数量,2是每场比赛的团队数量。

我对Prolog和逻辑编程很陌生,所以会很感激帮助:)

谢谢,

BD。

1 个答案:

答案 0 :(得分:1)

也许更好?

home_away(N, A-B) :-
    between(1, N, A),
    between(1, N, B),
    A \== B.

这将按字典顺序排列所有可能性。

?- findall(X, home_away(3, X), Xs).
Xs = [1-2, 1-3, 2-1, 2-3, 3-1, 3-2].

低于旧答案。

更容易使用between/3

home_away(N, X) :-
    succ(N0, N), between(1, N0, A),
    succ(A, A1), between(A1, N, B),
    (   X = A-B
    ;   X = B-A
    ).

现在甚至没有选择点:

?- home_away(3, X).
X = 1-2 ;
X = 2-1 ;
X = 1-3 ;
X = 3-1 ;
X = 2-3 ;
X = 3-2.

下面你会找到更老的答案。

你的代码真的很难。也许这不是一个有用的想法,但你可以尝试给出一些团队并获得所有可能的游戏,其中每对数字都是家庭客人。

home_away(N, X) :-
    numlist(1, N, Teams),
    append(_, [A|T], Teams),
    member(B, T),
    (   X = A-B
    ;   X = B-A
    ).

现在有了这个,你可以给出一些团队,你得到的团队编号为1,2,......,N为主页和离开

?- home_away(3, X).
X = 1-2 ;
X = 2-1 ;
X = 1-3 ;
X = 3-1 ;
X = 2-3 ;
X = 3-2 ;
false.

?- bagof(X, home_away(4, X), Xs).
Xs = [1-2, 2-1, 1-3, 3-1, 1-4, 4-1, 2-3, 3-2, 2-4, 4-2, 3-4, 4-3].