The end of other
For language training our Robots want to learn about suffixes.
In this task, you are given a set of words in lower case. Check whether there is a pair of words, such that one word is the end of another (a suffix of another). For example: {"hi", "hello", "lo"} -- "lo" is the end of "hello", so the result is True.
Hints: For this task you should know how to iterate through set types and string data type functions. Read more about set type here and string functions here.
Input: Words as a set of strings.
Output: True or False, as a boolean.
題目大義:給出一個含有單詞的集合(set),如果某個單詞是另一個單詞的后綴,如"lo"是"hello"的后綴,則返回True,如果不存在則返回False。
一開始認為set可以使用index,就像數組般使用,可惜了,set並不支持。想想也合理,c++中的set也是不支持[]索引的,於是乎想到了for xx in xx形式,加上提示:str.endswith(suffix[, start[, end]]),恍然大悟,給出拙劣的Python代碼
1 def checkio(words_set): 2 for words in words_set: 3 for other_words in words_set: 4 if other_words != words and other_words.endswith(words): 5 return True 6 7 return False
Common Words
Let's continue examining words. You are given two string with words separated by commas. Try to find what is common between these strings. The words are not repeated in the same string.
Your function should find all of the words that appear in both strings. The result must be represented as a string of words separated by commas in alphabetic order.
Tips: You can easily solve this task with several useful functions:str.split, str.join and sorted. Also try using the built-in type -- set.
Input: Two arguments as strings.
Output: The common words as a string.
題目大義:給出兩個字符串,找出在兩個字符串中同時出現的單詞,並按字典序輸出
當然使用了str.split方法,然后想到set有in方法,於是乎得到這么一段代碼
1 def checkio(first, second): 2 first_str = first.split(',') 3 words_set = set(first_str) 4 5 second_str = second.split(',') 6 7 result = [] 8 9 for each in second_str: 10 if each in words_set: 11 result.append(each) 12 else: 13 words_set.add(each) 14 15 result.sort() 16 17 18 return ','.join(result);
接下來看了別人的解答,發現其實可以把兩個字符串split后,轉化為set,再使用set的intersection方法即可得到相同單詞
Absolute sort
Let's try some sorting. Here is an array with the specific rules.
The array (a tuple) has various numbers. You should sort it, but sort it by absolute value in ascending order. For example, the sequence (-20, -5, 10, 15) will be sorted like so: (-5, 10, 15, -20). Your function should return the sorted list or tuple.
Hints: This task can be easily solved using these functions: sorted andabs. You should try to use the key parameter for sorting.
Precondition: The numbers in the array are unique by their absolute values.
Input: An array of numbers , a tuple..
Output: The list or tuple (but not a generator) sorted by absolute values in ascending order.
題目大義:按絕對值排序
還是C語言的思路,sorted中傳入cmp函數,如果x < y返回負值,x > y返回正值,x = y返回0
1 def cmp(numberA, numberB): 2 return abs(numberA) - abs(numberB) 3 4 def checkio(numbers_array): 5 return sorted(numbers_array, cmp)
不過既然用了Python如此高大上的語言,自然要顯擺下,sorted還有一個參數為key,實際上sorted(number_array, key=abs)即可
Non-unique Elements
You are given a non-empty list of integers (X). For this task, you should return a list consisting of only the non-unique elements in this list. To do so you will need to remove all unique elements (elements which are contained in a given list only once). When solving this task, do not change the order of the list. Example: [1, 2, 3, 1, 3] 1 and 3 non-unique elements and result will be [1, 3, 1, 3].
題目大義:將數組中唯一的元素清除
還是C語言的思想,直接粗暴,首先是遍歷求出唯一的元素,再使用數組的remove方法
1 def checkio(data): 2 3 only = [] 4 5 for each in data: 6 count = 0 7 for other in data: 8 if each == other: 9 count += 1 10 11 if count == 1: 12 only.append(each) 13 14 for each in only: 15 data.remove(each) 16 17 return data
當然我們有更高級的方法list = [x for x in data if x.count > 1],簡單明了,使用了數組的另一種構造方法,使用了數組count方法
1 def checkio(data): 2 list = [x for x in data if data.count(x) > 1] 3 return list
新技能get
The Most Wanted Letter
You are given a text, which contains different english letters and punctuation symbols. You should find the most frequent letter in the text. The letter returned must be in lower case.
While checking for the most wanted letter, casing does not matter, so for the purpose of your search, "A" == "a". Make sure you do not count punctuation symbols, digits and whitespaces, only letters.
If you have two or more letters with the same frequency, then return the letter which comes first in the latin alphabet. For example -- "one" contains "o", "n", "e" only once for each, thus we choose "e".
Input: A text for analysis as a string (unicode for py2.7).
Output: The most frequent letter in lower case as a string.
題目大義:找出出現次數最多的字母,不區分大小寫,如果出現次數相同,則取字典序最小的輸出
一開始想需要諸如'a' : 0,即字母到數字的對應,於是想到dict;查閱str手冊后,發現str.lower方法,將字符串轉換為小寫;最后是對dict的排序,需要先按字母排序,再按出現次序排序(ps:python中的排序是穩定的)
1 def checkio(text): 2 lower_text = text.lower() 3 4 appear_time = {} 5 6 for each in lower_text: 7 if each.islower(): 8 if each not in appear_time: 9 appear_time[each] = 0 10 else: 11 appear_time[each] += 1 12 13 14 array = appear_time.items(); 15 array.sort(key=lambda x:x[0]) 16 array.sort(key=lambda x:x[1], reverse=True) 17 18 return array[0][0]
不過呢,這是笨方法,沒有充分利用Python的豐富資源,給出大神bryukh的解答
1 import string 2 3 def checkio(text): 4 """ 5 We iterate through latyn alphabet and count each letter in the text. 6 Then 'max' selects the most frequent letter. 7 For the case when we have several equal letter, 8 'max' selects the first from they. 9 """ 10 text = text.lower() 11 return max(string.ascii_lowercase, key=text.count)
學藝不精,現在想來key的意思是每個元素的順序由key決定吧,max的第一參數是ascii碼的小寫字母,相當於把26個字母算了個遍
Xs and Os Referee
1 def checkio(game_result): 2 winner = 'D' 3 4 for row in game_result: 5 if row[0] == row[1] == row[2] and row[0] != '.': 6 winner = row[0] 7 8 for col in range(0, 3): 9 if game_result[0][col] == game_result[1][col] == game_result[2][col] and game_result[0][col] != '.': 10 winner = game_result[0][col] 11 12 if game_result[0][0] == game_result[1][1] == game_result[2][2] and game_result[0][0] != '.': 13 winner = game_result[0][0] 14 15 if game_result[0][2] == game_result[1][1] == game_result[2][0] and game_result[0][2] != '.': 16 winner = game_result[0][2] 17 18 return winner
此題的結論是python支持形如此等模式的判斷: row[0] == row[1] == row[2], 即支持連等
再來看看大神代碼
1 def checkio(result): 2 rows = result 3 cols = map(''.join, zip(*rows)) 4 diags = map(''.join, zip(*[(r[i], r[2 - i]) for i, r in enumerate(rows)])) 5 lines = rows + list(cols) + list(diags) 6 7 return 'X' if ('XXX' in lines) else 'O' if ('OOO' in lines) else 'D'
zip函數可將兩個數組柔和在一起,如學生姓名name = ['bob', 'jenny'], 成績grade = [80, 90], zip(name, grade) = [('bob', 80), ('jenny', 90)], 在函數調用中使用*list/tuple的方式表示將list/tuple分開,作為位置參數傳遞給對應函數(前提是對應函數支持不定個數的位置參數), 如test = ["XXX", "OOO", "..."], zip(*test) = [('X', 'O', '.'), ('X', 'O', '.'), ('X', 'O', '.')]
map函數接受兩個參數, 第一個為函數名, 第二個為可迭代對象, 如array = [1, 2, 3], map(str, array) = ['1', '2', '3'], 即對第二個對象應用第一函數
Speech Module
1 FIRST_TEN = ["one", "two", "three", "four", "five", "six", "seven", 2 "eight", "nine"] 3 SECOND_TEN = ["ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", 4 "sixteen", "seventeen", "eighteen", "nineteen"] 5 OTHER_TENS = ["twenty", "thirty", "forty", "fifty", "sixty", "seventy", 6 "eighty", "ninety"] 7 HUNDRED = "hundred" 8 9 10 def checkio(number): 11 spoken = [] 12 13 hundred_bit = number / 100 14 15 if hundred_bit > 0: 16 spoken.append(FIRST_TEN[hundred_bit - 1]) 17 spoken.append(HUNDRED) 18 19 remain = number % 100 20 21 if remain >= 10 and remain <= 19: 22 spoken.append(SECOND_TEN[remain % 10]) 23 else: 24 decade = remain / 10 25 if decade > 0: 26 spoken.append(OTHER_TENS[decade - 2]) 27 28 unit = remain % 10 29 if unit > 0: 30 spoken.append(FIRST_TEN[unit - 1]) 31 32 return ' '.join(spoken)
python有個divmod函數, 即可返回商又可返回余數h, number
=
divmod
(number,
100
)
可以如此構造字符串
final_string
=
"%s%s%s"
%
(hundred_s, decade_s, unit_s)
使用strip去除字符,lstrip, rstrip; rstrip()去除右邊空格
The Flat Dictionary
原來的代碼沒處理dict為空的情況
1 def flatten(dictionary): 2 #[] is a list 3 #() is a tuple 4 stack = [((), dictionary)] 5 6 result = {} #result is a dict 7 8 while stack: 9 path, current = stack.pop() #get a tuple 10 11 for k, v in current.items(): #dict::items return key and values tuple 12 if isinstance(v, dict): #is a instance of dict 13 stack.append((path + (k,), v)) #add key to tuple such as (xxx, yyy, zzz) and the element in stack is like ((xxx, yyy, zzz), value) 14 else: 15 result["/".join((path + (k,)))] = v 16 17 if len(current) == 0: #when the dict is empty 18 result["/".join(path)] = "" 19 20 return result
(k,)一個元素的tuple
Pawn Brotherhood
1 alpha_table = "abcdefgh" 2 3 def safe_pawns(pawns): 4 safe_count = 0 5 6 for spawn in pawns: 7 if spawn[1] == '1': 8 continue 9 10 pos = alpha_table.find(spawn[0]) 11 str_row = str(int(spawn[1]) - 1) 12 13 if pos == 0: 14 if (alpha_table[1] + str_row) in pawns: 15 safe_count += 1 16 continue 17 18 if pos == 7: 19 if (alpha_table[6] + str_row) in pawns: 20 safe_count += 1 21 continue 22 23 if (alpha_table[pos - 1] + str_row) in pawns or (alpha_table[pos + 1] + str_row) in pawns: 24 safe_count += 1 25 26 return safe_count
自定義了一個小寫字母表, 找出某字母的前后字母, 如b的(a, c)
另外可以使用chr
(
ord
(pawn[
0
])
+
1
),
chr
(
ord
(pawn[
0
])
-
1
)獲得前后字母, ord相當於獲得字母的數碼(如ascii碼), chr是逆過程
How to find friends
思路簡單,編碼不易
1 def check_connection(network, first, second): 2 link_dictionary = dict() 3 4 for link in network: 5 drones = link.split('-') 6 7 link_dictionary.setdefault(drones[0], []).append(drones[1]) 8 link_dictionary.setdefault(drones[1], []).append(drones[0]) 9 10 future = [] 11 visited = [] 12 future.append(first) 13 14 while future: 15 current = future.pop() 16 visited.append(current) 17 18 extend = link_dictionary[current] 19 20 if second in extend: 21 return True 22 23 for each in extend: 24 if each not in visited: 25 future.append(each) 26 27 return False
使用dict存儲每個人的直接關系, 如{lyly : [lala, gege]}; 使用兩個list, 其中一個表示已遍歷過的人, 另一個表示即將遍歷的人;
另外python中的二維數組可以這么定義: connection = [[False for col in range(5)] for row in range(5)], 即一個5*5的數組, 原先嘗試過這么定義error = [[False] * 5] * 5, 發現只要修改了
error[0][0], 那么error[1][0], error[2][0] ...都修改了, 因為[False] * 5產生了一個一維數組, 而外面的*5只是產生了5個引用因此, 無論修改哪一個其余的均會改變.
觀摩下大神的代碼
1 def check_connection(network, first, second): 2 setlist = [] 3 for connection in network: 4 s = ab = set(connection.split('-')) 5 # unify all set related to a, b 6 for t in setlist[:]: # we need to use copy 7 if t & ab: # check t include a, b 8 s |= t 9 setlist.remove(t) 10 setlist.append(s) # only s include a, b 11 12 return any(set([first, second]) <= s for s in setlist)
將每條關系作為set, 若關系間交集不為空, 則求關系間的並集, 即關系圈;
最后查看first與second是否在某個關系圈中;
充分利用了set的操作, &交, |並, <=子集;
還有第12行的語法特性
Roman numerals
羅馬數字的題目, 注意幾個關鍵的數字即可: (100, 400, 500, 900) -> ('C', 'CD', 'D', 'CM'); (10, 40, 50, 90)->('X', 'XL', 'L', 'XC')
1 def checkio(data): 2 rel = '' 3 4 thonsand = data / 1000 5 rel += thonsand * 'M' 6 7 data %= 1000 8 9 table = [['C', 'CD', 'D', 'CM'], ['X', 'XL', 'L', 'XC']] 10 11 pos = 100 12 13 for i in range(0, 2): 14 bit = data / pos 15 if bit > 0: 16 if bit < 4: 17 rel += bit * table[i][0] 18 elif bit == 4: 19 rel += table[i][1] 20 elif bit == 5: 21 rel += table[i][2] 22 elif bit == 9: 23 rel += table[i][3] 24 else: 25 rel += (table[i][2] + table[i][0] * (bit - 5)) 26 27 data %= pos 28 pos /= 10 29 30 if data > 0: 31 unit = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X'] 32 rel += unit[data - 1] 33 34 #replace this for solution 35 return rel
另外還需注意沒有個位數的情況, 即第30行所示
觀摩JulianNicholls的代碼
1 elements = { 1000 : 'M', 900 : 'CM', 500 : 'D', 400 : 'CD', 2 100 : 'C', 90 : 'XC', 50 : 'L', 40: 'XL', 3 10 : 'X', 9 : 'IX', 5 : 'V', 4: 'IV', 1 : 'I' } 4 5 def checkio(data): 6 roman = '' 7 8 for n in sorted(elements.keys(), reverse=True): 9 while data >= n: 10 roman += elements[n] 11 data -= n 12 13 return roman
sorted(elements.keys(), reverse=True), 按key從大到小排列; 思路不錯, 比數位對應的值大, 即加上該數位對應的字母, 並減去對應的數值, 直到data為0
Min and Max
需要處理不同數據類型; 另外*args, 表示的是位置參數, *kwargs表示的是key參數, args的類型為tuple類型, 參數為min(3, 2)時, args為(3, 2), 參數為min([3, 2])時, args為([3, 2], );
列表解析為[i for i in range(0, 1)], 而(i for i in range(0, 1))為generator, 通過.next()屬性獲取下一個元素, 它不像列表解析一次性生成所有元素, 每次調用next生成一個元素;
1 def min(*args, **kwargs): 2 key = kwargs.get("key", None) 3 4 sort_source = args if len(args) > 1 else args[0] #tuple comprehension 5 6 if isinstance(sort_source, set): 7 rel = sort_source.pop() 8 elif type(sort_source) == type((i for i in range(0, 1))): 9 rel = sort_source.next() 10 else: 11 rel = sort_source[0] 12 13 if key != None: 14 for each in sort_source: 15 if key(each) < key(rel): 16 rel = each 17 else: 18 for each in sort_source: 19 if each < rel: 20 rel = each 21 22 return rel
觀摩Cjkjvfnby的代碼
1 def get_first_from_sorted(args, key, reverse): 2 if len(args) == 1: 3 args = iter(args[0]) 4 return sorted(args, key=key, reverse=reverse)[0] 5 6 7 def min(*args, key=None): 8 return get_first_from_sorted(args, key, False) 9 10 11 def max(*args, key=None): 12 return get_first_from_sorted(args, key, True)
無他, 在len(arg) == 1的情況, 仍然需要提取出實際的對象, 如([1, 2], )中的[1, 2]; 高明的地方在於使用了sorted, 省去了自己判斷類型