python self study diary 5 - word game

Keywords: Python less IPython

It's better to record yourself or observe others' thinking from mistakes to right when learning python than only seeing the right answers

1. Judge whether there is letter "e" in the word“

Write a function has no e to return True when the given word does not contain the letter 'e'

At the beginning, I wrote as follows:

def has_no_e(word):
    for letter in word:
        if letter=='e':
            return False
        return True
has_no_e('tdy')

But it is always different from the expected result. When the word has "e", it also returns True. So add a print to see the situation:

def has_no_e(word):
    for letter in word:
        if letter=='e':
            print(letter)
            return False
        return True
has_no_e('hello')

But it didn't work. It seems that print didn't work. At this time, I doubt the printing problem.

def has_no_e(word):
    for letter in word:
        print(letter)
has_no_e('hello')

But there is no problem with this print, so I want to take out the judgment conditions separately and try it:

word='hello'
for letter in word:
    if letter=='e':
        return False
    else:
        return True
  File "<ipython-input-14-bb84b00c1080>", line 4
    return False
    ^
SyntaxError: 'return' outside function

This report has a syntax error. I checked it on the Internet. The reason is that return has no meaning outside the function. I want to change return to break later, but break can only break one level in the multi-level cycle, and can't jump out of the cycle. Since it hasn't been resolved, I can only find the reason from the original code. Later, I found that return True is in the cycle, and it should be OK to put it outside the cycle. However, I think After the test.

def has_no_e(word):
    for letter in word:
        if letter=='e'or letter=='E':
            return False
    return True
has_no_e('tdy')

Return to normal, so it's OK. There's a supplementary screening for 'E'.

2. Read in words.txt, print out the word without 'e', and calculate the percentage of the word in the whole word list.

words.txt can be found in http://thinkpython.com/code/w... , then calculate the number of printed words and the total number of words, and then calculate the percentage. First, calculate the number of printed words as follows

def has_no_e(word):
    for letter in word:
        if letter=='e'or letter=='E':
            return False
    print(word)
    return True
fin=open('words.txt')
count=0
sum=0
for line in fin:
    word=line.strip()
    has_no_e(word)
    count+=1
    sum+=1
print(count)

It's right to print words, but sum and count are the same. At this time, I want to find out the total number of words and see which one is wrong.

fin=open('words.txt')
count=0
for line in fin:
    count+=1
print(count)

The result is the same as the above. So the total number of words above indicates that you are not familiar with the cycle. You think that adding a condition in front of you is calculating the number of conditions. But I added a function and didn't know how to count the number of words in the function, so I didn't want to use the function, as follows

fin=open('words.txt')
sum=0
count=0
for line in fin:
    for letter in word:
        if letter=='e':
            continue
        print(word)
        count+=1
    sum+=1
print(sum)
print(count)

But the printing is the last letter, and there is also a problem in the statistics of numbers. Later, I think this logic is still correct. Try adding the judgment to the function of the original code.

def has_no_e(word):
    for letter in word:
        if letter=='e'or letter=='E':
            return False
    return True
fin=open('words.txt')
sum=0
count=0
for line in fin:
    word=line.strip()
    if has_no_e(word): #Only when you return True can you follow the logic below, so that not all the words are counted.
        print(word)
        count+=1
    sum+=1
print(count)
print(sum)
print(count/sum)

So the result is right, but the result is a decimal, which needs to be converted to a percentage.

a=count/sum
b='%.2f%%'%(a*100)#Convert decimal to percentage and keep two decimal places
print(b)

3. Write a function is "abecedarian" to return True if the letters in the words are arranged in alphabetical order (two repetitions are OK).

Seeing this reminds me of doing a string comparison before. The topic says that strings can also be compared by operators. Upper case letters are smaller than lower case letters, and similar letters are sorted according to the alphabet. Then write the following code according to this:

def is_abecedarian(word):
    for i in range(0,len(word)-1): #Note here is len(word)-1, because there is word[i+1] below. If you do not subtract one, the subscript will be out of range.
        if word[i]>word[i+1]:
            return False
    return True
is_abecedarian('Aabbcee')

Based on this function and the previously written code, you can calculate the total number of words that meet this rule in the words.txt word list.

fin=open('words.txt')
count=0
sum=0
for line in fin:
    word=line.strip()
    if is_abecedarian(word):
        print(word)
        count+=1
    sum+=1
print(count)
print(sum)
a=count/sum
b='%.2f%%'%(a*100)
print(b)

Among 113809 words, 596 (0.52%) were consistent.

After reading the answers, there are three ways:

#for loop method, but slightly different from mine
def is_abecedarian1(word):
    previous=word[0]
    for c in word:
        if c<previous:
            return False
        previous=c
    return True
#Recursive Method
def is_abecedarian2(word):
    if len(word)<=1:
        return True
    if word[0]>word[1]:
        return False
    return is_abecedarian2(word[1:])
is_abecedarian2('aello')
#while Loop
def is_abecedarian3(word):
    i=0
    while i<len(word)-1:
        if word[i+1]<word[i]:
            return False
        i+=1
    return True
is_abecedarian3('aello')

Debugging suggestions:

Of all the words that contain 'e', you should test the words that begin with 'e', the words that end with 'e', and their position in the middle of the word. You should test long words, short words, and very short words, such as empty strings. Empty string is an example of a special case, which is often not so obvious, but often hides errors.

Note: you may find one type of error (words that should not be included but are included), but not another (words that should be included but not included).

Program tests can be used to show the existence of bug s, but they cannot show their absence.

Today I learned a new way to solve the problem: problem identification

A way to solve a problem by expressing the problem as a special case of a problem that has been solved.

4. Exercise: there are 6 digits in the car odometer. The first four digits are palindromes. The last five digits are palindromes after one kilometer. After another kilometer, the middle four digits are palindromes. After another kilometer, the six digits are palindromes. Find the initial value. Test whether a word is palindromes by [:: - 1].

At the beginning, according to the string slicing and the condition setting of the topic, the following code is obtained:

def is_palindrome(word):
    if word==word[::-1]:
        return True
    return False
def chushizhi():
    for mile in range(1000000):
        if len(str(mile))!=6:
            return False 
        if is_palindrome(str(mile)[2:]) and is_palindrome(str(mile+1)[1:]) and is_palindrome(str(mile+2)[1:5]) and is_palindrome(str(mile+3)):
            print(mile)
    return False
chushizhi()  

This return is False, because we know there must be a result, so we know there must be a problem. But we should pay attention to this later. If we don't know the expected result, then we can't check the bug. The first idea is to reduce the judgment conditions to see the situation, as follows:

def is_palindrome(word):
    if word==word[::-1]:
        return True
    return False
def chushizhi():
    for mile in range(1000000):
        if len(str(mile))!=6:
            return False #Because the return is not executed, the following code becomes invalid due to this return
        if is_palindrome(str(mile)[2:]):#Reduce the judgment conditions here
            print(mile)
    return False
chushizhi()  

The result is the same as the above. If you look at the above judgment condition carefully, if the mile is from 0 to 1000000, it will return False directly when the length of the previous character is not equal to 6. Therefore, the return after the previous judgment condition causes the subsequent code to be unable to execute, so it is changed to the following code:

def is_palindrome(word):
    if word==word[::-1]:
        return True
    return False
def chushizhi():
    for mile in range(1000000):
        if len(str(mile))==6 and is_palindrome(str(mile)[2:]) and is_palindrome(str(mile+1)[1:]) and is_palindrome(str(mile+2)[1:5]) and is_palindrome(str(mile+3)):
            print(mile)
chushizhi()

The results of 198888 and 199999 are returned, and the following tests are correct. But there is always a question: the mileage of a car starts not from 100000, but from 000000. So, is there any one between 000000 and 100000 that fits this? Let's see how to write the answer first.

def has_palindrome(i, start, len):
    """Returns True if the integer i, when written as a string,
    contains a palindrome with length (len), starting at index (start).
    """
    s = str(i)[start:start+len]
    return s[::-1] == s
    

def check(i):
    """Checks whether the integer (i) has the properties described
    in the puzzler.
    """
    return (has_palindrome(i, 2, 4)   and
            has_palindrome(i+1, 1, 5) and
            has_palindrome(i+2, 1, 4) and
            has_palindrome(i+3, 0, 6))


def check_all():
    """Enumerates the six-digit numbers and prints any that satisfy the
    requirements of the puzzler"""

    i = 100000
    while i <= 999996:
        if check(i):
            print(i)
        i = i + 1


check_all()

The result is the same as mine, and from the perspective of the code, the answer code does not consider the number of 100000 years ago.

I decided to write it myself and change the code above to look like this:

def is_palindrome(word):
    if word==word[::-1]:
        return True
    return False
def chushizhi():
    for mile in range(1000000):
        a=len(str(mile))
        if a<6 and is_palindrome(str(mile).zfill(6)) and is_palindrome(str(mile+1).zfill(6)) and is_palindrome(str(mile+2).zfill(6)) and is_palindrome(str(mile+3).zfill(6)):
            print(mile)
        elif len(str(mile))==6 and is_palindrome(str(mile)[2:]) and is_palindrome(str(mile+1)[1:]) and is_palindrome(str(mile+2)[1:5]) and is_palindrome(str(mile+3)):
            print(mile)
chushizhi()

Add a judgment. When the number is less than 6 digits, use the string method zfill to complement with 0 in the front, but the result is the same, but it feels more rigorous.

5. Practice: the two figures of my mother's age are reciprocal to each other, which has happened six times so far. It may happen eight times in total. How old am I now

Tip: you may find the string method zfill useful

According to this prompt, when my age is less than 10, I also have reciprocal situations. I need to make an analysis. The reciprocal function uses the previously written function is "reverse". Then I judge the condition that my age is reciprocal and my age is less than my mother's age, and get the following Code:

def is_reverse(word1,word2):
    if len(word1)!=len(word2):
        return False
    i=0
    j=len(word2)-1
    while j>=0:
        if word1[i]!=word2[j]:
            return False
        i=i+1
        j=j-1
    return True
def age_me():
    for mo_age in range(10,100):
        for age in range(100):
            if len(str(age))<2 and is_reverse(str(age).zfill(2),str(mo_age)) and age<mo_age:
                print(age,mo_age,mo_age-age)
            if is_reverse(str(age),str(mo_age)) and age<mo_age :
                print(age,mo_age,mo_age-age)
     return a
age_me()

A lot of eligible number pairs have been obtained, but it is impossible to see which match intuitively. Therefore, it is necessary to calculate the difference between the two. The sixth group of value pairs with the difference number of 8 is the current age:

def is_reverse(word1,word2):
    if len(word1)!=len(word2):
        return False
    i=0
    j=len(word2)-1
    while j>=0:
        if word1[i]!=word2[j]:
            return False
        i=i+1
        j=j-1
    return True
def all_list(arr): #Count the number of occurrences of each element in the list
    result={}
    for i in set(arr):
        result[i]=arr.count(i)
    return result
def age_me():
    a=[]
    for mo_age in range(10,100):
        for age in range(100):
            if len(str(age))<2 and is_reverse(str(age).zfill(2),str(mo_age)) and age<mo_age:
                print(age,mo_age,mo_age-age)
                a.append(mo_age-age)
            if is_reverse(str(age),str(mo_age)) and age<mo_age :
                print(age,mo_age,mo_age-age)
                a.append(mo_age-age)
    return all_list(a)
age_me() 

Then we got the difference of 18:00 and 8:00. The sixth time is 57 and 75, so I'm 57 now.

Here is the code for the answer:

def str_fill(i, len):
    """return the integer (i) written as a string with at least
    (len) digits"""
    return str(i).zfill(len)


def are_reversed(i, j):
    """ return True if the integers i and j, written as strings,
    are the reverse of each other"""
    return str_fill(i,2) == str_fill(j,2)[::-1]


def num_instances(diff, flag=False):
    """returns the number of times the mother and daughter have
    pallindromic ages in their lives, given the difference in age.
    If flag==True, prints the details."""
    daughter = 0
    count = 0
    while True:
        mother = daughter + diff
        if are_reversed(daughter, mother) or are_reversed(daughter, mother+1):
            count = count + 1
            if flag:
                print(daughter, mother)
        if mother > 120:
            break
        daughter = daughter + 1
    return count
    

def check_diffs():
    """enumerate the possible differences in age between mother
    and daughter, and for each difference, count the number of times
    over their lives they will have ages that are the reverse of
    each other."""
    diff = 10
    while diff < 70:
        n = num_instances(diff)
        if n > 0:
            print(diff, n)
        diff = diff + 1

print('diff  #instances')
check_diffs()

# print
print('daughter  mother')
num_instances(18, True)

Posted by NeverPool on Wed, 23 Oct 2019 11:58:30 -0700