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
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方法即可得到相同单词
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)即可
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
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个字母算了个遍
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'], 即对第二个对象应用第一函数
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()去除右边空格
原来的代码没处理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
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是逆过程
思路简单,编码不易
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行的语法特性
罗马数字的题目, 注意几个关键的数字即可: (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
需要处理不同数据类型; 另外*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, 省去了自己判断类型