随机生成100组N个数,数的范围是1到35,并检查是否包含目标数组的数字
python版本
python
import numpy as np
def count_groups_containing_obj(N, obj):
# 随机生成100组N个数,数的范围是1到35
groups = np.random.randint(1, 36, size=(1000, N))
#print(groups)
# 目标数组obj转换为numpy数组
obj = np.array(obj)
# 初始化包含obj的组数计数
count = 0
k=0
ks=[]
# 遍历每组,检查是否包含目标数组obj中的所有数
for group in groups:
k+=1
# 使用np.isin检查组中的每个数是否都在obj中
#print(np.all(np.isin(obj,group)))
ii = np.all(np.isin(obj,group))
if ii:
count += 1
ks.append(group)
return count,ks
# 输入N和obj
N = 8 # 每组的数的个数
obj = [2,3,10,16,28] # 目标数组
# 调用函数并打印结果
result,ks = count_groups_containing_obj(N, obj)
print(f"包含目标数组的组数: {result}",result/10000)
print(ks)
matlab版本
matlab
function [count, ks] = count_groups_containing_obj(N, obj)
% 随机生成100组N个数,数的范围是1到35
groups = randi(35, 20000, N);
% 目标数组obj转换为列向量
obj = obj(:);
% 初始化包含obj的组数计数
count = 0;
ks = [];
% 遍历每组,检查是否包含目标数组obj中的所有数
for i = 1:size(groups, 1)
group = groups(i, :);
% 使用ismember检查组中的每个数是否都在obj中
if all(ismember(obj, group))
count = count + 1;
ks = [ks; group]; %#ok<AGROW>
end
end
% 打印结果
fprintf('包含目标数组的组数: %d\n', count);
fprintf('比例: %.4f%%\n', count / 20000 * 100);
end
C++版本
把这个转C++,将Python代码转换为C++代码需要一些调整,特别是由于C++中没有直接对应的NumPy库。不过,我们可以使用标准库中的容器和算法来实现类似的功能。以下是一个C++版本的实现:
cpp
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <numeric>
// 生成一个包含N个1到35之间随机数的组
std::vector<int> generateGroup(int N) {
std::vector<int> group(N);
std::generate(group.begin(), group.end(), std::rand); // 生成随机数,但未限制范围
std::transform(group.begin(), group.end(), group.begin(), [](int x) { return x % 35 + 1; }); // 将随机数映射到1-35
return group;
}
// 检查一个组是否包含目标数组中的所有数
bool containsAll(const std::vector<int>& group, const std::vector<int>& obj) {
for (int num : obj) {
if (std::find(group.begin(), group.end(), num) == group.end()) {
return false;
}
}
return true;
}
// 统计包含目标数组的组的数量
std::pair<int, std::vector<std::vector<int>>> countGroupsContainingObj(int N, const std::vector<int>& obj) {
std::srand(std::time(0)); // 初始化随机数种子
int count = 0;
std::vector<std::vector<int>> ks;
for (int i = 0; i < 1000; ++i) {
std::vector<int> group = generateGroup(N);
if (containsAll(group, obj)) {
count++;
ks.push_back(group);
}
}
return {count, ks};
}
int main() {
int N = 8; // 每组的数的个数
std::vector<int> obj = {2, 3, 10, 16, 28}; // 目标数组
auto [result, ks] = countGroupsContainingObj(N, obj);
double percentage = static_cast<double>(result) / 1000;
std::cout << "包含目标数组的组数: " << result << ", 百分比: " << percentage << std::endl;
// 输出包含的组(为了简洁,这里不打印所有组,只打印组数)
std::cout << "包含的组数: " << ks.size() << std::endl;
// 如果需要打印所有组,可以取消下面的注释
/*
for (const auto& group : ks) {
for (int num : group) {
std::cout << num << " ";
}
std::cout << std::endl;
}
*/
return 0;
}
几种初始化 std::pair
的方法:
在 C++ 中,std::pair
是一个模板类,用于存储两个元素的容器,这两个元素可以是不同的类型。std::pair
通常用于函数返回多个值,或者在标准库算法中作为键值对存储在容器中。
使用构造函数
cpp
#include <utility> // 或者 <pair>
int main() {
// 直接使用构造函数初始化
std::pair<int, std::string> p(1, "one");
return 0;
}
使用花括号 {} 初始化(列表初始化)
cpp
#include <utility> // 或者 <pair>
int main() {
// 使用花括号初始化
std::pair<int, std::string> p = {1, "one"};
return 0;
}
使用 make_pair
函数
cpp
#include <utility> // 包含 make_pair
int main() {
// 使用 make_pair 创建 pair
std::pair<int, std::string> p = std::make_pair(1, "one");
return 0;
}
使用 std::piecewise_construct
(C++11 及以后版本)
如果你需要使用不同的构造函数来初始化 pair 的两个元素,可以使用 std::piecewise_construct
:
cpp
#include <utility> // 包含 piecewise_construct
struct MyStruct {
int x;
std::string y;
};
int main() {
// 使用 piecewise_construct 初始化
std::pair<MyStruct, int> p(std::piecewise_construct,
std::forward_as_tuple(1), // 使用 MyStruct 的构造函数
std::forward_as_tuple(2)); // 使用 int 的默认构造函数
return 0;
}
在这些例子中,std::pair
被用来存储不同类型的值。你可以根据需要选择最适合你的场景的初始化方法。
std::piecewise_construct
std::piecewise_construct
是 C++11 引入的一个实用工具,它用于构造 std::pair
或 std::tuple
等容器时,分别对每个元素使用不同的构造参数。这在你需要使用不同类型或不同构造函数初始化容器中的元素时非常有用。
用途和场景
-
不同构造参数 :当你需要构造一个包含多种类型的
pair
或tuple
时,std::piecewise_construct
允许你为每个类型提供特定的构造参数。 -
效率:它可以帮助避免不必要的临时对象和拷贝,特别是在构造复杂对象时。
-
灵活性:它提供了一种灵活的方式来构造容器,特别是当元素的构造需要不同的参数或条件时。
示例
以下是使用 std::piecewise_construct
来构造 std::pair
的示例:
cpp
#include <utility>
#include <iostream>
struct Person {
std::string name;
int age;
Person(const std::string& name, int age) : name(name), age(age) {}
};
int main() {
// 使用 piecewise_construct 来构造 pair
std::pair<std::string, Person> personPair(
std::piecewise_construct,
std::forward_as_tuple("John Doe"), // 第一个元素的构造参数
std::forward_as_tuple("John Doe", 30) // 第二个元素的构造参数
);
std::cout << "Name: " << personPair.first << ", Age: " << personPair.second.age << std::endl;
return 0;
}
在这个例子中,std::pair
的第一个元素是一个 std::string
,只需要一个字符串参数来构造。第二个元素是 Person
类型,需要两个参数:一个字符串和一个整数。std::piecewise_construct
允许我们分别为这两个元素提供不同的构造参数。
注意事项
std::piecewise_construct
需要包含头文件<utility>
。- 使用
std::forward_as_tuple
来确保参数以正确的方式传递给构造函数。 - 这种方法在构造包含复杂对象的
pair
或tuple
时特别有用,尤其是当这些对象的构造函数参数不同时。
std::piecewise_construct
提供了一种高效且灵活的方式来构造包含多种类型元素的容器,使得代码更加清晰和易于维护。