Write a program to find out the probability of each
"total value" when several unbiased irregular dices (possibly with different number of
faces) are thrown at the same time.
When an unbiased dice is thrown, the probability of having different face value should
be equal. For instance, a typical cubic dice should give a probability of 1/6 for the face
values 1,2,3,4,5 and 6.
If two cubic dices were thrown, the total of the face values on the two dices is in range
[2..12]. However, the probability of each "total value” is not equal. For example, the
total of 4 is having a probability of 3/36 (for combinations 1+3, 2+2 and 3+3) while
the probability of a total of 2 is only 1/36 (when both dices give 1).
Sample output as follow: (the one with * are the input from user)
Input the number of dice(s): *2
Input the number of faces for the 1st dice: *6
Input the number of faces for the 2nd dice: *6
Probability of 2 = 1/36
Probability of 3 = 2/36
Probability of 4 = 3/36
Probability of 5 = 4/36
Probability of 6 = 5/36
Probability of 7 = 6/36
Probability of 8 = 5/36
Probability of 9 = 4/36
Probability of 10 = 3/36
Probability of 11 = 2/36
Probability of 12 = 1/36
Input the number of dice(s): *5
Input the number of faces for the 1st dice: *1
Input the number of faces for the 2nd dice: *2
Input the number of faces for the 3rd dice: *3
Input the number of faces for the 4th dice: *4
Input the number of faces for the 5th dice: *5
Probability of 5 = 1/120
Probability of 6 = 4/120
Probability of 7 = 9/120
Probability of 8 = 15/120
Probability of 9 = 20/120
Probability of 10 = 22/120
Probability of 11 = 20/120
Probability of 12 = 15/120
Probability of 13 = 9/120
Probability of 14 = 4/120
Probability of 15 = 1/120
I don't actually know how to finish the probability part. I want to have some tips about the method to calculate the problem.
#include <iostream>
#include <string>
using namespace std;
//Initialise output function
string output(int num){
case 1:
return "st";
break;
case 2:
return "nd";
break;
case 3:
return "rd";
break;
default:
return "th";
}
//Roll function
int roll(int num, int result, int value[20]){
int dice[num][20];
for (int i=0; i<num;i++){
for (int j=1; j<=value[i];j++){
for (int k=0; k<value[i];k++)
dice[i][k]=j;
}
}
}
}
int main(){
int number;
//Initialise the number variable
cout <<"Input the number of dice(s): ";
cin >> number;
cout<<endl;
//Initialise the face of the dice using std::array
int value[11];
for (int i=0; i<number; i++){
cout << "Input the number of faces for the "<< i+1 << output(i+1)
<<" dice: ";
cin>>value[i];
}
//set the base of the probability (multiply), the maxrange (sum) for
the dice probability
int base=1;
int sum;
for (int i=0; i<number; i++){
base = base*value[i];
sum = sum +value[i];
}
//Output statements
if (sum >9){
for (int i=number; i<10; i++){
cout << "Probability of "<<i<<" = "<<roll(number, i, value);
}
for (int i=10; i<=sum;i++){
cout << "Probability of "<<i<<" = "<<roll(number, i, value);
}
} else {
for (int i=number; i<=sum; i++){
cout << "Probability of "<<i<<" = "<<roll(number, i, value);
}
}
return 0;
}
You can use brute froce and calculate all combinations using a recursive function and use a map to count the number each result occur.
Further, use the C++ containers instead of C-style arrays.
Like:
#include <iostream>
#include <vector>
#include <map>
void calcAll(const uint32_t value,
const uint32_t index,
const std::vector<uint32_t>& dices,
std::map<uint32_t, uint32_t>& count,
uint32_t& total)
{
if (index == dices.size())
{
// No more dices -> save result and stop recursion
auto it = count.find(value);
if (it == count.end())
{
count[value]=1;
}
else
{
count[value]++;
}
++total;
return;
}
// Iterate over all dice values
for (uint32_t i = 0; i < dices[index]; ++i)
{
calcAll(value + i + 1, index + 1, dices, count, total);
}
}
int main() {
std::vector<uint32_t> dices {6, 6, 6}; // 3 dices, 6 sides each
std::map<uint32_t, uint32_t> count;
uint32_t total = 0;
calcAll(0, 0, dices, count, total);
for (const auto& v : count)
{
std::cout << v.first << " seen " << v.second << " times out of " << total << std::endl;
}
return 0;
}
Output:
3 seen 1 times out of 216
4 seen 3 times out of 216
5 seen 6 times out of 216
6 seen 10 times out of 216
7 seen 15 times out of 216
8 seen 21 times out of 216
9 seen 25 times out of 216
10 seen 27 times out of 216
11 seen 27 times out of 216
12 seen 25 times out of 216
13 seen 21 times out of 216
14 seen 15 times out of 216
15 seen 10 times out of 216
16 seen 6 times out of 216
17 seen 3 times out of 216
18 seen 1 times out of 216
For a 6-sided die you have a "probability vector" [1/6, 1/6, 1/6, 1/6, 1/6, 1/6] then for each additional die you convolve the vector with the "probability vector" of the next die to get a longer and more "bell shaped" vector.
[1/6, 1/6, 1/6, 1/6, 1/6, 1/6] * [1/6, 1/6, 1/6, 1/6, 1/6, 1/6] =
[1/36, 2/36, 3/36, 4/36, 5/36, 6/36, 5/36, 4/36, 3/36, 2/36, 1/36]
You can code it like this: (Please note that i factored the denominators out of the convolution).
static std::vector<int> conv(const std::vector<int>& f, const std::vector<int>& g) {
const int nf = f.size();
const int ng = g.size();
const int n = nf + ng - 1;
std::vector<int> out(n);
for(int i = 0; i < n; ++i) {
const int jmn = (i >= ng - 1) ? i - (ng - 1) : 0;
const int jmx = (i < nf - 1) ? i : nf - 1;
for(int j = jmn; j <= jmx; ++j) {
out[i] += (f[j] * g[i - j]);
}
}
return out;
}
static void rollDice(const std::vector<int>& dice) {
std::vector<int> firstDie(dice[0], 1);
std::vector<int> a = firstDie;
int denominator = dice[0];
for (int i = 1; i < dice.size(); ++i) {
a = conv(a, std::vector<int>(dice[i], 1));
denominator *= dice[i];
}
for (auto aa : a) {
std::cout << aa << '/' << denominator << '\n';
}
}
int main() {
rollDice({6, 6});
rollDice({1, 2, 3, 4, 5});
}
The output is:
1/36
2/36
3/36
4/36
5/36
6/36
5/36
4/36
3/36
2/36
1/36
1/120
4/120
9/120
15/120
20/120
22/120
20/120
15/120
9/120
4/120
1/120
Related
The question is to find the number of interesting numbers lying between two numbers. By the interesting number, they mean that the product of its digits is divisible by the sum of its digits.
For example: 459 => product = 4 * 5 * 9 = 180, and sum = 4 + 5 + 9 = 18; 180 % 18 == 0, hence it is an interesting number.
My solution for this problem is having run time error and time complexity of O(n2).
#include<iostream>
using namespace std;
int main(){
int x,y,p=1,s=0,count=0,r;
cout<<"enter two numbers"<<endl;
cin>>x>>y;
for(int i=x;i<=y;i++)
{
r=0;
while(i>1)
{
r=i%10;
s+=r;
p*=r;
i/=10;
}
if(p%s==0)
{
count++;
}
}
cout<<"count of interesting numbers are"<<count<<endl;
return 0;
}
If s is zero then if(p%s==0) will produce a divide by zero error.
Inside your for loop you modify the value of i to 0 or 1, this will mean the for loop never completes and will continuously check 1 and 2.
You also don't reinitialise p and s for each iteration of the for loop so will produce the wrong answer anyway. In general limit the scope of variables to where they are actually needed as this helps to avoid this type of bug.
Something like this should fix these problems:
#include <iostream>
int main()
{
std::cout << "enter two numbers\n";
int begin;
int end;
std::cin >> begin >> end;
int count = 0;
for (int number = begin; number <= end; number++) {
int sum = 0;
int product = 1;
int value = number;
while (value != 0) {
int digit = value % 10;
sum += digit;
product *= digit;
value /= 10;
}
if (sum != 0 && product % sum == 0) {
count++;
}
}
std::cout << "count of interesting numbers are " << count << "\n";
return 0;
}
I'd guess the contest is trying to get you to do something more efficient than this, for example after calculating the sum and product for 1234 to find the sum for 1235 you just need to add one and for the product you can divide by 4 then multiply by 5.
I want to solve a question like this:
Enter a specified amount (in units of yuan, such as 345.78) from the keyboard, and then display the amount of RMB in various denominations that pay the amount, and ask to display 100 yuan, 50 yuan, 10 yuan, 5 yuan, 2 yuan, 1 yuan, 5 angles, 1 point, 5 points, 1 point each.
like 345.78=100*3+10*4+5*1+0.5*1+0.1*2+0.01*8
Here are the codes:
#include<stdio.h>
int main()
{int a1=0,a2=0,a3=0,a4=0,a5=0,a6=0,a7=0,a8=0,a9=0;
float m;
printf("enter money:");
scanf("%f",&m);
while(m>100.0)
{m=m-100;
a1++;}
while(m>50.0)
{m=m-50;
a2++;}
while(m>10.0)
{m=m-10;
a3++;}
while(m>5.0)
{m=m-5;
a4++;}
while(m>2.0)
{m=m-2;
a5++;}
while(m>1.0)
{m=m-1;
a6++;}
while(m>0.1)
{m=m-0.1;
a7++;}
while(m>0.05)
{m=m-0.05;
a8++;}
while(m>0.01)
{m=m-0.01;
a9++;}
printf("a1=%d,a2=%d,a3=%d,a4=%d,a5=%d,a6=%d,a7=%d,a8=%d,a9=%d\n",a1,a2,a3,a4,a5,a6,a7,a8,a9);
return 0;
}
#include<stdio.h>
int main()
{
double n,r[8];
int k;
scanf("n=%lf",&n);
int a=n/100;
r[0]=n-a*100;
int b=r[0]/50;
r[1]=r[0]-b*50;
int c=r[1]/10;
r[2]=r[1]-c*10;
int d=r[2]/5;
r[3]=r[2]-d*5;
int e=r[3]/2;
r[4]=r[3]-e*2;
int f=r[4];
r[5]=r[4]-f*1;
int g=r[5]*10.00;
r[6]=r[5]-g*0.1;
int h=r[6]*20.00;
r[7]=r[6]-h*0.05;
int i=r[7]*100.00;
printf("%d\n",a);
printf("%d\n",b);
printf("%d\n",c);
printf("%d\n",d);
printf("%d\n",e);
printf("%d\n",f);
printf("%d\n",g);
printf("%d\n",h);
printf("%d\n",i);
return 0;
}
However, while entering the numbers like 0.78, 0.98, 0.99, the value i is ALWAYS one less.
How does this happen?
You should avoid floating point arithmetic. Read the input as floating point and store the number of smallest units as integer:
#include <iostream>
int main()
{
double input;
std::cin >> input;
int money = input * 100;
for (auto n : {10000, 5000, 1000, 500, 200, 100, 10, 5, 1}) {
std::cout << n / 100.0 << ":\t" << money / n << '\n';
money %= n;
}
return 0;
}
Input:
1288.56
Output:
100: 12
50: 1
10: 3
5: 1
2: 1
1: 1
0.1: 5
0.05: 1
0.01: 1
So I N - numbers I have to input, and I got M - numbers of places for those numbers and I need to find all combinations with repetition of given numbers.
Here is example:
Let's say that N is 3(I Have to input 3 numbers), and M is 4.
For example let's input numbers: 6 11 and 533.
This should be result
6,6,6,6
6,6,6,11
6,6,6,533
6,6,11,6
...
533,533,533,533
I know how to do that manualy when I know how much is N and M:
In example where N is 3 and M is 4:
int main()
{
int N = 3;
int M = 4;
int *numbers = new int[N + 1];
for (int i = 0; i < N; i++)
cin >> numbers[i];
for (int a = 0; a < N; a++)
for (int b = 0; b < N; b++)
for (int c = 0; c < N; c++)
for (int d = 0; d < N; d++)
{
cout << numbers[a] << " " << numbers[b] << " " << numbers[c] << " " << numbers[d] << endl;
}
return 0;
}
But how can I make algorithm so I can enter N and M via std::cin and I get correct resut?
Thanks.
First one short tip: don't use "new" or C-style arrays in C++ when we have RAII and much faster data structures.
For the solution to your problem I would suggest making separate function with recursion. You said you know how to do it manually so the first step in making it into algorithm is to tear down you manual solution step by step. For this problem when you solve it by hand you basically start with array of all first numbers and then for last position you just loop through available numbers. Then you go to the second last position and again loop through available numbers just now with the difference that for every number there you must also repeat the last spot number loop. Here is the recursion. For every "n"th position you must loop through available numbers and for every call the same function for "n+1"th number.
Here is a simplified solution, leaving out the input handling and exact print to keep code shorter and more focused on the problem:
#include <vector>
#include <iostream>
void printCombinations(const std::vector<int>& numbers, unsigned size, std::vector<int>& line) {
for (unsigned i = 0; i < numbers.size(); i++) {
line.push_back(numbers[i]);
if (size <= 1) { // Condition that prevents infinite loop in recursion
for (const auto& j : line)
std::cout << j << ","; // Simplified print to keep code shorter
std::cout << std::endl;
line.erase(line.end() - 1);
} else {
printCombinations(numbers, size - 1, line); // Recursion happens here
line.erase(line.end() - 1);
}
}
}
int main() {
std::vector<int> numbers = {6, 11, 533};
unsigned size = 4;
std::vector<int> line;
printCombinations(numbers, size, line);
return 0;
}
If you have any questions feel free to ask.
Totally there is no need for recursion here. This is a typical job for dynamic programming. Just get the first solution right for n = 1 (1 slot is available) which means the answer is [[6],[11],[533]] and then move on one by one by relying on the one previously memoized solution.
Sorry that i am not fluent in C, yet in JS this is the solution. I hope it helps.
function combosOfN(a,n){
var res = {};
for(var i = 1; i <= n; i++) res[i] = res[i-1] ? res[i-1].reduce((r,e) => r.concat(a.map(n => e.concat(n))),[])
: a.map(e => [e]);
return res[n];
}
var arr = [6,11,533],
n = 4;
console.log(JSON.stringify(combosOfN(arr,n)));
Normally the easiest way to do dynamic nested for loops is to create your own stack and use recursion.
#include <iostream>
#include <vector>
void printCombinations(int sampleCount, const std::vector<int>& options, std::vector<int>& numbersToPrint) {
if (numbersToPrint.size() == sampleCount) {
// got all the numbers we need, print them.
for (int number : numbersToPrint) {
std::cout << number << " ";
}
std::cout << "\n";
}
else {
// Add a new number, iterate over all possibilities
numbersToPrint.push_back(0);
for (int number : options) {
numbersToPrint.back() = number;
printCombinations(sampleCount, options, numbersToPrint);
}
numbersToPrint.pop_back();
}
}
void printCombinations(int sampleCount, const std::vector<int>& options) {
std::vector<int> stack;
printCombinations(sampleCount, options, stack);
}
int main()
{
printCombinations(3, {1,2,3});
}
output
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
2 1 1
2 1 2
2 1 3
2 2 1
2 2 2
2 2 3
2 3 1
2 3 2
2 3 3
3 1 1
3 1 2
3 1 3
3 2 1
3 2 2
3 2 3
3 3 1
3 3 2
3 3 3
Here is an algorithm to solve this, that does't use recursion.
Let's say n=2 and m=3. Consider the following sequence that corresponds to these values:
000
001
010
011
100
101
110
111
The meaning of this is that when you see a 0 you take the first number, and when you see a 1 you take the second number. So given the input numbers [5, 7], then 000 = 555, 001=557, 010=575 etc.
The sequence above looks identical to representing numbers from 0 to 7 in base 2. Basically, if you go from 0 to 7 and represent the numbers in base 2, you have the sequence above.
If you take n=3, m=4 then you need to work in base 3:
0000
0001
0002
0010
0011
0012
....
So you go over all the numbers from 0 to 63 (4^3-1), represent them in base 3 and follow the coding: 0 = first number, 1 = second number, 2 = third number and 3 = fourth number.
For the general case, you go from 0 to M^N-1, represent each number in base N, and apply the coding 0 = first number, etc.
Here is some sample code:
#include <stdio.h>
#include <math.h>
void convert_to_base(int number, char result[], int base, int number_of_digits) {
for (int i = number_of_digits - 1; i >= 0; i--) {
int remainder = number % base;
number = number / base;
result[i] = '0' + remainder;
}
}
int main() {
int n = 2, m = 3;
int num = pow(n, m) - 1;
for (int i = 0; i <= num; i++) {
char str[33];
convert_to_base(i, str, n, m);
printf("%s\n", str);
}
return 0;
}
Output:
000
001
010
011
100
101
110
111
I have a problem with one task, so if you could help me a little bit.
Numbers are "lucky" or "unlucky". Number is "lucky" just if every
digit 7
or every digit is 4. So "lucky" numbers are for example 4, 44, 7, 77.
"Unlucky" are the others numbers.
You will get sequence of n-elements and number K. Your task is to
compute number of all possible k-elements subsequence, which fulfill a one
condition. The condition is that in the subsequence mustn't be two same "lucky"
numbers. So for example there mustn't 77 and 77...
Output number of all possible k-elements subsequence mod 10^9+7
0 < N,K < 10^5
Few examples:
Input:
5 2
7 7 3 7 77
Output:
7
Input:
5 3
3 7 77 7 77
Output:
4
Input:
34 17
14 14 14 ... 14 14 14
Output:
333606206
I have code which seems to work, but it is too slow when I try to compute binomial coefficient. I'm using map. In string I store number in string format. In second - int - part of the map is number which represents how many times was that number(in the first map parameter) used. So now I have stored every "unlucky" numbers stored together. Also every same "lucky" number is together. When I have it stored like this, I just compute all multiplications. For example:
Input
5 2
3 7 7 77 7
Are stored like this: map["other"] = 1 map["7"] = 3 map["77"] = 1
Because k = 2 --> result is: 1*3 + 1*1 + 1*3 = 7.
I think problem is with computing binomial coefficient. For the third example it needs to compute (34 choose 17) and it is computing very long time.I've found this article and also this , but I don't understand how they are solving this problem.
My code:
#include<iostream>
#include<string>
#include<map>
#include <algorithm>
#include <vector>
using namespace std;
int binomialCoeff(int n, int k)
{
// Base Cases
if (k == 0 || k == n)
return 1;
// Recur
return binomialCoeff(n - 1, k - 1) + binomialCoeff(n - 1, k);
}
int main()
{
int n, k;
cin >> n >> k;
map<string, int> mapa; // create map, string is a number, int represents number of used string-stored numbers ---> so if 7 was used two times, in the map it will be stored like this mapa["7"] == 2 and so on)
for (int i = 0; i < n; i++) // I will load number as string, if this number is "lucky" - digist are all 7 or all 4
{ // every "unlucky" numbers are together, as well as all same "lucky" numbers ---> so 77 and 77 will be stored in one element....
string number;
cin >> number;
char digit = number[0];
bool lucky = false;
if (digit == '7' || digit == '4')
lucky = true;
for (int j = 1; j < number.length(); j++) {
if (digit != '7' && digit != '4')
break;
if (number[j] != digit) {
lucky = false;
break;
}
}
if (lucky)
mapa[number]++;
else
mapa["other"]++;
}
vector<bool> v(mapa.size());
bool lack = k > mapa.size(); //lack of elements in map --> it is when mapa.size() < k; i. e. number of elements in array can't make k-element subsequence.
int rest = lack ? k - mapa.size() + 1 : 1; // how many elements from "unlucky" numbers I must choose, so it makes base for binomial coefficient (n choose rest)
if (lack) //if lack is true, different size of vector
fill(v.begin() + mapa.size(), v.end(), true);
else
fill(v.begin() + k, v.end(), true);
int *array = new int[mapa.size()]; //easier to manipulate with array for me
int sum = 0;
int product = 1;
int index = 0;
for (map<string, int> ::iterator pos = mapa.begin(); pos != mapa.end(); ++pos) // create array from map
{
if (lack && pos->first == "other") { //if lack of elements in map, the number in elemets representing "unlucky" numbers will be binomial coefficient (mapa["other] choose rest)
array[index++] = binomialCoeff(mapa["other"], rest);
continue;
}
array[index++] = pos->second;
}
do { // this will create every posible multiplication for k-elements subsequences
product = 1;
for (int i = 0; i < mapa.size(); ++i) {
if (!v[i]) {
product *= array[i];
}
}
sum += product;
} while (next_permutation(v.begin(), v.end()));
if (mapa["other"] >= k && mapa.size() > 1) { // if number of "unlucky" numbers is bigger than k, we need to compute all possible k-elements subsequences just from "unlucky" number, so binomial coefficient (mapa["other] choose k)
sum += binomialCoeff(mapa["other"], k);
}
cout << sum % 1000000007 << endl;
}
Here is my code for uva 3n+1 problem:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios_base::sync_with_stdio(false);
while(1){
long long n, n2, i, iConst, maximum;
vector<long long> vCycle;
cin >> n >> n2;
if(n < n2){
for(long long i = n; i <= n2; i++){
long long j = 1;
iConst = i;
while(iConst > 1){
if(iConst%2 == 0)
iConst = iConst / 2;
else
iConst = (iConst*3)+1;
j++;
}
vCycle.push_back(j);
}
}else{
for(long long i = n2; i <= n; i++){
long long j = 1;
iConst = i;
while(iConst > 1){
if(iConst%2 == 0)
iConst = iConst / 2;
else
iConst = (iConst*3)+1;
j++;
}
vCycle.push_back(j);
}
}
maximum = *max_element(vCycle.begin(), vCycle.end());
cout << n << " " << n2 << " " << maximum << endl;
}
return 0;
}
But the judge is giving the following error: "Time limit exceed".
Is there anything in my code which is using much CPU?
What's wrong with my program?
*Problem link: here
This is not the way, for few numbers it takes a lot of iterations to get the final output where they are already precalculated.
For Example
for n = 10,
10
5
16
8
4
2
1
for n = 20,
20
10
5
16
8
4
2
1
for n = 160,
160
80
40
20
10
5
16
8
4
2
1
Look at how many numbers are getting repeated, you already calculated the number of steps for 10, when calculating for n = 20, we need not calculate it again when n becomes 10 as we have done it already.
I suggest you to maintain a cache of calculated numbers and check each time if the value is pre-calculated, if yes just give the number + the existing count.
else do the math.
This is a Project Euler problem. Longest Collatz sequence is what it is called. They need more than code to solve them.
It is timing out because your algorithm is quite inefficient.
Just think of the test case given with the problem description -
22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
When you are generating the sequence for finding the answer for 22, you can also calculate the answers for every other number in the sequence.
int foo( int n )
{
if ( ans[n] has been calculated )
{
return ans[n]
}
if ( n is odd )
{
ans[n] = foo( 3n + 1 ) + 1
}
else
{
ans[n] = foo( n / 2 ) + 1
}
return ans[n]
}
where ans is an array of size 10^6.
As far as the task of finding the maximum between any 2 numbers is concerned, you can use a segment tree rather than simply finding the maximum element using a linear search