每日委托:一位大学生的忏悔

救命,好后悔上学期没好好学c语言搞得现在小学期痛苦的想死。
是一道挺简单的题了,已经挣扎了两天了。
我的测试用例已经过去了,但是还有一个隐藏的就是过不去。
描述
Tom 和 Jerry 做猜数字的游戏,Tom 想一个数字然后让 Jerry 去猜,数字的范围在 1 到 10 之间。对于 Jerry 每讲的一个数,Tom 都要讲这个数是 too high 或者 too low 或者 right on,直到 right on 结束。为了防止 Tom 作弊,Jerry 把每一次的对话记录下来,现在让你去判断 Tom 有没有作弊。

输入
游戏可能做很多次,直到 Jerry 猜 0 的时候游戏结束,每一次猜测由一个正整数和一行回答组成。

输出
对每一次游戏如果 Tom 的回答有自相矛盾的地方,就输出 Tom is dishonest,否则输出 Tom may be honest。

测试输入
5↵
too low↵
7↵
too high↵
6↵
right on↵
10↵
too high↵
3↵
too low↵
4↵
too high↵
2↵
right on↵
0↵

期望输出
Tom may be honest↵
Tom is dishonest↵

然后是我那个拉胯的代码


```c
#include <stdio.h>
#include <string.h>

typedef struct {
    int guess;
    char response[15];
} Record;

int main() {
    int guess;
    char response[15];
    int correctAnswer = 0;
    int foundCorrectAnswer = 0;
    int i = 0;

    // 定义记录数组和计数变量
    Record history[1000]; // 假设最多记录1000个数据
    int count = 0;

    // 定义诚实程度标志变量
    int isHonest = 1;

    while (scanf("%d", &guess) == 1 && guess != 0) {
        getchar();
        fgets(response, sizeof(response), stdin);
        response[strcspn(response, "\n")] = '\0';

        // 判断是否为 "right on",并设置正确答案
        if (strcmp(response, "right on") == 0) {
            if (foundCorrectAnswer==i) {
                correctAnswer = guess;
                foundCorrectAnswer++;
                i++;
                break;
            }
        }

        // 存储记录
        Record record;
        record.guess = guess;
        strcpy(record.response, response);
        history[count] = record;
        count++;

        // 判断之前记录中的描述是否与正确答案相符
        for (int i = 0; i < count - 1; i++) {
            if (history[i].guess <= correctAnswer && strcmp(history[i].response, "too high") == 0 ) {
                isHonest = 0;
                break;
            }
            if (history[i].guess >= correctAnswer && strcmp(history[i].response, "too low") == 0) {
                isHonest = 0;
                break;
            }
        }

        // 根据判断结果输出诚实程度
        if (!isHonest) {
            printf("Tom is dishonest\n");
        }
        else {
            printf("Tom may be honest\n");
        }
    }

    return 0;
}

思路是先把他们存起来按照right on分组进行判定,不知道哪里还不完善。(躺)

  • 算法:根据回答重置目标数(Tom心中所想的数)可能区间的上下限,当出现非法区间(上限数小于下限时),即证明Tom is dishonest。

  • 我仅会点Python,就用python代码走一走“算法逻辑”

    img

python代码

#!/sur/bin/nve python
# coding: utf-8

def isHonest(text):
    ''' 猜数字游戏诚实判定 '''
    high, low = 10, 1
    text = text.split('\n')
    k = 0
    
    while True:
        
        if text[k] == '0':
            break # 收到游戏结束信号,退出while循环。
        
        num, tip = text[k:k+2] # 截取每次猜测的数字和回答。
        
        if tip == 'too high':
            high = int(num) - 1
        elif tip == 'too low':
            low = int(num) + 1
        elif tip == 'right on':
            
            if low == high:
                print(f"\n{' 恭喜猜中!':~^36}")
            high, low = 10, 1
        myRange = list(range(low, high+1))
        
        if not myRange:
            return 'Tom is dishonest.'
        
        print(f"\n目标数据区间:{myRange}")
        k += 2
    
    return 'Tom may be honest.'


if __name__ == '__main__':
    # 测试用例
    text = '''5
too low
7
too high
6
right on
10
too high
3
too low
4
too high
2
right on
0'''
    print(f"\n游戏过程:\n{text}\n\n诚实判定:{isHonest(text)}")



【以下回答由 GPT 生成】

#include <stdio.h>
#include <string.h>

typedef struct {
    int guess;
    char response[15];
} Record;

int main() {
    int guess;
    char response[15];
    int correctAnswer = 0;
    int foundCorrectAnswer = 0;

    // 定义记录数组和计数变量
    Record history[1000]; // 假设最多记录1000个数据
    int count = 0;

    // 定义诚实程度标志变量
    int isHonest = 1;

    while (scanf("%d", &guess) == 1 && guess != 0) {
        getchar();
        fgets(response, sizeof(response), stdin);
        response[strcspn(response, "\n")] = '\0';

        // 判断是否为 "right on",并设置正确答案
        if (strcmp(response, "right on") == 0) {
            if (foundCorrectAnswer == 0) {
                correctAnswer = guess;
                foundCorrectAnswer = 1;
            } else {
                // 已经找到了正确答案,说明已经作弊
                isHonest = 0;
            }
        }

        // 存储记录
        Record record;
        record.guess = guess;
        strcpy(record.response, response);
        history[count++] = record;
    }

    // 判断之前记录中的描述是否与正确答案相符
    for (int i = 0; i < count - 1; i++) {
        if ((history[i].guess < correctAnswer && strcmp(history[i].response, "too low") != 0) ||
            (history[i].guess > correctAnswer && strcmp(history[i].response, "too high") != 0) ||
            (history[i].guess == correctAnswer && strcmp(history[i].response, "right on") != 0)) {
            isHonest = 0;
            break;
        }
    }

    // 输出结果
    if (isHonest) {
        printf("Tom may be honest\n");
    } else {
        printf("Tom is dishonest\n");
    }

    return 0;
}

优化解决方案: 1. 可以省略变量 i,因为它与 count 变量的值相同,不需要额外的计数变量。 2. 将 foundCorrectAnswer 变量的初始值设为 -1,表示还未找到正确答案。这样可以省略 count 变量的使用,直接判断 foundCorrectAnswer 是否为 -1 来确定是否已经找到正确答案。 3. 在记录对话记录时,可以一边读取一边判断是否有自相矛盾的描述,如果发现自相矛盾就可以立即判断 Tom 作弊并提前结束程序。

优化后的代码如下:

#include <stdio.h>
#include <string.h>

typedef struct {
    int guess;
    char response[15];
} Record;

int main() {
    int guess;
    char response[15];
    int correctAnswer = 0;
    int foundCorrectAnswer = -1;

    // 定义记录数组
    Record history[1000]; // 假设最多记录1000个数据

    while (scanf("%d", &guess) == 1 && guess != 0) {
        getchar();
        fgets(response, sizeof(response), stdin);
        response[strcspn(response, "\n")] = '\0';

        // 判断是否为 "right on",并设置正确答案
        if (strcmp(response, "right on") == 0) {
            if (foundCorrectAnswer == -1) {
                correctAnswer = guess;
                foundCorrectAnswer = 1;
            } else {
                // 已经找到了正确答案,说明已经作弊
                printf("Tom is dishonest\n");
                return 0;
            }
        }

        if ((guess < correctAnswer && strcmp(response, "too low") != 0) ||
            (guess > correctAnswer && strcmp(response, "too high") != 0) ||
            (guess == correctAnswer && strcmp(response, "right on") != 0)) {
            // 发现自相矛盾的描述,说明 Tom 作弊
            printf("Tom is dishonest\n");
            return 0;
        }

        // 存储记录
        Record record;
        record.guess = guess;
        strcpy(record.response, response);
        history[foundCorrectAnswer++] = record;
    }

    printf("Tom may be honest\n");

    return 0;
}

这个版本的代码在每次读取输入时即时判断是否有自相矛盾的描述,如果发现自相矛盾则提前输出 "Tom is dishonest" 并结束程序,否则在程序结束时输出 "Tom may be honest"。



【相关推荐】


  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/648660
  • 除此之外, 这篇博客: C语言实现八大排序算法详解及其性能之间的中的 我们老师给我们花了100个星星的重要,那就是非常重要,快速排序。名字就很嚣张。。。言归正传,快排采用了分治算法。把大问题,分解成小问题。首先我们先找一个基准值,基准值的寻找法,有很多,这里我先用一个取边上值得方法,找到基准值以后呢拿着这个基准值和所有数组比较,使这个数组中比基准值小的都放左边,比基准值大的都放到右边,然后就把原来数组分成三块,中间基准值,左边都是比它小的,右边都是比它大的。然后这两个数组,继续分,一直分。直到他的终止条件,也就是小数组有序了就停止,那么什么时候有序停止呢?小区间长度为1或者长度为0的时候,就是有序了。所有小数组都有序了,那么就是整个数组有序了。只是原理,那么问题,又来了,怎么放左放右呢?我目前会三种。 部分也许能够解决你的问题。

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

供参考:

#include <stdio.h>
#include <string.h>
int main()
{
    char begin[8], end[8];
    int  n, min, max;
    scanf("%d", &n);
    min = 1, max = 10;
    while (n){
        scanf("%s %s", begin, end);
        if (strcmp(begin, "too") == 0){
            if (strcmp(end, "low") == 0)
                min = n + 1;
            else
                max = n - 1;
        }
        else{
            if (n >= min && n <= max)
                printf("Tom may be honest\n");
            else
                printf("Tom is dishonest\n");
            min = 1;
            max = 10;
        }
        scanf("%d", &n);
    }
    return 0;
}