我确信这很简单,但我很难想办法做到这一点。基本上如果我有一个P柱和V ^ P行的数组,我怎样才能填写所有组合,即基本上是P数字基数V中所有可能的数字。例如,对于P = 3和V = 2:
000
001
010
011
100
101
110
111
请记住,这是一个二维数组,而不是一个整数数组。
P = 4且V = 3。
0000
0001
0002
0010
0011
0012
....
生成这个数组后,我正在尝试开发的其余工作是微不足道的。因此,非常感谢有关如何执行此操作的一些代码/提示。感谢。
答案 0 :(得分:1)
基本上,这是从0到基数p
中最大的数字宽度v
的v p 个数字的列表。 numpy.base_repr
可用于在Python中执行此操作:
from numpy import base_repr
def base_of_size(base, size):
for i in range(base ** size):
yield base_repr(i, base).rjust(size, "0")
另外,itertools.product(range(v), repeat=p)
是另一个完成此任务的Python内置程序(结果效率最高-参见下面的基准)。
这是将numpy.base_repr
中的算法转换为C#(Convert.ToString()
对基数的选择非常严格):
using System;
using System.Collections.Generic;
class Converter
{
public static IEnumerable<string> BaseOfSize(int baseN, int size)
{
for (int i = 0; i < Math.Pow(baseN, size); i++)
{
yield return BaseRepr(i, baseN).PadLeft(size, '0');
}
}
public static string BaseRepr(int n, int baseN)
{
string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var res = new List<char>();
for (int num = Math.Abs(n); num > 0; num /= baseN)
{
res.Add(digits[num%baseN]);
}
if (n < 0) res.Add('-');
res.Reverse();
return string.Join("", res);
}
public static void Main(string[] args)
{
foreach (var n in BaseOfSize(2, 3))
{
Console.WriteLine(n);
}
Console.WriteLine();
foreach (var n in BaseOfSize(3, 4))
{
Console.WriteLine(n);
}
}
}
输出:
000
001
010
011
100
101
110
111
0000
0001
0002
0010
0011
0012
0020
...
2220
2221
2222
尽管numpy版本易于使用且可迭代,但它也很慢。使用递归DFS方法意味着我们不必从头开始计算每个数字,而可以简单地递增之前的数字,直到到达新的叶子为止。这些版本不使用生成器,但这是一个简单的调整:
Python:
def base_of_size(base, size):
def recurse(res, row, i=0):
if i >= size:
res.append(row[:])
else:
for j in range(base):
row[i] = j
recurse(res, row, i + 1)
return res
return recurse([], [None] * size)
C#:
using System;
using System.Collections.Generic;
class Converter
{
public static List<List<int>> BaseOfSize(int v, int p)
{
var res = new List<List<int>>();
BaseOfSize(v, p, 0, new List<int>(new int[p]), res);
return res;
}
private static void BaseOfSize(int v, int p, int i, List<int> row, List<List<int>> res)
{
if (i >= p)
{
res.Add(new List<int>(row));
}
else
{
for (int j = 0; j < v; j++)
{
row[i] = j;
BaseOfSize(v, p, i + 1, row, res);
}
}
}
}
快速基准测试(带有生成器):
from itertools import product
from time import time
from numpy import base_repr
def base_of_size(base, size):
def recurse(res, row, i=0):
if i >= size:
yield row[:]
else:
for j in range(base):
row[i] = j
yield from recurse(res, row, i + 1)
return res
yield from recurse([], [None] * size)
def base_of_size2(base, size):
for i in range(base ** size):
yield base_repr(i, base).rjust(size, "0")
if __name__ == "__main__":
start = time()
list(base_of_size(10, 6))
end = time()
print("dfs:", end - start)
start = time()
list(base_of_size2(10, 6))
end = time()
print("base_repr:", end - start)
start = time()
list(product(range(10), repeat=6))
end = time()
print("product:", end - start)
输出:
dfs: 4.616123676300049
base_repr: 9.795292377471924
product: 0.5925478935241699
itertools.product
以远射获胜。
答案 1 :(得分:0)
以P = 3和V = 2为例,在第一列中需要这个数字序列:
0, 0, 0, 0, 1, 1, 1, 1
所以你基本上想要四个0,然后是四个1。
在第二栏中,您需要:
0, 0, 1, 1, 0, 0, 1, 1
所以你想要两个0,然后是两个1,然后又一个。
通常,在列号n中,您需要每个数字的V ^(P-n),重复V ^(n-1)次。
当P = 3且V = 2时的示例:
第1列:我们需要每个数字的V ^(P-n)= 2 ^(3-1)= 4,重复V ^(n-1)= 2 ^ 0 = 1次:
[0, 0, 0, 0, 1, 1, 1, 1]
第2列:我们需要每个数字的V ^(P-n)= 2 ^(3-2)= 2,重复V ^(n-1)= 2 ^ 1 = 2次:
[0, 0, 1, 1], [0, 0, 1, 1]
第3列:我们需要每个数字的V ^(P-n)= 2 ^(3-3)= 1,重复V ^(n-1)= 2 ^ 2 = 4次:
[0, 1], [0, 1], [0, 1], [0, 1]
生成此序列的一些Python代码:
def sequence(v, p, column):
subsequence = []
for i in range(v):
subsequence += [i] * v**(p - column)
return subsequence * v**(column - 1)
答案 2 :(得分:0)
如果每个“数字”中有不同数量的选项,则可以使用此代码。
也许在某些优化工具中存在执行此操作的算法,因为它可能对蛮力方法很有用。下面的代码添加了一个列,显示“最大位数”,可以忽略:
import numpy as np
val=np.arange(15)
options=[2,2,3]
print(val)
print(options)
opt = options + [1] # Assumes options to be a list
opt_cp = np.flip(np.cumprod(np.flip(np.array(opt))))
ret = np.floor_divide(val[:,np.newaxis], opt_cp[np.newaxis,:])
ret[:,1:] = np.remainder(ret[:,1:], np.array(opt[:-1])[np.newaxis,:])
inds = ret[:,1:]
print(inds)
答案 3 :(得分:0)
您也可以使用 numpy 的 N 维网格函数。
例如
np.mgrid[0:2,0:2,0:2].reshape((3, 8)).T
array([[0, 0, 0],
[0, 0, 1],
[0, 1, 0],
[0, 1, 1],
[1, 0, 0],
[1, 0, 1],
[1, 1, 0],
[1, 1, 1]])
或
np.stack(np.meshgrid(range(2), range(2), range(2), indexing='ij')).reshape(3, -1).T
或一般对于任何 P
、V
:
np.mgrid[[slice(0, V)]*P].reshape((P, -1)).T
或
np.stack(np.meshgrid(*[range(V)]*P, indexing='ij')).reshape((P, -1)).T
一定有更明显的方法,但我想不出是什么。