如何计算位图?

发布于 2024-11-09 10:53:00 字数 484 浏览 0 评论 0原文

我正在寻找一种方法来获取列表项的所有组合。 我的想法是有一个二维数组,类似于位图 例如位[][] mybitmap;

例如,如果我的列表中有 4 个项目“A、B、C、D” 我希望我的位图像这样填充

A  B  C  D

0, 0, 0, 1  --> D
0, 0, 1, 0  --> C
0, 0, 1, 1  --> C, D
0, 1, 0, 0  --> B
0, 1, 0, 1
0, 1, 1, 0
0, 1, 1, 1
1, 0, 0, 0
1, 0, 0, 1
1, 0, 1, 0
1, 0, 1, 1  --> A, C, D
1, 1, 0, 0
1, 1, 0, 1
1, 1, 1, 0
1, 1, 1, 1  --> A, B, C, D

,但是我如何编写一些 C# 代码来填充我的位图? (PS:我的清单可能有 80 到 90 左右的项目,而不是 100 到 200,刚刚确认)

谢谢

I am looking for a way to get all combination of a list item.
what i thinking is to have a two dimention array, similary to a bit map
e.g bit[][] mybitmap;

for example if i have 4 item in my list "A, B, C, D"
i want my bitmap to be populate like this

A  B  C  D

0, 0, 0, 1  --> D
0, 0, 1, 0  --> C
0, 0, 1, 1  --> C, D
0, 1, 0, 0  --> B
0, 1, 0, 1
0, 1, 1, 0
0, 1, 1, 1
1, 0, 0, 0
1, 0, 0, 1
1, 0, 1, 0
1, 0, 1, 1  --> A, C, D
1, 1, 0, 0
1, 1, 0, 1
1, 1, 1, 0
1, 1, 1, 1  --> A, B, C, D

but how can i write some C# code to populate my bit map?
(PS: my list might have items around 80 to 90, not 100 to 200, just confirmed)

Thanks

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

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

发布评论

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

评论(3

贵在坚持 2024-11-16 10:53:00

所以...只需从 1 数到 15 (=(2^n)-1),并以二进制形式写入,也许使用移位运算。

这对于小数字来说是合理的……但很快就会变得相当大。对于 64 个项目,您可以长时间建模,但这是 18,446,744,073,709,551,615 种组合...提示:您永远、永远、永远不会循环那么远。

对于小案例:

int n = 4;
int max = 1 << n;
for (long val = 1; val < max; val++)
{
    long mask = 1 << (n - 1);
    for (int bit = 0; bit < n; bit++)
    {
        bool set = (val & mask) != 0;
        Console.Write(set ? "1 " : "0 ");
        mask >>= 1;
    }
    Console.WriteLine();
}

So... just count from 1 to 15 (=(2^n)-1), and write as binary, perhaps using shift operations.

This is sane for small numbers... but gets rather large quite quickly. For 64 items you can model in a long, but that is 18,446,744,073,709,551,615 combinations... hint: you are never, ever, ever going to loop that far.

For small cases:

int n = 4;
int max = 1 << n;
for (long val = 1; val < max; val++)
{
    long mask = 1 << (n - 1);
    for (int bit = 0; bit < n; bit++)
    {
        bool set = (val & mask) != 0;
        Console.Write(set ? "1 " : "0 ");
        mask >>= 1;
    }
    Console.WriteLine();
}
Saygoodbye 2024-11-16 10:53:00

同意马克·格拉维尔的观点。您不能假装生成一个像您所描述的那样的列表,然后收集您需要的元素。
我一直在做类似的事情,但我只需要所有组合的子集,因此我在列表生成过程中过滤了我的元素。这样,每次递归迭代(我使用的是 F#)都不会创建我已经知道最终会被丢弃的元素。

通过这种方法,我可以执行 200 个元素的变化并获得有效结果列表(我已经知道它不会那么大......)

如果您感兴趣,您所描述的问题是一个组合问题。 这里有一篇关于 C# 的好文章

Agree with Marc Gravell. You cannot pretend to generate a list like the one you describe and then collect the elements you need.
I've been doing something similar, but I only needed a subset of all the combinations, so I was filtering my elements during the list generation process. This way, each recursive iteration (I was using F#) does not create the elements that I already know that will be discarded at the end.

With this approach I could perform variations of 200 elements and get the list of valid results (which I already knew it was going to be not so big...)

In case you are interested, the problem you are describing is a combinatory problem. There's a nice article in C# here

落在眉间の轻吻 2024-11-16 10:53:00

我相信你不需要将所有组合存储在内存中。
只需从全零位的数组开始(第一个组合)。要得到下一个组合,只需在前一个组合的最后一位上加 1(很容易实现操作)。等等。
内存占用低,支持高达20亿位数字。 :)

    private void button1_Click(object sender, EventArgs e)
    {
        string[] items = {"A", "B", "C", "D"};
        bool[] bits = new bool[items.Length];
        for (int i = 0; i < bits.Length; i++)
        {
            bits[i] = false;
        }
        while (!bits.All(x => x))
        {
            listBox1.Items.Add(string.Join(", ", GetCombination(items, bits)));
            AddBit(bits, bits.Length - 1);
        }
    }

    public string[] GetCombination(string[] items, bool[] bits)
    {
        List<string> combination = new List<string>();
        for (int i = 0; i < bits.Length; i++)
        {
            if (bits[i])
            {
                combination.Add(items[i]);
            }
        }
        return combination.ToArray();
    }

    private void AddBit(bool[] bits, int pos)
    {
        if (pos < 0)
        {
            // overflow :)
            return;
        }
        if (bits[pos])
        {
            bits[pos] = false;
            AddBit(bits, pos - 1);
        }
        else
        {
            bits[pos] = true;
        }
    }

I believe you don't need to store all combinations in memory.
Just start from array with all zero bits (first combination). To get next combination just add 1 to last bit of previous combination (it is easily implementing operation). And so on.
Low memory usage, support of up to 2 billions of digits. :)

    private void button1_Click(object sender, EventArgs e)
    {
        string[] items = {"A", "B", "C", "D"};
        bool[] bits = new bool[items.Length];
        for (int i = 0; i < bits.Length; i++)
        {
            bits[i] = false;
        }
        while (!bits.All(x => x))
        {
            listBox1.Items.Add(string.Join(", ", GetCombination(items, bits)));
            AddBit(bits, bits.Length - 1);
        }
    }

    public string[] GetCombination(string[] items, bool[] bits)
    {
        List<string> combination = new List<string>();
        for (int i = 0; i < bits.Length; i++)
        {
            if (bits[i])
            {
                combination.Add(items[i]);
            }
        }
        return combination.ToArray();
    }

    private void AddBit(bool[] bits, int pos)
    {
        if (pos < 0)
        {
            // overflow :)
            return;
        }
        if (bits[pos])
        {
            bits[pos] = false;
            AddBit(bits, pos - 1);
        }
        else
        {
            bits[pos] = true;
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文