LychrelNumber实现V1.0

一、代码

1.main.cpp

#include <iostream>

using namespace std;

#include "BigNumber.h"

#define MAX_RANGE 1000
#define TIME 10000

#define UNKNOWN -1
#define YES 1

CBigNumber next[TIME+5] = {0};

void init();
int caculate(int number);
void result(int number, int ret);
void setAllInNextTable(bool result);

int main()
{
	for(int i = 1; i < MAX_RANGE; i++)
	{
		init();
		int ret = caculate(i);
		result(i, ret);
	}
	return 0;
}

void init()
{
	memset(next, 0, sizeof(next));
}

int caculate(int number)
{
	int cnt = 0;
	CBigNumber temp(number);
	int ret;
	while((ret = temp.isLychrelNumber()) == UNKNOWN)
	{
		if(cnt > TIME)
		{
			ret = YES;
			break;
		}
		temp.add();
		next[cnt++] = temp;
	}
	return ret;
}

void result(int number, int ret)
{
	if(ret == YES)
	{
		setAllInNextTable(false);
		cout<<number<<endl;
	}
	else
	{
		setAllInNextTable(true);
	}
}

void setAllInNextTable(bool result)
{
	for(int i = 0; next[i].size != 0; i++)
	{
		next[i].setValue(result);
	}
}
2.BigNumber.h
#define MAX_TABLE_SIZE 1000000
#define MAX_DIGIT 18

bool value[MAX_TABLE_SIZE] = {0};
bool isCaculated[MAX_TABLE_SIZE] = {0};

bool isReverse(long long number)
{
	int word[10] = {0};
	int cnt = 0;
	while(number)
	{
		word[cnt++] = number % 10;
		number /= 10;
	}
	for(int i = 0; i < cnt; i++)
	{
		if( word[i] !=  word[cnt - i - 1])
		{
			return false;
		}
	}
	return true;
}

bool isAllDigitSmallerThan5(long long number)
{
	while(number)
	{
		int last = number % 10;
		if(last >= 5)
			return false;
		number /= 10;
	}
	return true;
}

int isLychrelNumber(long long number)
{
	if(isReverse(number) == true)
		return 0;

	if(isAllDigitSmallerThan5(number) == true)
		return 0;

	if(number >= MAX_TABLE_SIZE || isCaculated[number] == false)
		return -1;

	return !value[number];
}

#define MAX_SIZE 200
class CBigNumber
{
private:
	long long data[MAX_SIZE];
	bool isNumberTooBig();
	bool isReverse();
	bool isAllDigitSmallerThan5();
	bool isInRecord();
public:
	int size;
	CBigNumber();
	CBigNumber(const CBigNumber &B);
	CBigNumber(long long normalData);
	int isLychrelNumber();
	void add();
	void setValue(bool flag);
	void print();
	CBigNumber &operator=(const CBigNumber & B);
	bool operator==(const CBigNumber & B);
	CBigNumber getReverseNumber();
};
CBigNumber::CBigNumber()
{
	size = 0;
	memset(data, 0, sizeof(data));
}
CBigNumber::CBigNumber(const CBigNumber &B)
{
	size = B.size;
	for(int i = 0; i < B.size; i++)
		data[i] = B.data[i];
}
CBigNumber::CBigNumber(long long normalData)
{
	memset(data, 0, sizeof(data));
	data[0] = normalData;
	size = 1;
}
int CBigNumber::isLychrelNumber()
{
	if(size == 1)
		return ::isLychrelNumber(data[0]);
	
	if(isNumberTooBig() == true)
		return 1;

	if(isReverse() == true)
		return 0;

	if(isAllDigitSmallerThan5() == true)
		return 0;

	if(isInRecord() == false)
		return -1;

	return !value[data[0]];
}
void CBigNumber::add()
{
	CBigNumber reverse = getReverseNumber();
	for(int i = 0; i < size; i++)
	{
		data[i] = data[i] + reverse.data[i];
		if(data[i] > 1000000000000000000)
		{
			data[i] = data[i] - 1000000000000000000;
			data[i+1]++;
		}
	}
	if(data[size] > 0)
		size++;
}
void CBigNumber::setValue(bool flag)
{
	if(size == 1 && data[0] < MAX_TABLE_SIZE)
	{
		isCaculated[data[0]] = true;
		value[data[0]] = flag;
	}
}
void CBigNumber::print()
{
	for(int i = 0; i < size; i++)
		cout<<data[i];
}
CBigNumber& CBigNumber::operator=(const CBigNumber & B)
{
	size = B.size;
	for(int i = 0; i < size; i++)
		data[i] = B.data[i];
	return *this;
}
bool CBigNumber::operator==(const CBigNumber & B)
{
	if(size != B.size)
		return false;
	for(int i = 0; i < size; i++)
		if(data[i] != B.data[i])
			return false;
	return true;
}
bool CBigNumber::isNumberTooBig()
{
	if(size >= MAX_SIZE)
		return true;
	return false;
}
bool CBigNumber::isReverse()
{
	CBigNumber reverse = getReverseNumber();
	if(reverse == *this)
		return true;
	else
		return false;
}
bool CBigNumber::isAllDigitSmallerThan5()
{
	for(int i = 0; i < size; i++)
		if(::isAllDigitSmallerThan5(data[i]) == false)
			return false;
	return true;
}
bool CBigNumber::isInRecord()
{
	if(size > 1)
		return false;
	if(data[0] >= MAX_TABLE_SIZE)
		return false;
	return isCaculated[data[0]];
}
CBigNumber CBigNumber::getReverseNumber()
{
	CBigNumber ret;
	
	int digit[10000] = {0}, start;
	for(int i = 0; i < size; i++)
	{
		start = i * 18;
		long long temp = data[i];
		while(temp)
		{
			digit[start++] = temp % 10;
			temp = temp / 10;
		}
	}

	memset(ret.data, 0, sizeof(ret.data));
	for(int i = 0; i < start; i+=18)
	{
		for(int j = i; j < i+18; j++)
		{
			if(j >= start)break;
			ret.data[ret.size] = ret.data[ret.size] * 10 + digit[j];
		}
		ret.size++;
	}
	return ret;
}

二、评论

1.main.cpp逻辑太复杂

2.不应该在.h中写实现代码

3.int CBigNumber::isLychrelNumber()函数太长,其中的判断不在一个逻辑层次

4.isNumberTooBig()优化效果不明显,却严重影响代码阅读,建议去掉

5.Record是对中间过程的缓存,建议更名为buffer

6.部分魔应定义为宏

7.垂直的函数顺序不好,应参考《代码简洁之道》5.2.3和5.2.5

8.部分命名需要重新设计

你可能感兴趣的:(LychrelNumber实现V1.0)