[英]Given a list of tuples, check to see if it's possible to construct a word in which the second value in the tuple is not consecutively repeated
假设我有一个像这样的元组列表:
list_of_tuples = [('A', 'R'), ('B', 'R'), ('C', 'G'), ('D', 'G'), ('E', 'B'), ('D', 'B'), ('R', 'B'), ('F', 'R'), ('V', 'R'), ('A', 'G')]
每个元组中的第二个值将始终是R
、 B
或G
。 我想创建一个函数validate
来检查是否可以使用每个元组第一个位置的字母构造某个单词,但前提是该元组的部分位置中的字母不重复。
例如,可以构造单词:
ACE
与(A, R)
, (C, G)
和(E, B)
因为每个元组中的第二个值对应于不连续重复任何字母的RGB
。
ACED
与(A, R), (C, G), (E, B), and ('D', 'B')
是不可能的,因为这将对应于RGBB
在其中有一个连续的B.
请注意,有时同一个字母的第二个位置可以有不同的字母,例如:
('A', 'R') and ('A', 'G')
。 如果您选择了第一个元组,则只能拼写ACE
而不是第二个,否则G
会重复。
另请注意,即使第二个位置字母“重复”它们不会连续重复,像GBRBG
这样的组合也是可能的。
所以我想要一个可以通过以下方式验证单词的函数:
def validate(submitted_word, list_of_tuples)
一种可能性是构造这个集合可能的序列的每一个可能的组合以及第二个序列中的字母将产生的相应序列,过滤掉有效单词的那些,然后过滤掉那些连续的字母重复,但我担心考虑到元组列表可以变得有多大效率低下。
这是一个图遍历问题。 您的可用节点是 (letter, color) 的元组; 您的边缘是给定单词中的字母转换。
对于每个输入,“简单地”构建该单词的图形。 给定 ACE,你有
Layer 1 -- transition START to any A
START -> AR
START -> AG
Layer 2 -- transition A to C
AR -> CG
not allowed: AG -> CG
Layer 3 -- transition C to E
CG -> EB
Layer 4 -- transition any E to GOAL
EB -> GOAL
现在您只需应用图形遍历功能(任何自尊的图形包都有)来解决您的拼写问题。
请参阅下面的独立解决方案和测试:
list_of_tuples = [
('A', 'R'),
('B', 'R'),
('C', 'G'),
('D', 'G'),
('E', 'B'),
('D', 'B'),
('R', 'B'),
('F', 'R'),
('V', 'R'),
('A', 'G')
]
def validate(submitted_word, list_of_tuples):
# Check length of word
if len(submitted_word) == 0:
raise ValueError("len(submitted_word) must be > 0")
# Initialise options for first character
options = [[tup for tup in list_of_tuples if tup[0] == submitted_word[0]]]
# Iterate through the rest of the characters
for char in submitted_word[1:]:
# Initialise set of characters in second position of previous tuple
forbidden_chars = set(tup[1] for tup in options[-1])
# Add valid options for the next character
options.append([
tup
for tup in list_of_tuples
if (tup[0] == char) and len(forbidden_chars - set(tup[1])) > 0
])
# If there are no options, then submitted_word does not validate
if len(options[-1]) == 0:
print(options)
return False
print(options)
return True
print(validate("ACE", list_of_tuples))
print()
print(validate("ACED", list_of_tuples))
print()
print(validate("ACFFFED", list_of_tuples))
控制台输出:
[[('A', 'R'), ('A', 'G')], [('C', 'G')], [('E', 'B')]]
True
[[('A', 'R'), ('A', 'G')], [('C', 'G')], [('E', 'B')], [('D', 'G')]]
True
[[('A', 'R'), ('A', 'G')], [('C', 'G')], [('F', 'R')], []]
False
我们可以使用回溯,其中状态是每个字母使用的每个 R、G、B 的计数,以及我们构造单词时选择的先前“RGB”。
Python 代码(未记忆):
def f(i, word, prev, state):
if i == len(word):
return True
letter = word[i]
for second in ["R", "G", "B"]:
if state[letter][second] and prev != second:
state[letter][second] -= 1
is_valid = f(i + 1, word, second, state)
state[letter][second] += 1
if is_valid:
return True
return False
def get_counts(tuples):
result = {}
for letter, rgb in tuples:
if letter in result:
result[letter][rgb] += 1
else:
result[letter] = {"R": 0, "G": 0, "B": 0}
result[letter][rgb] = 1
return result
tuples = [('A', 'R'), ('B', 'R'), ('C', 'G'), ('D', 'G'), ('E', 'B'), ('D', 'B'), ('R', 'B'), ('F', 'R'), ('V', 'R'), ('A', 'G')]
counts = get_counts(tuples)
print f(0, "ACE", "", counts) # True
print f(0, "ACED", "", counts) # True
print f(0, "BF", "", counts) # False
我构建了以下内容。 首先,我们创建一个函数来比较 2 个列表并检查它们是否至少有一个不同的元素。 其次,我们为单词中所有连续字母对的关联列表运行此函数。 我认为单词的所有字母都在 list_of_tuples 中表示。 否则它将需要多几行来检查是否存在(在这种情况下让我知道,以便我添加它们)。
def validate(word, list_of_tuples):
def rgb(l1,l2):
return len(set(l1).difference(set(l2)))>0
l=[[i, [k[1] for k in list_of_tuples if k[0]==i]] for i in word]
for i in range(len(l)-1):
if not rgb(l[i][1], l[i+1][1]):
return False
return True
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.