我需要根据C#/ Java中的最小差异对数组数据进行分区。
<input>
e.g。
B3,D4之间的差异= | 3 - 4 | = 1
A23,B25之间的差异= | 23 - 25 | = 2
D4,C7之间的差异= | 4 - 7 | = 3
B12,A12之间的差异= | 12 - 12 | = 0
规则是:
对于每个小组,信件不能重复
对于每个组,它可以包含1到4个元素
元素之间的差异必须为&lt; = 3
$(document).ready(function($){
var options = $.makeArray( $('.showSection') );
function doStuff() {
var that;
if (this === window) {
that = options[0];
options.push(options.shift());
} else {
that = this;
}
$(that).addClass('selected').siblings().removeClass('selected');
$('.targetSection').hide();
jQuery('#div' + jQuery(that).data('target')).show();
}
$('.showSection').on('click', doStuff);
setInterval(doStuff, 5000);
$('.showSection').first().click();
});
答案 0 :(得分:1)
您提供的输入包含多个解决方案。可能大约15左右(A1-A2,A35-A36,D4-C7将改变解决方案)。因为当我问你想要哪个解决方案时你没有回答,我写了这个代码,它将给出一个(最简单的)&#34;解决方案&#34;对于这个问题=)
static string[][] Solve(string[] input)
{
List<string> myList = new List<string>(input);
List<string[]> groups = new List<string[]>();
while (myList.Count > 0)
{
string currentStr = myList[0];
int currentNum = int.Parse(currentStr.Substring(1));
List<string> lessThan4 = new List<string>();
lessThan4.Add(currentStr);
for (int i = 1; i < myList.Count; i++)
{
if (Math.Abs(currentNum - int.Parse(myList[i].Substring(1))) < 4)
{
// Add it to the list only if there's not the same letter in there
if (!lessThan4.Where(a => a.Contains(myList[i].Substring(0, 1))).Any())
{
lessThan4.Add(myList[i]);
}
}
}
lessThan4.Sort();
groups.Add(lessThan4.ToArray());
myList = myList.Except(lessThan4).ToList();
}
return groups.ToArray();
}
您可以使用以下内容进行测试:
string[] input = new string[] { "A2", "B3", "D4", "C7", "B12", "A12", "C14", "D15", "C22", "A23", "B25", "A35", "A36", "D37" };
Solve(input);
在这种情况下Solve()的输出将是:
{ A2, B3, D4 },{ C7 },{ B12, A12, C14, D15 },{ C22, A23, B25 },{ A35, D37 },{ A36 }
重要提示:此代码假定输入内的字符串是唯一的。
答案 1 :(得分:1)
用Dyalog APL并行数组处理语言编写代码只花了10分钟,但我花了2个小时写下答案。我根本不会提交任何代码,所以不要打破问题中的语言限制,但我会尝试使用数据和一些伪代码来澄清下面的原则。
提供参数固定顺序,有512种可能的解决方案,如下所示:
┌──────────┬─┬─┬──┬──┬───┬───┬──┬──┬──┬──┬─────┐
│Partitions│6│7│8 │9 │10 │11 │12│13│14│15│Total│
├──────────┼─┼─┼──┼──┼───┼───┼──┼──┼──┼──┼─────┤
│Solutions │1│9│36│84│126│126│84│36│9 │1 │512 │
└──────────┴─┴─┴──┴──┴───┴───┴──┴──┴──┴──┴─────┘
具有最小分区(6)的解决方案是:
┌──┬───────────┬───────────────┬───────────┬───┬───────┐
│A1│A2 B3 D4 C7│B12 A12 C14 D15│C22 A23 B25│A35│A36 D37│
└──┴───────────┴───────────────┴───────────┴───┴───────┘
下一个(有7个分区)是:
┌──┬───────────┬───────────────┬───────────────┬───────────┬───┬───────┐
│A1│A2 B3 D4 C7│B12 A12 C14 D15│C22 A23 B25 │A35 │A36│D37 │
├──┼───────────┼───────────────┼───────────────┼───────────┼───┼───────┤
│A1│A2 B3 D4 C7│B12 A12 C14 D15│C22 A23 │B25 │A35│A36 D37│
├──┼───────────┼───────────────┼───────────────┼───────────┼───┼───────┤
│A1│A2 B3 D4 C7│B12 A12 C14 D15│C22 │A23 B25 │A35│A36 D37│
├──┼───────────┼───────────────┼───────────────┼───────────┼───┼───────┤
│A1│A2 B3 D4 C7│B12 A12 C14 │D15 │C22 A23 B25│A35│A36 D37│
├──┼───────────┼───────────────┼───────────────┼───────────┼───┼───────┤
│A1│A2 B3 D4 C7│B12 A12 │C14 D15 │C22 A23 B25│A35│A36 D37│
├──┼───────────┼───────────────┼───────────────┼───────────┼───┼───────┤
│A1│A2 B3 D4 C7│B12 │A12 C14 D15 │C22 A23 B25│A35│A36 D37│
├──┼───────────┼───────────────┼───────────────┼───────────┼───┼───────┤
│A1│A2 B3 D4 │C7 │B12 A12 C14 D15│C22 A23 B25│A35│A36 D37│
├──┼───────────┼───────────────┼───────────────┼───────────┼───┼───────┤
│A1│A2 B3 │D4 C7 │B12 A12 C14 D15│C22 A23 B25│A35│A36 D37│
├──┼───────────┼───────────────┼───────────────┼───────────┼───┼───────┤
│A1│A2 │B3 D4 C7 │B12 A12 C14 D15│C22 A23 B25│A35│A36 D37│
└──┴───────────┴───────────────┴───────────────┴───────────┴───┴───────┘
最后一个(分为15个分区)很自然:
┌──┬──┬──┬──┬──┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│A1│A2│B3│D4│C7│B12│A12│C14│D15│C22│A23│B25│A35│A36│D37│
└──┴──┴──┴──┴──┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
解决此问题的最佳,最安全的方法是使用蛮力并遍历所有可能性。首先,您需要调整使用零和一的原则来指示分区位置。由于参数中有15个元素,我们使用15个长度的二进制向量来完成这项工作。例如:
(1 0 0 1 0 0 0 0 1 0 0 1 0 0 0) partition 'stackoverflowex'
暗示/将返回4个分区:
┌───┬─────┬───┬────┐
│sta│ckove│rfl│owex│
└───┴─────┴───┴────┘
您还可以对另一个15长度的布尔矢量进行分区:
(1 0 0 1 0 0 0 0 1 0 0 1 0 0 0) partition (1 1 0 0 1 1 0 1 0 0 0 1 1 0 0)
应返回:
┌─────┬─────────┬─────┬───────┐
│1 1 0│0 1 1 0 1│0 0 0│1 1 0 0│
└─────┴─────────┴─────┴───────┘
您可以计算每个分区中的总和。上面的那个将返回:
┌─┬─┬─┬─┐
│2│3│0│2│
└─┴─┴─┴─┘
要解决您的问题,您必须生成所有可能的分区向量。这比做起来更简单。您只需要这两者之间的所有分区向量:
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 // This would create 1 single, big partition
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 // This would create 15 small partitions
这些是什么?非常简单,它们是16384和32767的2基(二进制)表示。您必须简单地遍历 16384和32767之间的所有数字(包括两者),将每个数字转换为2-base,分区您的数据,并查看当前分区是否可接受(=符合您的标准,如“对于每个组,信不能重复”)。转换区间中的所有数字将覆盖所有可能的分区 - 任何可能的零和1组合都在那里。计算只需要一秒钟的片段。
伪:
// The character part of the argument: 15-length vector of characters:
Chars = "A","A","B","D","C","B","A","C","D","C","A","B","A","A","D"
// From that, extract the locations of the unique characters:
CharsA = 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0 // Where Chars == A
CharsB = 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 // Where Chars == B
CharsC = 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 // Where Chars == C
CharsD = 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 // Where Chars == D
// The numeric part of the argument: 15-length vector of numbers:
// Btw, is this about lottery... hmmm
Nums = 1, 2, 3, 4, 7, 12, 12, 14, 15, 22, 23, 25, 35, 36, 37
:For Number :In [all numbers between 16384 and 32767]
Base2 = [2-base of Number] // 20123 would give: 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1
// Test 1: "For each group, it can contains 1 - 4 elements"
[using Base2, partition the partition vector Base2 itself;
bail out if any partition length exceeds 4]
// Test 2: "Difference between element must be <= 3"
[using Base2, partition Nums;
check differences inside each partition;
bail out if bigger than 3 anywhere]
// Test 3: "For each group, letter cannot be repeated"
[using Base2, partition CharsA, CharsB, CharsC, CharsD (each in turn);
count number of ones in each partition;
bail out if exceeds 1 anywhere (meaning a character occurs more than once)]
// If we still are here, this partition Number is ACCEPTABLE
[add Number to a list, or do a parallel boolean marking 1 for Number]
:End
此时,512 Number已满足指定的条件,而其余的则在某些测试中失败。这是一个纯粹的巧合,它们是512,这对于我们的编码员来说是一个特殊的数字。假设您现在在变量中有512个可接受的数字,名为结果。现在,您需要通过解析每个Result中的分区数(=其二进制表示中的分区数)对其进行排序。通过再次将Result中的每个数字转换为base 2,然后计算&amp;将每个中的一个数加起来,按该总和升序排序。最小的总和将是6,它只出现一次 - 这是在这个答案的顶部提到的分区。
它的值是25126,而2的基础是
1 1 0 0 0 1 0 0 0 1 0 0 1 1 0