· 6 years ago · Jul 09, 2019, 06:14 AM
1def permute(n, chars='01', limit=128, start=0):
2 appended = 0
3 counter = 0
4
5 def f(s, a):
6 nonlocal appended
7 nonlocal counter
8 if appended == limit:
9 return a
10 if len(s) == n:
11 if counter >= start:
12 a.append(s)
13 appended += 1
14 counter += 1
15 return a
16
17 for char in chars:
18 a = f(s+char, a)
19
20 return a
21
22 return f('', [])
23
24# 7-bit values, starting at 16
25# >>> permute(7, limit=4, start=16)
26# ['0010000', '0010001', '0010010', '0010011']
27
28# Some web colors, starting at "magenta" (:)blue (ff), no green (00), red (ff))
29# >>> permute(6, '0123456789abcdef', limit=10, start=16711935)
30# ['ff00ff', 'ff0100', 'ff0101', 'ff0102', 'ff0103',
31# 'ff0104', 'ff0105', 'ff0106', 'ff0107', 'ff0108']
32
33# And the encoding that started it all, punctuation for mixing into Gmail names:
34# >>> puncs = permute(6, '. ', limit=2, start=40)
35# >>> puncs
36# [' . ...', ' . .. ']
37# >>> zips = [list(zip([x for x in 'mytest'], [x for x in punc])) for punc in puncs]
38# >>> zips
39# [
40# [('m', ' '), ('y', '.'), ('t', ' '), ('e', '.'), ('s', '.'), ('t', '.')],
41# [('m', ' '), ('y', '.'), ('t', ' '), ('e', '.'), ('s', '.'), ('t', ' ')]
42# ]
43# >>> [[''.join(y).strip() for y in x] for x in zips]
44# [['m', 'y.', 't', 'e.', 's.', 't.'], ['m', 'y.', 't', 'e.', 's.', 't']]
45# >>> [''.join([''.join(y).strip() for y in x]) + '@gmail.com' for x in zips]
46# ['my.te.s.t.@gmail.com', 'my.te.s.t@gmail.com']
47
48
49# Hey, still making it better!!
50def permute3(n, notation, start=0, count=None, f=None):
51 if notation is 'hex':
52 s = '{:0%dx}' % n
53 base = 16
54
55 if notation is 'bin':
56 s = '{:0%db}' % n
57 base = 2
58
59 if notation is 'oct':
60 s = '{:0%do}' % n
61 base = 8
62
63 space_size = base**n
64
65 if count:
66 end = start+count
67 else:
68 end = space_size
69
70 assert end <= space_size, \
71 'Start + count (%d) exceeds size of the encoded space (%d**%d = %d)' % (
72 end, base, n, space_size)
73
74 if not f:
75 f = s.format
76
77 return [f(i) for i in range(start, end)]
78
79# Web colors
80# >>> permute3(6, 'hex', start=16711935, limit=10)
81# ['ff00ff', 'ff0100', 'ff0101', 'ff0102', 'ff0103', 'ff0104', 'ff0105', 'ff0106', 'ff0107', 'ff0108']
82
83# 7-bit values, starting at 16
84# >>> permute3(7, 'bin', start=16, limit=10)
85# ['0010000', '0010001', '0010010', '0010011', '0010100', '0010101', '0010110', '0010111', '0011000', '0011001']
86
87# Same as above, but with a custom func to effect the 'punctuation encoding'; have to ensure the padding value in `{:07b}`
88# matches the `n` param in `permute3(7...`
89# >>> punc_func = lambda x: '{:07b}'.format(x).replace('0',' ').replace('1','.')
90# >>> punc_func(31)
91# ' .....'
92# >>> punc_func(63)
93# '......'
94# >>> permute3(7, 'bin', start=16, limit=10, f=punc_func)
95# [' . ', ' . .', ' . . ', ' . ..', ' . . ', ' . . .', ' . .. ', ' . ...', ' .. ', ' .. .']
96# ['0010000', '0010001', '0010010', '0010011', '0010100', '0010101', '0010110', '0010111', '0011000', '0011001']