1014 福尔摩斯的约会

我在做pat练习的时候遇到一个问题,两段逻辑上我看不出不同的两段代码,为什么在提交后结果不相同?题目如下
大侦探福尔摩斯接到一张奇怪的字条:

我们约会吧! 
3485djDkxh4hhGE 
2984akDfkkkkggEdsb 
s&hgsfdk 
d&Hyscvnm

大侦探很快就明白了,字条上奇怪的乱码实际上就是约会的时间星期四 14:04,因为前面两字符串中第 1 对相同的大写英文字母(大小写有区分)是第 4 个字母 D,代表星期四;第 2 对相同的字符是 E ,那是第 5 个英文字母,代表一天里的第 14 个钟头(于是一天的 0 点到 23 点由数字 0 到 9、以及大写字母 A 到 N 表示);后面两字符串第 1 对相同的英文字母 s 出现在第 4 个位置(从 0 开始计数)上,代表第 4 分钟。现给定两对字符串,请帮助福尔摩斯解码得到约会的时间。

输入格式:
输入在 4 行中分别给出 4 个非空、不包含空格、且长度不超过 60 的字符串。

输出格式:
在一行中输出约会的时间,格式为 DAY HH:MM,其中 DAY 是某星期的 3 字符缩写,即 MON 表示星期一,TUE 表示星期二,WED 表示星期三,THU 表示星期四,FRI 表示星期五,SAT 表示星期六,SUN 表示星期日。题目输入保证每个测试存在唯一解。

输入样例:

3485djDkxh4hhGE 
2984akDfkkkkggEdsb 
s&hgsfdk 
d&Hyscvnm

输出样例:

THU 14:04

以下是我的代码,仅使用一个for循环(有两个测试点未通过,提示非0返回):

img

list_1 = input()  #字符串输入
list_2 = input()
list_3 = input()
list_4 = input()
len_x = [len(list_1), len(list_2), len(list_3), len(list_4)]
same_1 = []
same_2 = []
flag = 0
for i in range(max(min(len_x[0:1]),min(len_x[2:3]))):
    if i < min(len_x[0:1]):
        if list_1[i] == list_2[i] and (
                ord('A') <= ord(list_1[i]) <= ord('G') and flag == 0):
            same_1.append(list_1[i])
            flag += 1
        elif list_1[i] == list_2[i] and (ord('0') <= ord(list_1[i]) <= ord('9') or ord('A') <= ord(list_1[i]) <= ord('N')) and flag == 1:
            same_1.append(list_1[i])
    if i < min(len_x[2:3]):
        if list_3[i] == list_4[i] and (
                ord('a') <= ord(list_3[i]) <= ord('z') or ord('A') <= ord(list_3[i]) <= ord('Z')):
            same_2.append(i)

dic1 = {'A': 'MON', 'B': 'TUE', 'C': 'WED', 'D': 'THU', 'E': 'FRI', 'F': 'SAT', 'G': 'SUN'}
if ord('0') <= ord(same_1[1]) <= ord('9'):
    H = int(same_1[1])
else:
    H = ord(same_1[1]) - ord('A') + 10
if same_2[0] >= 60:
    H = H + 1
    same_2[0] = same_2[0] - 60
if H > 23:
    H = H-24
print(dic1.get(same_1[0]), '{:02}'.format(H) + ':' + '{:02}'.format(same_2[0]))

但如果将中间的for循环拆开,变成两个循环,这段代码就能完美通过所有测试点,如下:

for i in range(min(len_x[0:1])):
    if list_1[i] == list_2[i] and (
            ord('A') <= ord(list_1[i]) <= ord('G') and flag == 0):
        same_1.append(list_1[i])
        flag += 1
    elif list_1[i] == list_2[i] and (ord('0') <= ord(list_1[i]) <= ord('9') or ord('A') <= ord(list_1[i]) <= ord('N')) and flag == 1:
        same_1.append(list_1[i])
        break
for i in range(min(len_x[2:3])):
    if list_3[i] == list_4[i] and (
            ord('a') <= ord(list_3[i]) <= ord('z') or ord('A') <= ord(list_3[i]) <= ord('Z')):
        same_2.append(i)

img

我认为这两段代码在逻辑上是没有问题的,能不能给我解释一下为什么会这样?真的很苦恼。

你两个for在一起就会执行i*j次,而单独两个就变成了,i+j次,我马上给你举个例子
样例:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int sum=0,ans=0;
    for(int i=1;i<=5;i++)
    {
        for(int j=1;j<=3;j++)
        {
            sum++;
        }
     } 
     for(int i=1;i<=5;i++) ans++;
     for(int j=1;j<=3;j++) ans++;
     cout<<sum<<" "<<ans<<endl;
}

你会发现这两个代码一个输出15,一个输出8

在你的代码中,使用了一个for循环来同时处理两个字符串的字符,但是由于输入的字符串长度可能不同,所以在第一个for循环中,你加入了条件 i < min(len_x[0:1])i < min(len_x[2:3]) 来保证在较短的字符串长度范围内进行循环。这样做可能会导致在某些情况下,不同长度的字符串无法完全匹配,从而影响到最终的结果。

具体来说,当输入的两个字符串中较短的那个字符串的长度小于第一个不同字符的位置时,第一个for循环无法遍历完整个字符串,导致相应的字符无法加入到same_1列表中。这就导致了你的代码在处理输入不同长度的字符串时,得到的结果不一致。

而将两个for循环拆开后,分别处理两个字符串,就避免了这个问题。拆开后的第一个for循环只处理相同长度的字符串的字符,确保所有的匹配字符都会加入到same_1列表中。然后再处理第二个字符串,同样可以确保所有匹配字符都会加入到same_2列表中。

因此,拆开两个for循环后,你的代码可以正确处理不同长度的字符串,得到正确的结果。而合并为一个for循环后,由于长度不同的字符串无法完全匹配,导致结果出现了问题。

差不多就是这个逻辑,你理解看看

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7603367
  • 除此之外, 这篇博客: C语言项目-后宫选妃系统-第三天-终结中的 其实上面都是今天上午就做好的,但是一直有点烦恼,因为在解决问题的过程中发现如果要去修改的话要对之前的代码大动干戈在这个项目里还好我变量名用的统一,因此只是改了一下每个子函数的返回类型和添加了一个判断,可是自己感觉还是不满意,这个项目算上注释总共420行,不大也不小,但是逻辑还算简单,由此可见在进行中大型项目之前进行构思,伪代码实现多重要!!不要像我这样一头扑上来就写代码,也算是吃了教训了,继续加油!奥利给! 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
    /*
    后宫选妃系统
    六大模块:
        1.下旨选妃 -完成
            输入一名新妃子的名字,新增加一位新的妃子,然后其他妃子的宠爱度减 10 点
        2.翻牌宠幸-完成
            输入一名妃子的名字,翻牌宠幸其,增加其宠爱度10点,减少其他妃子宠爱度10点
        3.打入冷宫-完成
            输入一名妃子的名字,删除一位妃子,然后其他所有的妃子宠爱度加 10 点,若无此人则显示虚惊一场
        4.朕的爱妃呢-完成
            查找妃子,输入妃子的姓名并显示基本信息,被选中的妃子宠幸度加 10 点.其他妃子宠爱度减10点
        5.巡视后宫-完成
            巡视后宫,显示所有在宫妃子信息
        6.游戏规则判定-未
    妃子等级制(始皇制):
        一后
        三夫人
        九嫔
        二十七世妇
        八十一御女
    游戏规则:1.若有三名妃子宠爱度处于50以下则发生暴动,游戏结束
            2.若有人宠爱度达到100,镇压后宫,游戏结束
            3.每名妃子默认宠爱度70点
    */
    
    #include <stdio.h>
    #include <string.h>
    
    typedef struct concubine
    {
        char name[10];  //名字,最多十个字符
        int level;      //后宫等级
        int likability; //宠爱度
    } concu;
    
    //函数声明
    int addOne(concu *ptca, int *num);
    int chooseOne(concu *ptca, int *num);
    int forsakeOne(concu *ptca, int *num);
    int findOne(concu *ptca, int *num);
    void seeAll(concu *ptca, int *num);
    int judege_1(concu *ptca, int *num);
    int judege_2(concu *ptca, int *num);
    
    //   游戏规则判断计数器1   冷宫总人数
    int count = 0, leave = 0; //初始化总比不初始化好
    
    int main(void)
    {
        //存储conu的(X可变长)数组
        concu concus[31];
        int n = 0, *num = &n; //存储后宫妃子总数,使用指针方便更改!数字指针定义时需要&取地址
        concu *p;
    
        //后宫初始化,默认有三位妃子
        concu c1 = {"刘解忧", 1, 70};
        concu c2 = {"孙尚香", 1, 70};
        concu c3 = {"鱼幼薇", 1, 70};
        concus[0] = c1;
        concus[1] = c2;
        concus[2] = c3;
        *num = 3;
    
        //选妃系统界面控制
    
        int c, d; //控制,循环控制界面
        while (d)
        {
            p = concus; //初始化指针
            printf("-------后宫选妃系统-------\n\
                四大模块:\n\
                    1.下旨选妃\n\
                    2.翻牌宠幸\n\
                    3.打入冷宫\n\
                    4.朕的爱妃呢\n\
                    5.后宫巡视\n\
                    6.退出选妃系统\n\
                请输入序号选择功能:\n");
    
            scanf("%d", &c);
            switch (c)
            {
            case 1:
                // printf("1\n");
                addOne(p, num); //函数1
                printf("输入任意键以继续.....\n");
                scanf("%d", &c);
                break;
            case 2:
                // printf("2");
                chooseOne(p, num); //函数2
                printf("输入任意键以继续.....\n");
                scanf("%d", &c);
                break;
            case 3:
                // printf("3");
                forsakeOne(p, num); //函数3
                printf("输入任意键以继续.....\n");
                scanf("%d", &c);
                break;
            case 4:
                // printf("4");
                findOne(p, num); //函数4
                printf("输入任意键以继续.....\n");
                scanf("%d", &c);
                break;
            case 5:
                // printf("5");
                seeAll(p, num); //函数5
                printf("输入任意键以继续.....\n");
                scanf("%d", &c);
                break;
            case 6:
                printf("退出成功...\n");
                c = 0;
                break;
            default:
                printf("小主,查无此功能啊!\n");
                printf("输入任意键以继续.....\n");
                scanf("%d", &c);
                break;
            }
    
            d = judege_1(p, num) && judege_2(p, num);
            if (d == 0)
            {
                printf("后宫暴动,游戏失败!");
                printf("输入任意键以退出.....\n");
                scanf("%d", &c);
            }
        }
    }
    
    //1.下旨选妃-输入一名新妃子的名字,新增加一位新的妃子,然后其他妃子的宠爱度减 10 点
    int addOne(concu *ptca, int *num)
    {
        //根据输入初始化一位妃子的信息
        char ch[10];
        int lev;
        printf("请输入妃子姓名,等级(1-5)(空号间隔):\n");
        scanf("%s %d", ch, &lev);
        concu c;
        strcpy(c.name, ch);
        c.level = lev;
        c.likability = 70;
        int n = *num; //临时数量控制器,操纵循环
        //使用遍历完成下旨选妃中的操作
        concu *p = ptca;
        for (int i = 0; i < n + 1; i++)
        {
            if (strcmp(p->name, ch) == 0)
            {
                printf("皇上,%s已经在宫中了呢!\n", ch);
                return 0;
            }
            p++;
        }
        for (int i = 0; i < n + 1; i++)
        {
    
            if (i < *num)
            {
                ptca->likability -= 10;
                ptca++;
            }
            else
            {
                *ptca = c;
                *num += 1; //总数加一
                printf("恭喜选妃成功;妃子信息:姓名:%s,等级:%d,宠爱度:%d\n", ptca->name, ptca->level, ptca->likability);
                // printf("当前后宫总人数:%d\n", *num);
            }
        }
    }
    
    //2.翻牌宠幸-输入一名妃子的名字,翻牌宠幸其,增加其宠爱度10点,减少其他妃子宠爱度10点
    int chooseOne(concu *ptca, int *num)
    {
        int n = *num; //临时变量,控制循环
        char a_name[10];
    
        //准备翻牌
        printf("皇上,可以翻牌了呢,输入想翻牌的妃子名字即可:\n");
        scanf("%s", a_name);
        // gets(name);
        // printf("1");
        // int i = 0;
        printf("当前即将被翻牌的妃子名称是 %s ...\n", a_name);
    
        //判断是否在宫中
        concu *p = ptca;
        int a_count = 0; //不同名妃子计数器
        for (int i = 0; i < n; i++)
        {
            // printf("%s --- %s\n", p->name, a_name);
            if (strcmp(p->name, a_name) != 0)
            {
                a_count++;
            }
            // printf("%d\n", a_count);
            p++;
        }
        if (a_count == n)
        {
            printf(" %s 还不在宫中呢...\n", a_name);
            return 0;
        }
    
        printf("\n");
        for (int i = 0; i < n; i++)
        {
            if ((strcmp(a_name, (ptca->name)) == 0)) //判断名字是否相等,相等返回0
            {
                ptca->likability += 10;
                printf(" %s 翻牌成功!\n", ptca->name);
            }
            else
            {
                ptca->likability -= 10;
                printf("后宫徒生嫉妒, %s 宠爱度减少10点!\n", ptca->name);
            }
            ptca++; //指针指向下一个结构体
        }
    };
    
    //3.打入冷宫-输入一名妃子的名字,删除一位妃子,然后其他所有的妃子宠爱度加 10 点,若无此人则显示虚惊一场
    int forsakeOne(concu *ptca, int *num)
    {
        int n = *num; //临时变量,控制循环
        char a_name[10];
        concu c;
        strcpy(c.name, "0");
        c.level = 0;
        c.likability = 0;
    
        //准备翻牌
        printf("皇上,您要抛弃哪位妃子呢,输入妃子名字即可:\n");
        scanf("%s", a_name);
        // gets(name);
        // printf("1");
        int i = 0;
        printf("当前即将被即将被打入冷宫的妃子名称是 %s ...", a_name);
    
        //判断是否在宫中
        concu *p = ptca;
        int a_count = 0; //不同名妃子计数器
        for (int i = 0; i < n; i++)
        {
            // printf("%s --- %s\n", p->name, a_name);
            if (strcmp(p->name, a_name) != 0)
            {
                a_count++;
            }
            // printf("%d\n", a_count);
            p++;
        }
        if (a_count == n)
        {
            printf(" %s 还不在宫中呢...\n", a_name);
            return 0;
        }
    
        printf("\n");
        for (int i = 0; i < n; i++)
        {
    
            if ((strcmp(a_name, (ptca->name)) == 0)) //判断名字是否相等,相等返回0
            {
                *ptca = c;
            }
            else
            {
                ptca->likability += 10;
                printf("因 %s 被打入冷宫, %s宠爱度增加10点!\n", a_name, ptca->name);
            }
    
            ptca++; //指针指向下一个结构体
        }
    };
    
    //4.朕的爱妃呢-查找妃子,输入妃子的姓名并显示基本信息,被选中的妃子宠幸度加 10 点.其他妃子宠爱度减10点
    int findOne(concu *ptca, int *num)
    {
        int n = *num; //临时变量,控制循环
        char a_name[10];
        printf("皇上您要查找哪一位妃子呢,输入名字即可:\n");
        scanf("%s", a_name);
        printf("当前要查找的妃子是%s....\n", a_name);
    
       //判断是否在宫中
        concu *p = ptca;
        int a_count = 0; //不同名妃子计数器
        for (int i = 0; i < n; i++)
        {
            // printf("%s --- %s\n", p->name, a_name);
            if (strcmp(p->name, a_name) != 0)
            {
                a_count++;
            }
            // printf("%d\n", a_count);
            p++;
        }
        if (a_count == n)
        {
            printf(" %s 还不在宫中呢...\n", a_name);
            return 0;
        }
    
        //在遍历中寻找符合要求的妃子并打印信息
        for (int i = 0; i < n; i++)
        {
    
            if ((strcmp(a_name, (ptca->name)) == 0))
            {
                printf("姓名\t等级\t宠爱度\t\n");
                printf("%s\t", ptca->name);
                //打印等级,并用中文替代
                switch (ptca->level)
                {
                case 1:
                    printf("御女\t");
                    break;
                case 2:
                    printf("世妇\t");
                    break;
                case 3:
                    printf("嫔\t");
                    break;
                case 4:
                    printf("夫人\t");
                    break;
                case 5:
                    printf("后\t");
                    break;
                default:
                    printf("0\t");
                    break;
                }
                //打印宠爱度
                printf("%d\n", ptca->likability);
            }
            ptca++;
        }
    };
    
    //5.巡视后宫,打印所有妃子信息,跳过被打入冷宫的妃子信息
    void seeAll(concu *ptca, int *num)
    {
        int n = *num; //临时变量控制循环
        printf("-----------------------------------------\n");
        printf("姓名\t等级\t宠爱度\t\n");
        for (int i = 0; i < n; i++)
        {
            if (ptca->level != 0)
            {
                //打印姓名
                printf("%s\t", ptca->name);
                //打印等级,并用中文替代
                switch (ptca->level)
                {
                case 1:
                    printf("御女\t");
                    break;
                case 2:
                    printf("世妇\t");
                    break;
                case 3:
                    printf("嫔\t");
                    break;
                case 4:
                    printf("夫人\t");
                    break;
                case 5:
                    printf("后\t");
                    break;
                default:
                    printf("0");
                    break;
                }
                //打印宠爱度
                printf("%d\n", ptca->likability);
            }
            ptca++;
        }
    };
    
    //6.1.若有三名妃子宠爱度处于50以下则发生暴动,游戏结束
    int judege_1(concu *ptca, int *num)
    {
        int n = *num; //临时变量,控制循环
        count = 0;    //计数器清0
    
        //循环  计数器
        for (int i = 0; i < n; i++)
        {
            if (ptca->likability < 50)
            {
                count++;
            }
        }
    
        //判断
        if (count >= 3)
        {
            return 0;
        }
        else
        {
            return 1;
        }
    }
    
    //6.2.若有人宠爱度达到100,镇压后宫,游戏结束
    int judege_2(concu *ptca, int *num)
    {
        int n = *num; //临时变量,控制循环
    
        //循环  计数器
        for (int i = 0; i < n; i++)
        {
            if (ptca->likability >= 100)
            {
                return 0;
            }
        }
        return 1;
    }
    
    

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