C语言实现24点程序
一、简介
本程序的思想和算法来自于C语言教材后的实训项目,程序通过用户输入四个整数计算出能够通过加减乘除得到数字24的所有表达式,程序的设计有别于一般通过穷举实现的方式,效率得到提高。算法介绍如下:
如用户输入1,2,3,4四个数字,先将其看成四个集合即{1},{2},{3},{4},整个叫做第一集群,后通过任意两个集合加减乘除{1,2},{1,3},{1,4},{2,3},{2,4},{3,4}六个集合叫做第二集群,而第三集群由第一集群和第二集群产生,而第四集群可由第一集群和第三集群以及由第二集群自身产生,最后比较第四集群所得到的的值是否24,输出结果
二、程序流程如下:
- 程序调用input函数处理用户输入,并同时生成四个相应的集合
- 调用函数calc,通过其中的list_cross函数产生第二、三、四集群
- 调用函数output输出,并同时删除相同的表达式
- 删除所有集群所占的空间,程序结束
三、主要的数据结构以及算法
为了提高计算精度,使用分数表示每一次计算结果
分数的结构 FRACTION
typedef struct{
int num;//分子
int den;//分母
}FRACTION; //注意分数的符号放在分子上集群链表节点 s_ item
typedef char EXPRESS[]; //存储具体的表达式,如2*3
typedef struct s_item{
FRACTION value; //集合的值 如expr为2*3,value.num=6,value.den=1
EXPRESS expr; //表达式
int flag[]; //每一个元素代表是否使用相应的数字,如用户输入了1,2,3,4,flag{1,1,0,0},表示
//集合含有数字1和2
struct s_item* next; //指向下一节点
}ITEM,*PITEM;
主要的算法
分数的四则运算:
1.声明
int commonDivisor(int a,int b);//最大公约数
int commonMultiple(int a,int b);//最小公倍数
//公倍数和公约数用于化简和计算分数 FRACTION plus(FRACTION a,FRACTION b);//分数的加法
FRACTION sub(FRACTION a,FRACTION b);//分数的减法
FRACTION multiple(FRACTION a,FRACTION b);//分数乘法
FRACTION division(FRACTION a,FRACTION b);//分数的除法
2.定义
//最大公约数
int commonDivisor(int a,int b){
int temp=;
while(b!=){
temp=a%b;
a=b;
b=temp;
}
return a;
} //最小公倍数
int commonMultiple(int a,int b){
return a*b/commonDivisor(a,b);
} //分数的加法
FRACTION plus(FRACTION a,FRACTION b){ if(a.den==b.den){ //分母相同 a.num=a.num+b.num;
}else{
int cm=commonMultiple(a.den,b.den);
a.num=a.num*(cm/a.den)+b.num*(cm/b.den);
a.den=cm;
} //简化a,分子分母同除公约数
int cm= commonDivisor(abs(a.num),a.den);
a.num/=cm;
a.den/=cm; return a;
} //分数减法
FRACTION sub(FRACTION a,FRACTION b){ if(a.den==b.den){ //分母相同 a.num=a.num-b.num;
}else{
int cm=commonMultiple(a.den,b.den);
a.num=a.num*(cm/a.den)-b.num*(cm/b.den);
a.den=cm;
}
//简化a,分子分母同除公约数
int cm= commonDivisor(abs(a.num),a.den);
a.num/=cm;
a.den/=cm; return a;
} //分数乘法
FRACTION multiple(FRACTION a,FRACTION b){ a.num*=b.num;
a.den*=b.den; int cm= commonDivisor(abs(a.num),a.den);
a.num/=cm;
a.den/=cm; return a;
} //分数的除法
FRACTION division(FRACTION a,FRACTION b){
int temp;
if(b.num==){
a.num=;
a.den=;
return a;//不能除0 ,返回分子,分母为0,作为标志
}else if(b.num>){
temp=b.num;
b.num=b.den;
b.den=temp;
}else{
temp =abs(b.num);
b.num=b.den;
b.den=temp;
b.num*=-;
}
return multiple(a,b);
}
集合之间的加减乘除产生新集合
1.声明
PITEM add(PITEM a,PITEM b); //两个相加
PITEM divide(PITEM a,PITEM b); //两个相除
PITEM mutiply(PITEM a,PITEM b); //两个相乘
PITEM subtract(PITEM a,PITEM b); //两个相减
2.定义
PITEM add(PITEM a,PITEM b) //两个相加
{ PITEM x=(struct s_item*)malloc(sizeof(struct s_item));
x->value=plus(a->value,b->value); int m;
for(m=;m<;m++){
x->flag[m]=;
} int k=;
x->expr[k]='(';
int j;
for(j=;a->expr[j]!='\0';j++){
x->expr[++k]=a->expr[j];
}
x->expr[++k]='+';
for(j=;b->expr[j]!='\0';j++){
x->expr[++k]=b->expr[j];
}
x->expr[++k]=')';
x->expr[++k]='\0'; int i=;
for(i=;i<;i++){
if(a->flag[i]==){
x->flag[i]=;
} if(b->flag[i]==){
x->flag[i]=;
} } x->next=NULL; return x;
} PITEM divide(PITEM a,PITEM b){ //集合相除
PITEM x=(struct s_item*)malloc(sizeof(struct s_item));
x->value=division(a->value,b->value); int m;
for(m=;m<;m++){
x->flag[m]=;
}
if(x->value.num==&&x->value.den==){
free(x);
return NULL;
} int k=;
x->expr[k]='(';
int j;
for(j=;a->expr[j]!='\0';j++){
x->expr[++k]=a->expr[j];
}
x->expr[++k]='/';
for(j=;b->expr[j]!='\0';j++){
x->expr[++k]=b->expr[j];
}
x->expr[++k]=')';
x->expr[++k]='\0'; int i=;
for(i=;i<;i++){
if(a->flag[i]==){
x->flag[i]=;
} if(b->flag[i]==){
x->flag[i]=;
} } x->next=NULL;
return x;
}
PITEM mutiply(PITEM a,PITEM b)//两个相乘
{
PITEM x=(struct s_item*)malloc(sizeof(struct s_item));
x->value=multiple(a->value,b->value);
int m;
for(m=;m<;m++){
x->flag[m]=;
}
int k=;
x->expr[k]='(';
int j;
for(j=;a->expr[j]!='\0';j++){
x->expr[++k]=a->expr[j];
}
x->expr[++k]='*';
for(j=;b->expr[j]!='\0';j++){
x->expr[++k]=b->expr[j];
}
x->expr[++k]=')';
x->expr[++k]='\0'; int i=;
for(i=;i<;i++){
if(a->flag[i]==){
x->flag[i]=;
} if(b->flag[i]==){
x->flag[i]=;
} } x->next=NULL;
return x;
} PITEM subtract(PITEM a,PITEM b){ //相减
PITEM x=(struct s_item*)malloc(sizeof(struct s_item));
x->value=sub(a->value,b->value);
int m;
for(m=;m<;m++){
x->flag[m]=;
}
int k=;
x->expr[k]='(';
int j;
for(j=;a->expr[j]!='\0';j++){
x->expr[++k]=a->expr[j];
}
x->expr[++k]='-';
for(j=;b->expr[j]!='\0';j++){
x->expr[++k]=b->expr[j];
}
x->expr[++k]=')';
x->expr[++k]='\0'; int i=;
for(i=;i<;i++){
if(a->flag[i]==){
x->flag[i]=;
} if(b->flag[i]==){
x->flag[i]=;
} } x->next=NULL;
return x;
}
核心代码
产生新集群 list_cross
//比较集群之间是否有相同数字
int cmp(PITEM left,PITEM right){
int i;
for(i=;i<;i++){
if(left->flag[i]==&&right->flag[i]==){
return ;
}
}
return ;
} //结合两个集群产生下一个集群
void list_cross(PITEM left,PITEM right,PITEM result){ PITEM p,q;
for(p=left->next;p!=NULL;p=p->next){ //循环调用两个集群中所有集合
for(q=right->next;q!=NULL;q=q->next)
if(cmp(p,q)==){ //只有两集合不含相同数字才运算
PITEM temp=NULL;
if((temp=add(p,q))!=NULL){
temp->next=result->next;
result->next=temp;
}
if((temp=subtract(p,q))!=NULL){
temp->next=result->next;
result->next=temp;
}
if((temp=divide(p,q))!=NULL){
temp->next=result->next;
result->next=temp;
}
if((temp=mutiply(p,q))!=NULL){
temp->next=result->next;
result->next=temp;
} }
}
}
因为用户有可能输入相同的数字,所以要消除相同的表达式:
消除重复表达式
PITEM p=p4_head->next; //p指向第四集群的头结点,第四集群即最后四个数字都已经使用的集合 //消除重复的表达式 PITEM q,pre;
for(;p!=NULL;p=p->next){
for(q=p->next,pre=p;q!=NULL;){
if(strcmp(p->expr,q->expr)==){ pre->next=q->next;
PITEM temp=q; //pre为p的前一个节点
q=q->next; free(temp);//消失重复点;
temp=NULL; }else{
q=q->next;
pre=pre->next;
}
}
}
判断集合的值,输出结果
//输出
p=p4_head->next;
while(p!=NULL){
if(p->value.num==&&p->value.den==){ puts(p->expr); } p=p->next;
}
四、运行
源代码地址:C语言实现24点src
C语言实现24点程序的更多相关文章
- C语言学习书籍推荐《学通C语言的24堂课》下载
下载地址:点我 编辑推荐 <学通C语言的24堂课>:用持续激励培养良好习惯以良好习惯铸就伟大梦想——致亲爱的读者朋友在开始学习<学通C语言的24堂课>的同时,强烈建议读者朋友同 ...
- C语言之简易了解程序环境
C语言之简易了解程序环境 大纲: 程序的翻译环境 预编译 编译 汇编 链接 程序的运行环境 在ANSI C的任何一种实现中,存在两个不同的环境. 第1种是翻译环境,在这个环境中源代码被转换为可执行的机 ...
- 基于php基础语言编写的小程序之计算器
基于php基础语言编写的小程序之计算器 需求:在输入框中输入数字进行加.减.乘.除运算(html+php) 思路: 1首先要创建输入数字和运算符的输入框,数字用input的text属性,运算符用sel ...
- 利用Scala语言开发Spark应用程序
Spark内核是由Scala语言开发的,因此使用Scala语言开发Spark应用程序是自然而然的事情.如果你对Scala语言还不太熟悉,可 以阅读网络教程A Scala Tutorial for Ja ...
- SAS进阶《深入解析SAS》之开发多语言支持的SAS程序
SAS进阶<深入解析SAS>之开发多语言支持的SAS程序 1. 多语言支持的应用程序是指该程序在世界给第使用时,其能够处理的数据,以及处理数据的方式.信息展现的方式都符合当地的语言.文化习 ...
- JAVA 基础编程练习题24 【程序 24 根据输入求输出】
24 [程序 24 根据输入求输出] 题目:给一个不多于 5 位的正整数,要求:一.求它是几位数,二.逆序打印出各位数字. package cskaoyan; public class cskaoya ...
- [转载] 使用C/C++语言编写基于DSP程序的注意事项
原文地址:『转』使用C/C++语言编写基于DSP程序的注意事项作者:skysmile 1.不影响执行速度的情况下,可以使用c或c/c++语言提供的函数库,也可以自己设计函数,这样更易于使用“裁缝师 ...
- 程序员之---C语言细节24(段错误、类型提升、sizeof 'A')
主要内容:段错误.类型提升.sizeof 'A' #include <stdio.h> int main() { union test{ char a[10]; int b; }u; i ...
- 平方根的C语言实现(三) ——最终程序实现
版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/7223254.html 作者:窗户 Q ...
随机推荐
- 2018-2019学年第一学期Java课设--魔塔
目录 Magic-Towers 一.团队名称.团队成员介绍.任务分配 团队名称:MoTa 团队成员介绍 任务分配 二.项目简介 三.项目采用技术 四.项目亮点 主界面显示主要信息功能 游戏动画 五.项 ...
- [UE4]运行时创建Actor
- javascript控制滚动条的位置,获取控件的位置
一.如下是定位鼠标在视窗中的位置,先定位视窗和页面直接的距离. function getMousePoint() { var point = {x:0,y:0}; // 如果浏览器支持 pageYOf ...
- [UE4]运行时UMG组件跟随鼠标的逻辑:拖拽UMG组件(蓝图)
转自:http://aigo.iteye.com/blog/2279860 UMG - Mouse screen position problem https://forums.unrealengin ...
- 给iOS开发新手送点福利,简述UITableView的属性和用法
UITableView UITableView内置了两种样式:UITableViewStylePlain,UITableViewStyleGrouped <UITableViewDataSo ...
- Windows10 命令行中使用网络驱动器
Windows10中,我们在局域网内使用共享文件夹,建立映射的网络驱动器,有时候需要一些软件去调用网络驱动器内的资源,但是发现在资源管理器能正常打开,应用软件却无法识别,命令行中提示:“系统找不到指定 ...
- Fork-Join分治编程介绍(一)
一.Fork-Join 框架介绍 1. 什么是 Fork-Join 分治编程框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每 ...
- js中的数组操作
<!DOCTYPE HTML> <html > <head> <meta http-equiv="Content-Type" conten ...
- centos7.3安装zend guard loader3.3 for php5.6
1 下载zend guard loader 到这里选择自己的系统版本 我选择的64位 for php5.6.3 linux http://www.zend.com/en/products/load ...
- leetcode7
public class Solution { public int Reverse(int x) { ; ) { fuhao = -; } try { x = Math.Abs(x); } catc ...