从有限列表进行简单选择
Simple selection from finite list
我有三个变量需要以某种方式设置。 例如
int a, b, c;
a = choose(1, 2, 3); // a can take the value 1 to 3 inclusive
b = choose(1, 2, 3); // b can take the value 1 to 3 inclusive
c = ?????? // c can't take either of the values in a or b.
我能想到的设置 c 的最简单方法是使用循环:
do
{
c = choose(1, 2, 3);
}
while(c == a || c == b);
或者,我可以使用 ifs 或开关,或开关/if 组合:
a = choose(1, 2, 3);
b = choose(1, 2, 3);
switch(a){
case 1:
switch(b){
case 1:
c = choose(2, 3)
break;
case 2:
c = 3;
break;
case 3:
c = 2;
break;
}
break;
case 2:
…
这些看起来都不优雅,后者只是血腥丑陋。
我在一个项目中遇到了另一个类似的情况,我使用了std::set
和set_difference
,但我不能在这里使用它,并且必须使用一个不太像 STL 和更老派C++解决方案。
有什么想法吗?
Edit
再看一眼,首先选择独特的元素,然后再选择其他两个元素更有意义。这样更干净,虽然可能仍然不优雅。
如果您坚持使用 choose
的离散变量实现,它可能看起来像这样:
int choose(int, int); // two choice overload
int choose(int, int, int); // three choice overload
int main()
{
int c = choose(1, 2, 3);
int x = 1 + c % 3;
int y = 1 + (c + 1) % 3;
int a = choose(x, y);
int b = choose(x, y);
}
使用数组甚至更简洁,可以毫不费力地变得更加通用:
int choose(int[], int); // takes an array and its (effective) size
int main()
{
constexpr int maxNum = 3;
int choices[maxNum] = {1, 2, 3};
//for larger values of maxNum, loop initialize:
//for(int i = 0; i < maxNum; i++)
//{
// choices[i] = i + 1;
//}
int c = choose(choices, maxNum);
choices[c-1] = maxNum;
int a = choose(choices, maxNum - 1);
int b = choose(choices, maxNum - 1);
}
<小时 />对于仅三个变量,我将采用最简单的方法并使用您发布的while
循环:
do
{
c = choose(1, 2, 3);
}
while(c == a || c == b);
如果您确实需要确定性运行时的保证,您可以尝试如下方法。但是,我不确定每个人都会觉得它更"优雅",而且我认为可维护性打击不值得。
if(a != b)
{
c = 6 - (a + b);
}
else
{
c = choose(0, 1);
c = 1 + (a + c) % 3;
}
考虑到问题的设置方式,也不是那么可扩展,但在需要使其更普遍之前,我会假设 YAGNI。
您可以将其视为第二个解决方案的改进(优雅方面):
switch ((1<<a)|(1<<b))
{
case 2: // a,b == 1,1
c = choose(2,3);
break;
case 4: // a,b == 2,2
c = choose(1,3);
break;
case 6: // a,b == 1,2 or 2,1
c = 3;
break;
case 8: // a,b == 3,3
c = choose(1,2);
break;
case 10: // a,b == 1,3 or 3,1
c = 2;
break;
case 12: // a,b == 2,3 or 3,2
c = 1;
break;
}
您可以通过映射两个值来进一步改进它,对于每个值(1<<a)|(1<<b)
:
static int first[] = {2,1,3,1,2,1};
static int second[] = {3,3,3,2,2,1};
int index = ((1<<a)|(1<<b))/2-1; // reduce from [2,4,6,8,10,12] to [0,1,2,3,4,5]
c = choose(first[index],second[index]);
在那里,您有一个优雅的解决方案,没有switch
,while
或任何其他条件语句...
你真的只有 3 个这样的值还是这是一个最小化的例子?对于这种情况,我会直接排除取值
int a, b, c;
a = choose(1, 2, 3); // a can take the value 1 to 3 inclusive
b = choose(1, 2, 3); // b can take the value 1 to 3 inclusive
c = 1;
if(a == c || b == c)
c = 2;
if(a == c || b == c)
c = 3;
如果值为 1,2,3,您可以将其替换为与您的c++
类似的 while 循环:
c = 1;
while(a == c || b == c)
c++;
如果需要c
chosen
您提出的 while 循环对我来说似乎很好。
也许是这样的:
int a, b, c;
int myList[]= {1, 2, 3};
a = choose(myList); // if choose can take a list as input
b = choose(myList);
myList.remove(a);
myList.remove(b);
c = choose(myList); // the selection from a and b are out of the list at this point
此解决方案可确保
a != b && a != c
解决方案是将链表(通过引用)传递到choose
函数中。 所选元素将从列表中删除并返回。 对该函数的后续调用将有越来越少的元素可供选择。
您必须记下列表何时为空并相应地处理它。
如果允许a
和b
相同,则choose
将不是您用于确定c
的函数。 在这种情况下,有一个单独的函数chooseC
,该函数采用所选值的列表(通过常量引用)和可用值的列表(按值)。 从可用值中删除所选值,然后从剩余值中进行选择。
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 使用简单类型列表实现的指数编译时间.为什么
- 列表视图更改选择颜色
- 如何使用cpp编写选择排序算法以降序对元素列表进行排序?
- 正在分析BoostSpirit中固定列表中的选择
- 如何修复列表视图中的错误?,封装控件时无法选择任何项
- 如何在C++中创建数字列表,以便它可以选择一个随机数?
- 从简单连接的列表中删除最大值
- 在链接列表中添加字符串的简单方法
- 带有选择的菜单列表
- 如何打印简单的链接列表(C )
- 在修改项目列表时,请防止可编辑的Qcombobox选择更改
- 为 STL 列表编写选择排序
- 简单的链接列表删除失败
- 如何从图形的邻接列表表示中随机选择边缘
- 有没有一种方法可以在基于枚举的可变参数模板函数之间进行选择,这比将函数包装在结构中更简单
- 如何根据MFC中的列表控制选择禁用按钮
- C :获取带有孔的多边形的简单多边形列表
- 从有限列表进行简单选择
- 简单变量列表参数C++