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 ...
随机推荐
- 【Spring学习笔记-MVC-11--】Spring MVC之表单标签
一.使用方法 1.要使用Spring MVC提供的表单标签,首先需要在视图页面添加: <%@ taglib prefix="form" uri="http://ww ...
- request笔记记录
1.https请求报错解决方法,添加verify=False参数 r = requests.get(json=payload, headers=headers,verify=False) 1)由于这里 ...
- [UE4]C++调用蓝图函数:BlueprintImplementableEvent函数说明符用法
用BlueprintImplementableEvent标明的函数在C++代码中不需要有方法体,方法体在蓝图中实现. 用法: 1,现在C++头文件中定义函数名 UFUNCTION(BlueprintI ...
- javascript的防篡改对象之preventExtensions()方法
js在默认情况下,所有的对象都是可扩展的.这也是让很多开发人员头特疼的问题.因为在同一环境中,一不小心就会发生修改了不必要的对象,而自己却不知道. 在ECMAScript5可以解决这种问题了. pre ...
- asp控制项目超时
If Session("username")="" or isnull(Session("username")) Then %> &l ...
- docker容器修改时区(java应用log信息与标准容器时间有八个小时时间差)
在docker容器中运行的java应用打出的日志时间和通过date -R方式获取的容器标准时间有八个小时时间差- 因为docker容器的原生时区为0时区,为了和国内时区保持一致,需要把容器时区调为东八 ...
- navicate for mysql mac 含注册机 亲测可用
百度网盘:https://pan.baidu.com/s/1hrXnRes
- mysql级联删除
一个building对应多个rooms,building删除----级联删除相关的rooms 第一步, 创建buildings表,如下创建语句: USE testdb; CREATE TABLE bu ...
- Hive 简介
hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行. 其优点是学习成本低,可以通过 ...
- Angular5 UI post 请求 输出 文件下载
this.httpClient.post(url1, JSON.parse(data1) , {responseType: 'blob'}).subscribe(data => { const ...