What I need this program to do is roll 36000 2d6, output the results of each value and how often it occurs in a table format. Unfortunately I'm unfamiliar with how arrays work. This is what I have so far:
int DiceArray()
{
int rollOne = 0;
int rollTwo = 0;
int countrolls = 0;
int sum = 0;
for (countrolls=1; countrolls<=36000; countrolls++)
{
rollOne = (rand() % 6) + 1;
rollTwo = (rand() % 6) + 1;
sum = rollOne+rollTwo;
}
}
So, I need an array for the dice results which I'm guessing is gonna look like result[11] because it lists 2 through 12 for the sum of the dice. Then I'm gonna have to make the array multidimensional; I'll need a second column for the results.
So, for instance, the result of two would occur we'll say 700 times. So I'd need something like outcome[2]. Is that right? And how would I get the right values for my array, anyways?
I suppose for the result array I just list them like so since they'll always be the same: {2, 3, 4,... 12}
But how do I output my sum to array?
Not sure, what you're asking, but it seems like you need a simple histogram. Like this:
void DiceArray()
{
int rollOne = 0;
int rollTwo = 0;
int sum = 0;
// This array holds histogram. hist[0] and hist[1] are always zero.
int hist[13] = { 0 };
for (int countrolls = 0; countrolls < 36000; ++countrolls)
{
rollOne = (rand() % 6) + 1;
rollTwo = (rand() % 6) + 1;
sum = rollOne+rollTwo;
hist[sum]++;
}
for (int i = 2; i <= 12; ++i)
{
std::cout << i << ": " << hist[i] << std::endl;
}
}
This function prints the following:
2: 949
3: 1974
4: 2898
5: 3987
6: 5133
7: 6088
8: 4944
9: 3976
10: 3075
11: 1991
12: 985
Something like this should work:
#include <iostream>
#include <random>
#include <array>
std::array<std::size_t, 13> DiceArray(const std::size_t count)
{
std::random_device device;
std::mt19937 engine(device());
std::uniform_int_distribution<std::size_t> distribution(1, 6);
std::array<std::size_t, 13> result = {};
for (std::size_t i = 0; i < count; ++i) {
++result[distribution(engine)+distribution(engine)];
}
return result;
}
int main(int argc, char* argv[])
{
auto result = DiceArray(36000);
for (std::size_t i = 0; i < result.size(); ++i) {
std::cout<<i<<" "<<result[i]<<std::endl;
}
return 0;
}
Your idea of result[11]; would work. You would have to zero-initialize it too.
int result[11] = {0};
Keep in mind that arrays are zero-based. So this array would cover the range of 0-10. You can work with that by subtracting off the minimum dice roll. Increment the corresponding array location for each roll in your loop:
++result[sum-2];
Accessing the value again requires subtracting the minimum dice roll:
int numTwos = result[2-2];
int numTens = result[10-2];
This is a C++11 answer. Based off this stack overflow answer
typedef std::mt19937 MyRNG; // the Mersenne Twister with a popular choice of parameters
std::vector< unsigned > DiceArray(
unsigned how_many_rolls, unsigned dice_count,
MyRNG& rng
)
{
// d6!
std::uniform_int_distribution<uint32_t> d6(1,6);
std::vector< unsigned > retval;
retval.resize( dice_count * 6+1 );
for (unsigned count = 0; count < how_many_rolls; ++count)
{
unsigned sum = 0;
for(unsigned i = 0; i < dice_count; ++i) {
sum += d6(rng);
}
retval[sum] += 1;
}
return retval;
}
And next we use it:
int main(int argc, char* argv[])
{
MyRNG rng;
uint32_t seed_val = 0; // populate somehow -- as `0` it will replicate the same sequence each time. A common trick is to grab the current time or some other source of entropy
rng.seed(seed_val); // avoid calling this more than once per experiment. It resets the RNG, if you call it again it will repeat the same sequence of numbers as the first time.
std::vector<unsigned> result = DiceArray(36000, 2, rng);
for (unsigned i = 0; i < result.size(); ++i) {
std::cout << i <<": " << result[i] << "\n";
}
}
Related
I am trying to create a sequence of 4 different numbers and randomly generated from 0 to 100 but it must have number 86, here is what I did:
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
srand((unsigned) time(NULL));
// Loop to get 3 random numbers
for(int i = 0; i < 3; i++)
{
int random = rand() % 101;
// Print the random number
cout << random << endl;
}
cout << 86 << endl;
}
But I don't want to put 86 at the end, are there any ways to place it at any random position in the sequence ? Thank you
My approach using modern C++
#include <algorithm>
#include <iostream>
#include <array>
#include <random>
namespace {
std::default_random_engine generator(std::random_device{}());
int random(int min, int max) {
return std::uniform_int_distribution<int>{min, max}(generator);
}
}
int main() {
std::array<int, 4> elements = {86};
for (int i = 1; i < elements.size(); ++i) {
elements[i] = random(0, 100);
}
std::shuffle(elements.begin(), elements.end(), generator);
for (int nbr : elements) {
std::cout << nbr << "\n";
}
return 0;
}
You can do exactly as you said - place it in a random position. First, you store the four numbers to be generated in an array; then, you decide which position is 86; then, you fill the rest and print it.
int main()
{
srand((unsigned) time(NULL));
int nums[4];
int loc86 = rand() % 4;
for(int i = 0; i < 4; i++)
{
nums[i] = i != loc86 ? rand() % 101 : 86;
}
for(int i = 0; i < 4; i++)
{
// Print the random number
cout << num[i] << endl;
}
}
A bit offtopic, but if you really care about precision of the random number generation (and that it approaches uniform random distribution well enough), you might use pragmatic c++ random number generators as described here.
Two approaches
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
srand((unsigned) time(NULL));
// Take a random position
const int j = rand() % 4;
// Loop to get 3 random numbers
for(int i = 0; i < 4; i++)
{
if (i == j)
cout << 86 << endl;
else
cout << rand() % 101 << end;
}
}
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
int main()
{
srand((unsigned) time(NULL));
// Fill and shuffle the array
int r[4] = {86, rand() % 101, rand() % 101, rand() % 101};
std::shuffle(std::begin(r), std::end(r));
for(int i = 0; i < 4; i++)
cout << r[i] << end;
}
Adding two integer array elements
if array1 = {0,0,0,0,9,9,9,9}—————> 00009999
and
array2 = {0,0,0,0,0,0,0,1}————————> 00000001
adding the two arrays together should result in 10000 being in array1, since 9999 + 1 = 10000
therefore, the result should be
array1 = {0,0,0,1,0,0,0,0}
Does anyone know how to write a code for this? I was trying to use a while loop which didn't work effectively within another for loop. Fairly new to coding and stack overflow, any help will be appreciated!
CODE THAT I TRIED
Note: both arrays will have the same number of elements, they were initialized with the same size
int length = sizeof(array1)/sizeof(array1[0]);
for(int i = length; i>0; i--){
if(array1[i-1] + array2[i-1] < 10){
array1[i-1] += array2[i-1];
}else{
array1[i-1] = array1[i-1] + array2[i-1] - 10;
if(array1[i-2]!=9){
array1[i-2]++;
} else{
int j = i-2;
while(j == 9){
array1[j] = 0;
j--;
}
array1[j-1]++;
}
}
}
Code below performs base10 arithmetic: you need to iterate the arrays in reverse, do the addition of i-th digit by modulo 10, then carry over any excess digits to the next array element:
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
int a1[] = { 0,0,0,0,9,9,9,9 };
int a2[] = { 0,0,0,0,0,0,0,1 };
const int b = 10;
int s = 0;
for (int i = size(a1) - 1; i >= 0; --i)
{
a1[i] += a2[i] + s;
s = a1[i] / b;
a1[i] %= b;
}
std::copy(a1, a1 + size(a1), ostream_iterator<int>(cout, " "));
cout << endl;
}
Alternative with C arrays and transform algorithm + make_reverse_iterator looks too heavy. Variant with std::arrays looks better:
#include <algorithm>
#include <array>
#include <iterator>
#include <iostream>
using namespace std;
int main()
{
std::array<int, 8> a1 = { 0,0,0,0,9,9,9,9 };
std::array<int, 8> a2 = { 0,0,0,0,0,0,0,1 };
const int b = 10;
int s = 0;
transform(a1.rbegin(), a1.rend(), a2.rbegin(), a1.rbegin(), [b, &s](int &i, int &j)
{
i += j + s;
s = i / b;
return i % b;
});
copy(a1.begin(), a1.end(), ostream_iterator<int>(cout, " "));
cout << endl;
}
It looks like you've overcomplicated the problem a bit. Your task is to perform base 10 addition on two arrays, carrying excess digits. You can simply iterate both arrays in reverse, perform addition on the individual elements, and ensure you carry over a digit when you exceed 10.
Here is an example based on the requirements you've described. You can further abstract this as needed.
I updated this code such that the result is now in array1.
#include <iostream>
int main(int argc, char *argv[], char *argp[]){
/* Initialize arrays and calculate array size */
int array1[] = {0,0,0,0,9,9,9,9};
int array2[] = {0,0,0,0,0,0,0,1};
int array_size = sizeof(array1) / sizeof(int);
/* Iterate the arrays in reverse */
int carry = 0;
for (int i = array_size - 1; i >= 0; i--) {
/* Perform addition on the current elements, remembering to include the carry digit */
int result = array1[i] + array2[i] + carry;
/* Determine if the addition should result in another carry */
if (result >= 10) {
carry = 1;
} else {
carry = 0;
}
/* Store the non-carried addition result */
array1[i] = result % 10;
}
/* View result */
for (int i = 0; i < array_size; i++) {
std::cout << array1[i];
}
std::cout << std::endl;
return 0;
}
uint32_t decode(int array[8]){
uint32_t multiple_of_ten=10000000;
uint32_t result = 0;
for(int i=0;i<8;i++){
result += (array[i] * multiple_of_ten);
multiple_of_ten = multiple_of_ten / 10;
}
return result;
}
int* encode(uint32_t number){
int result[8]={0,0,0,0,0,0,0,0};
uint32_t multiple_of_ten=10000000;
uint32_t recent = number;
for(int i=0;i<8;i++){
if(recent>0 && recent / multiple_of_ten > 0)
{
result[i] = recent / multiple_of_ten;
recent %= multiple_of_ten;
}
multiple_of_ten /= 10;
}
return result;
}
in your case , use encode(decode(array1) + decode(array2))
I want to generate different random numbers . I used srand and rand , but in my output some numbers are identical .
This is my output :
How to do with srand to generate different numbers ?
#include<iostream>
#include<time.h>
#include <windows.h>
int main(){
time_t t;
std::vector<int> myVector;
srand((unsigned)time(NULL));
for (int i = 0; i < 40; i++){
int b = rand() % 100;
myVector.push_back(b);
std::cout << myVector[i] << std::endl;
}
Sleep(50000);
}
One easy way is to add all numbers from 0-99 to a vector and shuffle it, then you can get as many (up to 100) non repeating random numbers as you require.
#include <algorithm>
#include <chrono>
#include <iostream>
#include <random>
#include <vector>
int main(void) {
std::vector<int> numbers;
for(int i=0; i<100; i++) // add 0-99 to the vector
numbers.push_back(i);
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::shuffle(numbers.begin(), numbers.end(), std::default_random_engine(seed));
for(int i=0; i<40; i++) // print the first 40 randomly sorted numbers
std::cout << numbers[i] << std::endl;
}
You could use a set:
std::set<int> numbers;
while (numbers.size() < 40)
{
numbers.add(rand() % 100);
}
and then copy it into a vector if necessary.
srand number generator can give identical numbers.
You could implement a solution which deletes duplicates not adding them to the vector. For example:
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> myVector;
srand((unsigned)time(NULL));
while(myVector.size() < 40)
{
int b = rand() % 100;
if ( !(std::find(myVector.begin(), myVector.end(), b) != myVector.end()))
{
myVector.push_back(b);
std::cout << myVector.at(myVector.size()-1) << std::endl;
}
}
Sleep(50000);
return 0;
}
An easy way of getting rid of duplicates is using std::unique in <algorithm>.
Here is an example of that in use:
#include <vector>
#include <iostream>
#include <algorithm>
#include <random>
int ran(int min, int max)
{
std::random_device r;
std::mt19937 gen(r());
std::uniform_int_distribution<> dis(min, max);
return dis(gen);
}
int main()
{
const int fill_size = 10;
const int min = 1; // min random number
const int max = 100; // max random number
std::vector<int> vec;
while (vec.size() != fill_size) {
vec.emplace_back(ran(min, max)); // create new random number
std::sort(begin(vec), end(vec)); // sort before call to unique
auto last = std::unique(begin(vec), end(vec));
vec.erase(last, end(vec)); // erase duplicates
}
std::random_shuffle(begin(vec), end(vec)); // mix up the sequence
for (const auto& i : vec) // and display elements
std::cout << i << " ";
}
As for me, the idea of using set is not so good, because the generating time of every new value increases. If you have enough memory it seems that usage of an array can be preferable.
In the next code, I don't use shuffle, instead, I use a random function just size times to choose one value. I add it to the destination vector, then in the source array, swap the value with the last element and decrease arr_size.
/*
* Return random unsigned int value using intrinsic
* */
unsigned getRandom() {
unsigned val;
_rdrand32_step(&val);
return val;
}
/*
* Return a vector<int> of uniq numbers in a range of [min ... max).
*
* #param min - min value.
* #param max - max value.
* #param size - amount of uniq numbers (size <= max-min).
* */
vector<int> getUniqNumbers(int min, int max, unsigned size) {
int arr_size = max - min;
int *a = new int[arr_size];
for (int i = 0; i < arr_size; i++) {
a[i] = min + i;
}
vector<int> numbers(size);
for (int i = 0; i < size; i++) {
unsigned u_rand = getRandom() % arr_size;
numbers[i] = a[u_rand];
a[u_rand] = a[--arr_size];
}
delete[] a;
return numbers;
}
You can easily achieve a unique set of random numbers writing:
#include<iostream>
#include<vector>
int main(){
std::vector<int> myVector;
srand((unsigned)time(NULL));
for (int i = 0; i < 40; i++) {
int b = rand() % 100;
if(!std::find(std::begin(myvector),std::end(myvector),b)) {
myVector.push_back(b);
std::cout << myVector[i] << std::endl;
}
}
}
This is a statistical (mathematical) issue. Random numbers may be identical to eachother. If you need unique numbers, you must check to see if they are used before. For example like this:
for (int i = 0; i < 40; i++){
int b = rand() % 100;
for (int j = 0; j < i; j++){
if(myVector[j]==b)i--;
else{
myVector.push_back(b);
std::cout << myVector[i] << std::endl;
}
}
}
I'm trying to devise an algorithm in the form of a function that accepts two parameters, an array and the size of the array. I want it to return the mode of the array and if there are multiple modes, return their average. My strategy was to take the array and first sort it. Then count all the occurrences of a number. while that number is occurring, add one to counter and store that count in an array m. So m is holding all the counts and another array q is holding the last value we were comparing.
For example: is my list is {1, 1, 1, 1, 2, 2, 2}
then i would have m[0] = 4 q[0] = 1
and then m[1] = 3 and q[1] = 2.
so the mode is q[0] = 1;
unfortunately i have had no success thus far. hoping someone could help.
float mode(int x[],int n)
{
//Copy array and sort it
int y[n], temp, k = 0, counter = 0, m[n], q[n];
for(int i = 0; i < n; i++)
y[i] = x[i];
for(int pass = 0; pass < n - 1; pass++)
for(int pos = 0; pos < n; pos++)
if(y[pass] > y[pos]) {
temp = y[pass];
y[pass] = y[pos];
y[pos] = temp;
}
for(int i = 0; i < n;){
for(int j = 0; j < n; j++){
while(y[i] == y[j]) {
counter++;
i++;
}
}
m[k] = counter;
q[k] = y[i];
i--; //i should be 1 less since it is referring to an array subscript
k++;
counter = 0;
}
}
Even though you have some good answers already, I decided to post another. I'm not sure it really adds a lot that's new, but I'm not at all sure it doesn't either. If nothing else, I'm pretty sure it uses more standard headers than any of the other answers. :-)
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <iostream>
#include <utility>
#include <functional>
#include <numeric>
int main() {
std::vector<int> inputs{ 1, 1, 1, 1, 2, 2, 2 };
std::unordered_map<int, size_t> counts;
for (int i : inputs)
++counts[i];
std::multimap<size_t, int, std::greater<size_t> > inv;
for (auto p : counts)
inv.insert(std::make_pair(p.second, p.first));
auto e = inv.upper_bound(inv.begin()->first);
double sum = std::accumulate(inv.begin(),
e,
0.0,
[](double a, std::pair<size_t, int> const &b) {return a + b.second; });
std::cout << sum / std::distance(inv.begin(), e);
}
Compared to #Dietmar's answer, this should be faster if you have a lot of repetition in the numbers, but his will probably be faster if the numbers are mostly unique.
Based on the comment, it seems you need to find the values which occur most often and if there are multiple values occurring the same amount of times, you need to produce the average of these. It seems, this can easily be done by std::sort() following by a traversal finding where values change and keeping a few running counts:
template <int Size>
double mode(int const (&x)[Size]) {
std::vector<int> tmp(x, x + Size);
std::sort(tmp.begin(), tmp.end());
int size(0); // size of the largest set so far
int count(0); // number of largest sets
double sum(0); // sum of largest sets
for (auto it(tmp.begin()); it != tmp.end(); ) {
auto end(std::upper_bound(it, tmp.end(), *it));
if (size == std::distance(it, end)) {
sum += *it;
++count;
}
else if (size < std::distance(it, end)) {
size = std::distance(it, end);
sum = *it;
count = 1;
}
it = end;
}
return sum / count;
}
If you simply wish to count the number of occurences then I suggest you use a std::map or std::unordered_map.
If you're mapping a counter to each distinct value then it's an easy task to count occurences using std::map as each key can only be inserted once. To list the distinct numbers in your list simply iterate over the map.
Here's an example of how you could do it:
#include <cstddef>
#include <map>
#include <algorithm>
#include <iostream>
std::map<int, int> getOccurences(const int arr[], const std::size_t len) {
std::map<int, int> m;
for (std::size_t i = 0; i != len; ++i) {
m[arr[i]]++;
}
return m;
}
int main() {
int list[7]{1, 1, 1, 1, 2, 2, 2};
auto occurences = getOccurences(list, 7);
for (auto e : occurences) {
std::cout << "Number " << e.first << " occurs ";
std::cout << e.second << " times" << std::endl;
}
auto average = std::accumulate(std::begin(list), std::end(list), 0.0) / 7;
std::cout << "Average is " << average << std::endl;
}
Output:
Number 1 occurs 4 times
Number 2 occurs 3 times
Average is 1.42857
Here's a working version of your code. m stores the values in the array and q stores their counts. At the end it runs through all the values to get the maximal count, the sum of the modes, and the number of distinct modes.
float mode(int x[],int n)
{
//Copy array and sort it
int y[n], temp, j = 0, k = 0, m[n], q[n];
for(int i = 0; i < n; i++)
y[i] = x[i];
for(int pass = 0; pass < n - 1; pass++)
for(int pos = 0; pos < n; pos++)
if(y[pass] > y[pos]) {
temp = y[pass];
y[pass] = y[pos];
y[pos] = temp;
}
for(int i = 0; i < n;){
j = i;
while (y[j] == y[i]) {
j++;
}
m[k] = y[i];
q[k] = j - i;
k++;
i = j;
}
int max = 0;
int modes_count = 0;
int modes_sum = 0;
for (int i=0; i < k; i++) {
if (q[i] > max) {
max = q[i];
modes_count = 1;
modes_sum = m[i];
} else if (q[i] == max) {
modes_count += 1;
modes_sum += m[i];
}
}
return modes_sum / modes_count;
}
So, I was searching for a good solution for my problem.
I need to generate(print) all the combination of a list of integers, for example:
if the array contain integers from 0 to n-1, where n = 5:
int array[] = {0,1,2,3,4};
the order of integers in the combination are NOT important, meaning {1,1,3}, {1,3,1} and {3,1,1} are actually the same combination because they all contain one 3 and two ones.
so for the above array, all combination of length 3:
0,0,0 -> the 1st combination
0,0,1
0,0,2
0,0,3
0,0,4
0,1,1 -> this combination is 0,1,1, not 0,1,0 because we already have 0,0,1.
0,1,2
0,1,3
0,1,4
0,2,2 -> this combination is 0,2,2, not 0,2,0 because we already have 0,0,2.
0,2,3
.
.
0,4,4
1,1,1 -> this combination is 1,1,1, not 1,0,0 because we already have 0,0,1.
1,1,2
1,1,3
1,1,4
1,2,2 -> this combination is 1,2,2, not 1,2,0 because we already have 0,1,2.
.
.
4,4,4 -> Last combination
For Now I Wrote Code for doing this, but my problem is:
if the numbers in the array are not integer from 0 to n-1, lets say if the array was like this
int array[] = {1,3,6,7};
my code doesn't work on this case, any algorithm or code for solving this problem,,
Here is my code :
unsigned int next_combination(unsigned int *ar, int n, unsigned int k){
unsigned int finished = 0;
unsigned int changed = 0;
unsigned int i;
for (i = k - 1; !finished && !changed; i--) {
if (ar[i] < n - 1) {
/* Increment this element */
ar[i]++;
if (i < k - 1) {
/* Make the elements after it the same */
unsigned int j;
for (j = i + 1; j < k; j++) {
ar[j] = ar[j - 1];
}
}
changed = 1;
}
finished = i == 0;
}
if (!changed) {
/* Reset to first combination */
for (i = 0; i < k; i++){
ar[i] = 0;
}
}
return changed;
}
And this is the main:
int main(){
unsigned int numbers[] = {0, 0, 0, 0, 0};
const unsigned int k = 3;
unsigned int n = 5;
do{
for(int i=0 ; i<k ; ++i)
cout << numbers[i] << " ";
cout << endl;
}while (next_combination(numbers, n, k));
return 0;
}
If you have working code to generate all combinations of numbers from 0 to n-1, then this is very simple. You have your array of numbers:
int array[] = {1,3,6,7};
Now, take n = 4, because there are 4 items in the array. Generate all combinations from 0 to 3, and use those as indices into your array. You now have all combinations of your array values by using all combinations of indices into that array.
This code requires that the "element pool" array be sorted from minimum to maximum, with no duplicate entries.
The function first_combination initializes the result array ("dist") to the first combination. After this, next_combination is called in a loop until it returns false (just like in your example). The "n" and "k" arguments have been replaced with template parameters that pick up the arrays' sizes -- so the enumeration functions need the pool array in addition to the result.
#include <iostream>
template<typename T, int N, int K>
void first_combination(const T (&pool)[N], T (&dist)[K]) {
for(int ki=0; ki<K; ++ki) {
dist[ki] = pool[0];
}
}
template<typename T, int N, int K>
bool next_combination(const T (&pool)[N], T (&dist)[K]) {
int ni = 0;;
int ki = 0;
for(;;) {
const int prev_ni = ni;
// search the pool for the value in this slot
for(ni=0; pool[ni] != dist[ki]; ++ni) {
if(ni == N) return false; // slot contains a value not found in the pool
}
if(++ni < N) break;
ni = 0;
dist[ki] = pool[0];
if(++ki == K) return false;
}
int v = pool[ni];
dist[ki] = v;
// code below assumes pool[] is sorted
for(--ki; ki>=0; --ki) {
if(dist[ki] < v) {
dist[ki] = v;
}
else {
v = dist[ki];
}
}
return true;
}
template<typename T, int COUNT>
void dumparray( T (&dist)[COUNT]) {
std::cout << '{';
for(int i=0; i<COUNT; ++i) {
if(i) std::cout << ',';
std::cout << dist[i];
}
std::cout << '}' << std::endl;
}
int main(int argc, char* argv[]) {
const int pool[] = {1,3,6,7};
int dist[3] = {0};
first_combination(pool, dist);
do {
dumparray(dist);
} while(next_combination(pool, dist));
return 0;
}
So you need program for generating combination (wiki link).
Here you have complete description and even ready to use algorithm: http://compprog.wordpress.com/2007/10/17/generating-combinations-1/