算法 - 从必须按顺序选择的项目中生成所有组合

发布于 2024-12-16 19:47:25 字数 1564 浏览 0 评论 0原文

我正在寻找是否已经存在特定的算法。 我想在应用程序中使用它,但我也看到它出现在几个 Project Euler< /a> 也有问题。

我正在计算一种特定类型的排列/输出集,其中选择的下一项必须是仅以下一组中的有限选项集中的一个。

例如,假设我有 3 个数组,

$a1 = array("a", "b", "c");
$a2 = array("d", "e", "f");
$a3 = array("g", "h", "i");

我希望生成一个序列的所有可能性,其中每个数组最多包含 1 个元素,按顺序选择。也就是说,作为输出,我希望看到:

adg aeg afg
adh aeh afh
adi aei afi

bdg beg bfg 
bdh beh bfh
bdi bei bfi

cdg ceg cfg
cdh ceh cfh
cdi cei cfi

Looking to Implement the algorithm in PHP or Javascript。本质上,它将遍历包含可变数量元素的可变数量的数组,并输出可能按顺序出现的所有可能的序列。

这存在吗?

如果是的话,它叫什么?从技术上讲,根据我对两者的了解,这不是排列或组合。

编辑:Daniel Fischer 告诉我这是一个笛卡尔积,这是一个取自 PHP 的实现 网站

function array_cartesian_product($arrays)
{
    $result = array();
    $arrays = array_values($arrays);
    $sizeIn = sizeof($arrays);
    $size = $sizeIn > 0 ? 1 : 0;
    foreach ($arrays as $array)
        $size = $size * sizeof($array);
    for ($i = 0; $i < $size; $i ++)
    {
        $result[$i] = array();
        for ($j = 0; $j < $sizeIn; $j ++)
            array_push($result[$i], current($arrays[$j]));
        for ($j = ($sizeIn -1); $j >= 0; $j --)
        {
            if (next($arrays[$j]))
                break;
            elseif (isset ($arrays[$j]))
                reset($arrays[$j]);
        }
    }
    return $result;
}

I'm looking to find out if a particular algorithm already exists.
I want to use it in an application, but I've also seen this come up in several Project Euler problems too.

I'm looking to calculate a specific type of permutation/output set, where the next item chosen must be one from a finite set of options in only the following set.

For example, say I've got 3 arrays

$a1 = array("a", "b", "c");
$a2 = array("d", "e", "f");
$a3 = array("g", "h", "i");

I'm looking to generate all the possibilities of a sequence containing at most 1 element from each array, chosen in order. That is to say as output, I'd like to see:

adg aeg afg
adh aeh afh
adi aei afi

bdg beg bfg 
bdh beh bfh
bdi bei bfi

cdg ceg cfg
cdh ceh cfh
cdi cei cfi

Looking to implement the algorithm in either PHP or Javascript. In essence it will go through a variable number of arrays containing a variable number of elements, and output all of the possiblities of sequences that can occurr in sequential order.

Does this exist?

If so, what is it called? Technically this isnt a permutation or a combination from what I know about both.

EDIT: Daniel Fischer has informed me this is a Cartesian product, here is an implementation taken from the PHP website:

function array_cartesian_product($arrays)
{
    $result = array();
    $arrays = array_values($arrays);
    $sizeIn = sizeof($arrays);
    $size = $sizeIn > 0 ? 1 : 0;
    foreach ($arrays as $array)
        $size = $size * sizeof($array);
    for ($i = 0; $i < $size; $i ++)
    {
        $result[$i] = array();
        for ($j = 0; $j < $sizeIn; $j ++)
            array_push($result[$i], current($arrays[$j]));
        for ($j = ($sizeIn -1); $j >= 0; $j --)
        {
            if (next($arrays[$j]))
                break;
            elseif (isset ($arrays[$j]))
                reset($arrays[$j]);
        }
    }
    return $result;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

锦上情书 2024-12-23 19:47:25

如果从每个列表/数组中选择一个项目,更准确地说是笛卡尔积的元素列表,则它是笛卡尔积。对于列表,它位于 Haskell 的标准库中:

Prelude> sequence ["abc","def","ghi"]
["adg","adh","adi","aeg","aeh","aei","afg","afh","afi","bdg","bdh","bdi","beg","beh"
,"bei","bfg","bfh","bfi","cdg","cdh","cdi","ceg","ceh","cei","cfg","cfh","cfi"]

我认为对于 PHP 或 Javascript,您必须自己编写代码。

It's a cartesian product, if exactly one item is chosen from each list/array, more precisely a list of the elements of the cartesian product. For lists, it's in Haskell's standard library:

Prelude> sequence ["abc","def","ghi"]
["adg","adh","adi","aeg","aeh","aei","afg","afh","afi","bdg","bdh","bdi","beg","beh"
,"bei","bfg","bfh","bfi","cdg","cdh","cdi","ceg","ceh","cei","cfg","cfh","cfi"]

I think for PHP or Javascript, you have to code it yourself.

二手情话 2024-12-23 19:47:25

您可以循环遍历元素。例如,您可以针对您的情况执行以下操作:

var ret = [];
for (var i=0; i<a1.length; i++) {
  for (var j=0; j<a2.length; j++) {
    for (var k=0; k<a3.length; k++) {
      ret.push( [a1[i], a2[j], a3[k]] );
    }
  }
}
// do stuff with ret

但请注意,这非常慢,特别是如果您有很多非常长的数组的数组。对于欧拉项目,通常可以使用一些其他见解,而不是枚举所有内容。

You can go through the elements in a loop. For example, you can do the following for your case:

var ret = [];
for (var i=0; i<a1.length; i++) {
  for (var j=0; j<a2.length; j++) {
    for (var k=0; k<a3.length; k++) {
      ret.push( [a1[i], a2[j], a3[k]] );
    }
  }
}
// do stuff with ret

Note though that this is pretty slow, especially if you have lots of arrays of very long arrays. For Project Euler, there is usually some other insight that you can use instead of enumerating everything.

你列表最软的妹 2024-12-23 19:47:25

我认为你是对的,它既不是排列也不是组合,因为字符串长度在你的情况下是固定的。请原谅我使用 java [7],但这是我目前最了解的。

public abstract class AFixedPermutation {
   private char[][] fields;
   private StringBuilder sb = new StringBuilder();
   private int[] callvec;
   private int maxDepth;

   public FixedPermutation(char[][] fields) { 
     this.fields = fields; 

     callvec = new int[fields.length];
     for (int i = 0; i < fields.length; i++) callvec[i] = 0;
     maxDepth = callvec.length - 1;
     recurse(0);
   }

   protected abstract emit(String s);

   private void recurse(int depth) {
     for (int i = 0; i < fields[depth].length; i++) { 
        callvec[depth] = i;
        if (depth == maxDepth) { apply(); }
        else {recurse(depth + 1); }
     }
   }

   private void apply() {
      sb.setLength(0);
      for (int i = 0; i < callvec.length; i++) {
        sb.append(fields[i][callvec[i]]);
      }
      emit(sb.toString());
   }
}

I think you're right that it's neither a permutation nor a combination because the string-length is fixed in your case. Pardon my use of java [7], but it's the one I currently know best.

public abstract class AFixedPermutation {
   private char[][] fields;
   private StringBuilder sb = new StringBuilder();
   private int[] callvec;
   private int maxDepth;

   public FixedPermutation(char[][] fields) { 
     this.fields = fields; 

     callvec = new int[fields.length];
     for (int i = 0; i < fields.length; i++) callvec[i] = 0;
     maxDepth = callvec.length - 1;
     recurse(0);
   }

   protected abstract emit(String s);

   private void recurse(int depth) {
     for (int i = 0; i < fields[depth].length; i++) { 
        callvec[depth] = i;
        if (depth == maxDepth) { apply(); }
        else {recurse(depth + 1); }
     }
   }

   private void apply() {
      sb.setLength(0);
      for (int i = 0; i < callvec.length; i++) {
        sb.append(fields[i][callvec[i]]);
      }
      emit(sb.toString());
   }
}
吾家有女初长成 2024-12-23 19:47:25

在 Mathematica 中,这本身是作为 Tuples

Tuples[{{a, b, c}, {d, e, f}, {g, h, i}}]
{{a, d, g}, {a, d, h}, {a, d, i}, {a, e, g}, {a, e, h}, {a, e, i},
 {a, f, g}, {a, f, h}, {a, f, i}, {b, d, g}, {b, d, h}, {b, d, i},
 {b, e, g}, {b, e, h}, {b, e, i}, {b, f, g}, {b, f, h}, {b, f, i},
 {c, d, g}, {c, d, h}, {c, d, i}, {c, e, g}, {c, e, h}, {c, e, i},
 {c, f, g}, {c, f, h}, {c, f, i}}

也可以使用 Outer (广义外部产品):

Outer[List, {a, b, c}, {d, e, f}, {g, h, i}]

或者通过迭代(Table):

Table[{x, y, z},
 {x, {a, b, c}},
 {y, {d, e, f}},
 {z, {g, h, i}}
]

或者用递归:

sets[{}, c__] := {{c}}
sets[{x_, r___}, c___] := Join @@ (sets[{r}, c, #] & /@ x)

sets[{{a, b, c}, {d, e, f}, {g, h, i}}]

In Mathematica this is natively implemented as Tuples.

Tuples[{{a, b, c}, {d, e, f}, {g, h, i}}]
{{a, d, g}, {a, d, h}, {a, d, i}, {a, e, g}, {a, e, h}, {a, e, i},
 {a, f, g}, {a, f, h}, {a, f, i}, {b, d, g}, {b, d, h}, {b, d, i},
 {b, e, g}, {b, e, h}, {b, e, i}, {b, f, g}, {b, f, h}, {b, f, i},
 {c, d, g}, {c, d, h}, {c, d, i}, {c, e, g}, {c, e, h}, {c, e, i},
 {c, f, g}, {c, f, h}, {c, f, i}}

It can also be done with Outer (generalized outer product):

Outer[List, {a, b, c}, {d, e, f}, {g, h, i}]

Or with iteration (Table):

Table[{x, y, z},
 {x, {a, b, c}},
 {y, {d, e, f}},
 {z, {g, h, i}}
]

Or with recursion:

sets[{}, c__] := {{c}}
sets[{x_, r___}, c___] := Join @@ (sets[{r}, c, #] & /@ x)

sets[{{a, b, c}, {d, e, f}, {g, h, i}}]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文