代码意识流——花朵数问题(七)

本文详细阐述了如何通过计算一组数字的三次方和来验证一个数是否为花朵数,包括算法实现、数据结构设计、以及如何进行验算。通过实例演示了从简单到复杂的逻辑流程,最终实现了对花朵数的有效识别。

本文前一部分的链接
http://www.cnblogs.com/KBTiller/archive/2011/06/05/2073421.html

20.验算
   验算过程的基本思路是求出“和”中各个数字有多少个,然后与得到这个"和"的数字组合比较,如果两者一致则“和”是一个花朵数。
   例如,由一个5、一个3和一个1可以得到这三个数字的3次方的和为5^3+3^3+1^3==153,而153恰好是由一个5、一个3和一个1这三个数字构成这时就可以断定153是花朵数。
   反之,由一个5、一个3和一个2可以得到这三个数字的3次方的和为,5^3+3^3+2^3==160,160中有一个6、一个1和一个0,与求得160的三个数字的组合(5,3,2)不符,这就表明160不是花朵数。
   这种算法首先要记录求出数字N次方之和的各个数字的个数。
  
记录各数字的个数

在"2_穷举.c"定义这种数据类型

typedef unsigned int SHUZI_GESHU[JINZHI];
//SHUZI_GESHU[d]存储数字d的个数    

在xunhuan()中定义这种类型的局部变量,显然这应该是static类别的

static SHUZI_GESHU sz_gs ;

记录递归过程中各个数字的个数,并测试


  
static void xunhuan( const int gssx /* 个数上限 */ ,
const int sz /* 关于哪个数字 */ ,
DASHU (
* p_hang)[WEISHU + 1 ] /* 指向一行数据 */ )
{
static DASHU he = { { 0 } } ; // static DASHU he ; // =0 待完成
DASHU he_ = he ; // 记录累加前的值 // 记录累加前的值
static SHUZI_GESHU sz_gs ;

if ( sz > 0 ){
int i;
for ( i = 0 ; i <= gssx ; i ++ ){
sz_gs[sz]
= i ; // 记录数字的个数
ds_jiaru ( & he , * p_hang + i ) ;
xunhuan( gssx
- i , sz - 1 , p_hang + 1 );
he
= he_ ; // 恢复原来的值
}
}
else {
sz_gs[sz]
= gssx ; // 记录数字的个数
#ifdef CESHI
{
int i;
for ( i = 0 ; i < JINZHI ; i ++ ){
printf(
" %d*%d " , sz_gs[i] , i );
}
putchar(
' \n ' );
}
#endif
// 验算<=>记录结果
}
}

测试通过。
接着在xunhuan()中写出验算的代码,判断“和”中数字出现的次数与sz_gs 中的记录是否一致

xunhuan()
{
     ……
     if( 吻合 ( & sz_gs , &he ) == 是 ){ //验算
          //<=>记录结果
      }

}

吻合 ( & sz_gs , &和 )
{
   int 和中各数字的个数[JINZHI];

   if( 超过W位(和) == 是  || 不足W位(和) == 是 ){   //#include "3_大数.h"
     return 否;
   }

   求和中各数字的个数( &和中各数字的个数 , &和 );//#include "3_大数.h"

   if ( memcmp (和中各数字的个数 ,sz_gs ,sizeof 和中各数字的个数 )==0 ){ //#include <string.h>
      return 是;
   }
   return 否;
}

这段代码涉及到很多回答是或否的问题,由于讨厌在写代码时费神用0或1思考这样的问题,在工程中加入了这样一个文件


  
/* 常用.h */

#ifndef CHANGYONG_H
#define CHANGYONG_H

typedef
enum { SHI , FOU } SF ;

#endif // CHANGYONG_H

并分别在"2_穷举.h"、"3_大数.h"中添加了
#include "常用.h"

现在,“2_穷举.h”演变成


  
/* 2_穷举.h */

#ifndef QIONGJU_H
#define QIONGJU_H


/* *************************类型定义************************* */
#include
" 3_大数.h "
#include
" 常用.h "

/* *************************函数原型************************* */

extern void qiongju( void );
#include
< stdlib.h > // malloc()

#endif // QIONGJU_H


2_穷举.c演变成


  
/* 2_穷举.c */

#include
" 2_穷举.h "
#include
" 0_问题.h "

typedef unsigned
int SHUZI_GESHU[JINZHI];
// SHUZI_GESHU[d]存储数字d的个数

typedef DASHU SHUJUBIAO[JINZHI
- 1 ][WEISHU + 1 ];
// 0*(JINZHI-1)^N 1*(JINZHI-1)^N ……WEISHU*(JINZHI-1)^N
// 0*(JINZHI-2)^N 1*(JINZHI-2)^N ……WEISHU*(JINZHI-1)^N
// ……
// 0*(1)^N 1*(1)^N ……WEISHU*(1)^N

static void xunhuan( const int , const int , DASHU ( * )[WEISHU + 1 ] ) ;

static void jianli_sjb ( SHUJUBIAO * * ); // 建立数据表

static SF wenhe( SHUZI_GESHU * const , const DASHU * const );

static SF wenhe( SHUZI_GESHU * const p_sz_gs ,
const DASHU * const p_he )
{
int sz_gs_he[JINZHI] = { 0 }; // 和中各数字的个数

if ( chaoguo_W(p_he) == SHI // 超过W位 || 不足W位
|| buzu_W (p_he) == SHI ){
return FOU ;
}

qiu_sz_gs(
& sz_gs_he , p_he ); // 求和中各数字的个数

if ( memcmp ( sz_gs_he , * p_sz_gs , sizeof sz_gs_he ) == 0 ){
return SHI ;
}
return FOU ;

}

// 建立数据表
static void jianli_sjb ( SHUJUBIAO * * p_p_sjb )
{
if ( ( * p_p_sjb = malloc( sizeof (SHUJUBIAO)) ) == NULL ){ // #include <stdlib.h>
exit( ! EXIT_SUCCESS);
}

{
int i , j ;
for ( i = 0 ; i < JINZHI - 1 ; i ++ ){
ds_fuzhi(
* ( * * p_p_sjb + i ) + 0 , 0 ); // 第一列为0
ds_fuzhi( * ( * * p_p_sjb + i ) + 1 , 1 ); // 第二列先赋值为1
for ( j = 0 ; j < N ; j ++ ){ // 求N次幂
ds_chengyi( * ( * * p_p_sjb + i ) + 1 , JINZHI - 1 - i );
}
for ( j = 2 ; j <= WEISHU ; j ++ ){
(
* ( * * p_p_sjb + i ))[j] = ( * ( * * p_p_sjb + i ))[j - 1 ] ;
ds_jiaru (
* ( * * p_p_sjb + i ) + j , * ( * * p_p_sjb + i ) + 1 ) ;
}
}
}
}

extern void qiongju( void )
{
SHUJUBIAO
* p_sjb = NULL ;

jianli_sjb (
& p_sjb ); // 建立数据表
xunhuan( WEISHU , JINZHI - 1 , * p_sjb ) ;
free ( p_sjb );

}

static void xunhuan( const int gssx /* 个数上限 */ ,
const int sz /* 关于哪个数字 */ ,
DASHU (
* p_hang)[WEISHU + 1 ] /* 指向一行数据 */ )
{
static DASHU he = { { 0 } } ; // static DASHU he ; // =0 待完成
DASHU he_ = he ; // 记录累加前的值 // 记录累加前的值
static SHUZI_GESHU sz_gs ;

if ( sz > 0 ){
int i;
for ( i = 0 ; i <= gssx ; i ++ ){
sz_gs[sz]
= i ; // 记录数字的个数
ds_jiaru ( & he , * p_hang + i ) ;
xunhuan( gssx
- i , sz - 1 , p_hang + 1 );
he
= he_ ; // 恢复原来的值
}
}
else {
sz_gs[sz]
= gssx ; // 记录数字的个数

if ( wenhe ( & sz_gs , & he ) == SHI ){ // 验算两者是否"吻合"
#ifdef CESHI
ds_shuchu (
& he );
puts(
" 吻合 " );
#endif
// <=>记录结果
}
}
}

"3_大数.h"演变为


  
/* 3_大数.h */

#ifndef DASHU_H
#define DASHU_H

#include
" 0_问题.h " // DASHU用到了WEISHU

/* *************************类型定义************************* */
// gw_sz[0]为个位,gw_sz[WEISHU-1]为最高位
// gw_sz[WEISHU-1]的值大于等于JINZHI表示溢出
typedef struct {
int gw_sz[WEISHU] ;
}
DASHU ;
#include
" 常用.h "

/* *************************函数原型************************* */

extern void ds_fuzhi ( DASHU * const , const int ) ;
extern void ds_shuchu( const DASHU * const ) ;
extern void ds_jiaru ( DASHU * const , const DASHU * const ) ;
extern void ds_chengyi( DASHU * const , const int );
extern SF chaoguo_W( const DASHU * const );
extern SF buzu_W( const DASHU * const );
extern void qiu_sz_gs( int ( * )[JINZHI] , const DASHU * const ) ;

#endif // DASHU_H

“3_大数.c”演变为


  
/* 3_大数.c */
#include
" 3_大数.h "

static void ds_jinwei ( DASHU * const );

// 统计*p_he中的各数字个数=> *p_sz_gs
extern void qiu_sz_gs( int ( * p_sz_gs)[JINZHI] , const DASHU * const p_he )
{
int * t = p_he -> gw_sz ;
while ( t < p_he -> gw_sz + WEISHU ){
(
* p_sz_gs)[ * t ++ ] ++ ;
}

}

extern SF buzu_W( const DASHU * const p_ds)
{
if (p_ds -> gw_sz[WEISHU - 1 ] == 0 ){
return SHI ;
}
return FOU ;
}
// 判断是否超过WEISHU
extern SF chaoguo_W( const DASHU * const p_ds)
{
if (p_ds -> gw_sz[WEISHU - 1 ] >= JINZHI ){
return SHI ;
}
return FOU ;
}

// * p_ds *= cs
extern void ds_chengyi( DASHU * const p_ds , const int cs )
{
int * t = p_ds -> gw_sz ;
while ( t < p_ds -> gw_sz + WEISHU ){
* t ++ *= cs ;
}
ds_jinwei ( p_ds );
}

// 进位
static void ds_jinwei ( DASHU * const p_ds )
{
int * t = p_ds -> gw_sz , * const w = t + WEISHU - 1 ;
while ( t < w ){
* ( t + 1 ) += * t / JINZHI ;
* t ++ %= JINZHI ;
}
}

// *p_he += *p_js
extern void ds_jiaru ( DASHU * const p_he , const DASHU * const p_js )
{
int * he_t = p_he -> gw_sz , * const he_w = he_t + WEISHU ; // - 1 ;
const int * js_t = p_js -> gw_sz ;
while ( he_t < he_w ){
* he_t ++ += * js_t ++ ;
}
ds_jinwei ( p_he );
// static void ds_jinwei ( DASHU * const );
}

extern void ds_shuchu( const DASHU * const p_ds )
{
int * const t = p_ds -> gw_sz , * w = t + WEISHU - 1 ;
while ( w > t && * w == 0 ){ // 高位0不输出
w -- ;
}
while ( w > t ){
printf(
" %d " , * w -- );
}
printf(
" %d\n " , * t ) ;
}

// 在*p_ds中写入n
extern void ds_fuzhi ( DASHU * const p_ds , const int n )
{
p_ds
-> gw_sz[ 0 ] = n ;
// 可能有进位,同时把高位写为0
{
int * t = p_ds -> gw_sz , // 指向 p_ds->gw_sz[0]
* w = t + WEISHU - 1 ; // 指向 p_ds->gw_sz[WEISHU-1]
while ( t < w ){
* ( t + 1 ) = * t / JINZHI ;
* t ++ %= JINZHI ;
}
}
}

编译运行,结果为
153
吻合
370
吻合
371
吻合
407
吻合

总算看到点亮了。

转载于:https://www.cnblogs.com/KBTiller/archive/2011/06/07/2074344.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值