2020-04
22

字典还能这样玩!

By xrspook @ 18:30:55 归类于: 扮IT

一开始,我自己写的脚本能运行,但慢到怀疑人生。吃了个饭,折腾了半个小时后,字母表才处理到b而已,显然这是个失败的操作。我的做法是常规地为词汇表建立字典,然后历遍字典里的每个单词,单词进入函数后跟字典的另一个单词比较,比较方法是把单词(即字符串)打散为字符列表然后排列,如果排列一致,且被比较的单词小于拿去比的单词,它们就是一伙的,贴在被比较的单词列表下。列表长度大于2就返回列表然后打印。这样是可以选出异构词的,但非常非常慢!

看过参考答案之后我跳起来了,他们用了一句”.join(lists),这等于是把列表str重新粘成一个字符串,我那个去!他们把单词用列表打散重排再粘回去,最关键的是,这个唯一的重排字符串他们在建立字典的时候就作为key,所有与之有一样字符的全部被看作小弟被放置这个键的键值里。字典还是字典,但字典的键成了规则字符串,键值则是排列组合过的词汇表。我根本没想到啊,怎么可能想得到呢!!!!!

题目要求倒序打印,然后要求找出能组成最多异构词的8个字母。但实际上参考答案的输出问非所答,比如没有倒序,比如只是把8个字母的异构词摆出来,没确切告诉你最多的是什么。

Exercise 2: More anagrams! Write a program that reads a word list from a file (see Section 9.1) and prints all the sets of words that are anagrams. Here is an example of what the output might look like:
[‘deltas’, ‘desalt’, ‘lasted’, ‘salted’, ‘slated’, ‘staled’]
[‘retainers’, ‘ternaries’]
[‘generating’, ‘greatening’]
[‘resmelts’, ‘smelters’, ‘termless’]
Hint: you might want to build a dictionary that maps from a collection of letters to a list of words that can be spelled with those letters. The question is, how can you represent the collection of letters in a way that can be used as a key? Modify the previous program so that it prints the longest list of anagrams first, followed by the second longest, and so on. In Scrabble a “bingo” is when you play all seven tiles in your rack, along with a letter on the board, to form an eight-letter word. What collection of 8 letters forms the most possible bingos? Solution: http://thinkpython2.com/code/anagram_sets.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from time import time
def sorted_anagram(d):
    l = []
    for key in d:
        if len(d[key]) > 1:
            l.append((len(d[key]), d[key])) # 这是个由列表创建的元组?
    return sorted(l, reverse = True) # 倒序神马真折腾
def eight_letters(d, num):
    global length # 全局变量都用上了,就为了记录个最大值
    new_l = []
    for key in d:
        if len(key) == num and len(d[key]) > 1:
           new_l.append((len(d[key]), d[key]))
           if len(d[key]) >= length:
               length = len(d[key])
    return sorted(new_l)
def sorted_letters(word):
    list_word = sorted(list(word)) # 先把字符串打散为字符列表,然后排序
    reword =''.join(list_word) # 再把字符列表回粘成字符串
    return reword
def set_dict(fin):
    d = {}
    for line in fin:
        word = line.strip()
        reword = sorted_letters(word) # 打散重排相当关键,必须在建立字典时就做!!!
        if reword not in d:
            d[reword] = [word] # 字典的键已经不是单词,是纯粹的规律字符串
        else:
            d[reword].append(word) # 字典的键值才是词汇表里的单词
    return d
fin = open('words.txt')
length = 0
count = 0
start = time()
d = set_dict(fin)
for item in sorted_anagram(d):
    print(item)
    count += 1
print(count)
for item in eight_letters(d, 8):
    if item[0] == length:
        print(item)
end = time()
print(end - start)
# ......
# (2, ['abacas', 'casaba'])
# (2, ['aba', 'baa'])
# (2, ['aals', 'alas'])
# (2, ['aal', 'ala'])
# (2, ['aahed', 'ahead'])
# (2, ['aah', 'aha'])
# 10157 # 全体异构词
# (7, ['angriest', 'astringe', 'ganister', 'gantries', 'granites', 'ingrates', 'rangiest'])
# 异构词最多的8字母单词(共7个异构词)
# 0.6079998016357422
2020-04
22

字典转元组

By xrspook @ 13:15:37 归类于: 扮IT

不搞复杂的,不用超纲的方法做感觉上很简单的事其实不简单。搞明白这个练习后,列表、字典、元组的相爱相杀我算是有点明白了。感谢那个我觉得过于复杂的参考答案,逼我折腾出了我自己的版本。

开心!居然习题1就用上了zip这个这章书最后才提到的大招。字典的键值对互换变得如此简单,我的脑洞又开大了。

Exercise 1: Write a function called most_frequent that takes a string and prints the letters in decreasing order of frequency. Find text samples from several different languages and see how letter frequency varies between languages. Compare your results with the tables at http://en.wikipedia.org/wiki/Letter_frequencies. Solution: http://thinkpython2.com/code/most_frequent.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def most_frequent(sth):
    d = {}
    for letter in sth: # 字符串转为字符映射到频率的字典
        d[letter.lower()] = d.get(letter.lower(), 0) + 1 # 大写的你给我降为小写
    t = tuple(zip(d.values(), d.keys())) # 用zip互换字典的键和键值,生成元组(也可以生成列表,但生成新字典你会哭死)
    return sorted(t, reverse = True) # 以第一元素降序输出
sth = 'This chapter presents one more built-in type, the tuple, and then shows how lists, dictionaries, and tuples work together. I also present a useful feature for variable-length argument lists, the gather and scatter operators.'
t = most_frequent(sth)
for item in t:
    print(item) # 原汁原味输出元组好,因为空格不用''圈着都不知道那里有东西
# (33, ' ')
# (25, 'e')
# (23, 't')
# (16, 's')
# (15, 'r')
# (14, 'a')
# (11, 'o')
# (11, 'n')
# (10, 'i')
# (10, 'h')
# (9, 'l')
# (7, 'u')
# (7, 'p')
# (5, ',')
# (4, 'g')
# (4, 'd')
# (3, 'w')
# (3, 'f')
# (3, 'c')
# (2, 'm')
# (2, 'b')
# (2, '.')
# (2, '-')
# (1, 'y')
# (1, 'v')
# (1, 'k')
2020-04
22

写得过于简单了吧

By xrspook @ 9:29:12 归类于: 烂日记

我看的那个中文版Think Python 2的第11章,习题几乎可以这么说,没一道题的相关是做对的。有些东西,习题跟现在的Think Python 2英文版不一样,我觉得可能是英文版修正了某些东西。修正完以后,英文版并没有写什么更新说明之类的东西,但即便有,中文版翻译的人翻译完以后大概也不会时刻关注英文版有没有变动。同一道题的关联引用,这种东西怎么可以凭着感觉来呢?第一次遇到的时候,我云里雾里,因为按照中文版的那个说法,在某一章书的习题里根本找不到那个东西,但在我印象中,我的确是做过那些习题,到底是在哪一章书里的呢?另外一个版本的中文版那里的索引做对了。当我回看英文原版的时候,发现他们引用某个习题真的写得超简单,但是那些习题全部都是有超连接的,而且锚点到了某一章书的某个确切位置。所以我看的那个中文版之所以是现在这个样子,是不是因为他只是进行了文字上的翻译,还没有仔细研究那些超链接之类的东西呢?又或者在他翻译的时候,他并不是看着英文电子版,我是看英文纸质或者PDF等没有超链接之类的东西。电子版这种东西最让人觉得舒服的应该是哪怕你不标明是那是哪一章书的习题,你只是说那是习题几,只要你把超链接做上去,一切好办。

我看的那个中文版让我无语,但是英文原版也好不到哪里去。因为英文原版的作者脑洞实在太大,让人不知道如何言表。我觉得变成编程这东西,你得给出一个范围,然后再给出一个参考结果,才能让人有奔头。但是他只叫你这般测试,然后再给出一个参考的脚本。在不看脚本之前,如果我只是运行的脚本,而一开始的时候,我们设定的自定义参数不同,该如何判断读者自己的脚本写得对不对呢?有些参数他们完全可以先给出来,或者你会说,那岂不是成了一个提示。这又不是测验考试,重要的不是结果,而是如何整出那个结果,所以即便给你看到最终结果,你不懂过程,还是折腾不出来。英文原版的作者把那些条件参数写在他的脚本里面,而当你写自己的脚本的时候,你又清楚明白到你必须得设定那些参数,但是应该确定为什么呢?拿不准。这就会进入一个怪圈。首先是读者看着题目,自己解答,解答完以后测试,觉得没问题,打开参考答案运行,因为参数答案的结果跟读者得到的不一样,接着我们还得去仔细研究参考答案到底用了什么参数。然后把那个参数放在我们自己的脚本里再运行。对比两个运行的效果。这不是非常折腾吗?如果没有那个隐藏的参数,读者完全可以自己运行一遍,拿参考答案再运行一遍,对比结果就行了。我们最终要做到的不就是那个结果吗?当然,如果得出结果完全一致以后,还是建议大家再研究一下参考答案跟自己的脚本有什么区别,想一想这些区别会不会导致什么问题。

Think Python 2这本书,不只是习题参数设置很让人迷茫。在某些章节里,写得也不细致,比如说元组那一章。元组这个东西据说在其他编程语言里面是没有的。在介绍元组之前,已经说过字符串、列表以及字典。前面三个东西一个套一个,挺容易理解,但是加了元祖进去以后,世界就变得混沌了。因为列表字典元组这三个东西可以互相组合互相转化。有些可变,有些不可变。有些人可排序,有些无效。要真的说清楚元组,第12章书里面已经说到的东西以及已经举过的例子还不足以解决问题。如果他们不把所有东西都说一遍,起码他们得给我们一个列表。告诉我们这些东西可以控制元组,至于具体的使用方法,大家可以查手册。

或许当我把一整本书都看完以后,我的想法又不是我现在这个了。

2020-04
21

PK我自己

By xrspook @ 19:04:38 归类于: 扮IT

用了几分钟时间,写了个用字典法查找10万单词的词汇表回文词的脚本。字典法肯定要比列表二分法快,但到底快多少呢?实测大概10倍。相比之下,字典法语言实在简练太多。二分法的函数还得考虑递归和起点终点神马,字典法一个in杀到底。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# import time
# def in_bisect(library, first, last, myword): # 二分法搜索,10万数据查询最多只需不到20步
#     if first > last: # 这是一句拯救了我的条件
#         return -1
#     else:
#         mid = (first + last)//2
#         if myword == library[mid]:
#             return mid
#         elif library[mid] > myword:
#             return in_bisect(library, first, mid-1, myword)
#         else:
#             return in_bisect(library, mid+1, last, myword)
# j = 0
# count = 0
# library = []
# fin = open('words.txt')
# for line in fin:
#     word = line.strip()
#     library.append(word)
# library.sort()
# start = time.time()
# for i in range(len(library)-1): # 二分法搜索 
#     j = in_bisect(library, 0, len(library)-1, library[i][::-1])
#     if j > -1 and library[i] < library[j]:
#         print(library[i], library[j])
#         count += 1
# print(count)
# end = time.time()
# print(end - start)
# 397, 1.2810001373291016 # 二分法搜索
 
import time
def set_dict(fin): # 字典法搜索
    d = {}
    for line in fin:
        word = line.strip()
        d[word] = 0
    return d
count = 0
fin = open('words.txt')
start = time.time()
mydict = set_dict(fin)
for word in mydict:
    if word[::-1] in mydict and word < word[::-1]:
        print(word, word[::-1])
        count += 1
print(count)
end = time.time()
print(end - start)
# 397, 0.14300012588500977 # 字典法搜索
2020-04
21

找2个词汇表

By xrspook @ 17:59:37 归类于: 扮IT

最根本的在于做好词语的切片和组合,知道要找什么词,丢到字典里找那是秒杀的事。我不知道他们为什么这么折腾,直接在有音标的词汇表里找不就得了,但偏偏要两个词汇表都要求同时存在,于是循环判断神马不得不多一层。幸好字典里用in那是非常简单快捷的事。

Exercise 6: Here’s another Puzzler from Car Talk (http://www.cartalk.com/content/puzzlers): This was sent in by a fellow named Dan O’Leary. He came upon a common one-syllable, five-letter word recently that has the following unique property. When you remove the first letter, the remaining letters form a homophone of the original word, that is a word that sounds exactly the same. Replace the first letter, that is, put it back and remove the second letter and the result is yet another homophone of the original word. And the question is, what’s the word? Now I’m going to give you an example that doesn’t work. Let’s look at the five-letter word, ‘wrack.’ W-R-A-C-K, you know like to ‘wrack with pain.’ If I remove the first letter, I am left with a four-letter word, ’R-A-C-K.’ As in, ‘Holy cow, did you see the rack on that buck! It must have been a nine-pointer!’ It’s a perfect homophone. If you put the ‘w’ back, and remove the ‘r,’ instead, you’re left with the word, ‘wack,’ which is a real word, it’s just not a homophone of the other two words. But there is, however, at least one word that Dan and we know of, which will yield two homophones if you remove either of the first two letters to make two, new four-letter words. The question is, what’s the word? You can use the dictionary from Exercise 1 to check whether a string is in the word list. To check whether two words are homophones, you can use the CMU Pronouncing Dictionary. You can download it from http://www.speech.cs.cmu.edu/cgi-bin/cmudict or from http://thinkpython2.com/code/c06d and you can also download http://thinkpython2.com/code/pronounce.py, which provides a function named read_dictionary that reads the pronouncing dictionary and returns a Python dictionary that maps from each word to a string that describes its primary pronunciation. Write a program that lists all the words that solve the Puzzler. Solution: http://thinkpython2.com/code/homophone.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pronounce import read_dictionary
from time import time
def set_dict(fin):
    d ={}
    for line in fin:
        word = line.strip()
        d[word] = 0
    return d
def same_pronounce(a, b, c, mydict, pdict):
    if b in mydict and c in mydict:
        if b in pdict and c in pdict:
            if pdict[a] == pdict[b] and pdict[a] == pdict[c]:
                return True
    return False
start = time()
count = 0
pdict = read_dictionary()
fin = open('words.txt')
mydict = set_dict(fin)
for word in mydict:
    if word in pdict:
        word1 = word[1:]
        word2 = word[:1] + word[2:]
        if same_pronounce(word, word1, word2, mydict, pdict):
            print(word, word1, word2)
            count += 1
print(count)
end = time()
print(end - start)
# llama lama lama
# llamas lamas lamas
# scent cent sent
# 3
# 0.28800010681152344
© 2004 - 2024 我的天 | Theme by xrspook | Power by WordPress