Problem 17:Number letter counts

原题链接:http://projecteuler.net/problem=17


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到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" 的使用与英国标准一致。


解法1:

1.先初始化1~20,30,40,50,60,70,80,90,100,1000这些数字对应的英文的长度的字典

2.对于1~20的英文字符的长度,直接从第1步的字典里取得其长度

3.对于21~99,则分解成两部分,一部分是个位数,可从第1步的字典取得其长度,另一部分是这个数减去个位数的值,亦从第1步的字典里取得其长度

4.对于100~999的number,也要分解成两部分,一部分是a,其中a=100n,0<n<10,另一部分是b,其中b=number-a. 对于a转换成英文的话,长度等于百位数对应的英文长度和"hundred"的长度之和,对于b转换成英文的话,则用第3步的方法,则number对应的英文长度为a,b及"and"这三者的长度之和

5.对于1000,直接从第1步的字典里取得其长度

6.求和

php代码如下:

<?php


$dict = array(
    1 => 3, //one
    2 => 3, //two
    3 => 5, //three
    4 => 4, //four
    5 => 4, //five
    6 => 3, //six
    7 => 5, //seven
    8 => 5, //eight
    9 => 4, //nine
    10 => 3, //ten
    11 => 6, //eleven
    12 => 6, //twelve
    13 => 8, //thirteen
    14 => 8, //fourteen
    15 => 7, //fifteen
    16 => 7, //sixteen
    17 => 9, //seventeen
    18 => 8, //eighteen
    19 => 8, //nineteen
    20 => 6, //twenty
    30 => 6, //thirty
    40 => 5, //forty
    50 => 5, //fifty
    60 => 5, //sixty
    70 => 7, //seventy
    80 => 6, //eighty
    90 => 6, //ninety
    100 => 7, //hundred
    1000 => 8, //thousand
);


function get_letter_num_of_number_which_under_100($number, $dict) {
    $letter_num = 0;
    if ($number <= 20) {
        $letter_num = $dict[$number];
    } elseif ($number < 100) {
        $mod = $number % 10;
        if ($mod == 0) {
            $letter_num = $dict[$number - $mod];
        } else {
            $letter_num = $dict[$number - $mod] + $dict[$mod];
        }
    }
    return $letter_num;
}


function get_letter_num_of_number_which_between_100_and_999($number, $dict) {
    $letter_num = 0;
    $h = intval($number / 100);
    $remain = $number - ($h * 100);
    $letter_num+=$dict[$h] + $dict[100];
    if ($remain > 0) {
        $letter_num+=3; //and
        $letter_num+=get_letter_num_of_number_which_under_100($remain, $dict);
    }
    return $letter_num;
}


$up = 1000;
$letter_num = 0;
for ($i = 1; $i <= $up; $i++) {
    if ($i < 100) {
        $letter_num+=get_letter_num_of_number_which_under_100($i, $dict);
    } elseif ($i < 1000) {
        $letter_num+=get_letter_num_of_number_which_between_100_and_999($i, $dict);
    } else {
        $letter_num+=$dict[1] + $dict[1000];
    }
}
echo $letter_num;



注:题目的中文翻译源自http://pe.spiritzhang.com

问题集 3:文档间距离 介绍 目标 • 介绍 Python 中字典(dictionary)的概念 • 编写和调用 Python 中的辅助函数 合作 • 学生可以一起合作,但每个学生都应该单独编写和提交作业。学生不能提交完全相同的代码。 • 学生不允许查看或复制彼此的代码或代码结构。 • 在每个文件的开头的注释中包含你合作伙伴的名字。 尽管这个手册很长,但这里的信息是为了给你提供背景、实用的例子和提示,所以一定要仔细阅读。 A)文件设置 下载文件 1_ps3.zip 并将所有文件提取到同一目录中。包含的文件有:document_distance.py、test_ps3_student.py 和 tests/student_tests 目录中 的各种文本和歌词文档。当你完成后,确保运行测试器文件 test_ps3_student.py 来检查你的代码是否符合我们的某些测试用例。 你只需修改 document_distance.py。 B)文档距离概述 针对给定的两个单词或文档,你将计算一个介于 0 和 1 之间的分数,以表示它们的相似程度。如果单词或文档相同,则得分为 1。如果文档完全不同,则 得分为 0。你将以两种不同的方式计算分数,并观察哪种方式效果更好。第一种方法将使用两个文本中的单个单词频率。第二种方法将使用 TF-IDF(词 频-逆文档频率) 来处理文件中的单词。 注意,在整个 pset 中你不需要担心大小写敏感性。所有输入都将是小写的。 1)文本转列表 在任何数据分析问题中,第一步是准备数据。我们提供了一个名为 load_file 的函数来读取文本文件,并将文件中的所有文本输出到一个字符串中。此函 数接受一个名为 filename 的变量,该变量是要加载的文件名的字符串,包括扩展名。 该函数删除所有标点符号,并将文本保存为字符串。不要修改此函数。 这是一个示例用法: # hello_world.txt looks like this: 'hello world, hello' >>> text = load_file("tests/student_tests/hello_world.txt") >>> text 'hello world hello' 接下来,你需要将字符串转换为文本的列表表示形式。基于上面给定的示例,期望得到如下的效果: >>> text_to_list('hello world hello') [‘hello’, ‘world’, ‘hello’] 按照给定的说明和文档字符串在 document_distance.py 中实现 text_to_list。除了运行测试文件外,你还可以通过取消注释 document_distance.py 底部提供的相关行来快速检查你的实现: if __name__ == "__main__": # Tests Problem 0: Prep Data test_directory = "tests/student_tests/" hello_world, hello_friend = load_file(test_directory + 'hello_world.txt'), load_file(test_directory + 'hello_friend.txt') world, friend = text_to_list(hello_world), text_to_list(hello_friend) print(world) # should print ['hello', 'world', 'hello'] print(friend) # should print ['hello', 'friends'] 1 注意:你可以假设我们提供的文本文件中唯一的空白是换行符或单词之间的空格(即没有制表符) 2)获取频率 让我们开始计算给定列表中每个元素的频率。目标是返回一个字典,其中每个唯一元素作为键,元素在列表中出现的次数作为值。 参考以下示例: 示例 1: >>> get_frequencies(['h', 'e', 'l', 'l', 'o']) {'h': 1, 'e': 1, 'l': 2, 'o': 1} 示例 2: >>> get_frequencies(['hello', 'world', 'hello']) {'hello': 2, 'world': 1} 根据以上说明和提供的文档字符串在 document_distance.py 中实现 get_frequencies。除了运行测试文件外,你还可以通过取消注释 document_distance.py 底部提供的相关行来快速检查你的实现: if __name__ == "__main__": # Tests Problem 1: Get Frequencies test_directory = "tests/student_tests/" hello_world, hello_friend = load_file(test_directory + 'hello_world.txt'), load_file(test_directory + 'hello_friend.txt') world, friend = text_to_list(hello_world), text_to_list(hello_friend) world_word_freq = get_frequencies(world) friend_word_freq = get_frequencies(friend) print(world_word_freq) # should print {'hello': 2, 'world': 1} print(friend_word_freq) # should print {'hello': 1, 'friends': 1} 3)字母频率 现在,给定一个字符串形式的单词,让我们创建一个字典,其中每个字母作为键,每个字母在单词中出现的次数作为值。这听起来和 get_frequencies 非 常相似… 提示:你必须在 get_letter_frequencies 中调用 get_frequencies 。 示例 1: >>> get_letter_frequencies('hello') {'h': 1, 'e': 1, 'l': 2, 'o': 1} 示例 2: >>> get_letter_frequencies('that') {'t': 2, 'h': 1, 'a': 1} 根据以上说明和提供的文档字符串在 document_distance.py 中实现 get_letter_frequencies。除了运行测试文件外,你还可以通过取消注释 document_distance.py 底部提供的相关行来快速检查你的实现: if __name__ == "__main__": # Tests Problem 2: Get Letter Frequencies freq1 = get_letter_frequencies('hello') freq2 = get_letter_frequencies('that') print(freq1) # should print {'h': 1, 'e': 1, 'l': 2, 'o': 1} print(freq2) # should print {'t': 2, 'h': 1, 'a': 1} 4)相似性 终于到了计算相似度的时候!根据下一个段落中给出的 相似性 定义,完成函数 calculate_similarity_score。你的函数应该能够与 get_frequencies 或 get_letter_frequencies 的输出一起使用。 考虑两个列表 𝐿1 和 𝐿2 。设 𝑈 是由 𝐿1 、 𝐿2 中的所有元素组成的一个列表,但不重复(例如,如果 𝐿1 = ['a', 'b'],𝐿2 = ['b', 'c'],则 𝑈 = ['a', 'b', 'c'])。 对于 𝐿1 或 𝐿2 中的元素 𝑒,令 count(𝑒,𝐿𝑖 ) = { 𝑒 出现在 𝐿𝑖 中的次数 如果 𝑒 在 𝐿𝑖 中 0 如果 𝑒 不在 𝐿𝑖 中 我们可以定义: • 𝜎(𝑒) = |count(𝑒,𝐿1 ) + count(𝑒,𝐿2 )| . (其中竖线表示绝对值),以及 2 • 𝜎(𝑒) = count(𝑒,𝐿1 ) + count(𝑒,𝐿2 ) . 相似性 定义为: 1 − 𝛿(𝑢1 ) + 𝛿(𝑢2 ) + 𝛿(𝑢3 ) + … 𝜎(𝑢1 ) + 𝜎(𝑢2 ) + 𝜎(𝑢3 ) + … 其中求和是对 𝑈 中所有元素 𝑢1 , 𝑢2 , 𝑢3 , … 进行的,结果四舍五入到小数点后两位。 示例(元素是单词): • 假设 ‣ 𝐿1 = ['hello', 'world', 'hello'], ‣ 𝐿2 = ['hello', 'friends']。 • 去掉重复元素后的列表 𝑈 = ['hello', 'world', 'friends']。 • 频率差 𝛿(𝑢) 是 ‣ 𝛿('hello') = 2 + 1 = 3 ‣ 𝛿('world') = 1 + 0 = 1 ‣ 𝛿('friends') = 0 + 1 = 1 • 因此,相似性 是 1 − 1 3 + + 1 1 + + 1 1 = 1 − 3 5 = 0.4 你可以在 calculate_similarity_score 的文档字符串中找到相同的计算和另一种(等效的)解释。 重要提示:确保将最终的相似度计算结果四舍五入到小数点后两位。 根据给定的说明和文档字符串在 document_distance.py 中实现函数 calculate_similarity_score。除了运行测试文件外,你还可以通过取消注释 document_distance.py 底部提供的相关行来快速检查你的实现: if __name__ == "__main__": # Tests Problem 3: Similarity test_directory = "tests/student_tests/" hello_world, hello_friend = load_file(test_directory + 'hello_world.txt'), load_file(test_directory + 'h world, friend = text_to_list(hello_world), text_to_list(hello_friend) world_word_freq = get_frequencies(world) friend_word_freq = get_frequencies(friend) word1_freq = get_letter_frequencies('toes') word2_freq = get_letter_frequencies('that') word3_freq = get_frequencies('nah') word_similarity1 = calculate_similarity_score(word1_freq, word1_freq) word_similarity2 = calculate_similarity_score(word1_freq, word2_freq) word_similarity3 = calculate_similarity_score(word1_freq, word3_freq) word_similarity4 = calculate_similarity_score(world_word_freq, friend_word_freq) print(word_similarity1) # should print 1.0 print(word_similarity2) # should print 0.25 print(word_similarity3) # should print 0.0 print(word_similarity4) # should print 0.4 5)出现频次最高的单词 接下来,你将找出在两个字典中哪个单词出现的频率最高。你将计算每个单词在两个文本中出现的次数,并返回出现频率最高的单词列表。出现频率最高 的单词不必要在两个字典中都有。它是基于两个字典中所有单词频率的总和。如果一个单词在两个字典中都出现,则将频率之和视为该单词的总频率。如 果多个单词并列(即具有相同的最高频率),则返回按字母顺序排列的所有这些单词的列表。 举例,参考以下用例: >>> freq1 = {"hello": 5, "world": 1} >>> freq2 = {"hello": 1, "world": 5} >>> get_most_frequent_words(freq1, freq2) ["hello", "world"] 根据给定的说明和文档字符串在 document_distance.py 中实现函数 get_most_frequent_words。除了运行测试文件外,你还可以通过取消注释 document_distance.py 底部提供的相关行来快速检查你的实现: if __name__ == "__main__": # Tests Problem 4: Most Frequent Word(s) freq_dict1, freq_dict2 = {"hello": 5, "world": 1}, {"hello": 1, "world": 5} most_frequent = get_most_frequent_words(freq_dict1, freq_dict2) print(most_frequent) # should print ["hello", "world"] 6)词频-逆文档频率(TF-IDF) 在这一部分,你将计算词频-逆文档频率,这是一个数值度量,表示单词在文档中的重要性。你将首先计算词频和逆文档频率,然后将两者结合起来得到 TF-IDF。 词频 (TF) 的计算公式为: 3 TF(𝑤) = number of times word total number of words in the document 𝑤 appears in the document TF(𝑤) = 𝑤 在文档中出现的次数 文档中的总单词数 逆文档频率 (IDF) 的计算公式为: IDF(𝑤) = log10( number of documents with word total number of documents 𝑤 in it) IDF(𝑤) = log10(含 𝑤 文档数量 的文档数量) 其中 log10 是以 10 为底的对数,可以调用 math.log10 完成计算。 结合 TF 和 IDF,我们可以得到 TF-IDF(𝑤) = TF(𝑤) × IDF(𝑤),其中值越高,单词越稀有,反之亦然。在本题目集中,我们只处理单个单词,但 TF-IDF 也适用于更大的单词组(例如 二元组、三元组等)。 你需要实现 get_tf 函数,它的输入参数 text_file 表示一个文件名,你需要加载对应文件,准备数据,并计算 text_file 中每个单词的 TF 值。输出应该 是一个字典,将每个单词映射到其 TF。想想你如何可以利用之前的函数。 你需要实现 get_idf 函数,它的输入参数 text_files 表示一个文件名列表,你需要加载每个文件,准备数据,并计算 text_files 中所有单词的 IDF 值。 输出应该是一个字典,将每个单词映射到其 IDF。 你需要实现 get_tfidf 函数,它的输入参数 text_file 和 text_files 分别表示一个文件名和一个文件名列表,你需要加载对应文件,准备数据,并计算 text_file 中所有单词的 TF-IDF 值。输出应该是一个排序后的元组列表(按 TF-IDF 分数递增),其中每个元组的形式为 (word, TF-IDF) 。如果多个单词 具有相同的 TF-IDF,则按字母顺序递增排序。 以下是一些用例: >>> text_file = "tests/student_tests/hello_world.txt" >>> get_tf(text_file) {"hello": 0.6666666666666666, "world": 0.3333333333333333} # Explanation: There are 3 total words in "hello_world.txt". 2 of the three total words are "hello", giving >>> text_files = ["tests/student_tests/hello_world.txt", "tests/student_tests/hello_friends.txt"] >>> get_idf(text_files) {"hello": 0.0, "world": 0.3010299956639812, "friends": 0.3010299956639812} # Explanation: There are a total of 2 documents in this example. "hello" is in both documents, giving "hello >>> text_file = "tests/student_tests/hello_world.txt" >>> text_files = ["tests/student_tests/hello_world.txt", "tests/student_tests/hello_friends.txt"] >>> get_tfidf(text_file, text_files) [('hello', 0.0), ('world', 0.10034333188799373)] # Explanation: We multiply the corresponding TF and IDF values for each word in "hello_world.txt" and get 根据给定的说明在 document_distance.py 中实现函数 get_tf、get_idf 和 get_tfidf。除了运行测试文件外,你还可以通过取消注释 document_distance.py 底部提供的相关行来快速检查你的实现: if __name__ == "__main__": # Tests Problem 5: Find TF-IDF tf_text_file = 'tests/student_tests/hello_world.txt' idf_text_files = ['tests/student_tests/hello_world.txt', 'tests/student_tests/hello_friends.txt'] tf = get_tf(tf_text_file) idf = get_idf(idf_text_files) tf_idf = get_tfidf(tf_text_file, idf_text_files) print(tf) # should print {'hello': 0.6666666666666666, 'world': 0.3333333333333333} print(idf) # should print {'hello': 0.0, 'world': 0.3010299956639812, 'friends': 0.3010299956639812} print(tf_idf) # should print [('hello', 0.0), ('world', 0.10034333188799373)] 完成后,请确保运行测试文件 test_ps3_student.py 以检查你的代码是否符合预设的测试用例。 7)提交程序 7.1)命名文件 将你的所有实现直接保存在原始的源代码文件 document_distance.py 中, 请不要忽略此步骤或使用其他名称保存文件! 7.2)时间和协作信息 在每个文件的开头,在注释中写下你在该部分问题上花费的时间(大致),以及你的合作伙伴的名字。例如: # Problem Set 3 # Name: Jane Lee # Collaborators: John Doe 4 7.3)中期提交 所有学生都应该在中期截止日期(最终截止日期前 1 周)之前提交他们的进展。此提交将占问题集成绩的一部分分数,并且不会根据正确性进行评分。目 的是确保你在问题集上稳步推进,而不是在截止日期前的最后几天才开始工作。 7.4)最终提交 确保运行学生测试文件并确保所有测试都通过。 文档相似性 补充阅读材料 这个问题集是信息检索中一个非常相关的问题的极大简化版本。文档相似性的应用范围从检索搜索引擎结果到比较基因和蛋白质,再到改善机器翻译。 计算文档距离的进阶技术包括将文本转换为向量空间,并计算余弦相似度、Jaccard 指数或向量的其他度量。 56-1 Problem Set 3 分数 60 作者 樊志伟 单位 许昌学院 Problem Set 3 - Document Distance 下载 实验三材料.zip 文件,解压后根据其中的 ps3_cn.pdf 文件完成实验。 实验三材料.zip 注意:把你的 document_distance.py 文件中的所有代码全部复制到提交框内后: 把 if __name__ == '__main__': 及其之后的代码 删掉或者注释掉,否则会影响此题的正常判题 输入样例: Tests Problem 0: Prep Data hello world, hello ===END=== 输出样例: ['hello', 'world', 'hello']
最新发布
05-31
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值