繁体   English   中英

循环遍历BitArray中每个可能的值组合

[英]Loop through every possible combination of values in a BitArray

我正在努力解决一个更大的问题。 作为其中的一部分,我创建了一个BitArray来表示顺序执行的一系列二进制决策。 我知道所有有效的决策系列都会有一半的决定是真的,有一半是假的,但我不知道顺序:

 ttttffff
[||||||||]

要么:

 tftftftf
[||||||||]

要么:

 ttffttff
[||||||||]

或者任何其他组合,其中一半的所有位都是真的,一半是假的。

我的BitArray比这长得多,我需要遍历每组可能的决定(每个可能的半真半假的组合),进一步检查它们的有效性。 然而,我正在努力从概念上解决如何使用循环来实现这一点。 看起来应该很简单,但我的大脑让我失望了。

编辑:因为BitArray不是很大,我使用了usr的建议并实现了一个bithift循环。 根据一些评论和答案,我用关键词“排列”重新搜索了问题,发现这个 Stack Overflow问题非常相似。

我会使用递归算法来做到这一点。 每个级别设置下一个位。 您可以跟踪已经确定了多少个零和一个零。 如果其中一个计数器超过N / 2 ,则中止分支并回溯。 这应该提供相当好的性能,因为它会倾向于快速切断不可行的分支。 例如,在设置tttt只有f选项是可行的。

一个更简单,性能更差的版本将是使用for循环遍历所有可能的N位整数并丢弃不满足条件的那些整数。 这很容易实现高达63位。 只需要一个从01 << 63的for循环。 显然,对于高位,这太慢了。

您正在寻找N / 2零和N / 2个的所有排列。 有生成这些的算法。 如果你能找到一个实现的,那么应该给出最好的性能。 我相信那些算法使用聪明的数学技巧只能访问可行的组合。

如果您可以使用整数中的位而不是BitArray,则这是生成具有一些常量位数的所有模式的通用解决方案。

从最低有效值开始,该值与数字右侧的所有值有关,您可以将其计算为low = ~(-1 << k) (对于k = 32不起作用,但这不是在这种情况下的问题)。

然后采用Gosper的Hack (也在这个答案中显示),这是一种生成下一个最高整数的方法,同样多的位设置,并继续应用它,直到你达到最高有效值,在这种情况下low << k

这将导致重复,但如果您愿意,可以在添加到列表之前检查重复项。

  static void Main(string[] args)
  {
     // Set your bits here:
     bool[] bits = { true, true, false };
     BitArray original_bits = new BitArray(bits);

     permuteBits(original_bits, 0, original_bits.Length - 1);

     foreach (BitArray ba in permutations)
     {
        // You can check Validity Here
        foreach (bool i in ba)
        {
           Console.Write(Convert.ToInt32(i));
        }
        Console.WriteLine();
     }
  }

  static List<BitArray> permutations = new List<BitArray>();

  static void permuteBits(BitArray bits, int minIndex, int maxIndex)
  {
     int current_index;
     if (minIndex == maxIndex)
     {
        permutations.Add(new BitArray(bits));
     }
     else
     {
        for (current_index = minIndex; current_index <= maxIndex; current_index++)
        {
           swap(bits, minIndex, current_index);
           permuteBits(bits, minIndex + 1, maxIndex);
           swap(bits, minIndex, current_index);
        }
     }
  }

  private static void swap(BitArray bits, int i, int j)
  {
     bool temp = bits[i];
     bits[i] = bits[j];
     bits[j] = temp;
  }

如果你想清除finding all the permutation具有重复条目的字符串的finding all the permutation的概念(即zeros and ones ),你可以阅读这篇文章

他们使用递归解决方案来解决这个问题,解释也很好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM