我为此任务准备了函数和排序数据: (实际上是 AoC 第 4 天,但要快速解释清楚) 我已经将数据排序到这个“结构”
byr:1991
eyr:2022
hcl:#341e13
iyr:2016
pid:729933757
hgt:167cm
ecl:gry
hcl:231d64
cid:124
ecl:gmt
eyr:2039
hgt:189in
pid:#9c3ea1
ecl:#1f58f9
pid:#758e59
iyr:2022
hcl:z
byr:2016
hgt:68
eyr:1933
[等等+250个包(包我的意思是一组byr,ecl,eyr......用新行分隔)。]
并准备好这段代码:
def check_fields(list):
comparison_list = ['byr', 'iyr', 'eyr',
'hgt', 'hcl', 'ecl',
'pid']
statement = True
for i in comparison_list:
statement = statement and (i in list)
return statement
def check_byr_iyr_eyr(line):
prefix,value = line.split(':')
cases = {'byr':{'min':1920, 'max':2002},
'iyr':{'min':2010, 'max':2020},
'eyr':{'min':2020, 'max':2030} }
return cases[prefix]['min'] <= int(value) <= cases[prefix]['max']
def check_hgt(line):
unit = line[len(line)-2] + line[len(line)-1]
value = line[line.index(':')+1: -2]
cases = {'cm':{'min':150, 'max':193},
'in':{'min':59, 'max':76}}
return cases[unit]['min'] <= int(value) <= cases[unit]['max']
def check_hcl(line):
statement = True
if line[line.index(':')+1] != '#' or len(line[line.index(':')+2:]) != 6:
return False
else:
string = line[line.index('#')+1:]
for i in string:
statement = statement and (97 <= ord(i) <= 102 or 48 <= ord(i) <= 57)
return statement
def check_ecl(line):
comparison_list = ['amb', 'blu', 'brn',
'gry', 'grn', 'hzl',
'oth' ]
if line[line.index(':') + 1:] in comparison_list:
return True
return False
def check_pid(line):
if len(line[line.index(':')+1:]) != 9:
return False
try:
int(line[line.index(':')+1:])
return True
except:
return False
line_list = []
valid_passports = 0
with open('results.txt', 'r') as f:
for line in f:
if line != '\n':
''' add line to line_list'''
pass
else:
'''
check lines from line_list
using above declared functions
if every line is ok:
valid_passports +=1
'''
我必须检查每个包是否包含除 cid 之外的每个键,然后检查每个键的每个值是否正确。
byr (Birth Year) - four digits; at least 1920 and at most 2002.
iyr (Issue Year) - four digits; at least 2010 and at most 2020.
eyr (Expiration Year) - four digits; at least 2020 and at most 2030.
hgt (Height) - a number followed by either cm or in:
If cm, the number must be at least 150 and at most 193.
If in, the number must be at least 59 and at most 76.
hcl (Hair Color) - a # followed by exactly six characters 0-9 or a-f.
ecl (Eye Color) - exactly one of: amb blu brn gry grn hzl oth.
pid (Passport ID) - a nine-digit number, including leading zeroes.
cid (Country ID) - ignored, missing or not.
(上述规则由较早声明的函数确保)
问题/问题是如何在检查添加到行列表的每一行时避免重复 if 语句(它指的是带有“伪代码”的多行注释部分)? - 我的意思是我可以这样做
if line[0:3] == "byr":
check_byr(line)
# and so on, many if statement checking the first 3 letters to adjust proper function to use
但这似乎不是适当而优雅的解决方案,也许您可以给我提示如何处理它,或者给出另一个想法以我没有使用的不同方式解决该问题。 请帮忙,谢谢。
答案 0 :(得分:2)
你不能有从前缀到目标函数的映射吗?
类似的东西
_textChange(text) {
this.setState({
textValue: text,
})
}
答案 1 :(得分:1)
@viGor207,这是另一种方法:(第 2 部分示例):
import re
passports = [
dict(
line.split(':')
for line
in pas.split()
)
for pas
in open('input').read().split('\n\n')
]
required = {'byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid'}
def valid(pas):
return bool(
1920 <= int(pas['byr']) <= 2002 and
2010 <= int(pas['iyr']) <= 2020 <= int(pas['eyr']) <= 2030 and
re.fullmatch(r'[0-9]{2,3}(cm|in)', pas['hgt']) and
(
(pas['hgt'][-2:] == 'cm' and 150 <= int(pas['hgt'][:-2]) <= 193) or
(pas['hgt'][-2:] == 'in' and 59 <= int(pas['hgt'][:-2]) <= 79)
) and
re.fullmatch(r'#[0-9a-f]{6}', pas['hcl']) and
pas['ecl'] in {'amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'} and
re.fullmatch(r'[0-9]{9}', pas['pid'])
)
print(
sum(
all(r in pas for r in required) and valid(pas)
for pas
in passports
)
)
答案 2 :(得分:1)
为了使它完整,这是第一部分:
passports = [
dict(
line.split(':')
for line
in pas.split()
)
for pas
in open('input').read().split('\n\n')
]
required = {'byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid'}
print(
sum(
all(r in pas for r in required)
for pas in passports
)
)
答案 3 :(得分:1)
任务说明:
<块引用>每本护照都表示为一系列键值对 以空格或换行符分隔。护照用空格隔开 线。
sequence
对的 key:value
在 Python 中使用 list
的 dicts
,但可以使用您的方法。
您可以使用将字段名称映射到检查该字段行 field_to_checker
的函数的字典。我将您的示例解析输入作为解析行的列表,然后添加了一个仅返回 True 的 cid 检查器,并创建了以下代码片段:
def check_cid(line):
return True
field_to_checker = {
'byr': check_byr_iyr_eyr,
'cid': check_cid,
'ecl': check_ecl,
'eyr': check_byr_iyr_eyr,
'hcl': check_hcl,
'hgt': check_hgt,
'iyr': check_byr_iyr_eyr,
'pid': check_pid,
}
line_data = """byr:1991
eyr:2022
hcl:#341e13
iyr:2016
pid:729933757
hgt:167cm
ecl:gry
hcl:231d64
cid:124
ecl:gmt
eyr:2039
hgt:189in
pid:#9c3ea1
ecl:#1f58f9
pid:#758e59
iyr:2022
hcl:z
byr:2016
hgt:68
eyr:1933""".split('\n')
valid_passports = 0
ok_passport = True # Accumulating over all fields of one passport
for line in line_data + ['\n']: # Add empty line to force processing last passport
line = line.rstrip()
if line: # Not blank line
if ok_passport: # One False value in a passport will prevail
key = line[:3]
ok_passport = (key in field_to_checker
and field_to_checker[key](line))
else: # Blank line, end of passport record
if ok_passport:
valid_passports += 1
ok_passports = True
在 for line in line_data + ['\n']
循环中,valid_passports
的计数仅在护照记录结束时出现空行时更新。最后一本护照后面需要有一个空行才能正确计数,因此在 line_data
的末尾添加了一个额外的空行。
以上内容未经测试,但应该会为您提供有关如何扩展已开始使用的内容的提示。
答案 4 :(得分:0)
我建议尽早将字典值放在变量中,以使逻辑更易于编写和读取。
这应该允许您制作可识别的单行条件:
data = \
"""byr:1991
eyr:2022
hcl:#341e13
iyr:2016
pid:729933757
hgt:167cm
ecl:gry
hcl:231d64
cid:124
ecl:gmt
eyr:2039
hgt:189in
pid:#9c3ea1
ecl:#1f58f9
pid:#758e59
iyr:2022
hcl:z
byr:2016
hgt:68
eyr:1933"""
...
# iterator to get packages
def getPackages(d):
package = dict()
for line in d:
if line:
field,value = line.split(":",1)
package[field]=value
else:
yield package.copy()
package.clear()
if package: yield package
fields = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid']
for package in getPackages(data.split("\n")):
values = [package.get(f,"") for f in fields]
byr, iyr, eyr, hgt, hcl, ecl, pid = values
isValid = "" not in values[:-1] \
and int(byr) in range(1920,2001+1) \
and int(iyr) in range(2010,2020+1) \
and int(eyr) in range(2020,2030+1) \
and int(hgt[:-2]) in {"cm":range(150,193+1),"in":range(59,76+1)}.get(hgt[-2:],[]) \
and hcl.startswith("#") and len(hcl)==7 \
and all(97 <= ord(i) <= 102 or 48 <= ord(i) <= 57 for i in hcl[1:]) \
and ecl in {'amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth' } \
and (pid == "" or pid.isdigit() and len(pid)==9)
print(pid,isValid)
"""
729933757 True
#9c3ea1 False
#758e59 False
"""