Python - enumerate a multidimensional list - python

Let's say I have a multidimensional array, foobar:
foobar = [[[0, 1, 2],
[3, 4, 5, 6],
[7, 8]],
[[9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18],
[19, 20, 21, 22]],
[[23, 24, 25],
[26, 27]]]
Note that foobar is jagged.
The thing I need to do is replace each number in foobar with a tuple containing that number and its exact position in foobar. I also need to be able to do this when the number of dimensions and whether or not foobar is jagged is unknown.
Here is something similar, except it only works for 2 dimensions:
def enum_multidim(data):
for i, a in enumerate(data):
for j, b in enumerate(a):
yield (i, j, b)
Is there a user-defined function that can do what I said above?

Recursive generator for an arbitrary number of dimensions
Code
def enum_multidim(data, t = None):
if t is None:
t = ()
if not isinstance(data, list):
yield t + (data,)
else:
for i, v in enumerate(data):
yield from enum_multidim(v, t + (i,))
Test
for t in enum_multidim(foobar):
print(t)
# Out:
(0, 0, 0, 0)
(0, 0, 1, 1)
(0, 0, 2, 2)
(0, 1, 0, 3)
(0, 1, 1, 4)
(0, 1, 2, 5)
(0, 1, 3, 6)
(0, 2, 0, 7)
(0, 2, 1, 8)
(1, 0, 0, 9)
(1, 0, 1, 10)
(1, 1, 0, 11)
(1, 1, 1, 12)
(1, 1, 2, 13)
(1, 1, 3, 14)
(1, 1, 4, 15)
(1, 2, 0, 16)
(1, 2, 1, 17)
(1, 2, 2, 18)
(1, 3, 0, 19)
(1, 3, 1, 20)
(1, 3, 2, 21)
(1, 3, 3, 22)
(2, 0, 0, 23)
(2, 0, 1, 24)
(2, 0, 2, 25)
(2, 1, 0, 26)
(2, 1, 1, 27)

So, I saw DarryIG's answer and modified it to fit my style:
def get_dims(data): # some other function I use
if not isinstance(data, itertypes):
return 0
return get_dims(data[0]) + 1
def enum_multidim(data, index = []):
if get_dims(data) == 0:
return index + [data]
return [enum_multidim(x, index + [i]) for i, x in enumerate(data)]
Credit will go to him. Thanks so much!

Related

All combinations in a 2d Numpy

I am trying to modify the code provided as answer by Hilberts in below question to allow it for multiple values and not only binary.
All binary combinations in a 2d Numpy
So, rather than only allow 0 and 1 like in the previous example, i would like find all combinations without rotations for data like 0, 1, 2 and 3 .
I modified it in this way, mainly replacing the "2" in the original code by a variable and tried to replace it by the variable "m" to follow the initial formula. But I think the issue here is related to the numpy type of data "bitwise_and" . Does anyone have any advices about what would be problem or any hint?
def get_binary_mats(n,m):
# all possible n by n binary matrices up to rotation:
bin_mats = (np.bitwise_and(np.arange(m**(n*n))[:,None], m ** np.arange(n*n)) > 0)\
.reshape(-1, n, n)
# define a score for each matrix based on position of ones
score = m ** np.arange(n*n).reshape(n,n)
# array([[ 1, 2, 4],
# [ 8, 16, 32],
# [ 64, 128, 256]])
score_arr = np.stack([np.rot90(score, k=k) for k in range(4)])
# array([[[ 1, 2, 4],
# [ 8, 16, 32],
# [ 64, 128, 256]],
# [[ 4, 32, 256],
# [ 2, 16, 128],
# [ 1, 8, 64]],
# [[256, 128, 64],
# [ 32, 16, 8],
# [ 4, 2, 1]],
# [[ 64, 8, 1],
# [128, 16, 2],
# [256, 32, 4]]])
scores = np.einsum("ijk,ljk->il", bin_mats, score_arr)
_, idx = np.unique(scores.min(1), return_index=True)
return bin_mats[idx,...]
Thank you
from itertools import combinations_with_replacement as combn
list(combn([0,1,2,3], 4))
[(0, 0, 0, 0),
(0, 0, 0, 1),
(0, 0, 0, 2),
(0, 0, 0, 3),
(0, 0, 1, 1),
(0, 0, 1, 2),
(0, 0, 1, 3),
(0, 0, 2, 2),
(0, 0, 2, 3),
(0, 0, 3, 3),
(0, 1, 1, 1),
(0, 1, 1, 2),
(0, 1, 1, 3),
(0, 1, 2, 2),
(0, 1, 2, 3),
(0, 1, 3, 3),
(0, 2, 2, 2),
(0, 2, 2, 3),
(0, 2, 3, 3),
(0, 3, 3, 3),
(1, 1, 1, 1),
(1, 1, 1, 2),
(1, 1, 1, 3),
(1, 1, 2, 2),
(1, 1, 2, 3),
(1, 1, 3, 3),
(1, 2, 2, 2),
(1, 2, 2, 3),
(1, 2, 3, 3),
(1, 3, 3, 3),
(2, 2, 2, 2),
(2, 2, 2, 3),
(2, 2, 3, 3),
(2, 3, 3, 3),
(3, 3, 3, 3)]

Find all permutations of numbers of exactly 9 characters long

I have the numbers [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 12, 15, 16].
I want to find all permutations of numbers of exactly 9 characters. For example, if I have 8 single digit numbers, the last one can't be a double digit, because it would exceed the character limit.
Clarifications:
The same number can be reused, so for example the number 1 nine times is valid.
There can be any number of double digit numbers, as long as the total character length of the digits is exactly 9. For example, 1, 10, 12, 15, 16 is valid.
I tried itertools.permutations, but I couldn't get it to work with two-digit numbers.
I would use a mixture of combination and permutations.
First find all of the combinations of the data which add up to the desired length. Then for each unique combination, find their permutations. There's probably some work to be done here which can limit the amount of incorrect combinations checked:
import itertools
def perm_of_length(data, length):
for i in range(len(data)):
for comb in itertools.combinations(data, i + 1):
if sum(map(len, (map(str, comb)))) == length:
for perm in itertools.permutations(comb):
yield perm
for perm in perm_of_length([0, 1, 2, 3, 10, 12], 4):
print(perm)
Outputs:
(10, 12)
(12, 10)
(0, 1, 10)
(0, 10, 1)
(1, 0, 10)
(1, 10, 0)
(10, 0, 1)
(10, 1, 0)
(0, 1, 12)
(0, 12, 1)
(1, 0, 12)
(1, 12, 0)
(12, 0, 1)
(12, 1, 0)
(0, 2, 10)
(0, 10, 2)
(2, 0, 10)
(2, 10, 0)
(10, 0, 2)
(10, 2, 0)
(0, 2, 12)
(0, 12, 2)
(2, 0, 12)
(2, 12, 0)
(12, 0, 2)
(12, 2, 0)
(0, 3, 10)
(0, 10, 3)
(3, 0, 10)
(3, 10, 0)
(10, 0, 3)
(10, 3, 0)
(0, 3, 12)
(0, 12, 3)
(3, 0, 12)
(3, 12, 0)
(12, 0, 3)
(12, 3, 0)
(1, 2, 10)
(1, 10, 2)
(2, 1, 10)
(2, 10, 1)
(10, 1, 2)
(10, 2, 1)
(1, 2, 12)
(1, 12, 2)
(2, 1, 12)
(2, 12, 1)
(12, 1, 2)
(12, 2, 1)
(1, 3, 10)
(1, 10, 3)
(3, 1, 10)
(3, 10, 1)
(10, 1, 3)
(10, 3, 1)
(1, 3, 12)
(1, 12, 3)
(3, 1, 12)
(3, 12, 1)
(12, 1, 3)
(12, 3, 1)
(2, 3, 10)
(2, 10, 3)
(3, 2, 10)
(3, 10, 2)
(10, 2, 3)
(10, 3, 2)
(2, 3, 12)
(2, 12, 3)
(3, 2, 12)
(3, 12, 2)
(12, 2, 3)
(12, 3, 2)
(0, 1, 2, 3)
(0, 1, 3, 2)
(0, 2, 1, 3)
(0, 2, 3, 1)
(0, 3, 1, 2)
(0, 3, 2, 1)
(1, 0, 2, 3)
(1, 0, 3, 2)
(1, 2, 0, 3)
(1, 2, 3, 0)
(1, 3, 0, 2)
(1, 3, 2, 0)
(2, 0, 1, 3)
(2, 0, 3, 1)
(2, 1, 0, 3)
(2, 1, 3, 0)
(2, 3, 0, 1)
(2, 3, 1, 0)
(3, 0, 1, 2)
(3, 0, 2, 1)
(3, 1, 0, 2)
(3, 1, 2, 0)
(3, 2, 0, 1)
(3, 2, 1, 0)
Proof this works:
for perm in perm_of_length([0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 12, 15, 16], 9):
assert sum(map(len, map(str, perm))) == 9
NOTE: this is much slower than it needs to be.
A simple, non-performant, brute-force approach with filtering:
symbols = [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 12, 15, 16]
symbols = [str(x) for x in symbols]
perms = itertools.chain.from_iterable(
itertools.permutations(symbols, i) for i in range(10)
)
perms = ("".join(x) for x in perms)
perms = [x for x in perms if len(x) <= 9]
>>> len(perms)
13600046
>>> perms[:4]
['', '0', '1', '2']
>>> perms[-4:]
['987643102', '987643120', '987643201', '987643210']
One can drop the empty string by simply skipping the first item in perms.
A similar approach which does not use strings:
symbols = [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 12, 15, 16]
lengths = {k: int(math.log10(k)) + 1 if k != 0 else 1 for k in symbols}
perms = itertools.chain.from_iterable(
itertools.permutations(symbols, i) for i in range(10)
)
perms = [x for x in perms if sum(lengths[k] for k in x) <= 9]
>>> len(perms)
13600046
If numbers can be reused (as mentioned in the comments), I would consider itertools.product instead of itertools.permutations:
symbols = [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 12, 15, 16]
lengths = {k: int(math.log10(k)) + 1 if k != 0 else 1 for k in symbols}
perms = itertools.product(symbols, repeat=9)
perms = [x for x in perms if sum(lengths[k] for k in x) <= 9]

How can I do "recursive" for loops in this coin change problem?

Im trying to solve the coin change problem. You get an amount of money (as example 55 cents) and have to give as few coins as possible back.
My solution is very simple (and probably extremely inefficient). I tried to do it with brute force.
First I tried to do it with fixed coins which are hardcoded and it worked great
money = 55
def findMinCoins(money):
nq = int(money/25)
nd = int(money/10)
nc = int(money/1)
smallest = nq + nd + nc
for q in range(nq+1):
for d in range(nd+1):
for c in range(nc+1):
if q*25 + d*10 + c == money:
if q + d + c < smallest:
smallest = q + d + c
print(q, d, c)
return smallest
After that I tried to do it with an coins array such as coins = [25, 10, 1] and there is my question.
coins = [25, 10, 1]
def findMinCoins(money, coins):
n_coins = [(int(money/coin) for coin in coins)]
smallest = sum(n_coins)
I don't know how I should do the for loops with the arrays. Can somebody help me to find a solution?
You can make recursive calls with each of the coins deducted from the current money, and get the minimum value from the returning value of the calls. Return infinity if the deduction results in money less than 0 so that it would not be considered to be viable:
def findMinCoins(money, coins):
if money < 0:
return float('inf')
return money and min(findMinCoins(money - coin, coins) for coin in coins) + 1
so that:
findMinCoins(55, [25, 10, 1])
returns:
4
The above recursion is slow, however, since it makes a large number of calls with the same amount of money when considering different paths. You can improve the performance dramatically by using a dict as a cache to memoize the results of a given combination of money amount and coins :
def findMinCoins(money, coins, cache={}):
key = money, tuple(coins)
if key in cache:
return cache[key]
if money < 0:
number = float('inf')
else:
number = money and min(findMinCoins(money - coin, coins) for coin in coins) + 1
cache[key] = number
return number
Literally re-writing your for loops:
>>> money=55
>>> lst=[(q+d+c, [q,d,c]) for q in range(int(money/25)+1) for d in range(int(money/10)+1) for c in range(int(money/1)+1) if q*25 + d*10 + c == money]
>>> lst
[(55, [0, 0, 55]), (46, [0, 1, 45]), (37, [0, 2, 35]), (28, [0, 3, 25]), (19, [0, 4, 15]), (10, [0, 5, 5]), (31, [1, 0, 30]), (22, [1, 1, 20]), (13, [1, 2, 10]), (4, [1, 3, 0]), (7, [2, 0, 5])]
Then to find best fit:
>>> list(filter(lambda x: x[0]==min(el[0] for el in lst), lst))
[(4, [1, 3, 0])]
-------------EDIT
To generalize the solution:
>>> import itertools
>>> money=55
>>> coins=[25,10,1]
>>> lst=[(len(el), el) for num in range(1, money//min(coins)+1) for el in itertools.combinations_with_replacement(coins, num) if sum(el) == money]
>>> lst
[(4, (25, 10, 10, 10)), (7, (25, 25, 1, 1, 1, 1, 1)), (10, (10, 10, 10, 10, 10, 1, 1, 1, 1, 1)), (13, (25, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), (19, (10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), (22, (25, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), (28, (10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), (31, (25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), (37, (10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), (46, (10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), (55, (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))]
>>> list(filter(lambda x: x[0]==min(el[0] for el in lst), lst))
[(4, (25, 10, 10, 10))]
The above is very general, and for your problem, especially that you have 1 cent among your coins - you might want to reduce number of calculation greatly by replacing cap on potential number of coins from money//min(coins)+1 to any other positive integer.
For example:
>>> coins=[1,2,5,25,50]
>>> money=100
>>> lst=[(len(el), el) for num in range(1, 5) for el in itertools.combinations_with_replacement(coins, num) if sum(el) == money]
>>> lst
[(2, (50, 50)), (3, (25, 25, 50)), (4, (25, 25, 25, 25))]
>>> list(filter(lambda x: x[0]==min(el[0] for el in lst), lst))
[(2, (50, 50))]
There may be a more pythonic way to do this, but the general recursive approach is to do this:
Take the amount of money remaining
Try a recursive calls for each coin that reduces the amount without going negative.
Take the smallest result of that set
def findMinCoins(money, coins):
if money <= 0:
return 0
results = []
for c in coins:
if money >= c:
results.append(1 + findMinCoins(money-c, coins))
results.sort()
return results[0] #return the smallest result
Now the only issue with the above is that it's VERY SLOW because it will make a lot of redundant calls for values that were previously computed. So we'll amend that to have a lookup table for each final result and have that passed recursively as well.
def findMinCoins(money, coins, lookup):
if money <= 0:
return 0
if money in lookup:
return lookup[money]
results = []
for c in coins:
if money >= c:
results.append(1 + findMinCoins(money-c, coins, lookup))
results.sort()
best = results[0]
lookup[money] = best
return best
Testing out some examples:
>>> findMinCoins(95,[25,10,5,1], {})
5
>>> findMinCoins(4,[25,10,5,1], {})
4
>>> findMinCoins(44,[25,10,5,1], {})
7

Python: how do I create a list of combinations from a series of ranges of numbers

For a list of numerical values of n length, e. g. [1, 3, 1, 2, ...], I would like to create a list of the lists of all possible combinations of values from range[x+1] where x is a value from the list. The output might look something like this:
for list[1, 3, 2] return all possible lists of range[x+1] values:
# the sequence of the list is unimportant
[
[0,0,0],[1,0,0],[0,1,0],[0,2,0],[0,3,0],[0,0,1],[0,0,2],[1,1,0],
[1,2,0],[1,3,0],[1,0,1],[1,0,2],[0,1,1],[0,2,1],[0,3,1],[0,1,2],
[0,2,2],[0,3,2],[1,1,1],[1,2,1],[1,3,1],[1,1,2],[1,2,2],[1,3,2]
]
So in this example I am looking for all variations of [e1, e2, e3] from e1 in [0,1], e2 in [0,1,2,3] and e3 in [0,1,2]
Use itertools.product with a dynamically-specified list of iterators:
vals = [1,3,2]
for item in itertools.product(*[range(x+1) for x in vals]):
print item
Output:
(0, 0, 0)
(0, 0, 1)
(0, 0, 2)
(0, 1, 0)
(0, 1, 1)
(0, 1, 2)
(0, 2, 0)
(0, 2, 1)
(0, 2, 2)
(0, 3, 0)
(0, 3, 1)
(0, 3, 2)
(1, 0, 0)
(1, 0, 1)
(1, 0, 2)
(1, 1, 0)
(1, 1, 1)
(1, 1, 2)
(1, 2, 0)
(1, 2, 1)
(1, 2, 2)
(1, 3, 0)
(1, 3, 1)
(1, 3, 2)
Python's itertools module has a tool that does what you need:
import itertools
p = itertools.permutations([0, 1, 2, 3])
p_as_list = list(p)
Edit: As your needs are fairly specific you could benefit from having your own function that does something alike this one: (note I haven't got the implementation down just yet, maybe someone might refine this):
def magic_permutations (*args):
lists = []
larg = len(args)
for i in range(larg):
lists.append([])
i = 0
for nums in args:
for num in nums:
if i >= larg:
i = 0
lists[i].append(num)
i += 1
return lists
Edit: I misunderstood your question the first time, so I'll apologize for that. I'll however leave this be.
To obtain the exact sequence shown in the question (albeit in a different order, but that's not a problem) use this function:
import itertools as it
def combs(lst):
return [list(e) for e in it.product(*(range(x+1) for x in lst))]
The result is as expected:
combs([1, 3, 2])
=> [[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 1, 0], [0, 1, 1], [0, 1, 2],
[0, 2, 0], [0, 2, 1], [0, 2, 2], [0, 3, 0], [0, 3, 1], [0, 3, 2],
[1, 0, 0], [1, 0, 1], [1, 0, 2], [1, 1, 0], [1, 1, 1], [1, 1, 2],
[1, 2, 0], [1, 2, 1], [1, 2, 2], [1, 3, 0], [1, 3, 1], [1, 3, 2]]
for ii in itertools.product(range(2),range(4),range(3):
print ii
(0, 0, 0)
(0, 0, 1)
(0, 0, 2)
(0, 1, 0)
(0, 1, 1)
(0, 1, 2)
(0, 2, 0)
(0, 2, 1)
(0, 2, 2)
(0, 3, 0)
(0, 3, 1)
(0, 3, 2)
(1, 0, 0)
(1, 0, 1)
(1, 0, 2)
(1, 1, 0)
(1, 1, 1)
(1, 1, 2)
(1, 2, 0)
(1, 2, 1)
(1, 2, 2)
(1, 3, 0)
(1, 3, 1)
(1, 3, 2)
It's not in the same order, but I think this is what you wanted:
def xrangeCombinations(input):
if len(input) > 1:
for i in xrange(input[-1] + 1):
for j in xrangeCombinations(input[:-1]):
yield j + [i]
else:
for i in xrange(input[-1] + 1):
yield [i]
for i in xrangeCombinations([1, 3, 2]):
print i
Produces the output:
[0, 0, 0]
[1, 0, 0]
[0, 1, 0]
[1, 1, 0]
[0, 2, 0]
[1, 2, 0]
[0, 3, 0]
[1, 3, 0]
[0, 0, 1]
[1, 0, 1]
[0, 1, 1]
[1, 1, 1]
[0, 2, 1]
[1, 2, 1]
[0, 3, 1]
[1, 3, 1]
[0, 0, 2]
[1, 0, 2]
[0, 1, 2]
[1, 1, 2]
[0, 2, 2]
[1, 2, 2]
[0, 3, 2]
[1, 3, 2]
This solution might be slower than alternatives so if speed is an issue you should probably improve it.
Using numpy if you don't mind getting tuples in the end:
>>> import numpy as np
>>> e1=np.array([0,1])
>>> e2=np.array([0,1,2])
>>> e3=np.array([0,1,2,3])
>>> g=np.meshgrid(e1,e2,e3) #you need numpy ver>1.7.0, change the order of final result by changing the order of e1, e2, e3
>>> zip(*[item.flatten() for item in g])
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 0, 3), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (0, 2, 0), (0, 2, 1), (0, 2, 2), (0, 2, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3)]

python construct a dictionary {0: [0, 0, 0], 1: [0, 0, 1], 2: [0, 0, 2], 3: [0, 0, 3], ...,999: [9, 9, 9]}

I have to construct a dictionary using variables base=10 and digits=set(range(10)) and have to write a comprehension that maps each integer from 0 through 999 to the list of three digits that represents that integer in base 10. That is, the value should be
{0: [0, 0, 0], 1: [0, 0, 1], 2: [0, 0, 2], 3: [0, 0, 3], ...,10: [0, 1, 0], 11: [0, 1, 1], 12: [0, 1, 2], ...,999: [9, 9, 9]}
I am stuck .
I tried something like
{q:[x,y,z] for q in list[range(1000)] for x in digits for y in digits for z in digits}
but the index q should be x * base**2 + y * base**1 + z * base**0
this is not the right way of thinking, any idea?
I would use itertools. For example
dict( (i, tup) for i, tup in enumerate(itertools.product(range(10), repeat=3)) )
If you really require each value to be a list, you can add (i, list(tup)) above.
The product function computes cartesian product, equivalent to a nested for-loop, according to the documentation. For example
In [34]: list(itertools.product(range(3), repeat=3))
Out[34]:
[(0, 0, 0),
(0, 0, 1),
(0, 0, 2),
(0, 1, 0),
(0, 1, 1),
(0, 1, 2),
(0, 2, 0),
(0, 2, 1),
(0, 2, 2),
(1, 0, 0),
(1, 0, 1),
(1, 0, 2),
(1, 1, 0),
(1, 1, 1),
(1, 1, 2),
(1, 2, 0),
(1, 2, 1),
(1, 2, 2),
(2, 0, 0),
(2, 0, 1),
(2, 0, 2),
(2, 1, 0),
(2, 1, 1),
(2, 1, 2),
(2, 2, 0),
(2, 2, 1),
(2, 2, 2)]
product(range(3), repeat=3) is equivalent to product(range(3), range(3), range(3)). The product function accepts *iterables, so the above syntax is valid.
alphabet = range(10)
base = 10
dict((x*base**2+y*base+z,(x,y,z)) for x in alphabet
for y in alphabet
for z in alphabet )
is what you want ... i think
alphabet = range(2)
base = 2
dict((x*base**2+y*base+z,(x,y,z)) for x in alphabet
for y in alphabet
for z in alphabet )
generates
{0: (0, 0, 0), 1: (0, 0, 1), 2: (0, 1, 0), 3: (0, 1, 1), 4: (1, 0, 0), 5: (1, 0, 1), 6: (1, 1, 0), 7: (1, 1, 1)}
You can use divmod to decompose each number:
d = {}
for i in xrange(base**3):
a,b = divmod(i, base**2)
b,c = divmod(b, base)
d[i] = [a,b,c]
Alternately, a constructive solution using the rarely-used reduce function:
from itertools import product
d = {reduce(lambda x,y: base*x+y, p):list(p) for p in product(xrange(base), repeat=3)}
There are a few wrong things in your code:
You use list, which is a type, as an array. Maybe you meant to write list(range(1000))? Just use range(1000).
Your for q in range(1000) is too many: you have a total loop of 1000*10*10*10 instead of a 10*10*10 loop.
Without modifying too much of your code, here is what you should write (by using your code for computing q):
{(x*base**2 + y*base**1 + z*base**0):[x,y,z] for q in list[range(1000)] for x in digits for y in digits for z in digits}
f= lambda x : [int(x/100),int(x/10)%10,x%10]
k={}
for p in xrange(0,1000):
k[p]=f(p)
or even:
d = {x: [int(x/100),int(x/10)%10,x%10] for x in xrange(0,1000)}
What about this:
{x:map(int,str(x).rjust(3,'0')) for x in xrange(1000)}
Here is a nice one-liner:
result = dict((n,['0']*(3-len(str(n))) + list(str(n))) for n in xrange(1000))
This will let you change the base:
import numpy as np
base = 10
nmax = 10
fill = len(np.base_repr(nmax, base=base))
d = {q:map(int, list(np.base_repr(q, base=base).zfill(fill))) for q in range(nmax+1)}
print(d)
str.zfill will left-pad the string result of numpy.base_repr with zeros out to a specified length (fill in my case).
For base=10, nmax=10 (you would want nmax=999).
{0: [0, 0], 1: [0, 1], 2: [0, 2], 3: [0, 3], 4: [0, 4], 5: [0, 5], 6: [0, 6], 7: [0, 7], 8: [0, 8], 9: [0, 9], 10: [1, 0]}
for base=2, nmax=10:
{0: [0, 0, 0, 0], 1: [0, 0, 0, 1], 2: [0, 0, 1, 0], 3: [0, 0, 1, 1], 4: [0, 1, 0, 0], 5: [0, 1, 0, 1], 6: [0, 1, 1, 0], 7: [0, 1, 1, 1], 8: [1, 0, 0, 0], 9: [1, 0, 0, 1], 10: [1, 0, 1, 0]}
Thank you friends, I found a solution, I think the easiest way to figure out something like this since I'm a beginner
base = 10
digits = set(range(10))
dict = {(x*base**2 + y*base**1 + z*base**0):[x,y,z] for x in digits for y in digits for z in digits}
the basic algorithm I'd use would be
for(1->1000)
{
if(x < 10)
insert(x,[0,0,x]))
else if(x<100)
insert(x,[0,x/10,x%10]))
else
insert(x,[x/100,x/10,x%10]))
}

Categories

Resources