练习 12-3
编写一个函数 most_frequent,接收一个字符串并按照频率的降序打印字母。
1 import random
2
3 def most_frequent(s):
4 hist = make_histogram(s)
5
6 t = []
7 for x, freq in hist.iteritems():
8 t.append((freq, x))
9
10 t.sort(reverse=True)
11
12 res = []
13 for freq, x in t:
14 res.append(x)
15
16 return res
17
18
19 def make_histogram(s):
20 hist = {}
21 for x in s:
22 hist[x] = hist.get(x, 0) + 1
23 return hist
24
25
26 def read_file(filename):
27 return open(filename).read()
28
29 if __name__ == '__main__':
30 s = read_file('words.txt')
31 t = most_frequent(s)
32 for x in t:
33 print x
练习 12-4
1 编写一个程序从文件中读入一个单词列表,并打印出所有是回文的单词集合。
2 修改前一个问题的程序,让它先打印最大的回文集合,再打印第二大的回文集合,以此类推。
3 在Scrabble 拼字游戏中,一个“bingo”代表你自己架子上全部7个字母和盘上的一个字母组合成一个8字母单词。哪一个8字母单词可以生成最多的bingo?
1 def signature(s):
2 t = list(s)
3 t.sort()
4 t = ''.join(t)
5 return t
6
7
8 def all_anagrams(filename):
9 d = {}
10 for line in open(filename):
11 word = line.strip().lower()
12 t = signature(word)
13
14 if t not in d:
15 d[t] = [word]
16 else:
17 d[t].append(word)
18 return d
19
20
21 def print_anagram_sets(d):
22 for v in d.values():
23 if len(v) > 1:
24 print len(v), v
25
26
27 def print_anagram_sets_in_order(d):
28 t = []
29 for v in d.values():
30 if len(v) > 1:
31 t.append((len(v), v))
32
33 t.sort()
34
35 for x in t:
36 print x
37
38
39 def filter_length(d, n):
40 res = {}
41 for word, anagrams in d.iteritems():
42 if len(word) == n:
43 res[word] = anagrams
44 return res
45
46
47 if __name__ == '__main__':
48 d = all_anagrams('words.txt')
49 print_anagram_sets_in_order(d)
50
51 eight_letters = filter_length(d, 8)
52 print_anagram_sets_in_order(eight_letters)
练习 12-5
两个单词,如果可以通过交换两个字母将一个单词转化为另一个,就成为”置换对“;例如:”converse“和”conserve“。编写一个程序查找字典中所有的置换对。提示:不要测试所有的单词对,也不要测试所有可能的交换。
1 from anagram_sets import *
2
3 def metathesis_pairs(d):
4 for anagrams in d.itervalues():
5 for word1 in anagrams:
6 for word2 in anagrams:
7 if word1 < word2 and word_distance(word1, word2) == 2:
8 print word1, word2
9
10
11 def word_distance(word1, word2):
12 assert len(word1) == len(word2)
13
14 count = 0
15 for c1, c2 in zip(word1, word2):
16 if c1 != c2:
17 count += 1
18
19 return count
20
21
22 if __name__ == '__main__':
23 d = all_anagrams('words.txt')
24 metathesis_pairs(d)
练习 12-6
一个英文单词,当逐个删除它的字母时,仍然是英文单词。这样的单词中最长的是什么?
首先,字母可以从两头或者中间删除,但你不能重排字母。每次你去掉一个字母,则得到另一个英文单词。如果一直这么做,最终会得到一个字母,它本身也是一个英文单词——可以从字典上找到的。我想知道这样的最长的单词是什么,它有多少字母?
我会给你一个普通的例子,Sprite。你从sprite开始,取出一个字母,从单词内部取,取走r,这样我们就剩下单词spite,接着我们取走结尾的e,剩下spit,接着取走s,我们剩下pit,it,i。
编写一个程序来找到所有这样可缩减的单词,然后找到最长的一个。
1 def make_word_dict():
2 """Reads the words in words.txt and returns a dictionary
3 that contains the words as keys."""
4 d = dict()
5 fin = open('words.txt')
6 for line in fin:
7 word = line.strip().lower()
8 d[word] = word
9
10 # have to add single letter words to the word list;
11 # also, the empty string is considered a word.
12 for letter in ['a', 'i', '']:
13 d[letter] = letter
14 return d
15
16
17 """memo is a dictionary that maps from each word that is known
18 to be reducible to a list of its reducible children. It starts
19 with the empty string."""
20
21 memo = {}
22 memo[''] = ['']
23
24
25 def is_reducible(word, word_dict):
26 """If word is reducible, returns a list of its reducible children.
27
28 Also adds an entry to the memo dictionary.
29
30 A string is reducible if it has at least one child that is
31 reducible. The empty string is also reducible.
32
33 word: string
34 word_dict: dictionary with words as keys
35 """
36 # if have already checked this word, return the answer
37 if word in memo:
38 return memo[word]
39
40 # check each of the children and make a list of the reducible ones
41 res = []
42 for child in children(word, word_dict):
43 t = is_reducible(child, word_dict)
44 if t:
45 res.append(child)
46
47 # memoize and return the result
48 memo[word] = res
49 return res
50
51
52 def children(word, word_dict):
53 """Returns a list of all words that can be formed by removing one letter.
54
55 word: string
56
57 Returns: list of strings
58 """
59 res = []
60 for i in range(len(word)):
61 child = word[:i] + word[i+1:]
62 if child in word_dict:
63 res.append(child)
64 return res
65
66
67 def all_reducible(word_dict):
68 """Checks all words in the word_dict; returns a list reducible ones.
69
70 word_dict: dictionary with words as keys
71 """
72 res = []
73 for word in word_dict:
74 t = is_reducible(word, word_dict)
75 if t != []:
76 res.append(word)
77 return res
78
79
80 def print_trail(word):
81 """Prints the sequence of words that reduces this word to the empty string.
82
83 If there is more than one choice, it chooses the first.
84
85 word: string
86 """
87 if len(word) == 0:
88 return
89 print word,
90 t = is_reducible(word, word_dict)
91 print_trail(t[0])
92
93
94 def print_longest_words(word_dict):
95 words = all_reducible(word_dict)
96
97 # use DSU to sort by word length
98 t = []
99 for word in words:
100 t.append((len(word), word))
101 t.sort(reverse=True)
102
103 # print the longest 5 words
104 for length, word in t[0:5]:
105 print_trail(word)
106 print '\n'
107
108
109 if __name__ == '__main__':
110 word_dict = make_word_dict()
111 print_longest_words(word_dict)
运行结果为:
complecting completing competing compting comping coping oping ping pig pi i
twitchiest witchiest withiest withies withes wites wits its is i
stranglers strangers stranger strange strang stang tang tag ta a
staunchest stanchest stanches stances stanes sanes anes ane ae a
restarting restating estating stating sating sting ting tin in i