'leet' 程序 - 获取所有排列
'leet' program - getting all permutations
我编写了一个简单的函数,可以将单词中的字母转换为 'leet' 对应的数字。
def Leet(word):
letters = list(word.lower())
for n, letter, in enumerate(letters):
if letter == 'o':
letters[n]= '0'
elif letter == 'i':
letters[n]= '1'
elif letter == 'z':
letters[n]= '2'
elif letter == 'e':
letters[n]= '3'
elif letter == 'a':
letters[n]= '4'
elif letter == 's':
letters[n]= '5'
elif letter == 'g':
letters[n]= '6'
elif letter == 't':
letters[n]= '7'
elif letter == 'b':
letters[n]= '8'
return ''.join(letters)
所以当我输入 'zit'
时,程序将 return '217'
。
我的问题是,如何更改它以提供所有可能的排列('217'
、'2it'
、'z1t'
、'zi7'
、'21t'
, ETC。)?我读过 itertools
但我对如何将它应用到我的函数感到困惑。
使用itertools.product
。此外,我建议使用 dict
进行映射,而不是 if/elif
.
的级联
>>> from itertools import product
>>> LEET = { 'z': '2', 'i': '1', 't': '7' } # and all the others
>>> word = "zit"
>>> [''.join(letters) for letters in product(*({c, LEET.get(c, c)} for c in word))]
['zit', 'zi7', 'z1t', 'z17', '2it', '2i7', '21t', '217']
注意LEET.get(c, c)
会从dict中获取"leet"字母,或者默认使用原始字母。 {...}
用于制作这些对集,因此没有重复的字母没有替换。在 Python 的旧版本中,您可能必须改用 set([...])
。
那条相当复杂的 product(*...)
行大致如下所示:
product(*({c, LEET.get(c, c)} for c in 'zit'))
==> product(*({'z', LEET.get('z', 'z')}, {'i', LEET.get('i', 'i')}, {'t', LEET.get('t', 't')}))
==> product(*({'z', '2'}, {'i', '1'}, {'t', '7'}))
==> product( {'z', '2'}, {'i', '1'}, {'t', '7'} )
生成所有这些字母及其替换的 cartesian product。
一种方法是使用 itertools.product,正如您提到的,它将执行列表的笛卡尔积。
问题是要有每个组合的这个列表,例如对于 zit,列表应该是:
[['z', '2'], ['i', '1'], ['t', '7']]
我的代码:
import itertools
def leet(word):
leet_matches = [['a', '4'],
['b' ,'8'],
['c'],
['d'],
['e', '3'],
['f'],
['g', '6'],
['h'],
['i', '1'],
['j'],
['k'],
['l'],
['m'],
['n'],
['o', '0'],
['p'],
['q'],
['r'],
['s', '5'],
['t', '7'],
['u'],
['v'],
['w'],
['x'],
['y'],
['z', '2']]
l = []
for letter in word:
for match in leet_matches:
if match[0] == letter:
l.append(match)
return list(itertools.product(*l))
print leet("zit")
请注意,使用列表(或元组)的列表而不是 Dict 允许您对一个字母进行多次替换,例如"i"可以变成“1”或“!”
首先观察到您可以缩短查找时间,如下所示:
REPLACE = { letter: str(index) for index, letter in enumerate('oizeasgtb') }
def Leet2(word):
letters = [ REPLACE.get(l, l) for l in word.lower() ]
return ''.join(letters)
REPLACE
看起来像:
{'a': '4', 'b': '8', 'e': '3', 'g': '6', 'i': '1',
'o': '0', 's': '5', 't': '7', 'z': '2'}
REPLACE.get(l,l)
返回替换字母,如果没有替换字母,则返回原始字母。
第二个观察结果是您真的不需要排列,排列是顺序的变化。 '217'的排列是:
>>> [ ''.join(p) for p in permutations('217') ]
['217', '271', '127', '172', '721', '712']
您真正需要的是一个列表的产品,该列表对给定字符位置的所有可能选择进行编码:
[('z', '2'), ('i', '1'), ('t', '7')]
如果我还展示了一个可能的列表,其中包含一些没有有效替换的字符,那么它的工作原理可能会更清楚。对于 'red'
例如:
[('r',), ('e', '3'), ('d',)]
现在我们需要这些选项的字符串连接乘积。把它们放在一起:
from itertools import product
def Leet2Combos(word):
possibles = []
for l in word.lower():
ll = REPLACE.get(l, l)
possibles.append( (l,) if ll == l else (l, ll) )
return [ ''.join(t) for t in product(*possibles) ]
print Leet2Combos('zit')
print Leet2Combos('red')
给出:
['zit', 'zi7', 'z1t', 'z17', '2it', '2i7', '21t', '217']
['red', 'r3d']
我编写了一个简单的函数,可以将单词中的字母转换为 'leet' 对应的数字。
def Leet(word):
letters = list(word.lower())
for n, letter, in enumerate(letters):
if letter == 'o':
letters[n]= '0'
elif letter == 'i':
letters[n]= '1'
elif letter == 'z':
letters[n]= '2'
elif letter == 'e':
letters[n]= '3'
elif letter == 'a':
letters[n]= '4'
elif letter == 's':
letters[n]= '5'
elif letter == 'g':
letters[n]= '6'
elif letter == 't':
letters[n]= '7'
elif letter == 'b':
letters[n]= '8'
return ''.join(letters)
所以当我输入 'zit'
时,程序将 return '217'
。
我的问题是,如何更改它以提供所有可能的排列('217'
、'2it'
、'z1t'
、'zi7'
、'21t'
, ETC。)?我读过 itertools
但我对如何将它应用到我的函数感到困惑。
使用itertools.product
。此外,我建议使用 dict
进行映射,而不是 if/elif
.
>>> from itertools import product
>>> LEET = { 'z': '2', 'i': '1', 't': '7' } # and all the others
>>> word = "zit"
>>> [''.join(letters) for letters in product(*({c, LEET.get(c, c)} for c in word))]
['zit', 'zi7', 'z1t', 'z17', '2it', '2i7', '21t', '217']
注意LEET.get(c, c)
会从dict中获取"leet"字母,或者默认使用原始字母。 {...}
用于制作这些对集,因此没有重复的字母没有替换。在 Python 的旧版本中,您可能必须改用 set([...])
。
那条相当复杂的 product(*...)
行大致如下所示:
product(*({c, LEET.get(c, c)} for c in 'zit'))
==> product(*({'z', LEET.get('z', 'z')}, {'i', LEET.get('i', 'i')}, {'t', LEET.get('t', 't')}))
==> product(*({'z', '2'}, {'i', '1'}, {'t', '7'}))
==> product( {'z', '2'}, {'i', '1'}, {'t', '7'} )
生成所有这些字母及其替换的 cartesian product。
一种方法是使用 itertools.product,正如您提到的,它将执行列表的笛卡尔积。
问题是要有每个组合的这个列表,例如对于 zit,列表应该是:
[['z', '2'], ['i', '1'], ['t', '7']]
我的代码:
import itertools
def leet(word):
leet_matches = [['a', '4'],
['b' ,'8'],
['c'],
['d'],
['e', '3'],
['f'],
['g', '6'],
['h'],
['i', '1'],
['j'],
['k'],
['l'],
['m'],
['n'],
['o', '0'],
['p'],
['q'],
['r'],
['s', '5'],
['t', '7'],
['u'],
['v'],
['w'],
['x'],
['y'],
['z', '2']]
l = []
for letter in word:
for match in leet_matches:
if match[0] == letter:
l.append(match)
return list(itertools.product(*l))
print leet("zit")
请注意,使用列表(或元组)的列表而不是 Dict 允许您对一个字母进行多次替换,例如"i"可以变成“1”或“!”
首先观察到您可以缩短查找时间,如下所示:
REPLACE = { letter: str(index) for index, letter in enumerate('oizeasgtb') }
def Leet2(word):
letters = [ REPLACE.get(l, l) for l in word.lower() ]
return ''.join(letters)
REPLACE
看起来像:
{'a': '4', 'b': '8', 'e': '3', 'g': '6', 'i': '1',
'o': '0', 's': '5', 't': '7', 'z': '2'}
REPLACE.get(l,l)
返回替换字母,如果没有替换字母,则返回原始字母。
第二个观察结果是您真的不需要排列,排列是顺序的变化。 '217'的排列是:
>>> [ ''.join(p) for p in permutations('217') ]
['217', '271', '127', '172', '721', '712']
您真正需要的是一个列表的产品,该列表对给定字符位置的所有可能选择进行编码:
[('z', '2'), ('i', '1'), ('t', '7')]
如果我还展示了一个可能的列表,其中包含一些没有有效替换的字符,那么它的工作原理可能会更清楚。对于 'red'
例如:
[('r',), ('e', '3'), ('d',)]
现在我们需要这些选项的字符串连接乘积。把它们放在一起:
from itertools import product
def Leet2Combos(word):
possibles = []
for l in word.lower():
ll = REPLACE.get(l, l)
possibles.append( (l,) if ll == l else (l, ll) )
return [ ''.join(t) for t in product(*possibles) ]
print Leet2Combos('zit')
print Leet2Combos('red')
给出:
['zit', 'zi7', 'z1t', 'z17', '2it', '2i7', '21t', '217']
['red', 'r3d']