[关闭]
@sevenup233 2018-04-24T16:22:31.000000Z 字数 6342 阅读 619

4月PY题

CodeWar


20180403
题目:折叠函数float(a,n),例如float([1,2,3],1) = [4,2]
初见:

  1. def fold_array(a, n):
  2. b = a[:]
  3. for i in range(n):
  4. for i in range(len(b)//2):
  5. b[i] += b[-i-1]
  6. b[:] = b[:(len(b)+1)//2]
  7. return(b)

亮点答案:

  1. 我觉得挺好的了

总结:

  1. #list的深浅复制
  2. #浅复制只是表面功夫,牵一发而动全身
  3. a = [1,2,3]
  4. b = a
  5. b[0] = 2
  6. print(a,b)
  7. #都是[2,2,3]
  8. #深复制
  9. a = [1,2,3]
  10. b = a[:]
  11. b[0] = 2
  12. print(a,b)
  13. #a是[1,2,3]b是[2,2,3]

切片中负数是好东西,[:]是更好的东西。这题感受很多,题目本身并不难,折叠加法用个负数切片就能搞定,难点是测试程序会连续测试同一个list。最开始我直接对list修改,导致连续测试出现问题,让我想了很久,最后了解了深浅复制才得以解决。
所以不能把问题想得太简单,有时候你看得到的很容易,但你一下子没看到的就会要了你的命

20180405
题目:1^4 + 6^4 + 3^4 + 4^4 = 1 + 1296 + 81 + 256 = 1634,这样的返回bool Ture
初见:

  1. def narcissistic(a):
  2. b = 0
  3. for i in str(a):
  4. b += int(i)**len(str(a))
  5. return(b==a)

亮点答案:

  1. def narcissistic(a):
  2. return a == sum(int(i)**len(str(a)) for i in str(a))

总结:
bool类型还是挺方便的,最开始虽然想到但是没有想到直接用sum那么巧,多加了一个变量,注意缩进

20180406
题目:加密/解密
初见:

  1. def encrypt(s, n):
  2. for i in range(n):
  3. s = s[1::2]+s[::2]
  4. return(s)
  5. def decrypt(s, n):
  6. if n <= 0:
  7. return(s)
  8. else:
  9. ss = str()
  10. for j in range(n):
  11. s1 = s[:len(s)//2]
  12. s2 = s[len(s)//2:]
  13. ss = str()
  14. for i in range(len(s1)):
  15. ss += s2[i]+s1[i]
  16. if len(s) % 2 != 0:
  17. ss+=s2[-1]
  18. s = ss
  19. return(ss)

亮点答案:

  1. 加密挺好的,解密都差不多

总结:那张纸写一下就找到规律了

20180407
题目:rgb(-100, 255, 300) returns 00FFFF
初见

  1. def rgb(r, g, b):
  2. ans = ''
  3. for i in r,g,b:
  4. if i <= 0:
  5. ans += '00'
  6. elif i <= 15:
  7. ans += '0' + str.upper(hex(i)[-1:])
  8. elif i <= 255:
  9. ans += str.upper(hex(i)[2:])
  10. else:
  11. ans += 'FF'
  12. return(ans)

亮点答案:

  1. def rgb(r, g, b):
  2. return ''.join(['%02X' % max(0, min(x, 255)) for x in [r, g, b]])

总结:
hex()变16进制、bin()变10、oct()变8,str.upper()加粗;join对于字符串添加还是很方便,format是很牛逼的格式化函数,格式化字符也很常用,比如%02X %10就是两位16进制大。早知道有格式化中间一大段判断和修饰就能全省了

  1. print '%d'%10 # 输出十进制
  2. >> 10
  3. print '%o'%10 # 输出八进制
  4. >> 12
  5. print '%02x'%10 # 输出两位十六进制,字母小写空缺补零
  6. >> 0a
  7. print '%04X'%10 # 输出四位十六进制,字母大写空缺补零
  8. >> 000A

20180408
题目:把秒换成具体时间,一堆格式要求
初见:

  1. def format_duration(t):
  2. if t == 0:
  3. return('now')
  4. ans = []
  5. an = str()
  6. y = t//31536000
  7. d = (t%31536000)//86400
  8. h = ((t%31536000)%86400)//3600
  9. m = (((t%31536000)%86400)%3600)//60
  10. s = (((t%31536000)%86400)%3600)%60
  11. li = [('second',s),('minute',m),('hour',h),('day',d),('year',y)]
  12. for i,j in li:
  13. if j == 1:
  14. ans.append('%s %s'%(j,i))
  15. elif j >= 1:
  16. ans.append('%s %ss'%(j,i))
  17. for i,j in enumerate(ans):
  18. if i == 0:
  19. an += j
  20. elif i == 1:
  21. an = j + ' and ' + an
  22. else:
  23. an = j + ', ' + an
  24. return(an)

亮点答案:

  1. #最后用return join方法输出,比如这样,可以省一个完整的循环
  2. return ', '.join(chunks[:-1]) + ' and ' + chunks[-1] if len(chunks) > 1 else chunks[0]

总结:
难点在于输出要求的格式,两个循环都用在格式上了,基本上后面两个循环都跑不掉

20180409
题目:正则抓域名
初见:

  1. import re
  2. def domain_name(url):
  3. a = re.search(r'([a-zA-Z]+://|[0-9a-zA-Z-_]+)\.([0-9a-zA-Z/-_]+)', url)
  4. for i in a.groups():
  5. if i != 'www':
  6. return(i)
  7. break

亮点答案:

  1. def domain_name(url):
  2. return url.split("//")[-1].split("www.")[-1].split(".")[0]

总结:
正则这东西不好说,就是域名也有很多种情况出现,还是要特定情况分析,不过这个直接切还是牛逼

题目:判断括号升级版
初见:

  1. #虽然测试过了但其实是错的,比如({[)]}
  2. def validBraces(a):
  3. b,c,d = 0,0,0
  4. for i in a:
  5. if i == '(':
  6. b += 1
  7. if i == ')':
  8. b -= 1
  9. if i == '[':
  10. c += 1
  11. if i == ']':
  12. c -= 1
  13. if i == '{':
  14. d += 1
  15. if i == '}':
  16. d -= 1
  17. if b<0 or c<0 or d<0:
  18. return False
  19. return b==0 and c==0 and d==0

亮点答案:

  1. #用dict让左括号当键,右括号当值
  2. def validBraces(string):
  3. braces = {"(": ")", "[": "]", "{": "}"}
  4. stack = []
  5. for character in string:
  6. if character in braces.keys():
  7. stack.append(character)
  8. else:
  9. if len(stack) == 0 or braces[stack.pop()] != character:
  10. return False
  11. return len(stack) == 0
  12. #移除法,总有最小闭合括号,一层一层剥开你的心
  13. def validBraces(s):
  14. while '{}' in s or '()' in s or '[]' in s:
  15. s=s.replace('{}','')
  16. s=s.replace('[]','')
  17. s=s.replace('()','')
  18. return s==''

总结:
一开始想的很简单,他怎么说我怎么做,但是括号不只当做str,也可以当做计数工具

20180411
题目:数字变成罗马字符
初见:

  1. def solution(a):
  2. ans=[]
  3. re = [['I','V','IV','IX'],['X','L','XL','XC'],['C','D','CD','CM']]
  4. b=[i for i in str(a)][::-1]
  5. for i,j in enumerate(b):
  6. if j == '9':
  7. ans.append(re[i][3])
  8. elif j == '4':
  9. ans.append(re[i][2])
  10. else:
  11. if i < 3:
  12. f = int(j)//5
  13. o = int(j)%5
  14. add = f*re[i][1] + o*re[i][0]
  15. ans.append(add)
  16. if i >= 3:
  17. ans.append(int(j)*'M')
  18. return ''.join(ans[::-1])

亮点答案:

  1. def solution(n):
  2. return " M MM MMM".split(" ")[n//1000] + \
  3. " C CC CCC CD D DC DCC DCCC CM".split(" ")[n//100%10] + \
  4. " X XX XXX XL L LX LXX LXXX XC".split(" ")[n//10%10] + \
  5. " I II III IV V VI VII VIII IX".split(" ")[n%10]

总结:
原来可以把所有情况都列出再选。。。学到了,我是觉得这样太怂了还是用函数生成

20180415
题目:逆波兰式求值
初见:

  1. def calc(a):
  2. if a == "":
  3. return 0
  4. else:
  5. b=a.split(' ')
  6. c=[]
  7. li=['+','-','*','/']
  8. for i in b:
  9. if i not in li:
  10. c.append(float(i))
  11. elif i in li:
  12. c.append(eval('%s%s%s'%(c.pop(-2),i,c.pop())))
  13. return(c[-1])

亮点答案:

  1. def calc(expr):
  2. stack = []
  3. [stack.append(eval("{1}{2}{0}".format(stack.pop(), stack.pop(), e)) if e in ('+', '-', '/', '*') else e) for e in expr.split()]
  4. return float(stack.pop()) if stack else 0

总结:我的想法对于没有运算的情况字符串直接切会输出字符串,所以要用float,还是集成度不够高

20180416
题目:顺时针输出n*n表的数字
初见:

  1. def snail(a):
  2. if len(a)<=1:
  3. return a[0]
  4. snail=[a[0][0]]
  5. i,j=1,1
  6. t=len(a)
  7. while len(snail)!=len(a)**2:
  8. if j<t:
  9. j += 1
  10. elif i<t:
  11. i += 1
  12. elif i==j==t:
  13. j -= 1
  14. t = len(a)-j
  15. elif j>t:
  16. j -= 1
  17. elif i>t+1:
  18. i -= 1
  19. elif i==j+1:
  20. j += 1
  21. t = len(a)-j+1
  22. snail.append(a[i-1][j-1])
  23. return(snail)

亮点答案:

  1. #zip法
  2. def snail(array):
  3. return list(array[0]) + snail(list(zip(*array[1:]))[::-1]) if array else []
  4. def snail(array):
  5. a = []
  6. while array:
  7. a.extend(list(array.pop(0)))
  8. array = list(zip(*array))
  9. array.reverse()
  10. return a
  11. #拆迁法
  12. def snail(array):
  13. res = []
  14. while len(array) > 1:
  15. res = res + array.pop(0)
  16. res = res + [row.pop(-1) for row in array]
  17. res = res + list(reversed(array.pop(-1)))
  18. res = res + [row.pop(0) for row in array[::-1]]
  19. return res if not array else res + array[0]
  20. #旋转切割法,巨帅
  21. def snail(array):
  22. out = []
  23. while len(array):
  24. out += array.pop(0)
  25. array = list(zip(*array))[::-1]
  26. return out

总结:
看到别人写的答案后,第一感觉是我的智商收到了侮辱,我是想着转圈一个个加入,大神该拆的拆,该组装的组装。不过学到了zip在行列式中近乎无敌的旋转xy轴用法,牛逼。

20180419
题目:小键盘,每一个件都有可能是自己+四周的值,给一串按键,输出全部可能
初见:

  1. def get_pins(a):
  2. re = [['0','8'],
  3. ['1','2','4'],
  4. ['2','1','3','5'],
  5. ['3','2','6'],
  6. ['4','1','5','7'],
  7. ['5','2','4','6','8'],
  8. ['6','3','5','9'],
  9. ['7','4','8'],
  10. ['8','5','7','9','0'],
  11. ['9','6','8']]
  12. ans = [re[int(i)] for i in list(iter(a))]
  13. while len(ans)-1:
  14. ans[-1] = [j + i for i in ans.pop() for j in ans[-1]]
  15. return(ans[0])

亮点答案:

  1. #引用product模块,很方便,如
  2. #product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
  3. from itertools import product
  4. ADJACENTS = ('08', '124', '2135', '326', '4157', '52468', '6359', '748', '85790', '968')
  5. def get_pins(observed):
  6. return [''.join(p) for p in product(*(ADJACENTS[int(d)] for d in observed))]

总结:
经历了罗马字符的教训,学会提前准备一个表了,也学会用pop节约代码

20180422
题目:
初见:

  1. #小范围可行
  2. from itertools import product
  3. method=len([sum(x) for x in product(*[range((k+1)*coin[i])[::coin[i]] for i,k in enumerate([money//j for j in coin if money//j>=0])]) if sum(x)==money])
  4. #优化后节省了内存
  5. from itertools import product
  6. def count_change(money, coins):
  7. coins.sort()
  8. method=[range((k+1)*coins[i])[::coins[i]] for i,k in enumerate([money//j for j in coins if money//j>0])]
  9. while len(method)-1:
  10. method[-1]=[i+j for i in method.pop() for j in method[-1] if i+j<=money]
  11. method[0].count(money)
  12. return(method[0].count(money))

亮点答案:

  1. #迭代法
  2. def count_change(money, coins):
  3. if money<0:
  4. return 0
  5. if money == 0:
  6. return 1
  7. if money>0 and not coins:
  8. return 0
  9. return count_change(money-coins[-1],coins) + count_change(money,coins[:-1])
  10. #牛逼法
  11. def count_change(money, coins):
  12. dp = [1]+[0]*money
  13. for coin in coins:
  14. for x in xrange(coin,money+1):
  15. dp[x] += dp[x-coin]
  16. return dp[money]

总结:
一开始用循环来做发现要用到三层循环,虽然代码行数少但是内存炸了,想到要用迭代但是不知道怎么写,最终反复优化节约内存还是用循环强行做出来了。
迭代法思路清晰简单,但是牛逼法真的太牛逼了,看懂后佩服的五体投地

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注