2020-04
18

死磕二分法搜索

By xrspook @ 15:00:07 归类于: 扮IT

我是看着题目的中文版做题的

练习10:要检查一个单词是不是在上面这个词汇列表里,你可以使用 in 运算符,但可能会很慢,因为这个 in 运算符要从头到尾来搜索整个词汇表。我们知道这些单词是按照字母表顺序组织的,所以我们可以加速一下,用一种对折搜索(也叫做二元搜索),这个过程就和你在现实中用字典来查单词差不多。你在中间部分开始,看看这个要搜索的词汇是不是在中间位置的前面。如果在前面,就又对前半部分取中间,继续这样来找。当然了,不在前半部分,就去后半部分找了,思路是这样的。不论怎样,每次都会把搜索范围缩减到一半。如果词表包含了113809个单词,最多就是17步就能找到单词,或者能确定单词不在词汇表中。那么问题来了,写一个函数,名为 in_bisect,接收一个整理过的按照字母顺序排列的列表,以及一个目标值,在列表中查找这个值,找到了就返回索引位置,找不到就返回空。

做到死去活来词语在词汇表里有索引正确,没有时却会疯掉的时候我不得不去看答案,看到答案后傻眼了,答案对单词的判断只有True和False,再去找原题,我那个去,题目改了!不要求索引了好吗!

Exercise 10: To check whether a word is in the word list, you could use the in operator, but it would be slow because it searches through the words in order. Because the words are in alphabetical order, we can speed things up with a bisection search (also known as binary search), which is similar to what you do when you look a word up in the dictionary (the book, not the data structure). You start in the middle and check to see whether the word you are looking for comes before the word in the middle of the list. If so, you search the first half of the list the same way. Otherwise you search the second half. Either way, you cut the remaining search space in half. If the word list has 113,809 words, it will take about 17 steps to find the word or conclude that it’s not there. Write a function called in_bisect that takes a sorted list and a target value and returns True if the word is in the list and False if it’s not. Or you could read the documentation of the bisect module and use that! Solution: http://thinkpython2.com/code/inlist.py.

又纠结一番后我终于写出了一句“first > last”返回例外情况,终于,世界被拯救了!记录索引和不记录索引很不一样啊,按照参考答案的解法,i即便返回也永远是1,索引无能。纠结是有好处的,让我明白到二分法搜索有多么的高效,简直甩while循环几十条街,但如果真索引的话,估计我会很懒地直接用list.index(),虽然用之前必须用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 None
    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)
myword = 'zoo' # input('myword is: ')
i = 0
library = []
fin = open('words.txt')
for line in fin:
    word = line.strip()
    library.append(word)
library.sort()
start = time.time()
 
# j = 0
# while i < len(library) - 1: # 我的脑洞第一反应用的循环
#     if myword == library[i]:
#         j = i
#         break
#     i += 1
# if j == 0:
#     print('myword is not in library')
# else:
#     print('index =', j)
 
# if myword in library: # 伟大列表自带的查询索引号,但先得确定单词在那里
#     i = library.index(myword, 0, len(library)-1)
# if i == 0:
#     print('myword is not in library')
# else:
#     print('index =', i)
 
if in_bisect(library, 0, len(library), myword) == None: 
    print('myword is not in library')
else:
    print('index =', in_bisect(library, 0, len(library), myword))
end = time.time()
print(end-start)
# myword is not in library while 0.07   index 0.003  bisect 0.001
# apple 4450               while 0.003  index 0.001  bisect 0.001
# zoo 113707               while 0.07   index 0.005  bisect 0.001
# while,index和bisect没有对比就没有伤害
2020-04
17

51%的概率

By xrspook @ 22:15:06 归类于: 扮IT

思路很简单,但要得出这个概率结论要重复多少次呢?脚本写好以后我先用了10次,100次,1000次,效果都不好,数字太漂浮,于是我都怀疑自己了。搜索之后发现别人用MATLAB写了个大体意思跟我一样的程序,他重复了100万次,好吧,我懂了!本来这种扔随机数进去的测试重复就应该趋向于无穷,但试过你就知道,100万次绝对让你的电脑卡到怀疑死机了。所以我狡猾地控制百分数只输出整数,10万次有点卡(我的破电脑等待结果大概需要4秒),但还可以接受。

Exercise 8:This exercise pertains to the so-called Birthday Paradox, which you can read about at http://en.wikipedia.org/wiki/Birthday_paradox. If there are 23 students in your class, what are the chances that two of you have the same birthday? You can estimate this probability by generating random samples of 23 birthdays and checking for matches. Hint: you can generate random birthdays with the randint function in the random module. You can download my solution from http://thinkpython2.com/code/birthday.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import random
def chance(num):
    n = 0
    x = 100000 # 越大越好,但太大了运行慢到怀疑人生…… 1W小卡,10W卡,100W非常卡!
    for i in range(x):
        birth = []
        for i in range(num):
            birth.append(random.randint(1, 365))
        birth.sort()
        for i in range(num - 1):
            if birth[i] == birth[i+1]:
                n += 1
                break
    return n/x
num = 23
print('chance is', '{:.0%}'.format(chance(num)))
# chance is 51%  x = 10W 百分数显示小数将会是个测试噩梦!!!
2020-04
16

循环,循环

By xrspook @ 19:58:07 归类于: 扮IT

觉得自己虽然见过递归,但几乎不用,不逼着我我都不用,循环用得越来越遛。前两题我和参考答案得出的结论一致,最后一题,我觉得参考答案有问题。下面的都是我的脚本。下面要用到的words.txt在这里

Exercise 7:This question is based on a Puzzler that was broadcast on the radio program Car Talk: Give me a word with three consecutive double letters. I’ll give you a couple of words that almost qualify, but don’t. For example, the word committee, c-o-m-m-i-t-t-e-e. It would be great except for the ‘i’ that sneaks in there. Or Mississippi: M-i-s-s-i-s-s-i-p-p-i. If you could take out those i’s it would work. But there is a word that has three consecutive pairs of letters and to the best of my knowledge this may be the only word. Of course there are probably 500 more but I can only think of one. What is the word? Write a program to find it. Solution: http://thinkpython2.com/code/cartalk1.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def double_letter(word):
    num = 0
    i = 0
    if len(word) >= 6:
        while i < len(word)-1:
            if word[i] == word[i+1]: 
                num = num + 1
                i = i + 2
            elif i > 2 and word[i-2] != word[i-3]:
                break
            else:
                i = i + 1
        if num == 3:
            print(word)
fin = open('words.txt')
n = 0
for line in fin:
    word = line.strip()
    double_letter(word)
# bookkeeper
# bookkeepers
# bookkeeping
# bookkeepings

Exercise 8: Here’s another Car Talk Puzzler: “I was driving on the highway the other day and I happened to notice my odometer. Like most odometers, it shows six digits, in whole miles only. So, if my car had 300,000 miles, for example, I’d see 3-0-0-0-0-0. “Now, what I saw that day was very interesting. I noticed that the last 4 digits were palindromic; that is, they read the same forward as backward. For example, 5-4-4-5 is a palindrome, so my odometer could have read 3-1-5-4-4-5. “One mile later, the last 5 numbers were palindromic. For example, it could have read 3-6-5-4-5-6. One mile after that, the middle 4 out of 6 numbers were palindromic. And you ready for this? One mile later, all 6 were palindromic! “The question is, what was on the odometer when I first looked?” Write a Python program that tests all the six-digit numbers and prints any numbers that satisfy these requirements. Solution: http://thinkpython2.com/code/cartalk2.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def is_palindrome(word):
    if word[::-1] == word:
        return True 
def test_palindrome(number):
    if is_palindrome(str(number)[2:]):
        if is_palindrome(str(number+1)[1:]):
            if is_palindrome(str(number+2)[1:1]):
                if is_palindrome(str(number+3)):
                    return True
for number in range(100000, 999999):
    if test_palindrome(number):
        print(number)
# 198888
# 199999

Exercise 9: Here’s another Car Talk Puzzler you can solve with a search: “Recently I had a visit with my mom and we realized that the two digits that make up my age when reversed resulted in her age. For example, if she’s 73, I’m 37. We wondered how often this has happened over the years but we got sidetracked with other topics and we never came up with an answer. “When I got home I figured out that the digits of our ages have been reversible six times so far. I also figured out that if we’re lucky it would happen again in a few years, and if we’re really lucky it would happen one more time after that. In other words, it would have happened 8 times over all. So the question is, how old am I now?” Write a Python program that searches for solutions to this Puzzler. Hint: you might find the string method zfill useful. Solution: http://thinkpython2.com/code/cartalk3.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
56
57
58
year = 99
meet = int(input('how many times have we met?(1-8): '))
print('mom born me at', '\t','my age', '\t',"mon's age")
for i in range(10, 80): # 假设你妈生你的最低年龄是10,最高年龄是80
    n = 0
    for age in range(1, year):
        if age < int(str(age).zfill(2)[::-1]) and int(str(age).zfill(2)[::-1]) - age == i:            
            # print(i, '\t\t', age, '\t\t', str(age).zfill(2)[::-1])             
            n = n + 1
            if n == meet:
                print(i, '\t\t', age, '\t\t', str(age).zfill(2)[::-1])
 
# how many times have we met?(1-8): 6
# mom born me at   my age          mon's age
# 18               57              75
# 27               58              85
# 36               59              95
 
# how many times have we met?(1-8): 8
# mom born me at   my age          mon's age
# 18               79              97
 
# mom born me at   my age          mon's age
# 18               2               20
# 18               13              31
# 18               24              42
# 18               35              53
# 18               46              64
# 18               57              75
# 18               68              86
# 18               79              97
# 27               3               30
# 27               14              41
# 27               25              52
# 27               36              63
# 27               47              74
# 27               58              85
# 27               69              96
# 36               4               40
# 36               15              51
# 36               26              62
# 36               37              73
# 36               48              84
# 36               59              95
# 45               5               50
# 45               16              61
# 45               27              72
# 45               38              83
# 45               49              94
# 54               6               60
# 54               17              71
# 54               28              82
# 54               39              93
# 63               7               70
# 63               18              81
# 63               29              92
# 72               8               80
# 72               19              91
2020-04
15

反正这是我的答案

By xrspook @ 19:44:55 归类于: 扮IT

题目摆在这里,没有确切的答案,下面是我的解答,对不对不知道。words.txt资源在这里。

There are solutions to these exercises in the next section. You should at least attempt each one before you read the solutions.

Exercise 1: Write a program that reads words.txt and prints only the words with more than 20 characters (not counting whitespace).

Exercise 2: In 1939 Ernest Vincent Wright published a 50,000 word novel called Gadsby that does not contain the letter “e”. Since “e” is the most common letter in English, that’s not easy to do. In fact, it is difficult to construct a solitary thought without using that most common symbol. It is slow going at first, but with caution and hours of training you can gradually gain facility. All right, I’ll stop now. Write a function called has_no_e that returns True if the given word doesn’t have the letter “e” in it. Write a program that reads words.txt and prints only the words that have no “e”. Compute the percentage of words in the list that have no “e”.

Exercise 3: Write a function named avoids that takes a word and a string of forbidden letters, and that returns True if the word doesn’t use any of the forbidden letters. Write a program that prompts the user to enter a string of forbidden letters and then prints the number of words that don’t contain any of them. Can you find a combination of 5 forbidden letters that excludes the smallest number of words?

Exercise 4: Write a function named uses_only that takes a word and a string of letters, and that returns True if the word contains only letters in the list. Can you make a sentence using only the letters acefhlo? Other than “Hoe alfalfa”?

Exercise 5: Write a function named uses_all that takes a word and a string of required letters, and that returns True if the word uses all the required letters at least once. How many words are there that use all the vowels aeiou? How about aeiouy?

Exercise 6: Write a function called is_abecedarian that returns True if the letters in a word appear in alphabetical order (double letters are ok). How many abecedarian words are there?

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
fin = open('words.txt') # 第1小问
for line in fin:
    if len(line) >= (20+2):
        word = line.strip()
        print(word)
# counterdemonstrations
# hyperaggressivenesses
# microminiaturizations
 
def has_no_e(word): # 第2小问
    for letter in word:
        if letter == 'e':
            return False
    return True
fin = open('words.txt')
all = 0
count = 0
for line in fin:
    word = line.strip()
    all = all + 1
    if has_no_e(word):
        print(word)
        count = count + 1
print(count, 'words without e')
print('{:.0%}'.format(count/all), 'words without e')
# ...
# zymosis
# zymotic
# zymurgy
# 37641 words without e
# 33% words without e
 
def avoids(word, x): # 第3小问,最后一个问题举手投降
    for letterw in word:
        for letterx in x:
            if letterw == letterx:
                return False
    return True
fin = open('words.txt')
x = input('withtout: ')
num = 0
# word = 'jwrojgre' # input('word is ')
# print(avoids(word, x))
for line in fin:
    word = line.strip()
    if avoids(word, x):
        num = num + 1
print(num, 'words without', x)
# withtout: aeiou
# 107 words without aeiou
# count = 0
# import itertools
# for i in itertools.combinations('abcdefghijklmnopqrstuvwxyz', 5):
#     print(''.join(i))
#     count = count + 1
# print(count) # 65780个排列组合的可能性啊啊啊啊啊啊
 
 
def uses_only(word, x): # 第4小问
    for letter in word:
        if letter not in x:
            return False
    return True
word = input('word is ')
x = input('uses is ')
print(uses_only(word, x))
# word is abc
# uses is efg
# False
 
def uses_all(word, x): # 第5小问
    for letter in x:
        if letter not in word:
            return False
    return True
fin = open('words.txt')
x = input('must use: ' )
num = 0
for line in fin:
    word = line.strip()
    if uses_all(word, x):
        num = num + 1
print(num, 'words with', x)
# must use: aeiou
# 598 words with aeiou
# must use: aeiouy
# 42 words with aeiouy
 
def is_abecedarian(word): # 第6小问
    index = 1
    while index < len(word) - 1:
        if ord(word[index-1]) > ord(word[index]):
            return False
        index = index + 1
    return True
fin = open('words.txt')
num = 0
for line in fin:
    word = line.strip()
    if is_abecedarian(word):
        num = num + 1
print(num, 'words is abecedarian')
# 1573 words is abecedarian
2020-04
15

字符偏移加密

By xrspook @ 13:28:09 归类于: 扮IT

本来我根本没考虑字母以外的那些怎么办,测试过参考答案以后,发现原来字母以外的东西原始输出,于是我也这般弄了,等于再加一个是否字母的判断,折腾。不告诉人家怎么把字符合并成字符串,我就只好准备两个对象二人转连接。

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
def rotate_word(something, n): # a-z: 97-122, A-Z: 65-90
    newletter1 = ''
    for letter in something:
        if ord(letter) < ord('A') or ord('Z') < ord(letter) < ord('a') or ord('z') < ord(letter):
            newletter2 = newletter1 + letter
        else:
            if ord(letter) + n > ord('z'):
                newletter2 = newletter1 + chr(ord(letter) + n - 26)
            elif ord('a') > ord(letter) + n > ord('Z'):
                newletter2 = newletter1 + chr(ord(letter) + n - 26)
            else:
                newletter2 = newletter1 + chr(ord(letter) + n)
        newletter1 = newletter2
    return newletter2
something = input('please write something: ')
n = int(input('how many shifts do you want: '))
print('before:', something)
print('after :', rotate_word(something, n))
# please write something: IBM
# how many shifts do you want: -1
# before: IBM
# after : HAL
# please write something: g858^h{O
# how many shifts do you want: 6
# before: g858^h{O
# after : m858^n{U
© 2004 - 2024 我的天 | Theme by xrspook | Power by WordPress