减少Python中的二进制模式
我有一个我认为有点有趣的问题,即使只是从编程练习的角度来看 我有一长串的二进制模式,我想把它们简化成一个更紧凑的形式,呈现给用户。要遵循的符号是“-”可以表示“1”或“0”,因此减少Python中的二进制模式,python,Python,我有一个我认为有点有趣的问题,即使只是从编程练习的角度来看 我有一长串的二进制模式,我想把它们简化成一个更紧凑的形式,呈现给用户。要遵循的符号是“-”可以表示“1”或“0”,因此['1011','1010']可以表示为['101-']和 ['1100', '1000', '0100', '0000', '1111', '1011', '0111', '0011'] 可以用['-00','-11']表示。注意所有的模式都是相同的长度(尽管很可能超过4位) 扩展模式相当简单,减少模式则有点棘手 我
['1011','1010']
可以表示为['101-']
和
['1100', '1000', '0100', '0000', '1111', '1011', '0111', '0011']
可以用['-00','-11']
表示。注意所有的模式都是相同的长度(尽管很可能超过4位)
扩展模式相当简单,减少模式则有点棘手
我已经想出了一些代码来实现这一点,但它很长,很慢,而且有点难以阅读
def reducePatterns(patterns):
'''Reduce patterns into compact dash notation'''
newPatterns = [] #reduced patterns
matched = [] #indexes with a string that was already matched
for x,p1 in enumerate(patterns): #pattern1
if x in matched: continue #skip if this pattern has already been matched
for y,p2 in enumerate(patterns[x+1:],1):
if x+y in matched: continue #skip if this pattern has already been matched
diffs=0 # number of differences found
for idx,bit in enumerate(zip(p1,p2)):
if bit[0] != bit [1]: #count the number of bits that a different
diffs += 1
dbit = idx
if diffs >1:break
if diffs ==1: #if exactly 1 bit is different between the two, they can be compressed together
newPatterns.append(p1[:dbit]+'-'+p1[dbit+1:])
matched+=[x,x+y]
break
if x not in matched: newPatterns.append(p1) #if the pattern wasn't matched, just append it as is.
if matched: #if reductions occured on this run, then call again to check if more are possible.
newPatterns = reducePatterns(newPatterns)
return newPatterns
有没有人对更好/更有效的方法提出建议?
更有效地循环/使用迭代器?Regex魔术?我丢失了一些位操作包?至少可读性更高一点?您需要的是Python实现
一个快速的谷歌把我带到了这个页面我还没有完全测试过(它使用递归的方式可能不是很有效),但它似乎很有效,至少满足了你的“更可读”标准:
from itertools import combinations
def collapse(binaries):
result = set(binaries)
for b1, b2 in combinations(result, 2):
for i in range(len(b1)):
if b1[:i] + b1[i+1:] == b2[:i] + b2[i+1:]:
merged = "-".join([b1[:i], b1[i+1:]])
return sorted(collapse(result ^ {b1, b2, merged}))
return sorted(result)
示例:
>>> collapse(['1100', '1000', '0100', '0000', '1111', '1011', '0111', '0011'])
['--00', '--11']
>>> collapse(["00", "01", "10", "11"])
['--']
>>> collapse(["011", "101", "111"])
['-11', '101']
嗯。。。从技术上讲,您可以使用
---
:P@Doorknob,这将匹配所有16个可能的4位字符串,但在给定的列表中只有8个。对于第二个示例?不完全是这样,因为'-'
也会包含像'1110'
这样不在原始集合中的东西。我也有同样的问题。我尝试了你的代码,但它没有100%正确地完成工作。例如:reducePatterns(['1100','1000','0100','0000','1111','1011','0111','0011'])
给我输出:['10--','1100']
。但是它应该是['10--','1_00']
我想写的:reducePatterns(['1000','1010','1100','1001','1011'])整洁。我想我应该想到这个过程有一个正式的名字,但是我不可能自己偶然发现它。看起来肯定更好,我肯定会借用你的一些想法。我不得不同意你做递归的方式,但是…那里有很多浪费的工作。我也有同样的问题。我尝试了你的代码,但它没有100%正确地完成工作。例如:collapse(['1100','1000','0100','0000','1111','1011','0111','0011'])
给我输出:['10--','1100']
。但是它应该是['10--','100']
,否则你的代码很短而且看起来很好。我不知道你的代码是怎么做的,但也许你知道错误可能是什么?@HighwayJohn你在评论中粘贴了错误的输入了吗?您展示的是我的答案中的一个示例,并且(一旦缺少的引号被修复)继续正确地为我返回['-00','-11']
。哦,您是对的。我想写:collapse(['1000','1010','1100','1001','1011'])
那么,['10--','1100']
就是这个输入的正确表示<代码>['10--','1-00']导致'1000'
被表示两次。