标题:分享几个代码
只看楼主
qq1559361244
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2018-4-4
得分:0 
好,真的很用心哇~
2018-04-04 21:58
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
回复 2楼 xzlxzlxzl
今天我也打算弄个四则运算(记得之前写过一个复杂的,但这次感觉我还更复杂……先不说了)~
然后突然发现1楼的代码运算结果有误……还以为出了什么事情,以为是楼主的问题(然后无语地发现竟然又挖空了,第二个代码也一样)到底还是要认真看才行~

PS:大概看了个十来分钟(好像多了),第一个空结果是


 if (e!=-1)
                break;


好明显楼主是按照运算符优先级排序,如果找到符合条件的运算符必然就是合理的运算符~

顺便在这贴更,取余和乘除的优先级相同,然后就不用多说了,基于一楼这个框架就是只能两组两组来比较~
算一下6*6%4的四则运算结果和编译器自动计算的实际结果,我笑笑路过算~

还有的确这个算法回填存在问题~
 printf("2^10+1 =%d............测试幂运算、模运算\n",eval("2^10+1"));

PS:第二个空不到一分钟~
编程直觉:--top2;~

[此贴子已经被作者于2018-4-5 08:05编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-04-05 02:42
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
PS:我也可以试试给楼主出个小问题,就是说字符串去除空格运算嘛,但如果字符串不止有空格还有其它制表符例如\t \n这些在里面等等那又怎么去除呢(去除这些空白字符的这个功能感觉还是挺实用的)~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-04-05 02:55
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
得分:0 
回复 12楼 九转星河
仍然分开回答
1,答主填空“ if (e!=-1)break;”虽然可以正常执行,但不建议这样,标准答案是“if(e>s)break;”。因为值-1是函数内部定义的值,对于函数内部应该适用于黑盒测试法,对于应用函数的人只要知道接口参数和返回值,而对于内部可以不知情,因此应用了函数内部定义的值不合规范。对于这个函数,我们知道参数s和e分别对应与算术表达式的起点和下一个运算符位置,因此,如果该表达式如果参与运算了,下一个运算符位置一定大于起始值,反之如果不是表达式,只单纯是一个数字,则只有起始值,没有下一个运算符位置。
2,关于模运算优先级问题,我事先也百度了,也知道和乘除同级,只是要修改的较多,偷了个懒,就让模运算和幂运算同级了。现已修改,一样设置了两处填空。我设置填空主要目的是防止要作业的拷贝粘贴就轻松交作业,要作业也应该动脑子的,光拷贝粘贴是没有进步的。
3,关于幂运算受限算式长度问题,已经解决(参看一楼关于幂运算结果),现在这个代码已经很容易扩展为小数运算了,最长可容纳long long(有效位20位)的数据计算结果。
4,你在13楼提到的非法字符过滤问题,这个功能在eval中解决,eval1过滤空格,是因为空格参与了算法,递归中有用途,其他非法字符可一次性过滤。

谢谢答主参与讨论!

[此贴子已经被作者于2018-4-5 21:35编辑过]

2018-04-05 09:57
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
回复 14楼 xzlxzlxzl
这次要填的笑了一下~

第一个空的确复杂一点,但从j没有赋初值可以看出这里需要对运算符进行比较~
当然答案还是可以很简洁的~


for (j=0;op[j]&&p[i]!=op[j];++j);


第二个空要理解深入一点才知道,看最后的是以递归的形式返回的~
所以空着不处理会造成无穷递归这种相当于死循环这种情况~
解决方案理解后当然就简单了,大意就是说如果括号里面的表达式没有运算符号那就代表计算完毕,直接返回结果~


if (i==3)
            return k;


当然如果题主说防止抄作业,那我以后就或者会不直接公布答案,找题主短信私聊算了~

[此贴子已经被作者于2018-4-5 21:47编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-04-05 21:40
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
得分:0 
回复 15楼 九转星河
厉害!
你填空了也不要紧,不走心的人根本看不懂这些讨论。
一楼代码已解决幂运算结果超长的问题,直接做到long long的有效位了,稍加修改可做double的四则混合运算,欢迎测试指正。
2018-04-05 21:45
自学的数学
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:46
帖 子:967
专家分:4146
注 册:2017-11-15
得分:0 
回复 3楼 xzlxzlxzl
我这里有一个《马踏棋盘》的,献给大家啦!!
程序代码:
#include <stdio.h>
#define X 8
#define Y 8
int chess[X][Y];
int nextxy(int *x, int *y, int count)  /*找到基于x,y位置的下一个可走的位置*/
{
    switch(count)
    {
        case 0:
            if(*x+2<=X-1 && *y-1>=0 && chess[*x+2][*y-1]==0)
            {
                *x=*x+2;
                *y=*y-1;
                return 1;
            }
            break;
        case 1:
            if(*x+2<=X-1 && *y+1<=Y-1 && chess[*x+2][*y+1]==0)
            {
                *x=*x+2;
                *y=*y+1;
                return 1;
            }
            break;
        case 2:
            if(*x+1<=X-1 && *y-2>=0 && chess[*x+1][*y-2]==0)
            {
                *x=*x+1;
                *y=*y-2;
                return 1;
            }
            break;
        case 3:
            if(*x+1<=X-1 && *y+2<=Y-1 && chess[*x+1][*y+2]==0)
            {
                *x=*x+1;
                *y=*y+2;
                return 1;
            }
            break;
        case 4:
            if(*x-2>=0 && *y-1>=0 && chess[*x-2][*y-1]==0)
            {
                *x=*x-2;
                *y=*y-1;
                return 1;
            }
            break;
        case 5:
            if(*x-2>=0 && *y+1<=Y-1 && chess[*x-2][*y+1]==0)
            {
                *x=*x-2;
                *y=*y+1;
                return 1;
            }
            break;
        case 6:
            if(*x-1>=0 && *y-2>=0 && chess[*x-1][*y-2]==0)
            {
                *x=*x-1;
                *y=*y-2;
                return 1;
            }
            break;
        case 7:
            if(*x-1>=0 && *y+2<=Y-1 && chess[*x-1][*y+2]==0)
            {
                *x=*x-1;
                *y=*y+2;
                return 1;
            }
            break;
        default:
            break;
    }
    return 0;
}
int TravelChessBoard(int x, int y, int tag)  /*深度优先搜索地"马踏棋盘"*/
{
    int x1=x, y1=y, flag=0, count=0;
    chess[x][y]=tag;
    if(tag == X*Y)
    {
        return 1;
    }
    flag=nextxy(&x1, &y1, count);
    while(flag==0 && count<7)
    {
        count=count+1;
        flag=nextxy(&x1, &y1, count);
    }
    while(flag)
    {
        if(TravelChessBoard(x1, y1, tag+1))
            return 1;
        x1=x;
        y1=y;
        count=count+1;
        flag=nextxy(&x1, &y1, count);  /*寻找下一个(x,y)*/
        while(flag==0 && count<7)
        {  /*循环地寻找下一个(x,y)*/
            count=count+1;
            flag=nextxy(&x1, &y1, count);
        }
    }
    if(flag == 0)
        chess[x][y]=0;
    return 0;
}
int main()
{
    int i, j;
    for(i=0; i<X; i++)
        for(j=0; j<Y; j++)
            chess[i][j]=0;
    if(TravelChessBoard(2, 0, 1))
    {
        for(i=0; i<X; i++)
        {
            for(j=0; j<Y; j++)
                printf("%-5d", chess[i][j]);
            printf("\n");
        }
        printf("The horse has travelled the chess borad\n");
    }
    else
        printf("The horse cannot travel the chess board\n");
    return 0;
}

效果图:
2018-05-13 21:11
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
如果不是17楼顶了一下,我都不知道还有第三个程序并且还挖空了(估计除了九转没有谁会主动去填了)~

这个程序其实就是和哈密顿回路有关,初初看可以填空并且能"正常运行",
然后久久稍微加改动了其它一点(可以说还是保持楼主原先的结果的),从哈密顿通路改成了哈密顿回路的判断~

程序代码:
 
#include <stdio.h>

#define FLAG 0
#define DEBUG

#define bd 8

void print(int a[][bd])
{//输出棋盘数据
    int i,j;
    for(i=0;i<bd;i++,printf("\n"))
        for(j=0;j<bd;j++)printf("%-4d",a[i][j]);
}
int fun(int a[][bd],int x,int y,int s)
{//a:棋盘,x、y:坐标,s:步数

#define __SUCCESS    32767
    
    int i,j,n,b[8][2]=
    {
        //改变移动顺序这个程序得出的结果是否有解会有所不同
        {+2,+1},
        {+1,+2},        
        {-1,+2},
        {-2,+1},
        {-2,-1},
        {-1,-2},      
        {+1,-2},
        {+2,-1},
    };  //走马顺序
    if(x<0||x>bd-1||y<0||y>bd-1)return 0;
    
#if FLAG  
    if (a[x][y]==1&&s==bd*bd+1)          
        return __SUCCESS;            
#endif
        
    if(a[x][y])return a[x][y]*10000;        //返回该坐标周围符合马走日规则的数据,用于走途无路时剪枝参照
    a[x][y]=s;
        
#if !FLAG
    if (s==bd*bd)
        return __SUCCESS;
#endif

    for (i=j=0;i<8;i++)
    {
        n=fun(a,x+b[i][0],y+b[i][1],s+1);
        
        if (n==__SUCCESS)
            return __SUCCESS;
        
#undef __SUCCESS
        
        if (n&&n<s)                        
        {
            a[x][y]=0;
            return n;                     //剪枝
        }
        else if (n>10000&&n/10000<s-1&&n>j)
            j=n;     //确定剪枝数据  
        
    }
    
    a[x][y]=0;    
    return j/10000;
                         //返回剪枝数据
}
void main()
{
    //int a[bd][bd]={0};
    //有些编译器不支持这样的初始化~
    int a[bd][bd];
    int i,j,k;
    
    
    for (i=0;i!=bd;++i)
        for (j=0;j!=bd;++j)
        {            
            for (k=0;k!=bd*bd;++k)
                (*a)[k]=0;
                
            fun(a,i,j,1);
            
            printf("i=%-4d,j=%-4d\n",i,j);            
            print(a);
            
            #ifdef DEBUG
                if (!**a)
                    getchar();
            #endif
        }
}        


对以下代码说明和存在的问题作了一些补充~

1:当宏定义FLAG==0的时候是哈密顿通路,当FLAG==1的时候是哈密顿回路

2:这个在for循环输出了所有起始坐标的结果,但发现当bd=8的时候点(1,5)和点(6,5)是"无解"的~
具体细节可以通过是否定义宏DEBUG来判断是否在无解的情况下用getchar暂停~

3:当bd=8时至少存在一个点能输出哈密顿回路(当FLAG==1的时候),也就是说明正常来说所有点应该都有哈密顿回路,所以正常来说是所有点都是有解的而不是存在单独某个点无解是情况~

4:对棋盘跳马的顺序做了一些细节调整,主要是方便调试,交换了跳马顺序会影响到是否有解(正常来说跳马顺序和是否有解无关当然和解的顺序有关,但最终解集数不变)~

5:把重复标记映射从100改成了10000,这样支持了bd>=10的情况,但发现了当bd=12的时候,某些点输出比较快有些点比较慢(而是要等几秒甚至更久的那种)~

6:在调试的过程还曾经试过输出所有情况,发现bd=8的时候某个起点所有情况就那么几种,结合2,3的表现情况说明来看应该是漏解了,所以这个不是完全覆盖遍历,这个可能和程序本身的算法实现有关,具体个人感觉在

(n>10000&&n/10000<s-1&&n>j)
            j=n;     //确定剪枝数据  

这里判断j的取值虽然剪枝了,但这样选8个方向走过的步数作为最多的作为回溯值这个怎么理解,8个方向怎么确定就是选那个方向是保证肯定有解的?~

7:当然如果是我填空本身就有问题而楼主那边没有那我就无话可说了~

当然所以楼主这个可以叫AI的启发式算法,具体怎么弄还是期待楼主说明吧~


[此贴子已经被作者于2018-5-14 10:17编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-14 08:34
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
得分:0 
回复 18楼 九转星河

厉害!这种剪枝算法我也是在那种类死机状态下单步调试分析得来的,试了几种坐标,速度很快就得到结果,没有做广谱测试,有不足地方容后改进。
这种马走日好像还有一种更简便算法:得到在一个坐标下走满的数据,就可以此数据通过运算得到全部坐标下走满的数据,不需要每输入一次起始坐标都递归一次的。
最近忙毕业,上论坛少了,祝各位编程快乐!

[此贴子已经被作者于2018-5-19 07:49编辑过]

2018-05-19 07:48
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
以下是引用xzlxzlxzl在2018-5-19 07:48:25的发言:

最近忙毕业,上论坛少了,祝各位编程快乐!


好,最近我看见学校也在弄毕业庆典了~

当然说个有关或者说是无关题目的,这类问题可以归纳为哈密顿回路问题或者哈密顿通路问题,就是这个问题属于完备NP问题,也就是说目前没有有效解法(资料上也是这么说的)

但马走棋盘这个有特殊性有通用解法也不奇怪,但对于一般无向图而言,精确解法用路径压缩也要o((n^2)*(2^n))的时间复杂度才能解决,当然近似算法有很多的,楼主提供那个可以是叫一个近似算法~

其实在我的下载频道上面那个讲解C语言学习里面就有骑士走棋盘问题(那个软件不支持复制粘贴直接上图片讲解算是这样了)~




[此贴子已经被作者于2018-5-19 13:11编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-19 10:58



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-485738-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 1.118537 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved