algorithm - 枚举笛卡尔积同时最小化重复

标签 algorithm math enumeration discrete-mathematics cartesian-product

给定两个集合,例如:

{A B C}, {1 2 3 4 5 6}

我想以在相等元素之间放置尽可能多的空间的顺序生成笛卡尔积。例如,[A1, A2, A3, A4, A5, A6, B1...] 是不好的,因为所有的 A 都彼此相邻。一个可接受的解决方案是“沿着对角线”,然后每次它都将偏移量换行,例如:

[A1, B2, C3, A4, B5, C6, A2, B3, C4, A5, B6, C1, A3…]

视觉表达:

|   | A | B | C | A | B | C | A | B | C | A | B | C | A | B | C | A | B | C |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 2 |   | 2 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 3 |   |   | 3 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 4 |   |   |   | 4 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 5 |   |   |   |   | 5 |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 6 |   |   |   |   |   | 6 |   |   |   |   |   |   |   |   |   |   |   |   |
| 1 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 2 |   |   |   |   |   |   | 7 |   |   |   |   |   |   |   |   |   |   |   |
| 3 |   |   |   |   |   |   |   | 8 |   |   |   |   |   |   |   |   |   |   |
| 4 |   |   |   |   |   |   |   |   | 9 |   |   |   |   |   |   |   |   |   |
| 5 |   |   |   |   |   |   |   |   |   | 10|   |   |   |   |   |   |   |   |
| 6 |   |   |   |   |   |   |   |   |   |   | 11|   |   |   |   |   |   |   |
| 1 |   |   |   |   |   |   |   |   |   |   |   | 12|   |   |   |   |   |   |
| 2 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 3 |   |   |   |   |   |   |   |   |   |   |   |   | 13|   |   |   |   |   |
| 4 |   |   |   |   |   |   |   |   |   |   |   |   |   | 14|   |   |   |   |
| 5 |   |   |   |   |   |   |   |   |   |   |   |   |   |   | 15|   |   |   |
| 6 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   | 16|   |   |
| 1 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   | 17|   |
| 2 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   | 18| 

或者,等效但不重复行/列:

|   | A  | B  | C  |
|---|----|----|----|
| 1 | 1  | 17 | 15 |
| 2 | 4  | 2  | 18 |
| 3 | 7  | 5  | 3  |
| 4 | 10 | 8  | 6  |
| 5 | 13 | 11 | 9  |
| 6 | 16 | 14 | 12 |

我想还有其他解决方案,但这是我发现最容易想到的解决方案。但我一直在用头撞墙试图弄清楚如何通用地表达它——这两个集合的基数是彼此的倍数是一件很方便的事情,但我希望算法为集合做正确的事情例如,尺寸 5 和 7。或尺寸 12 和 69(这是一个真实的例子!)。

是否有任何既定的算法?我一直在思考如何将有理数映射到自然数集(以证明它们是可数的),但它通过 ℕ×ℕ 的路径不适用于这种情况。

碰巧应用程序是用 Ruby 编写的,但我不关心语言。伪代码、Ruby、Python、Java、Clojure、Javascript、CL、一段英文——选择你最喜欢的。


Python 中的概念验证解决方案(即将移植到 Ruby 并与 Rails 连接):

import sys

letters = sys.argv[1]
MAX_NUM = 6

letter_pos = 0
for i in xrange(MAX_NUM):
    for j in xrange(len(letters)):
        num = ((i + j) % MAX_NUM) + 1
        symbol = letters[letter_pos % len(letters)]
        print "[%s %s]"%(symbol, num)
        letter_pos += 1

最佳答案

String letters = "ABC";
int MAX_NUM = 6;

int letterPos = 0;
for (int i=0; i < MAX_NUM; ++i) {
    for (int j=0; j < MAX_NUM; ++j) {
        int num = ((i + j) % MAX_NUM) + 1;
        char symbol = letters.charAt(letterPos % letters.length);
        String output = symbol + "" + num;
        ++letterPos;
    }
}

关于algorithm - 枚举笛卡尔积同时最小化重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40955810/

相关文章:

iphone - 枚举二级 NSDictionaries

c - 包括外部声明的枚举在内的问题 - C 代码

java - 从列表中提取包含重复项的列表,并获取非重复列表java 8流

c# - 在 C# 中使用树进行目录(文件文件夹)操作

c++ - 执行双浮点除法的正确算法是什么?

c# - 最准确的定位数据类型

objective-c - 使用 + 或 - 运算符对两个 CGPoints 进行算术运算

r - 蒙特卡罗积分的错误答案

algorithm - 二叉堆插入,不懂for循环

java - 为什么我们在 Java 的枚举中使用非修改构造函数