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 ...
随机推荐
- Python网络爬虫-xpath模块
一.正解解析 单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 \d :数字 [0-9] \D : 非数字 \w :数字.字母.下划线.中文 \W : 非\ ...
- bzoj 4911: [Sdoi2017]切树游戏
考虑维护原树的lct,在上面dp,由于dp方程特殊,均为异或卷积或加法,计算中可以只使用fwt后的序列 v[w]表示联通子树的最浅点为w,且不选w的splay子树中的点 l[w]表示联通子树的最浅点在 ...
- 错误:Unsupported major.minor version 51.0(jdk版本错误)
Java.lang.UnsupportedClassVersionError: org/apache/nutch/crawl/Crawl3 : Unsupported major.minor vers ...
- 牛客网暑期ACM多校训练营(第七场)J题(Sudoku Subrectangles)题解
一.题意 给定一个高度为$n$,宽度为$m$的字母矩形(有大写和小写字母,共$52$种),问里面有多少个子矩形是“数独矩形”.数独矩形是指,该矩形内每一行内元素都不相同,每一列内元素也不相同. 二.思 ...
- Docker集群管理(二)—— docker+swarm+etcd+shipyard
引言 前一篇介绍如何简单的搭建一个可视化管理的docker集群,本篇将在此基础之上引入etcd发现服务. 目的 使用etcd发现服务解决swarm内置发现服务的不稳定问题.etcd采用raft算法,这 ...
- 链接mysql的两种方法
使用mysql二进制方式连接 您可以使用MySQL二进制方式进入到mysql命令提示符下来连接MySQL数据库. 实例 以下是从命令行中连接mysql服务器的简单实例: [root@host]# my ...
- storm的优化以及雪崩问题
下图来说明什么是雪崩现象: 当spout发送的速度非常快,而bolt的处理速度很慢,spout源源不断地向内存中发送tuple,这样下去迟早会把内存撑爆,这样就叫做雪崩现象! 怎么处理雪崩问题呢 第一 ...
- Linux入门之vi
How to Use the vi Editor* *Copyright 1991 by Simon Fraser University. Reprinted with permission. The ...
- java技术-重点方向
多线程 锁 事务 缓存 hashmap 并发编程
- 15.python操作mysql
导入包 from pymysql import* 1. 创建 Connection 连接 conn=conne(host='192.168.13.130',port=3306 ,database='' ...