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 ...
随机推荐
- 驳《编码规范是技术上的遮羞布》自由发挥==摆脱编码规范?X
引子: 看了一坨文字<编码规范是技术上的遮羞布>,很是上火,见人见智,本是无可厚非,却深感误人子弟者众.原文观点做一个简单的提炼: 1.扔掉编码规范吧,让程序员自由发挥,你会得到更多的好处 ...
- BASIC-23_蓝桥杯_芯片测试
思路: 1.当测试与被测试的芯片全部可以互相测试时,为好芯片; 示例代码: #include <stdio.h>#define N 20 int main(void){ int n = 0 ...
- StringIO-将字符串当做文件处理
StringIO将字符串当做文件处理,十分方便 >>> from StringIO import StringIO >>> file_like_string = S ...
- 数据库启动失败:The server quit without updating PID file
1.可能是/usr/local/mysql/data/mysql.pid文件没有写的权限解决方法 :给予权限,执行 “chown -R mysql:mysql /var/data” “chmod -R ...
- maven学习(5)-Maven 聚合与继承特性
接着上面的项目, 继承和聚合为了统一管理: 聚合: 有些项目中有很多小模块,可以合并到一起,将多个子项目可以统一管理,可以对user-dao,user-service进行统一管理(maven clea ...
- 修改phpMYadmin 链接其他数据库地址的方法
找到phpmyadmin的文件 修改 config.inc.php 文件 框红的地方修改成你需要链接的数据库信息 重启环境,再次访问 phpmyadmin 地址即可
- 小甲鱼-003 python插曲值变量和字符串
变量名就像现实生活人们的名字,把一个值赋值给一个名字时,他会存储在内存中,称之为变量variable,在大多数语言中,都把这种行为成为"给变量赋值"或"把值存储在变量中& ...
- [UE4]使机器人受伤
- securecrt8注册码
securecrt8注册码,两个可用 Name:meisiCompany:TEAM ZWTSerial Number:03-14-367662License Key:ACCFAX R9FHJ7 QZV ...
- centos 7 mount usb hard disk(ntfs format)
1. yum install -y epel-release* 2. yum install -y ntfs-3g 3. 命令:fdisk -l (查看磁盘分区信息) [root@devserverg ...