Project Euler Problem 17 (C++和Python代码实现和解析)

本文探讨了将1到1000的整数转换为其英文单词表示,并计算总字母数量的问题。通过分析不同数值范围的单词构成规律,设计了C++与Python代码实现方案,有效地解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem 17 : Number letter counts

If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?

NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of “and” when writing out numbers is in compliance with British usage.

1. 数的字母计数

如果从1到5的数是用单词写出来:one, two, three, four, five,那么总共使用的字母为 3 + 3 + 5 + 4 + 4 = 19。

如果从1到1000的所有数(含1000)用单词写出来,用到多少个字母呢?

注意:不要计算空格或连字符。例如,342 (three hundred and forty-two) 包含23个字母,115 (one hundred and fifteen) 包含20个字母。在写出数时,要使用“and”以符合英国用法。

2. 求解分析

首先,我们要知道1到1000个数用英语单词写出来的所有类型:
“one”, “two”, “three”, “four”, “five”, “six”, “seven”,“eight”, “nine”, “ten”, “eleven”, “twelve”, “thirteen”, “fourteen”,“fifteen”,“sixteen”, “seventeen”, “eighteen”, “nineteen”, “twenty”,“thirty”, “forty”, “fifty”, “sixty”, “seventy”, “eighty”, “ninety”,“hundred”, “thousand”, “and”

另外,要搞清楚每个数用单词写出的方法,主要是使用"and"。

然后,每种单词的字母个数可以在先算出来,保存在一个数组里,最后组合以下就算出最后的字母的个数。

3. C++ 代码实现

类PE0017的类图如下:
在这里插入图片描述

  • 全局变量numberString 是字符串数组,保存所有32种关键字字符串。

  • 成员变量m_digits[]用于保存每个数的数字,最多四个。 成员变量m_lettersArray[]用来保存32种类型的字符数。

  • 成员函数 getDigitsOfNumber(int number) 把数number的取每一位,结果保存在成员变量数组m_digits里。

  • 成员函数 getUnitValue() 返回个位数的数字。

  • 成员函数 getDecadeValue() 返回十位数的数字。

  • 成员函数 getHundredValue() 返回百位数的数字。

  • 构造函数PE0017() 遍历所有全局字符串数组 numberString, 给成员变量m_lettersArray赋初值。

  • 成员函数 getLettersSumOfNumber(int number) 计算一个数number的字符个数。

  • 成员函数 getSumOfLetters(int max_number) 统计从1到max_number的所有数的字母个数。

C++ 代码

#include <iostream>
#include <vector>
#include <string>
#include <cassert>

using namespace std;

const int max_types = 32;
string numberString[max_types]={"", "one", "two", "three", "four", "five",
"six", "seven","eight", "nine", "ten", "eleven", "twelve", "thirteen", 
"fourteen","fifteen","sixteen", "seventeen", "eighteen", "nineteen", 
"twenty","thirty", "forty", "fifty", "sixty", "seventy", "eighty", 
"ninety","hundred", "thousand", "and"};

/*
#define C_blank 0  // blank
#define C_1     1  // one
#define C_2     2  // two
#define C_3     3  // three
#define C_4     4  // four
#define C_5     5  // five
#define C_6     6  // six
#define C_7     7  // seven
#define C_8     8  // eight
#define C_9     9  // nine

#define C_10    10  // ten
#define C_11    11  // eleven
#define C_12    12  // twelve
#define C_13    13  // thirteen
#define C_14    14  // fourteen
#define C_15    15  // fifteen
#define C_16    16  // sixteen
#define C_17    17  // seventeen
#define C_18    18  // eighteen
#define C_19    19  // nineteen

#define C_20    20  // twenty
#define C_30    21  // thirty 
#define C_40    22  // forty
#define C_50    23  // fifty
#define C_60    24  // sixty
#define C_70    25  // seventy
#define C_80    26  // eighty
#define C_90    27  // ninety
#define C_100   28  // hundred
#define C_1000  29  // thousand 
#define C_and   30  // and

#define C_MAX   C_and
*/

class PE0017
{
private:
    static const int max_digits = 4;
    static const int C_1    = 1;
    static const int C_19   = 19;
    static const int C_100  = 28;
    static const int C_1000 = 29;
    static const int C_and  = 30;

    int m_digits[max_digits];
    int m_lettersArray[max_types];

    void getDigitsOfNumber(int number);
    int getUnitValue()    { return m_digits[0]; }
    int getDecadeValue()  { return m_digits[1]; }
    int getHundredValue() { return m_digits[2]; }
    
public:
    PE0017();
    int getLettersSumOfNumber(int number);
    int getSumOfLetters(int max_number);
};

PE0017::PE0017()
{
    for (int i=0; i<max_types; i++)
    {
        m_lettersArray[i] = numberString[i].size();
    }
}

void PE0017::getDigitsOfNumber(int number)
{
    memset(m_digits, 0, sizeof(m_digits));

    int i = 0;
    while(number > 0)
    {
        m_digits[i++] = number%10;
        number /= 10;
    }
}

int PE0017::getLettersSumOfNumber(int number)
{
    getDigitsOfNumber(number);

    int unitDigit    = getUnitValue();
    int decadeDigit  = getDecadeValue();
    int hundredDigit = getHundredValue();    

    int sumOfLetters = 0;

    if (1000 == number)
    {
        sumOfLetters += m_lettersArray[C_1000] + m_lettersArray[C_1];
    }
    else
    {
        if (hundredDigit > 0) 
        {
            sumOfLetters += m_lettersArray[hundredDigit]+m_lettersArray[C_100];
            if (decadeDigit+unitDigit > 0)
            {
                sumOfLetters += m_lettersArray[C_and]; 
            }
        }

        if (decadeDigit > 1) 
        {
            sumOfLetters += m_lettersArray[decadeDigit+C_19-1];
        }
        else if (decadeDigit == 1)
        {
            sumOfLetters += m_lettersArray[10+unitDigit];
        }

        if (unitDigit > 0 && decadeDigit != 1) 
        {
            sumOfLetters += m_lettersArray[unitDigit];
        }
    }

    return  sumOfLetters;  
}

int PE0017::getSumOfLetters(int max_number)
{
    int sumOfLetters = 0;

    for(int i=1; i<=max_number; i++)
    {
        sumOfLetters += getLettersSumOfNumber(i);
    }
    return sumOfLetters;
}

int main()
{
    PE0017 pe0017;

    assert(20 == pe0017.getLettersSumOfNumber(115));

    int sumOfLetters = pe0017.getSumOfLetters(1000);
    
    cout << "The letters "<<sumOfLetters<<" are used for all the numbers "<<endl;
    cout << "from 1 to 1000 (one thousand) inclusive in words." << endl; 

    return 0;
}

4. Python 代码实现

Python和C++采用一样的实现方法。虽然方法没有什么巧妙,但还是很实用和易懂的。

Python 代码

def getDigits(number):
    digits = [0]*4
    numOfDigits = 0
    while number >= 1:                           
        digits[numOfDigits] = number%10
        number      /= 10
        numOfDigits += 1
    return digits
        
def getLettersSumOfNumber(number):
    """
    C_blank = 0   # blank
    C_1 =     1   # one
    C_2 =     2   # two
    C_3 =     3   # three
    C_4 =     4   # four
    C_5 =     5   # five
    C_6 =     6   # six
    C_7 =     7   # seven
    C_8 =     8   # eight
    C_9 =     9   # nine
    C_10 =    10  # ten
    C_11 =    11  # eleven
    C_12 =    12  # twelve
    C_13 =    13  # thirteen
    C_14 =    14  # fourteen
    C_15 =    15  # fifteen
    C_16 =    16  # sixteen
    C_17 =    17  # seventeen
    C_18 =    18  # eighteen
    C_19 =    19  # nineteen
    C_20 =    20  # twenty
    C_30 =    21  # thirty 
    C_40 =    22  # forty
    C_50 =    23  # fifty
    C_60 =    24  # sixty
    C_70 =    25  # seventy
    C_80 =    26  # eighty
    C_90 =    27  # ninety
    C_100 =   28  # hundred
    C_1000 =  29  # thousand 
    C_and  =  30  # and
    """
    numberString = ["", "one", "two", "three", "four", "five",
        "six", "seven","eight", "nine", "ten", "eleven", "twelve", "thirteen", 
        "fourteen","fifteen","sixteen", "seventeen", "eighteen", "nineteen", 
        "twenty","thirty", "forty", "fifty", "sixty", "seventy", "eighty", 
        "ninety","hundred", "thousand", "and"]
    
    letters_list = [ len(item) for item in numberString ]
    
    digits = getDigits(number)

    unitDigit    = int(digits[0])
    decadeDigit  = int(digits[1])
    hundredDigit = int(digits[2])

    sumOfLetters = 0

    C_1, C_19, C_100, C_1000, C_and = 1, 19, 28, 29, 30

    if 1000 == number:
        sumOfLetters += letters_list[C_1000] + letters_list[C_1]
    else:
        if hundredDigit > 0:
            sumOfLetters += letters_list[hundredDigit]+letters_list[C_100]
            if decadeDigit+unitDigit > 0:
                sumOfLetters += letters_list[C_and]

        if decadeDigit > 1: 
            sumOfLetters += letters_list[decadeDigit+C_19-1]
        elif decadeDigit == 1:
            sumOfLetters += letters_list[10+unitDigit]

        if unitDigit > 0 and decadeDigit != 1:
            sumOfLetters += letters_list[unitDigit]

    return  sumOfLetters

def getSumOfLetters(max_number):
    sumOfLetters = 0;
    for i in range (1, max_number+1):
        sumOfLetters += getLettersSumOfNumber(i)
    return sumOfLetters
    
def main():
    assert 20 == getLettersSumOfNumber(115)
    assert 23 == getLettersSumOfNumber(342)
    print("The letters", getSumOfLetters(1000), "are used for all the numbers ")
    print("from 1 to 1000 (one thousand) inclusive in words.") 

if  __name__ == '__main__':
    main()
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值