我目前正在尝试在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。
答案 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].