生成没有重复的配对组,php和mysql

时间:2017-08-18 23:46:43

标签: php mysql

我已经找了一年试图弄清楚这个。我正在尝试建立一个支架运行系统,用于运行保龄球支架。

我有一个带有ID列和BowlerID列的表,称之为bowling_bracket_entries。 ID是唯一的,但可以有多个相同BowlerID的条目,范围从8到1。我想做的是从BowlerID行中成对,但从不重复同一对,然后从这些配对中,将它们分成4对组,其中没有BowlerID在4对配对中重复。

bowling.bracket_entries表的结构 ID | BowlerID

 766    151
767 230
768 201
769 202
770 140
771 205
772 62
773 75
774 56
775 140
759 129
760 60
761 165
762 223
763 145
764 131
765 145
704 197
705 230
706 202
707 167
708 223
709 205
710 217
711 217
712 56
713 60
714 141
715 60
716 193
717 181
718 217
719 75
720 218
721 151
722 223
723 202
724 197
725 140
726 220
727 203
728 56
729 62
730 218
731 160
732 205
733 141
734 167
735 165
736 151
737 205
738 224
739 203
740 142
741 181
742 60
743 60
744 218
745 217
746 224
747 160
748 218
749 223
750 203
751 193
752 202
753 62
754 60
755 142
756 201
757 151
758 203

我尝试随机选择2个BowlerID并将它们与分隔符(即22~100)放在一起,然后插入配对表,然后拉下一个配对(即36~92),创建该对的可变反转(即92~36),并检查Pairing表中是否匹配的值,如果未找到,则插入,从Entries表中删除这些BowlerID的ID并重复,直到它用完值。问题有时我会得到一个与自己配对的BowlerID。偶尔,我会得到一份没有BowlerID与自己配对的完整列表。

SELECT bracket_entries.ID, bracket_entries.BowlerID FROM bracket_entries ORDER BY rand() LIMIT 2

然后将它们放在一起并创建一个配对(即36~68)

$i = 0;
    while($pairing=$rsNewPair->fetch_assoc()) {
        //Build Pairing List
        $thisPairing .= $pairing['BowlerID'];
        $IDS .= $pairing['ID'];
        $i++;
            if($i < 2){
                $thisPairing .= "~";
                $IDS .= "~";
            }
        }


$flipFlop = explode('~', $thisPairing);
    $reversePairing = $flipFlop[1].'~'.$flipFlop[0];
    if($flipFlop[0] == $flipFlop[1]){
        header("Refresh:0");
    }

与现有的相比。

SELECT bracket_pairings.Pairing FROM bracket_pairings WHERE bracket_pairings.Pairing = '".$thisPairing."' OR bracket_pairings.Pairing = '".$reversePairing."'"

如果找不到任何内容,则将配对插入配对表并继续下一个2

bowling_bracket_pairings表结构

    1 203~218
2 193~218
3 217~129
4 201~60
5 60~141
6 141~165
7 197~202
8 230~203
9 220~167
10 60~62
11 151~140
12 151~230
13 193~205
14 60~140
15 217~223
16 203~142
17 60~205
18 197~151
19 205~201
20 218~62
21 56~223
22 217~167
23 56~202
24 217~75
25 224~223
26 160~203
27 151~60
28 131~145
29 140~205
30 202~75
31 62~160
32 142~181
33 224~181
34 145~223
35 165~56
36 218~202

SELECT
PairingID, SUBSTRING_INDEX(Pairing, '~', 1) AS entry1,
SUBSTRING_INDEX(SUBSTRING_INDEX(Pairing, '~', 2), '~', -1) AS entry2

FROM bracket_pairings

然后使用while循环在括号中显示配对,并将每个条目推送到4对中的数组,直到它满,然后进行比较以确保任何用户都不重复。

while(($pairings=$rsEntries->fetch_assoc())&&($loop < 5)){
    $thisBowlerID1 = $pairings['entry1'];
    $thisBowlerID2 = $pairings['entry2'];

    if((!in_array($thisBowlerID1, $thisBracket)) || (!in_array($thisBowlerID2, $thisBracket))){
    while($players=$rsPlayers->fetch_assoc()){
            if($players['BowlerID'] == $thisBowlerID1){
                echo $players['BowlerID'].'<br>';
                //echo $players['Name'].'('.$players['CurrentAvg'].')<br>';
            } 
    } mysqli_data_seek($rsPlayers, 0);
    array_push($thisBracket, $thisBowlerID1);

    while($players=$rsPlayers->fetch_assoc()){
        if($players['BowlerID'] == $thisBowlerID2){
            echo $players['BowlerID'].'<br><br>';
            //echo $players['Name'].'('.$players['CurrentAvg'].')<br><br>';
    } 
    } mysqli_data_seek($rsPlayers, 0);
    array_push($thisBracket, $thisBowlerID2);

    $removeSQL="DELETE FROM bracket_pairings WHERE bracket_pairings.PairingID = ".$pairings['PairingID'];
    $removePairing = $connAdmin->query($removeSQL);
    $loop++;
    }
    $thisBracket = array();
}
}

我有72个条目当我尝试将它们分成4个组(8个条目)时,它似乎永远不会填满9个括号,只有大约7.5,然后在表格中留下随机分配的各种配对放置,但我还有空位。

结果

    Bracket 1
62
141

142
151

131
218

140
56

Bracket 2
145
201

193
160

56
205

129
203

Bracket 3
167
75

217
201

224
217

230
140

Bracket 4
60
193

203
197

141
167

223
220

Bracket 5
60
165

202
142

181
60

202
202

Bracket 6
205
140

62
218

217
60

230
223

Bracket 7
165
223

205
218

205
75

56
151

Bracket 8
202
203

正如您所看到的,结果是8未填充。

以下是未包含的内容:

5   197~218
10  60~223
15  181~62
20  203~60
25  160~217
30  151~151
35  145~224

不确定为什么每五个人都跳过了。我认为我走在正确的轨道上,但任何帮助或想法如何解决我遇到的问题都会很棒。

1 个答案:

答案 0 :(得分:0)

好的,首先:不要将配对保存为“203~60”这样的字符串。当您必须始终组合/拆分值时,使用数据库变得更加困难。您的表格应位于3NF

第二:在构建配对时,不要将配对保存在数据库中。将它们保存在php的内存中以避免任何不必要的数据库调用,只是为了查看配对是否已经添加,这样就快得多。

话虽如此,有一些算法可以查找您的问题。您应该检查以下链接:

我可以想到一些算法,但在某些情况下失败了。该算法将如下工作: 您可以使用https://en.wikipedia.org/wiki/Round-robin_tournament#Scheduling_algorithm上的算法为9个团队创建一个计划,每个团队有8个成员。假设它们被称为“a”到“i”。配对将如下所示:

abcd  aibc  ahib  aghi afgh
hgfe  gfed  fedc  edcb dcbi

aefg  adef  acde  bcfg
cbih  bihg  ihgf  dehi

通过让“a”团队到位并围绕桌子/配对旋转其余团队来获得此种子。但是你必须跳过一个团队,因为你有9个团队可以获得4 * 2种种子。在第九组中,“a”团队缺失,其中包含剩余的“b”到“i”的种子。

当我们拥有9个团队,每个团队有8名成员时,他们可以表示为:

aaaaaaaa
bbbbbbbb
cccccccc
dddddddd
eeeeeeee
ffffffff
gggggggg
hhhhhhhh
iiiiiiii

当你有超过9支球队时,你应该尝试将它们组合在一起,就像它们属于一个大小为8的伪队伍一样。这可以是这样的:

aaaaaabb
ccccddde
fffffggg
hhiijjjj
kkkkklll
mmmmnnnn
ooopppqq
rrrrrsss
ttuuvvww

由于这些团队将处于“相同”的伪团队中,因此它们彼此不匹配,算法仍然有效。

然而,如果你不能把团队放在8人的伪团队中,算法会失败。假设你有2个团队,8个成员和8个团队,大小为7。 伪团队看起来像这样:

aaaaaaaa
bbbbbbbb
cccccccj
dddddddj
eeeeeeej
fffffffj
gggggggj
hhhhhhhj
iiiiiiij

在这种情况下,最终“c”行的“第8”玩家可能会对抗“d”行的“第8”玩家,但他们实际上是在同一个团队中。您可能会尝试将行“c”的“第8个”播放器移动到“c”行中的不同位置。但是当你正在修理这条道路时,无论如何你都可以使用回溯算法。

通过回溯您强制所有组合并在发现解决方案不起作用时跳过组合。检查上面的URL以了解回溯(动画gif可能会有所帮助)。