#c #algorithm #logic #cs50 #array-algorithms
Вопрос:
Я завершил и представил более легкую версию задачи, поставленной на неделю, на которой я работаю, я просто заинтересован в завершении более сложной версии для обучения, но я застрял на том, что кажется сутью этого. В принципе, вы должны внедрить систему голосования, которая регистрирует все звания каждого из избирателей. Так, например, предположим, что у вас есть 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("%in", ranks[j]);
}
return true;
}
}
return false;
}
Но затем нас просят преобразовать его в 2d-массив, который сравнивает каждого из кандидатов в основном в битве 1 на 1. Таким образом, в нашем примере ABC массив должен преобразовываться из [2,0,1] в [[0,1,0],[0,0,0],[1,1,0]]
где первый массив представляет первого кандидата и как они действовали против 2-го и 3-го соответственно и т. Д. (первое место в первом массиве всегда должно быть 0, потому что вы не можете сравнить кандидата с тем, сколько голосов они имели против себя, то же самое со средним местом во втором массиве и последним местом в последнем массиве). Другими словами, массив[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 amp;amp; ranks[k] < j) || (ranks[k] < i amp;amp; ranks[k] > j))
{
preferences[i][j] = 1;
}
}
printf("%in", preferences[i][j]);
}
}
return;
}
Имейте в виду, что я уже получил оценку за эту неделю, и я не планирую отправлять эту работу, так что это не обман, даже если вы прямо скажете мне ответ, но я бы предпочел, чтобы вы этого не делали. Я знаю, что многие люди считают, что вам нужно самому разобраться в логике, иначе вы на самом деле не учитесь, что я отчасти понимаю, но в то же время вы можете только много раз биться головой о стену, прежде чем обратиться за помощью.
Спасибо.
Изменить: вот ссылка на более четкое объяснение. Рассматриваемая функция начинается примерно в 7:30. https://www.youtube.com/watch?v=kb83NwyYI68amp;t=492samp;ab_channel=CS50
Комментарии:
1. Вам нужно заполнить массив 3×3, так что, по моему мнению, потребуется двойной массив. В вашем примере ранг {2,0,1} должен соответствовать {{0,1,0},{0,0,0},{1,1,0}} чего я не понимаю. Я получаю нулевую диагональ. Но я, должно быть, что-то упускаю. Если A является наименее любимым, почему предпочтение не {0, 0, 0}. Аналогично для B и C я ожидал бы { 1, 0, 1} и { 1, 0, 0}?
2. Для тех, кто читает в будущем: самый простой способ сделать это-учесть, что массив рангов показывает кандидатов в порядке от победителя до проигравшего. таким образом, предпочтения[ранг[i]] будут представлять позицию в массиве предпочтений, в которой находится победивший кандидат, а предпочтения[ранг[i][j]] будут представлять всех кандидатов, которых они победили (где i-количество кандидатов, а j-количество кандидатов после i).
Ответ №1:
Используя этот термин vote
вместо ranks
для согласованности с видео. Это также более понятно, поскольку нам также нужно иметь дело с формой множественного votes
числа .
Решение немного длинновато, но ключевым моментом является функция rank()
, которая возвращает позицию candidate
для данного vote
. Мы вызываем rank()
для кандидата i
и j
и увеличиваем preferences[i][j]
, если i
ранг выше ( < ), чем j
.
Введено enum candidates
для удобства чтения (использовались имена кандидатов из видео только для 2-го тестового примера; прокомментируйте определение ВОПРОСА). Это также приведет к ошибке компиляции, если вы неправильно напишете имя кандидата.
Кодекс предполагает, что все кандидаты ранжированы. Это прямолинейно, чтобы разделить количество кандидатов и количество кандидатов, которые оцениваются.
#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;
}
Комментарии:
1. Результат не должен отличаться, это означает, что это не сработало. Поскольку вторая строка представляет количество голосов, которые b получил против других кандидатов, и в примере b был последним выбором, поэтому во второй строке должны быть все нули. Но вы дали мне пищу для размышлений, сравнив ранги[i] с рангами[j], так что спасибо.
2. В вопросе, который вы сказали о [2, 0, 1] «Если первый избиратель выберет кандидата C в качестве своего первого выбора, а B в качестве второго (А в качестве последнего)», так что же это?
3. Извини, ты прав, я все испортил. Это должно быть c первым, a вторым, b последним. Вот ссылка на лучшее объяснение. с 7:30 они говорят об этой функции. Еще раз спасибо. Я отредактирую свой пост. youtube.com/watch?v=kb83NwyYI68amp;t=492samp;ab_channel=CS50
4. Не беспокойтесь. Я обновлю свой ответ после того, как вы уточните данные.