首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >CS50问题集3- Tideman中的逻辑缺陷?

CS50问题集3- Tideman中的逻辑缺陷?
EN

Stack Overflow用户
提问于 2020-06-09 13:24:03
回答 1查看 1.6K关注 0票数 0

我目前正在学习CS50,这是哈佛大学的一个基于在线的编程入门模块。当我为一个叫做"Tideman“的问题写代码时,我对lock_pairs函数有很多困难,因为我对编码非常陌生。问题的描述可以在这里找到:https://cs50.harvard.edu/x/2020/psets/3/tideman/

在@TomKarze的一些帮助下,我设法稍微改进了我的代码,但由于某些原因,我现在无法满足问题的一个要求,即我的代码不能像现在应该的那样工作,但我非常肯定几天前它工作了。即使我使用我的原始代码(没有Tom的输入),它仍然不再工作,所以我真的很困惑(就像...我是不是看到了什么?)。

我有问题的函数是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool iscycle(int index, bool visited[])
{
    if (visited[index])
    {
        return true;
    }
    visited[index] = true;
    for (int i = 0; i < candidate_count; i++)
    {
        if (locked[index][i] && iscycle(i, visited))
        {
            return true;
        }
    }
    return false;
}

// Lock pairs into the candidate graph in order, without creating cycles
void lock_pairs(void)
{
    for (int i = 0; i < pair_count; i++)
    {
        locked[pairs[i].winner][pairs[i].loser] = true;
        bool visited[candidate_count];
        for (int j = 0; j < candidate_count; j++)
        {
            visited[j] = false;
        }
        if (iscycle(i, visited))
        {
            locked[pairs[i].winner][pairs[i].loser] = false;
        }
    }
    return;
}

我的整个代码(包括上面的函数)如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <cs50.h>
#include <stdio.h>
#include <string.h>

// Max number of candidates
#define MAX 9

// preferences[i][j] is number of voters who prefer i over j
int preferences[MAX][MAX];

// locked[i][j] means i is locked in over j
bool locked[MAX][MAX];

// Each pair has a winner, loser
typedef struct
{
    int winner;
    int loser;
}
pair;

// Array of candidates
string candidates[MAX];
pair pairs[MAX * (MAX - 1) / 2];

int pair_count;
int candidate_count;

// Function prototypes
bool vote(int rank, string name, int ranks[]);
void record_preferences(int ranks[]);
void add_pairs(void);
void sort_pairs(void);
void lock_pairs(void);
void print_winner(void);

int main(int argc, string argv[])
{
    // Check for invalid usage
    if (argc < 2)
    {
        printf("Usage: tideman [candidate ...]\n");
        return 1;
    }

    // Populate array of candidates
    candidate_count = argc - 1;
    if (candidate_count > MAX)
    {
        printf("Maximum number of candidates is %i\n", MAX);
        return 2;
    }
    for (int i = 0; i < candidate_count; i++)
    {
        candidates[i] = argv[i + 1];
    }

    // Clear graph of locked in pairs
    for (int i = 0; i < candidate_count; i++)
    {
        for (int j = 0; j < candidate_count; j++)
        {
            locked[i][j] = false;
        }
    }

    pair_count = 0;
    int voter_count = get_int("Number of voters: ");

    // Query for votes
    for (int i = 0; i < voter_count; i++)
    {
        // ranks[i] is voter's ith preference
        int ranks[candidate_count];

        // Query for each rank
        for (int j = 0; j < candidate_count; j++)
        {
            string name = get_string("Rank %i: ", j + 1);

            if (!vote(j, name, ranks))
            {
                printf("Invalid vote.\n");
                return 3;
            }
        }

        record_preferences(ranks);

        printf("\n");
    }

    add_pairs();
    sort_pairs();
    lock_pairs();
    print_winner();
    return 0;
}

// Update ranks given a new vote
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;
            return true;
        }
    }
    return false;
}

// Update preferences given one voter's ranks
void record_preferences(int ranks[])
{
    for (int i = 0; i < candidate_count; i++)
    {
        for (int j = 0; j < candidate_count; j++)
        {
            if (i < j)
            {
                preferences[ranks[i]][ranks[j]]++;
            }
        }
    }
    return;
}

// Record pairs of candidates where one is preferred over the other
void add_pairs(void)
{
    for (int i = 0; i < candidate_count; i++)
    {
        for (int j = i + 1; j < candidate_count; j++)
        {
            if (preferences[i][j] > preferences[j][i])
            {
                pairs[pair_count].winner = i;
                pairs[pair_count].loser = j;
                pair_count++;
            }
            else if (preferences[i][j] < preferences[j][i])
            {
                pairs[pair_count].winner = j;
                pairs[pair_count].loser = i;
                pair_count++;
            }
        }
    }
    return;
}

// Sort pairs in decreasing order by strength of victory
void sort_pairs(void)
{
    int swapcounter = -1;
    pair toswap;
    do
    {
        swapcounter = 0;
        for (int i = 0; i < pair_count - 1; i++)
        if (preferences[pairs[i].winner][pairs[i].loser] < preferences[pairs[i + 1].winner][pairs[i + 1].loser])
        {
            toswap = pairs[i];
            pairs[i] = pairs[i + 1];
            pairs[i + 1] = toswap;
            swapcounter++;
        }
    }
    while (swapcounter != 0);
    return;
}

bool iscycle(int index, bool visited[])
{
    if (visited[index])
    {
        return true;
    }
    visited[index] = true;
    for (int i = 0; i < candidate_count; i++)
    {
        if (locked[index][i] && iscycle(i, visited))
        {
            return true;
        }
    }
    return false;
}

// Lock pairs into the candidate graph in order, without creating cycles
void lock_pairs(void)
{
    for (int i = 0; i < pair_count; i++)
    {
        locked[pairs[i].winner][pairs[i].loser] = true;
        bool visited[candidate_count];
        for (int j = 0; j < candidate_count; j++)
        {
            visited[j] = false;
        }
        if (iscycle(i, visited))
        {
            locked[pairs[i].winner][pairs[i].loser] = false;
        }
    }
    return;
}

// Print the winner of the election
void print_winner(void)
{
    for (int i = 0; i < candidate_count; i++)
    {
        for (int j = 0; j < candidate_count; j++)
        {
            if (locked[j][i] == false)
            {
                printf("%s\n", candidates[i]);
            }
        }
    }
    return;
}

当我通过Check50运行它时,一个内置的检查器来查看我的代码是否满足了问题的要求,我得到的结果是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
:) tideman.c exists
:) tideman compiles
:) vote returns true when given name of candidate
:) vote returns false when given name of invalid candidate
:) vote correctly sets rank for first preference
:) vote correctly sets rank for all preferences
:) record_preferences correctly sets preferences for first voter
:) record_preferences correctly sets preferences for all voters
:) add_pairs generates correct pair count when no ties
:) add_pairs generates correct pair count when ties exist
:) add_pairs fills pairs array with winning pairs
:) add_pairs does not fill pairs array with losing pairs
:) sort_pairs sorts pairs of candidates by margin of victory
:) lock_pairs locks all pairs when no cycles
:( lock_pairs skips final pair if it creates cycle
    lock_pairs did not correctly lock all non-cyclical pairs
:) lock_pairs skips middle pair if it creates a cycle
:) print_winner prints winner of election when one candidate wins over all others
:) print_winner prints winner of election when some pairs are tied

我无法理解我逻辑中的缺陷在哪里。

附注:如果任何人能花时间向我解释一下,从效率和“代码设计”的角度来看,什么时候递归比迭代更可取,反之亦然,我也会非常感激!

EN

回答 1

Stack Overflow用户

发布于 2020-10-19 01:40:21

我一直在努力使用这个函数。基本上,在这个递归函数中,如果其中一个获胜者等于失败者,那么所有的循环都被锁定,则必须返回TRUE。但是您正在检查已访问的数组,我也使用了“已访问”路径,并且我花了一些时间来寻找另一种方式:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62283700

复制
相关文章
父进程退出时如何确保子进程退出?
子进程退出的时候,父进程能够收到子进程退出的信号,便于管理,但是有时候又需要在父进程退出的时候,子进程也退出,该怎么办呢?
编程珠玑
2019/09/02
12.4K0
解决Mac终端退出时的不爽
从Fedora切换到Linux下,有很多不适应,与其说不适应不如说不爽,其中一个就是今天要说的终端输入exit的问题.在Linux发行版中,输入exit会推出当前窗口,而Mac居然不是,弄出来一个特别脑残的Process Completed,中文版提示大概是提示进程已完成. 然后什么也不能做,只能关闭.真心有点搞不懂这么设计的用意是什么.
技术小黑屋
2018/09/04
1.9K0
解决Mac终端退出时的不爽
nohup 退出终端不退出任务
你是否遇到过远程在linux 下运行node,python 监听脚本,程序跑起来以后,退出了终端,当你再登录时发现原先的任务已经退出了,怎么办?怎么才能在终端退出的情况下,让任务正常运行。
酒馆丁老师
2020/09/08
4.9K0
如何防止PHP进程异常退出(进程被杀)?
通常,在cli下运行的常驻后台PHP进程,可能异常退出,比如php执行过程中出现的致命错误,或被 kill 命令手动杀死等。如下面的php代码:
猿哥
2019/07/25
2.5K0
如何在 centos 终端中退出一个程序
在 Linux 中,你可以使用 Ctrl+C 键来中止终端中的运行程序。这对 Ubuntu 和其他 Linux 发行版都适用。
用户4988085
2021/09/17
4.6K0
cmd中如何退出Python
cmd中如何退出Python      (1)在命令行上输入exit()      (2)在命令行上输入quit() 好像还有一种方法是在命令行上输入Ctrl+Z,再按回车,但是我一直成功不了,
py3study
2020/01/03
2.2K0
cmd中如何退出Python
在 Linux 终端中退出一个程序的操作命令
在 Linux 中,你可以使用 Ctrl+C 键来中止终端中的运行程序。这对 Ubuntu 和其他 Linux 发行版都适用。
用户9105998
2021/11/22
5.2K0
PHP内存分配超过限制的退出流程
我们知道,在PHP的世界里,如果我们要申请一块内存 ,但是没有申请到,那么就会导致fatal级别的错误。我们来测试下:
桶哥
2020/07/15
1.7K0
Node 脚本遭遇异常时如何安全退出
一个 Node 相关的项目中,总是少不了跑脚本。跑一个脚本拉取配置、处理一些数据以及定时任务更是家常便饭。
山月
2020/08/28
1.8K0
当Python退出时,为什么不清除所有分配的内存?
在讨论为什么 Python 在退出时不清除所有分配的内存之前,我们需要了解 Python 的内存管理机制。Python 使用一种称为 引用计数 的垃圾回收机制来管理内存。在这种机制下,每个对象都有一个引用计数器,记录着当前有多少个引用指向该对象。当引用计数器为 0 时,对象将被销毁,内存得以释放。然而,在 Python 退出时,并不会清除所有分配的内存。本文将探讨这个问题,并给出相应的解释。
疯狂的KK
2023/08/05
1.2K0
当Python退出时,为什么不清除所有分配的内存?
如何退出Vim
阅读本文大概需要 1 分钟 退出Vim: 如果您处于编辑模式,请先<Esc>按键。 然后输入:wq + <Enter>保存并退出。 你想要的很少见,但是如果没有保存就退出,你就可以跑了 :q! + <Enter> 结束 鉴于您处于命令模式: :wqa将写入,退出所有缓冲区(如果您有多个缓冲区) :x 也将保存并退出 :ex 如上 ZZ 将保存并退出 ZQ 将退出 :1,5wq将只保存第1到第5行并退出 还有更多。多很多。感兴趣吗?你学会了吗?
硬核编程
2019/09/25
5.3K0
python中如何退出多层循环
 2、使用函数配合return关键字 实现跳出循环(在函数内部只要执行完return语句 则直接退出函数)
py3study
2020/01/20
2.2K0
[UWP]在应用退出时弹出确认提示框
在应用退出时(点击右上角的关闭按钮)弹出一个确认按钮可以说是一个最常见的操作了,例如记事本的“你是否保存”:
dino.c
2019/12/12
3.9K0
[UWP]在应用退出时弹出确认提示框
centos 如何退出vim
点击ESC进入“正常模式”,然后输入“:”,进入“命令模式”。此时屏幕的下方会出现一个冒号,你可以输入以下命令,并按“ENTER”执行:
全栈程序员站长
2022/08/31
3.1K0
linux vi命令 退出不保存,linux vi保存退出命令(如何退出vi)
若用户真的希望用文件的当前内容替换newfile中原有内容,可使用命令 :q! Vi放弃所作修改而直接退到shell下,则Vi在显示窗口的状态行给出提示信息: File exists (use ! to override) 此时, 在末行模式下,。
全栈程序员站长
2022/11/11
27.3K0
如何退出Vi或Vim编辑器「建议收藏」
The vi editor is confusing if you’re not used to it. It takes a secret handshake to escape this application if you’ve stumbled into it. Here’s how to quit vi or vim on Linux, macOS, or any other Unix-like system.
全栈程序员站长
2022/11/11
5K0
如何退出Vi或Vim编辑器「建议收藏」
Python 循环的继续与退出 continue and break
循环的继续与退出 continue and break continue语法 功能 循环遇到continue将停止本次数据循环 , 进入下一次循环 用法 while bool: continue for item in iterable: continue print(item) 参数 continue属于语法, 不需要加 ( )即可执行 无参数 返回值 continue是语法,没有返回值 break语法 功能 使循环正常停止循环(遍历) 这时如果循环配合了Else语句,else语句将不执行 用法
Zkeq
2022/05/18
9460
git 中的退出
链接:https://pan.baidu.com/s/1Zl7EEZY-kfMzSDGOeGgblw 提取码:ec35
李才哥
2019/08/12
3.8K0
git 中的退出
python中break退出for循环 和continue退出for循环
其实break和continue退出for循环的用法和退出while的用法是一样的。break,当某些条件成立退出循环,后面代码不执行,终止整个循环;continue,当某些条件成立终止当前循环继而执行下次循环。下面用2个代码示例来看看一下怎么使用以及执行结果。
python自学网
2022/03/28
2.5K0
python中break退出for循环 和continue退出for循环
当被监测的进程异常退出后,如何启动 - WGCLOUD
那么我们如何在进程退出后,怎么启动进程呢?以下三种方式均为WGCLOUD提供的功能
那年十八
2022/10/22
1.6K0
当被监测的进程异常退出后,如何启动 - WGCLOUD

相似问题

如何恢复ext3 fs上已删除的文件

50

在ubuntu8.04上升级ext3 fs

10

如何从损坏的ext3分区恢复数据?

30

EXT3 3-fs错误(设备dm-10)

10

在挂载上禁止EXT3 3-fs警告

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文