从文本文件中随机配对两次

时间:2016-05-10 01:09:37

标签: c random readfile

我对 C 编程相当新,我试图完成此随机配对程序,但我在启动它时遇到问题。基本上,程序需要从文本文件中读取3个字母的团队名称,将它们放入一个数组中,然后将团队随机地相互配对。有两轮,在第二轮,没有任何重赛。此外,来自同一所学校的团队不能互相对抗。来自同一所学校的团队在文本文件中共享相同的第一个字符和行。任何人都可以帮我解决这个问题吗? :)这是名为provisions.txt的文本文件:

  

ABA ABC ABD ABG
  BAA BAB BAC
  CAB CBA
  DAB DBC DBE DBA
  EAB
  FAB FAC FAA
  GAB GAA
  HAA HAB
  IAB
  JAA
  KAA
  LAL LAB
  MAA MAB MBA妈妈
  NAN NAB

到目前为止我的代码是:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

int main()
{
// Read characters from text file into array
FILE *file = fopen("provision.txt", "r");

char teamList[115];
char teams[32][4];  // Holds team names
int i;

for(i = 0; i < 32; i++){
    fscanf(file, "%s", teams[i]);
}

for(i = 0; i < 32; i++){
        printf("%s \n", teams[i]);  // Test to make sure teams are read in
}

// Clean up
fclose(file);

return 0;
}

如果可能的话,我想将这两轮的输出存储在名为round1_pairings.txt和round2_pairings.txt的文本文件中。

1 个答案:

答案 0 :(得分:0)

该程序试图解决一些微妙的问题,例如随机选择偏差,退出死端匹配尝试等等。由于团队不足,无法保证在给定轮次无法配对的情况下终止。其他学校,更有可能发生更多轮次(不太可能只有两轮和许多学校)。

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define NAMELEN 3
#define ROUNDS 2
#define RETRIES 10 // max attempts before restarting matching                                                           

#define STR_HELPER(x) #x // http://stackoverflow.com/a/5459929/4323                                                     
#define STR(x) STR_HELPER(x)
#define NAMEPRINTF "%" STR(NAMELEN) "s"

typedef char team_t[NAMELEN + 1];

typedef struct
{
    team_t team;
    team_t opponents[ROUNDS];
} pairing_t;

// the first round is round=0                                                                                           
// when round>0, prior round matches will be prevented from recurring                                                   
void make_matches(pairing_t* pairings, size_t count, size_t round)
{
    // clip random() range to avoid bias toward first teams                                                             
    long randmax = LONG_MAX - LONG_MAX % count - 1;
  begin:
    for(size_t ii = 0; ii < count; ++ii) {
        if(pairings[ii].opponents[round][0]) continue; // already paired                                                
        //printf("matching: %s\n", pairings[ii].team);                                                                  
        unsigned retry = 0;
        while(retry < RETRIES) {
            long rand = random();
            if (rand > randmax) continue; // avoid bias                                                                 
            pairing_t *opp = &pairings[rand % count];
            if(opp->team[0] == pairings[ii].team[0]) { // same school                                                   
                ++retry;
                continue;
            }
            if(opp->opponents[round][0]) continue; // already paired                                                    
            size_t prior;
            for(prior = 0; prior < round; ++prior) {
                if(!memcmp(opp->team, pairings[ii].opponents[prior], sizeof(team_t))) {
                    break;
                }
            }
            if(prior != round) continue; // duplicate pairing                                                           
            //printf("match made: %s %s\n", opp->team, pairings[ii].team);                                              
            memcpy(pairings[ii].opponents[round], opp->team, sizeof(team_t));
            memcpy(opp->opponents[round], pairings[ii].team, sizeof(team_t));
            break;
        }
        if(retry == RETRIES) { // matching failed, start again                                                          
            for(size_t ii = 0; ii < count; ++ii) {
                memset(pairings[ii].opponents[round], 0, sizeof(team_t));
            }
            goto begin;
        }
    }
}

int main(void)
{
    srandom(time(NULL));

    FILE *file = fopen("provision.txt", "r");

    size_t capacity = 15; // arbitrary initial size                                                                     
    pairing_t *pairings = calloc(capacity, sizeof(pairing_t));
    if(!pairings) abort();

    size_t count = 0;
    while(fscanf(file, NAMEPRINTF, pairings[count].team) != EOF) {
        //printf("%s\n", pairings[count].team);                                                                         
        ++count;
        if(count >= capacity) { // expand array                                                                         
            capacity *= 2;
            pairings = realloc(pairings, capacity * sizeof(pairing_t));
            if(!pairings) abort();
            memset(&pairings[count], 0, (capacity - count) * sizeof(pairing_t));
        }
    }

    for(size_t round = 0; round < ROUNDS; ++round) {
        make_matches(pairings, count, round);
    }

    for(size_t ii = 0; ii < count; ++ii) {
        printf("%s %s %s\n", pairings[ii].team, pairings[ii].opponents[0], pairings[ii].opponents[1]);
    }

    free(pairings);
    fclose(file);
    return 0;
}

输出是一个简单的表格,有三列:团队比赛,他们的第一个对手,以及他们的第二个对手。我确定你可以根据需要弄清楚如何将它们写成单独的文件。