cs50 tideman(将信息从一个数组转换为另一个更大的数组)

cs50 tideman (converting information from one array into another larger one)

我已经完成并提交了我所在一周的较简单版本的问题集,我只是想完成较难的版本以获得学习体验,但我仍然坚持似乎症结所在。基本上你应该实现一个记录每个选民的所有等级的投票系统。例如,假设您有 3 名候选人(A、B 和 C)。如果第一个选民选择候选人 C 作为他们的第一选择,而 A 作为他们的第二选择(B 作为他们的最后选择),那么您将拥有的原始数组看起来像这样 [2,0,1] 表示第三个候选人是第一个选择,第一候选人是第二选择,第二候选人是第三选择。我为此使用的代码如下:

bool vote(int rank, string name, int ranks[])
{
    for (int i = 0; i < candidate_count; i++)
    {
        if(strcmp(candidates[i], name) == 0)
        {
            ranks[rank] = i;

            for( int j = 0; j < candidate_count; j++)
            {
                printf("%i\n", ranks[j]);
            }
            return true;
        }
    }
    return false;
}

但随后我们被要求将其转换为二维数组,在基本上 1vs1 的战斗中比较每个候选人。所以在我们的 ABC 示例中,数组应该从 [2,0,1] 转换为 [[0,1,0],[0,0,0],[1,1,0]] 其中第一个数组代表第一个候选人以及他们分别如何反对第二和第三等(第一个数组中的第一个位置应始终为 0,因为您无法将候选人与他们对自己的投票数进行比较,与第二个阵列中的中间点和最后一个阵列中的最后一个点)。换句话说,array[i][j] 表示候选者 i 对候选者 j 的表现。您应该使用投票函数返回的数组来计算此函数。

我知道它会涉及另一个嵌套循环,可能有 3 层。我需要指出正确的方向。我对一个看起来像这样的函数进行了一系列不同的调整,但我知道它们都是错误的,因为我求助于反复试验而不是逻辑,因为此时逻辑已经打败了我。也许这个论坛并不是真正的逻辑帮助,但我仍然想在没有得到答案的情况下自己解决这个问题。无论如何,这是我一直无奈修补的功能的最新版本。

void record_preferences(int ranks[])
{
    printf("\n");

    for (int i = 0; i < candidate_count; i++)
    {
        for (int j = 0; j < candidate_count; j++)
        {
            for (int k = 0; k < candidate_count; k++)
            {
                if((ranks[k] > i && ranks[k] < j) || (ranks[k] < i && ranks[k] > j))
                {
                    preferences[i][j] += 1;
                }
            }
            printf("%i\n", preferences[i][j]);
        }
    }
    return;
}

请记住,我已经拿到了本周的成绩,我不打算提交这项作业,所以即使你直接告诉我答案也不算作弊,但我更愿意你没有。我知道很多人都相信你需要自己解决逻辑,否则你就不是真正的学习,我有点明白,但与此同时你只能用头撞墙很多次在寻求帮助之前。 谢谢

编辑:这里有一个link更清楚的解释。有问题的函数从 7:30 标记开始。 https://www.youtube.com/watch?v=kb83NwyYI68&t=492s&ab_channel=CS50

为了与视频保持一致,使用术语 vote 而不是 ranks。它也更清晰,因为我们还需要处理复数形式 votes.

解决方案有点长,但关键见解是函数 rank(),其中 returns 给定 votecandidate 的位置。如果 i 排名高于 (<) j.[=24=,我们将候选人 ijrank() 和增量 preferences[i][j] 称为增量 preferences[i][j] ]

引入 enum candidates 以提高可读性(使用视频中的候选名称只是为了获得第二个测试用例;注释掉 QUESTION 的定义)。如果您拼错了候选名称,这也会给您带来编译错误。

代码假定所有候选人都已排名。将候选人数量与正在排名的候选人数量脱钩是很直接的。

#include <stdio.h>
#define LEN(a) (sizeof(a) / sizeof(*a))

enum candidates {
    Alice,
    Bob,
    Charlie
};

void preferences_print(size_t candidates_len, unsigned preferences[candidates_len][candidates_len]) {
    for(size_t i = 0; i < candidates_len; i++) {
        for(size_t j = 0; j < candidates_len; j++) {
            printf("%u%s", preferences[i][j], j + 1 < candidates_len ? ", " : "");
        }
        printf("\n");
    }
}

unsigned rank(size_t candidates_len, unsigned vote[candidates_len], enum candidates candidate) {
    for(size_t i = 0; i < candidates_len; i++) {
        if(vote[i] == candidate) return i;
    }
    printf("Error: skipping invalid cadidate %d", candidate);
    return 0;
}

void votes_to_preferences(size_t votes_len, size_t candidates_len, enum candidates votes[votes_len][candidates_len], unsigned preferences[candidates_len][candidates_len]) {
    for(size_t v = 0; v < votes_len; v++) {
        for(size_t i = 0; i < candidates_len; i++) {
            for(size_t j = 0; j < candidates_len; j++) {
                preferences[i][j] +=
                    rank(candidates_len, votes[v], i) <
                    rank(candidates_len, votes[v], j);
            }
        }
    }
}

int main() {
    enum candidates votes[][3] = {
#define QUESTION
#ifdef QUESTION
        { Charlie, Alice, Bob },
#else // VIDEO
        { Alice, Charlie, Bob },
        { Alice, Charlie, Bob },
        { Charlie, Alice, Bob },
        { Bob, Alice, Charlie }
#endif
    };
    unsigned preferences[LEN(*votes)][LEN(*votes)] = { { 0 } };
    votes_to_preferences(LEN(votes), LEN(*votes), votes, preferences);
    preferences_print(LEN(*votes), preferences);
    return 0;
}