CheckIO是一个通过闯关游戏学习编程的网站(Python和JavaScript)。通过解题开发新“岛屿”,同时,通过做任务获得Quest Points解锁会员题目。
文章内容:题目、我自己的思路和代码以及优秀代码,如果想看大神解题可以直接跳到“优秀代码”部分。
本题链接:https://py.checkio.org/en/mission/parse-array/
题目
这一任务给出了题解,但是里面有bug,需要找出并修改。其中,"import"
, "exec"
和 "eval"
不可用。
给定一个包含包含整数或嵌套列表的列表组成的字符串,整数前面可以有正负号。如果输入字符串中不包含列表,会引发 ValueError
,格式错误的字符串也会引发 ValueError
, 数组中的元素用逗号分隔。
输入: 字符串
输出: 包含整数或嵌套列表的列表
举个栗子:
parse_array("[1, 2, 3]") == [1, 2, 3]
parse_array("[[1], 2, 3]") == [[1], 2, 3]
parse_array("[-3, [-2, 0], 10]") == [-3, [-2, 0], 10]
用处 : 这一任务用于提高找bug的能力,修改和改进代码,使其作为更大、更复杂的系统的一部分。
假设:
- 列表深度 < 5
- -1000 < 任意数字 < 1000
题目框架
WHITESPACE_STR = ' \t\n\r'
def parse_array(s, _w=WHITESPACE_STR, _sep=","):
array = None
stack = []
accumulator = ""
closed_flag = False
sep_flag = False
whitespace_flag = False
started_flag = False
for ch in s:
if ch in _w:
whitespace_flag = True
continue
if ch == "[":
if started_flag and not stack:
raise ValueError("Wrong string.")
if closed_flag or accumulator:
raise ValueError
in_array = []
if stack:
stack[-1](in_array)
else:
array = in_array
started_flag = True
stack.append(in_array.append)
elif not started_flag:
raise ValueError("Wrong string.")
elif ch == "]":
if not stack:
raise ValueError("Wrong string.")
if accumulator:
stack[-1](int(accumulator))
accumulator = ""
stack.pop()
closed_flag = True
sep_flag = False
whitespace_flag = False
elif ch in _sep:
if accumulator:
stack[-1](int(accumulator))
accumulator = ""
elif closed_flag:
pass
else:
raise ValueError("Wrong string.")
sep_flag = True
closed_flag = False
whitespace_flag = False
else:
if whitespace_flag and accumulator or closed_flag:
raise ValueError
accumulator += ch
whitespace_flag = False
if not array is None:
return array
else:
raise ValueError("Wrong string")
if __name__ == "__main__":
#These "asserts" using only for self-checking and not necessary for auto-testing
assert parse_array("[1, 2, 3]") == [1, 2, 3], "Simple"
assert parse_array("[[1], 2, 3]") == [[1], 2, 3], "Nested"
assert parse_array("[-3, [-2, 0], 10]") == [-3, [-2, 0], 10], "Negative integers"
assert parse_array("[100]") == [100], "One number"
assert parse_array("[2, 3]") == [2, 3], "Whitespaces"
assert parse_array("[[10, [11]], [[[1], 2], 3], 5]") == [[10, [11]], [[[1], 2], 3], 5], "Deep nested"
assert parse_array(" [3, 4] ") == [3, 4], "Skip whitespaces"
assert parse_array("[[], 0]") == [[], 0], "Empty arrays"
assert parse_array("[[0,], 0]") == [[0], 0], "Comma - closed bracket"
try:
parse_array("[asd]")
assert False, "Only integers"
except ValueError:
pass
try:
parse_array("[2, 3]]")
assert False, "Excess bracket"
except ValueError:
pass
try:
parse_array("[++2, 1]")
assert False, "Two plus"
except ValueError:
pass
try:
parse_array("[10, 11, , 12]")
assert False, "Two separators"
except ValueError:
pass
try:
parse_array(" 13 ")
assert False, "Where is a list?"
except ValueError:
pass
try:
parse_array("[[2]")
assert False, "Excess opened bracket"
except ValueError:
pass
try:
parse_array("[3 4]")
assert False, "Check for spurious spaces within a number"
except ValueError:
pass
try:
parse_array("[10, 11,, 12]")
assert False, "Check for double separators without a space in between"
except ValueError:
pass
try:
parse_array("[[]3]")
assert False, "Check for missing separators after []"
except ValueError:
pass
try:
parse_array("[2[]]")
assert False, " Check for missing separators before []"
except ValueError:
pass
try:
parse_array("[3],")
assert False, "Excess separator"
except ValueError:
pass
try:
parse_array("[1,2]3")
assert False, "Excess number"
except ValueError:
pass
try:
parse_array("[1], [2,3]")
assert False, "Here should be only one array."
except ValueError:
pass
难度:Moderate
思路及代码
思路
- 运行代码,找到产生bug的情况:
1)中括号个数不相等时
2)最后一个字符不是']'
时 - 修改代码:
1)判断'['
和']'
的个数是否相等
2)找到最后一个不是空格、制表符、换行和回车的字符,判断其是否是']'
代码
WHITESPACE_STR = ' \t\n\r'
def parse_array(s, _w=WHITESPACE_STR, _sep=","):
array = None
stack = []
accumulator = ""
closed_flag = False
sep_flag = False
whitespace_flag = False
started_flag = False
#判断中括号个数
if s.count('[') != s.count(']'):
raise ValueError("Wrong string.")
#判断最后一个字符串是否是']'
for i in range(len(s)-1,-1,-1):
if s[i] not in WHITESPACE_STR:
if s[i] != ']':
raise ValueError("Wrong string.")
break
else:
continue
for ch in s:
if ch in _w:
whitespace_flag = True
continue
if ch == "[":
if started_flag and not stack:
raise ValueError("Wrong string.")
if closed_flag or accumulator:
raise ValueError
in_array = []
if stack:
stack[-1](in_array)
else:
array = in_array
started_flag = True
stack.append(in_array.append)
elif not started_flag:
raise ValueError("Wrong string.")
elif ch == "]":
if not stack:
raise ValueError("Wrong string.")
if accumulator:
stack[-1](int(accumulator))
accumulator = ""
stack.pop()
closed_flag = True
sep_flag = False
whitespace_flag = False
elif ch in _sep:
if accumulator:
stack[-1](int(accumulator))
accumulator = ""
elif closed_flag:
pass
else:
raise ValueError("Wrong string.")
sep_flag = True
closed_flag = False
whitespace_flag = False
else:
if whitespace_flag and accumulator or closed_flag:
raise ValueError
accumulator += ch
whitespace_flag = False
if not array is None:
return array
else:
raise ValueError("Wrong string")