鱼C论坛

 找回密码
 立即注册
查看: 2371|回复: 6

[技术交流] 鱼C论坛Python精英挑战赛(第二季04期)评比结果

[复制链接]
发表于 2017-8-20 23:36:48 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
可能是由于本期题目的难度提高了,所以参与答题的鱼油人数明显减少了。

答题者中,有不少鱼油采用替换的方法并结合eval函数,虽然结果正确,但eval函数在大多数服务器上是禁止使用的(出于安全性考虑),所以都不计分。

剩下的鱼油中,@小锟 的解答当s6='!(apple & other) | !apple & !(yellow | green)'时,判断错误

小剑剑、gunjang、zmx296689210 测试结果都正确,而且代码长度都差不多,所以评选他们并列第一。

最后请@小甲鱼 老师评判并颁奖!

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2017-8-20 23:39:00 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2017-8-20 23:42 编辑

贴下我的解答,其实这题应该很明显可以考虑用递归函数,为什么大家都没有想到呢?

用递归写的话,逻辑很清楚,程序也很简洁,看注释吧。不算注释的话,才10多行代码。
  1. def search(string, txt):
  2.     #去首尾空格
  3.     string = string.strip()
  4.     #主循环,找不在括号中的“&”和“|”进行判断
  5.     layer = 0
  6.     for i in range(len(string)):
  7.         #判断括号层数
  8.         if string[i] == '(': layer += 1
  9.         if string[i] == ')': layer -= 1
  10.         #处理“&”的情况
  11.         if string[i] == '&' and layer == 0:
  12.             if search(string[:i], txt):
  13.                 return search(string[i+1:], txt)
  14.             else:
  15.                 return False
  16.         #处理“|”的情况
  17.         elif string[i] == '|' and layer == 0:
  18.             if search(string[:i], txt):
  19.                 return True
  20.             else:
  21.                 return search(string[i+1:], txt)
  22.     #去首尾括号
  23.     if string[0]=='(' and string[-1]==')': return search(string[1:-1], txt)
  24.     #处理“!”的情况
  25.     return not search(string[1:], txt) if string[0] == '!' else string in txt
复制代码

点评

我很赞同!: 5.0
我很赞同!: 5
递归用得妙~  发表于 2017-8-20 23:54
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-8-20 23:58:49 | 显示全部楼层
判断单目运算符 ! 的时候,没考虑到传入的是整数,考虑不全
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-8-21 00:35:47 | 显示全部楼层
楼主代码考虑错了的情况:


  1. txt = 'one apple with two leaves, one is green and the other is yellow.'
  2. string = 'ther'
  3. print(search(string, txt))

  4. # 正确结果是 False
  5. # 而楼主的运行结果是 True, 可能错在非全字匹配那里...我的代码这个样例测试也是错的...我代码需要修改一下判断条件
复制代码


修改后...主要是用了转换为后缀式(逆波兰式)
  1. import re


  2. def search(string, txt):

  3.     pattern = re.compile(r'[^!&|() .,!]+')
  4.     def changeKeywords(string, txt):
  5.         '''
  6.         将关键字转换为0或1
  7.         例如
  8.         txt = 'one apple with two leaves, one is green and the other is yellow.'
  9.         s1 = '(apple | others) & two'
  10.         转换后 string ='(1 | 0) & 1'
  11.         '''
  12.         string = ' ' + string + ' '
  13.         keywords = pattern.findall(string)
  14.         for each in keywords:
  15.             p = re.compile('[!&|() .,!]%s[!&|() .,!]' % each)
  16.             if p.findall(txt):
  17.                 string = re.sub('([!&|() ])(%s)([!&|() ])' % each, '\g<1>1\g<3>', string)
  18.             else:
  19.                 string = re.sub('([!&|() ])(%s)([!&|() ])' % each, '\g<1>0\g<3>', string)
  20.         string = string.replace(' ', '')
  21.         return string

  22.     operatorPrecedence = {
  23.         '(': 0,
  24.         ')': 0,
  25.         '|': 1,
  26.         '&': 2,
  27.         '!': 3
  28.     }

  29.     def postfixConvert(exp):
  30.         '''''
  31.         将表达式字符串,转为后缀表达式
  32.         如exp = "1+2*(3-1)-4"
  33.         转换为:postfix = ['1', '2', '3', '1', '-', '*', '+', '4', '-']
  34.         '''
  35.         stack = []  # 运算符栈,存放运算符
  36.         postfix = []  # 后缀表达式栈
  37.         for char in exp:
  38.             #        print char, stack, postfix
  39.             if char not in operatorPrecedence:  # 非符号,直接进栈
  40.                 postfix.append(char)
  41.             else:
  42.                 if len(stack) == 0:  # 若是运算符栈啥也没有,直接将运算符进栈
  43.                     stack.append(char)
  44.                 else:
  45.                     if char == "(":
  46.                         stack.append(char)
  47.                     elif char == ")":  # 遇到了右括号,运算符出栈到postfix中,并且将左括号出栈
  48.                         while stack[-1] != "(":
  49.                             postfix.append(stack.pop())
  50.                         stack.pop()

  51.                     elif operatorPrecedence[char] > operatorPrecedence[stack[-1]]:
  52.                         # 只要优先级数字大,那么就继续追加
  53.                         stack.append(char)
  54.                     else:
  55.                         while len(stack) != 0:
  56.                             if stack[-1] == "(":  # 运算符栈一直出栈,直到遇到了左括号或者长度为0
  57.                                 break
  58.                             # 将运算符栈的运算符,依次出栈放到表达式栈里面
  59.                             postfix.append(stack.pop())
  60.                         stack.append(char)  # 并且将当前符号追放到符号栈里面

  61.         while len(stack) != 0:  # 如果符号站里面还有元素,就直接将其出栈到表达式栈里面
  62.             postfix.append(stack.pop())
  63.         return postfix

  64.     def calculate(num1, op, num2='0'):
  65.         if not num1.isdigit() and not num2.isdigit():
  66.             raise "num error"
  67.         else:
  68.             num1 = int(num1)
  69.             num2 = int(num2)
  70.         if op == "&":
  71.             return int(num1 and num2)
  72.         elif op == "|":
  73.             return int(num1 or num2)
  74.         elif op == "!":
  75.             return int(not num1)
  76.         else:
  77.             raise "op error"

  78.     def calExpressionTree(postfix):
  79.         stack = []
  80.         for char in postfix:
  81.             stack.append(char)
  82.             if char in "&|":
  83.                 op = stack.pop()
  84.                 num2 = stack.pop()
  85.                 num1 = stack.pop()
  86.                 value = calculate(num1, op, num2)
  87.                 value = str(value)  # 计算结果是数值类型,将其化为字符串类型
  88.                 stack.append(value)
  89.             elif char == '!':
  90.                 op = stack.pop()
  91.                 num1 = stack.pop()
  92.                 value = calculate(num1, op)
  93.                 value = str(value)
  94.                 stack.append(value)
  95.         return bool(int(stack[0]))

  96.     string = changeKeywords(string, txt)
  97.     postfix = postfixConvert(string)
  98.     res = calExpressionTree(postfix)
  99.     return res


  100. if __name__ == '__main__':
  101.     txt = 'one apple with two leaves, one is green and the other is yellow.'

  102.     s1 = '(apple | others) & two'                               # True
  103.     s2 = 'one & yellow & leaf'                                  # False
  104.     s3 = '(!three | one & four) & !five'                        # True
  105.     s4 = '!green & (ones | two)'                                # False
  106.     s5 = '(big | !apple | the) & ((!yellow | !green) | others)' # False

  107.     s6 = '!(apple & other) | !apple & !(yellow | green)'
  108.     s7 = 'ther'

  109.     print(search(s1, txt))
  110.     print(search(s2, txt))
  111.     print(search(s3, txt))
  112.     print(search(s4, txt))
  113.     print(search(s5, txt))
  114.     print(search(s6, txt))
  115.     print(search(s7, txt))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-8-21 01:19:19 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2017-8-21 01:20 编辑
zmx296689210 发表于 2017-8-21 00:35
楼主代码考虑错了的情况:


如果ther的话,结果是为True啊, other的一部分,也确实是匹配的啊。

题目规定是包含关键词,并没有规定一定要全字符匹配。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-8-21 01:26:43 | 显示全部楼层
jerryxjr1220 发表于 2017-8-21 01:19
如果ther的话,结果是为True啊, other的一部分,也确实是匹配的啊。

题目规定是包含关键词,并没有 ...

好吧......
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-19 22:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表