2009-06-24 19 views
7

Tôi sẽ bắt đầu bằng cách nói rằng tôi hiểu rằng chủ đề này phức tạp và có thể không có câu trả lời dễ dàng. Nếu nó dễ dàng thì mọi người sẽ làm nó. Điều đó đang được nói ...Cách tự động tạo lịch biểu giải đấu thể thao

Tôi đã được yêu cầu xây dựng một ứng dụng để quản lý một giải đấu thể thao. Hầu hết các khái niệm khá dễ hiểu ngoại trừ cái này: Cách tạo lịch trình chơi không có sự chồng chéo (đội chơi 2 đội cùng một lúc), trong đó một đội trong một đội chơi hai lần nhưng chơi các đội từ các bộ phận khác một lần và đảm bảo rằng không có lỗ nào trong lịch biểu (mỗi đội chơi mỗi tuần)

Ngay bây giờ quá trình này được thực hiện bằng bảng tính loại đá rosetta mà tôi đã xây dựng để phục vụ mục đích này, nhưng nó chỉ hoạt động đối với số lượng đội được thiết kế. Tôi có các biến thể được thực hiện cho 30 đội, 24 đội và 28 đội. Thay vì liên tục cố gắng điều chỉnh bảng dịch của tôi, tôi muốn có thể mã hóa logic đó và tinh chỉnh quy trình đó thay thế.

Suy nghĩ?

Trả lời

10

Có một hệ thống khá đơn giản được sử dụng trong ví dụ: giải đấu cờ vua được gọi là round-robin.

Ý tưởng là chia các trình phát cho hai bên của bảng. Một trong những người chơi được chỉ định là một "trung tâm" (cho một mong muốn của một từ tốt hơn). Giải đấu bắt đầu bằng việc có người chơi đối đầu nhau chơi với nhau. Sau vòng đầu tiên tất cả mọi người, nhưng các trung tâm di chuyển một ghế phía trước và trắng/đen (nhà/đi trong thể thao) thứ tự được chuyển. Toàn bộ cuộc thi round-robin kết thúc khi các cầu thủ ngồi ở vị trí ban đầu của họ. Nếu bạn muốn tất cả mọi người chơi tất cả mọi người hai lần chỉ làm như vậy một lần nữa.

Wikipedia article với chi tiết triển khai.

Trong trường hợp đặc biệt của bạn, tôi sẽ thử thực hiện vòng quay một lần bao gồm tất cả các đội. Sau đó, bạn làm tương tự cho mỗi bộ phận một lần và để đảm bảo các đội trong các bộ phận chơi lẫn nhau một lần ở nhà và một lần, hãy kiểm tra từ vòng đầu tiên theo cách mà các đội chơi trong vòng đó. Tất nhiên, bạn sẽ chơi tất cả các trận đấu liên bộ trước khi trận đấu kết thúc (kể từ khi trận đấu n-1 cuối cùng chống lại các đội phân chia nội bộ [n = số đội trong phân chia]). Nếu đây là một vấn đề bạn có thể chỉ cần trao đổi các trận đấu xung quanh một chút.

Tôi thực sự đã viết một tập lệnh Python đơn giản thực hiện việc này. Nó không có nhiều dòng mã và tạo ra kết quả khá tốt. Điều này sẽ tạo ra một lịch trình mà mỗi đội chơi mỗi đội trong bộ phận của họ hai lần và một lần chống lại các đội trong các bộ phận khác. Không có kiểm tra để đảm bảo rằng các đội gặp nhau hai lần theo cách mà cùng một đội là ở nhà, tuy nhiên. Nhưng mã này nên cung cấp ý tưởng hay về cách tạo mã lập lịch của riêng bạn.

#!/usr/bin/python 

div1 = ["Lions", "Tigers", "Jaguars", "Cougars"] 
div2 = ["Whales", "Sharks", "Piranhas", "Alligators"] 
div3 = ["Cubs", "Kittens", "Puppies", "Calfs"] 

def create_schedule(list): 
    """ Create a schedule for the teams in the list and return it""" 
    s = [] 

    if len(list) % 2 == 1: list = list + ["BYE"] 

    for i in range(len(list)-1): 

     mid = int(len(list)/2) 
     l1 = list[:mid] 
     l2 = list[mid:] 
     l2.reverse()  

     # Switch sides after each round 
     if(i % 2 == 1): 
      s = s + [ zip(l1, l2) ] 
     else: 
      s = s + [ zip(l2, l1) ] 

     list.insert(1, list.pop()) 

    return s 


def main(): 
    for round in create_schedule(div1): 
     for match in round: 
      print match[0] + " - " + match[1] 
    print 
    for round in create_schedule(div2): 
     for match in round: 
      print match[0] + " - " + match[1] 
    print 
    for round in create_schedule(div3): 
     for match in round: 
      print match[0] + " - " + match[1] 
    print 
    for round in create_schedule(div1+div2+div3): 
     for match in round: 
      print match[0] + " - " + match[1] 
     print 

if __name__ == "__main__": 
    main() 
2

Tôi chỉ sẽ mã hóa những khó khăn này như một công thức boolean và sử dụng một số SAT-giải để có được giải pháp (ví dụ MiniSAT cho C++, SAT4J cho Java, và thậm chí bạn có thể viết bạn sở hữu giải đơn giản). Đầu vào cho các bộ giải này được standartized bởi DIMACS.

Xem thêm "Mã hóa SAT cho vấn đề Golfer xã hội" và "Lịch biểu dựa trên SAT cho Lịch thi đấu" cho mã hóa SAT của các vấn đề tương tự.

2

đây là một shot tại một thực hiện

public interface ITeam 
{ 
    bool PlaysOn(DateTime date); 
    bool canPlay(ITeam); //returns true if a game between the teams is legal (played once/twice 
         //already, same different divisions and other applicable rules 
} 

IEnumerable<ITeam> teams = null; //replace with initialization 
IEnumerable<ITeams> reversed = team.Reverse(); 
IEnumerable<DateTIme> gameDays = null;//replace with initialization 
var count = teams.Count(); 

foreach(var date in gameDays) 
{ 
    for(int i = 0;i<count;i++) 
    { 
     var innerTeams = i % 2 == 0 ? teams : reversed; 
     var team = (from t in innerTeams 
        where !t.PlaysOn(date) 
        select t).First(); 
     var opp = (from t in teams 
       where !t.PlaysOn(date) && t.CanPlay(team) 
       select t).First(); 
     SetupGame(team,opp); 
    } 
} //lot of optimazation possible :) 

Tôi chỉ thử nghiệm nó trên giấy nhưng đối với thiết lập của tôi nó hoạt động. Bằng cách xen kẽ giữa bắt đầu từ lúc bắt đầu danh sách đội và cuối danh sách, tôi tránh các tình huống mà cùng một đội sẽ phải chơi cùng một đội nhiều lần (hoặc chơi liên tục trong cùng một ngày) trong bài kiểm tra giấy của tôi đại diện cho mọi cuộc gặp gỡ có thể xảy ra với tư cách là một đối thủ khác nhau nhưng về cơ bản thì phương thức CanPlay nên làm. Hy vọng điều này sẽ giúp, dù cho nó không phải là một giải pháp hoàn chỉnh

6

Có hai thuật toán, một cho các đội lẻ, một cho cả các đội để đảm bảo vòng quay xảy ra.

Tôi sẽ tạo cho bạn hình ảnh nếu tôi có thể.

ODD # của các đội

Thuật toán là để xoay tất cả các đội bóng chiều kim đồng hồ. Nếu chúng tôi đã có 5 đội:

1 2 --> 3 1 --> 5 3 --> 4 5 --> 2 4 
3 4  5 2  4 1  2 3  1 5 
5  4  2  1  3 

Tại thời điểm này, chúng tôi đã hoàn thành một round robin nơi tất cả mọi người chơi với nhau một lần ... vòng tiếp theo sẽ một lần nữa được ..

1 2 
3 4 
5 

NGAY CẢ # của đội

Khi chúng tôi có số lượng đội đồng đều, bạn quay vòng tương tự, ngoại trừ bạn giữ đội # 1 ở vị trí cố định và xoay tất cả các đội khác xung quanh # 1 theo chiều kim đồng hồ. Vì vậy, nếu chúng ta có 4 đội ..

1 2 --> 1 3 --> 1 4 
3 4  4 2  2 3 

Đây sẽ là một hoàn round robin ... các trận đấu tiếp theo lên sẽ là ..

1 2 
3 4 

lập trình, Có một vài cách bạn có thể tiếp cận điều này. Có lẽ mã được đăng ở trên không giống như vậy ..

+1

Vâng đó là ý định của mã trên :) –

+0

@Rune: Trong trường hợp đó, +1 !!!! –

Các vấn đề liên quan