Skip to content

Commit 3d561a5

Browse files
authored
Add files via upload
1 parent 2f3ef4a commit 3d561a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1452
-1215
lines changed

autogram.py

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from random import Random
22

3-
# Convert an integer into its English language name.
3+
__googol = 10 ** 100
44

55
# http://lcn2.github.io/mersenne-english-name/tenpower/tenpower.html
66
__pows = (("thousand", 3), ("million", 6), ("billion", 9),
@@ -21,41 +21,45 @@
2121
)
2222

2323
# Dictionary comprehension, analogous to list comprehension.
24-
__pows = { p:n for (n, p) in __pows }
24+
__pows = {p: n for n, p in __pows}
25+
2526

26-
# Return the English name of a three-digit integer.
2727
def __int_to_eng(n):
28-
if n < 20: # Numbers 0 to 19 with a simple lookup table.
28+
"""Return the English name of a three-digit positive number."""
29+
assert 0 < n < 1000
30+
if n < 20: # Numbers 0 to 19 with a simple lookup table.
2931
return ["ERROR", "one", "two", "three", "four", "five",
3032
"six", "seven", "eight", "nine", "ten", "eleven",
3133
"twelve", "thirteen", "fourteen", "fifteen",
3234
"sixteen", "seventeen", "eighteen", "nineteen"][n]
33-
elif n < 100: # Numbers 20 to 99, tens again with a lookup table.
34-
tens = ["", "", "twenty", "thirty", "forty", "fifty",
35+
elif n < 100: # Numbers 20 to 99, again with a lookup table.
36+
tens = ["ERROR", "ERROR", "twenty", "thirty", "forty", "fifty",
3537
"sixty", "seventy", "eighty", "ninety"][n // 10]
36-
return tens if n % 10 == 0 else f"{tens}-{__int_to_eng(n % 10)}"
37-
else: # Numbers 100 to 999
38-
if n % 100 == 0:
39-
return f"{__int_to_eng(n // 100)} hundred"
40-
else:
41-
return f"{__int_to_eng(n // 100)} hundred and {__int_to_eng(n % 100)}"
42-
43-
__googol = 10 ** 100
38+
return tens if n % 10 == 0 else f"{tens}-{__int_to_eng(n % 10)}"
39+
else: # Numbers 100 to 999
40+
name = f"{__int_to_eng(n//100)} hundred"
41+
if n % 100 != 0:
42+
name += f"and {__int_to_eng(n%100)}"
43+
return name
44+
4445

45-
# Construct the English name of any integer.
4646
def int_to_english(n):
47-
if n < 0: # Negative numbers
47+
"""Construct the English name of the given integer n."""
48+
if n < 0: # Negative numbers
4849
return "minus " + int_to_english(-n)
49-
if n == 0: # Zero as a special case
50+
if n == 0: # Zero as a special case
5051
return "zero"
51-
if n >= __googol: # huge numbers
52+
if n >= __googol: # Huge numbers
5253
first = int_to_english(n // __googol)
5354
rest = int_to_english(n % __googol)
54-
return f"{first} googol" if rest == "zero" else f"{first} googol and {rest}"
55+
name = f"{first} googol"
56+
if rest != "zero":
57+
name += "and {rest}"
58+
return name
5559
# Otherwise, break the number into blocks of three and convert.
5660
result, p = [], 0
5761
while n > 0:
58-
trip, n = n % 1000, n // 1000
62+
trip, n = n % 1000, n // 1000
5963
if trip > 0:
6064
if p == 0:
6165
result.append(__int_to_eng(trip))
@@ -65,15 +69,16 @@ def int_to_english(n):
6569
return " ".join(reversed(result))
6670

6771
# Find an autogram, a text that describes in English how many times
68-
# each letter appears inside it. As with many of the 109 lab problems,
72+
# each letter appears inside it. As with many of the 109 lab problems,
6973
# this example was inspired by the works of the late great Martin
7074
# Gardner and his collected columns on recreational mathematics in
7175
# the Scientific American magazine.
72-
73-
def autogram_finder(text, rng, verbose=True, perturb = 20):
76+
77+
78+
def autogram_finder(text, rng, verbose=True, perturb=20):
7479
letters, rounds = "abcdefghijklmnopqrstuvwxyz", 0
7580
count, best = [rng.randint(2, 50) for c in letters], 0
76-
81+
7782
while True:
7883
rounds += 1
7984
# Fill in text placeholders with names for each number.
@@ -85,14 +90,15 @@ def autogram_finder(text, rng, verbose=True, perturb = 20):
8590
lfill = filled.lower()
8691
actual = [lfill.count(c) for c in letters]
8792
# Find the letters whose counts are correct.
88-
same = "".join([c for (i, c) in enumerate(letters) if count[i] == actual[i]])
93+
same = "".join([c for (i, c) in enumerate(letters)
94+
if count[i] == actual[i]])
8995
# Replace the previous best solution, if this one is better.
9096
if len(same) > best:
9197
best = len(same)
9298
if verbose:
9399
print(f"\n{filled}")
94-
print(f"Actual: {', '.join([f'{l}:{c}' for (l, c) in zip(letters, actual)])}")
95-
print(f"Matched {len(same)} letters '{same}' in {rounds} rounds.")
100+
print(f"Actual: {', '.join([f'{l}:{c}' for l, c in zip(letters, actual)])}")
101+
print(f"Matched {len(same)} letters '{same}'.")
96102
if best == 26:
97103
return filled
98104
count = actual
@@ -108,15 +114,16 @@ def autogram_finder(text, rng, verbose=True, perturb = 20):
108114
# $c is the count for the character c, and $$ is the total
109115
# number of letters in the text. (That one makes the search
110116
# far more difficult.)
111-
112-
text = """This zesty, bookish and joyful quip was composed by
117+
118+
119+
__text = """This zesty, bookish and joyful quip was composed by
113120
Ilkka Kokkarinen to serve as an example for this course, and it
114121
contains $a a's, $b b's, $c c's, $d d's, $e e's, $f f's, $g g's,
115122
$h h's, $i i's, $j j's, $k k's, $l l's, $m m's, $n n's, $o o's,
116123
$p p's, $q q's, $r r's, $s s's, $t t's, $u u's, $v v's, $w w's,
117124
$x x's, $y y's and finally, to top it all off, $z z's."""
118-
text = text.replace("\n", " ")
119-
text = text.replace("\t", " ")
125+
__text = __text.replace("\n", " ")
126+
__text = __text.replace("\t", " ")
120127

121128
# This zesty, bookish and joyful quip was composed by Ilkka
122129
# Kokkarinen to serve as an example for this course, and it
@@ -133,12 +140,12 @@ def autogram_finder(text, rng, verbose=True, perturb = 20):
133140
for x in [42, 3**7, 6**20, -(2**100), 9**200, 10**500]:
134141
print(f"{x} written in English is {int_to_english(x)}.")
135142
print("Here are integers 0-100 sorted in alphabetical order:")
136-
print(sorted(range(0, 101), key = int_to_english))
143+
print(sorted(range(0, 101), key=int_to_english))
137144
print("Here are integers 0-100 sorted in order of name lengths:")
138-
print(sorted(range(0, 101), key = lambda x: (len(int_to_english(x)), x)))
145+
print(sorted(range(0, 101), key=lambda x: (len(int_to_english(x)), x)))
139146
print("The numbers that do not contain the letter 'o':")
140147
print([x for x in range(1000) if 'o' not in int_to_english(x)])
141-
148+
142149
# When using a randomized algorithm, it is good to used a fixed
143150
# seed to make the results repeatable.
144-
autogram_finder(text, Random(9999), perturb = 0)
151+
autogram_finder(__text, Random(12345), True, 20)

bytearraydemo.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
# byte array can be processed with byte array operations such as
44
# checksums and compressions, not caring where these bytes came from.
55

6+
import zlib
7+
from hashlib import sha256
8+
69
s = "This will be turned into an array of bytes \U0001F603."
710

811
print(f"Length of s is {len(s)}.")
@@ -11,15 +14,12 @@
1114
s = sb.decode('utf-8')
1215
print(f"Decoding bytes gives the string {repr(s)}.")
1316

14-
import zlib
15-
from hashlib import sha256
16-
1717
print(f"Adler checksum of string s: {zlib.adler32(sb)}")
1818
print(f"CRC32 checksum of string s: {zlib.crc32(sb)}")
1919

2020
with open('warandpeace.txt', encoding="utf-8") as wap:
2121
s = " ".join(list(wap)) # this will be a really long string
22-
print(f"'War and Peace' contains {len(s)} characters.")
22+
print(f"'War and Peace' contains {len(s)} characters.")
2323

2424
sb = s.encode('utf-8')
2525
print(f"Encoded as byte array using utf-8, this gives {len(sb)} bytes.")

0 commit comments

Comments
 (0)