【ProjectEuler】ProjectEuler_055(10000以下有多少Lychrel数?)

#pragma once

#include <string>
#include <Windows.h>

using namespace std;
class MoonBigNum
{
public:
    MoonBigNum(void);
    MoonBigNum(const string &num);
    MoonBigNum(const UINT32 &num);
    MoonBigNum(const MoonBigNum &bigNum);
    ~MoonBigNum(void);

    //************************************
    // Method:    Value
    // Access:    public
    // Describe:  获取大数的值
    // Returns:   const string &
    //************************************
    const string &Value()const;

    //************************************
    // Method:    operator+
    // Access:    public
    // Describe:  大数相加
    // Parameter: const BigNum & right
    // Returns:   const BigNum
    //************************************
    const MoonBigNum operator+(const MoonBigNum &right)const;

    //************************************
    // Method:    operator==
    // Access:    public
    // Describe:  判断2个大数是否相等
    // Parameter: const BigNum & right
    // Returns:   bool
    //************************************
    bool operator==(const MoonBigNum &right)const;

    //************************************
    // Method:    operator<
    // Access:    public
    // Describe:  实现小于比较
    // Parameter: const BigNum & right
    // Returns:   bool
    //************************************
    bool operator<(const MoonBigNum &right)const;

    //************************************
    // Method:    operator>
    // Access:    public
    // Describe:  实现大于比较
    // Parameter: const BigNum & right
    // Returns:   bool
    //************************************
    bool operator>(const MoonBigNum &right)const;

    //************************************
    // Method:    operator++
    // Access:    public
    // Describe:  前自增,++value
    // Returns:   BigNum
    //************************************
    MoonBigNum operator++();

    //************************************
    // Method:    operator++
    // Access:    public
    // Describe:  后自增,value++
    // Parameter: int
    // Returns:   BigNum
    //************************************
    MoonBigNum operator++(int);

    //************************************
    // Method:    operator+=
    // Access:    public 
    // Describe:  重载+=
    // Parameter: MoonBigNum & right
    // Returns:   MoonBigNum
    //************************************
    MoonBigNum operator+=(MoonBigNum &right);
    MoonBigNum operator+=(UINT32 num);

    //************************************
    // Method:    Reverse
    // Access:    public
    // Describe:  数字逆转,比如123变成321,但是2000会变成2
    // Returns:   BigNum
    //************************************
    MoonBigNum Reverse()const;

private:
    string numStr;
};


#include "MoonBigNum.h"
#include "MoonString.h"

MoonBigNum::MoonBigNum(void): numStr("")
{
}

MoonBigNum::MoonBigNum(const string &num)
{
    string::size_type length = num.size();
    UINT32 startIndex = 0;                  // 起始转换位置,主要是为了排除前面的0

    for(string::size_type i = 0; i < length; ++i)
    {
        if(startIndex == i && num[i] == '0')
        {
            ++startIndex;
        }

        if(!isdigit(num[i]))
        {
            numStr = "";
            return;
        }
    }

    // 输入串全是0:"0000"
    if(startIndex == length)
    {
        --startIndex;
    }

    // 提高效率
    if(startIndex == 0)
    {
        numStr = num;
    }
    else
    {
        numStr = num.substr(startIndex);
    }
}

MoonBigNum::MoonBigNum(const UINT32 &num): numStr(MoonString::ToString(num))
{

}

MoonBigNum::MoonBigNum(const MoonBigNum &MoonBigNum)
{
    this->numStr = MoonBigNum.numStr;
}


MoonBigNum::~MoonBigNum(void)
{
}

const string &MoonBigNum::Value()const
{
    return numStr;
}

const MoonBigNum MoonBigNum::operator+(const MoonBigNum &right)const
{
    string result;
    string::const_reverse_iterator it1 = this->numStr.rbegin();
    string::const_reverse_iterator it2 = right.numStr.rbegin();
    UINT32 currValue = 0;
    UINT32 lastFlag = 0;
    bool notEnd = true;

    while(true)
    {
        currValue = 0;
        notEnd = false;

        if(lastFlag != 0)
        {
            ++currValue;
            notEnd = true;
        }
        lastFlag = 0;

        if(it1 != this->numStr.rend())
        {
            currValue += *it1 - '0';
            notEnd = true;
            ++it1;
        }

        if(it2 != right.numStr.rend())
        {
            currValue += *it2 - '0';
            notEnd = true;
            ++it2;
        }

        if(!notEnd)
        {
            break;
        }


        if(currValue >= 10)
        {
            lastFlag = 1;
            currValue -= 10;
        }

        result += currValue + '0';
    }

    return MoonBigNum(MoonString::Reverse(result));
}

bool MoonBigNum::operator==(const MoonBigNum &right) const
{
    return this->numStr == right.numStr;
}

bool MoonBigNum::operator<(const MoonBigNum &right) const
{
    return this->numStr < right.numStr;
}

bool MoonBigNum::operator>(const MoonBigNum &right) const
{
    return right < *this;
}

MoonBigNum MoonBigNum::operator++()
{
    *this = *this + MoonBigNum(1);

    return *this;
}

MoonBigNum MoonBigNum::operator++(int)
{
    MoonBigNum result(*this);

    *this = *this + MoonBigNum(1);

    return result;
}

MoonBigNum MoonBigNum::Reverse() const
{
    return MoonBigNum(MoonString::Reverse(numStr));
}

MoonBigNum MoonBigNum::operator+=(MoonBigNum &right)
{
    *this = *this + right;

    return *this;
}

MoonBigNum MoonBigNum::operator+=(UINT32 num)
{
    *this += MoonBigNum(num);

    return *this;
}

#pragma once

#include <string>
#include <sstream>
using namespace std;

class MoonString
{
public:
    
    //************************************
    // Method:    Reverse
    // Access:    public static 
    // Describe:  字符串逆序
    // Parameter: const string & srcString  要逆序的字符串
    // Returns:   std::string               逆序结果
    //************************************
    static string Reverse(const string &srcString);

    //************************************
    // Method:    ToString
    // Access:    public static 
    // Describe:  任意类型转换为string
    // Parameter: T value
    // Returns:   std::string
    //************************************
    template <class T>
    static const string ToString(T value);
};

template <class T>
const string MoonString::ToString( T value )
{
    stringstream ss;
    ss<<value;
    
    string result;
    ss>>result;

    return result;
}

#include "MoonString.h"


string MoonString::Reverse(const string &srcString)
{
    size_t len = srcString.length();
    string outString;

    for(size_t i = 0; i < len; ++i)
    {
        outString += srcString[len - i - 1];
    }

    return outString;
}

// Lychrel numbers
//     Problem 55
//     If we take 47, reverse and add, 47 + 74 = 121, which is palindromic.
//
//     Not all numbers produce palindromes so quickly. For example,
//
//     349 + 943 = 1292,
//     1292 + 2921 = 4213
//     4213 + 3124 = 7337
//
//     That is, 349 took three iterations to arrive at a palindrome.
//
//     Although no one has proved it yet, it is thought that some numbers, like 196, never produce a palindrome. A number that never forms a palindrome through the reverse and add process is called a Lychrel number. Due to the theoretical nature of these numbers, and for the purpose of this problem, we shall assume that a number is Lychrel until proven otherwise. In addition you are given that for every number below ten-thousand, it will either (i) become a palindrome in less than fifty iterations, or, (ii) no one, with all the computing power that exists, has managed so far to map it to a palindrome. In fact, 10677 is the first number to be shown to require over fifty iterations before producing a palindrome: 4668731596684224866951378664 (53 iterations, 28-digits).
//
//     Surprisingly, there are palindromic numbers that are themselves Lychrel numbers; the first example is 4994.
//
//     How many Lychrel numbers are there below ten-thousand?
//
// NOTE: Wording was modified slightly on 24 April 2007 to emphasise the theoretical nature of Lychrel numbers.
//
// 题目55:10000以下有多少Lychrel数?
//     我们将47与它的逆转相加,47 + 74 = 121, 可以得到一个回文。
//
//     并不是所有数都能这么快产生回文,例如:
//
//     349 + 943 = 1292,
//     1292 + 2921 = 4213
//     4213 + 3124 = 7337
//
//     也就是说349需要三次迭代才能产生一个回文。
//
//     虽然还没有被证明,人们认为一些数字永远不会产生回文,例如196。那些永远不能通过上面的方法(逆转然后相加)产生回文的数字叫做Lychrel数。因为这些数字的理论本质,同时也为了这道题,我们认为一个数如果不能被证明的不是Lychrel数的话,那么它就是Lychre数。此外,对于每个一万以下的数字,你还有以下已知条件:这个数如果不能在50次迭代以内得到一个回文,那么就算用尽现有的所有运算能力也永远不会得到。10677是第一个需要50次以上迭代得到回文的数,它可以通过53次迭代得到一个28位的回文:4668731596684224866951378664。
//
//     令人惊奇的是,有一些回文数本身也是Lychrel数,第一个例子是4994。
//
//     10000以下一共有多少个Lychrel数?

#include <iostream>
#include <windows.h>
#include <ctime>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <assert.h>
#include "MoonBigNum.h"

using namespace std;

// 打印时间等相关信息
class DetailPrinter
{
public:
    void Start();
    void End();
    DetailPrinter();

private:
    LARGE_INTEGER timeStart;
    LARGE_INTEGER timeEnd;
    LARGE_INTEGER freq;
};

DetailPrinter::DetailPrinter()
{
    QueryPerformanceFrequency(&freq);
}

//************************************
// Method:    Start
// Access:    public
// Describe:  执行每个方法前调用
// Returns:   void
//************************************
void DetailPrinter::Start()
{
    QueryPerformanceCounter(&timeStart);
}

//************************************
// Method:    End
// Access:    public
// Describe:  执行每个方法后调用
// Returns:   void
//************************************
void DetailPrinter::End()
{
    QueryPerformanceCounter(&timeEnd);
    cout << "Total Milliseconds is " << (double)(timeEnd.QuadPart - timeStart.QuadPart) * 1000 / freq.QuadPart << endl;

    const char BEEP_CHAR = '\007';

    cout << endl << "By GodMoon" << endl << __TIMESTAMP__ << BEEP_CHAR << endl;

    system("pause");
}

/*************************解题开始*********************************/

void TestFun1()
{

    cout << "TestFun1 OK!" << endl;
}

inline bool IsPalindromeNum(const MoonBigNum &bigNum)
{
    return bigNum == bigNum.Reverse();
}

//************************************
// Method:    IsLychrelNum
// Access:    public
// Describe:  判断是否是Lychrel数
// Parameter: UINT32 num
// Returns:   bool
//************************************
bool IsLychrelNum(UINT32 num)
{
    const UINT32 MAX_LOOP = 50;   // 最多加50次

    MoonBigNum bigNum(num);

    for(UINT32 i = 0; i < MAX_LOOP; ++i)
    {
        bigNum += bigNum.Reverse();

        if(IsPalindromeNum(bigNum))
        {
            return false;
        }
    }

    return true;
}

void F1()
{
    cout << "void F1()" << endl;

    // TestFun1();

    DetailPrinter detailPrinter;
    detailPrinter.Start();

    /*********************************算法开始*******************************/
    const UINT32 MAX_NUM = 10000;
    UINT32 lychrelNumCount = 0;

    for(UINT32 i = 1; i < MAX_NUM; ++i)
    {
        if(IsLychrelNum(i))
        {
            ++lychrelNumCount;
        }
//         else
//         {
//             cout << i << endl;
//         }
    }

    cout << MAX_NUM << "以内的Lychrel数有" << lychrelNumCount << "个" << endl;

    /*********************************算法结束*******************************/

    detailPrinter.End();
}

//主函数
int main()
{
    F1();
    return 0;
}

/*
void F1()
10000以内的Lychrel数有249个
Total Milliseconds is 4411.78

By GodMoon
Sun Jun  2 18:46:29 2013
*/


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值