Circumference of Sierpinski triangle - c++

I'm currently doing the this problem for own practice. I manage to pass all the testcases, so I can't figure out whats wrong. My code is:
#include <iomanip>
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
int main(){
int num = 1;
while(true){
string line,stringRes;
getline(cin,line);
if(cin.eof()){break;}
long double shrinks = atof(line.c_str());
long double triangels = pow(3,shrinks);
long double length = 3/pow(2,shrinks);
long double res = floor(triangels* length * 3);
int i = 0;
while(res >= 10){
i++;
res = res/10;
};
if(shrinks == 1){
printf("Case %d: %d\n",num ,1);
}else{
printf("Case %d: %d\n",num ,i+1);
}
num++;
}
return 0;
}
for exampel when I input 1000 I get 178 and 10000 I get 1762.
Input Sample
0
1
5
10
100
Output Samle
Case 1: 1
Case 2: 1
Case 3: 2
Case 4: 3
Case 5: 19
For each case, display the case number followed by the number of decimal digits required to represent the integer portion of the circumference for the given number of iterations. Follow the format of the sample output.

The reason you get the wrong result is, as described earlier: you get overflow by using pow, but also because you - as you seem to have realized - used 3 as your start side length.
Here is an alternative, and correct, solution that is a bit shorter (without overflow):
The circumference (or perimeter) P(n) of a Sierpinski triangle of order n >= 0 can be shown to be:
P(n) = 3^(n + 1) / 2^n
I don't provide a proof since it's not necessary to solve the problem. However, it's rather easy to understand that this must be the case. One way is by calculating the perimeter of the first few orders of the Sierpinski triangle: 3, 9/2, 27/4, 81/8, ..., another is to think about how the circumference changes when you (1) "shrink" the shape by a factor of ½ and (2) "extend" the triangle by a factor of 3.
The number of digits D(x) in any natural number (of base 10) x is:
D(x) = 1 + floor(log10(x))
So to calculate the number of decimal digits in the Sierpinski perimeter of order n we calculate the number of digits in the integer part of P(n) = 3^(n + 1) / 2^n, i.e. D(floor(P(n))), which is also the solution to the problem:
D(floor(P(n))) = 1 + floor(log10(3^(n + 1) / 2^n)) = /log(a/b) = log(a) - log(b)/ =
= 1 + floor(log10(3^(n + 1)) - log10(2^n)) = /log10(a^b) = b * log10(a)/ =
= 1 + floor((n + 1) * log10(3) - n * log10(2))
C++ implementation that solves the problem:
/** Calculates the number of digits in the integer part of the perimeter of the Sierpinski triangle of order n */
/** Author: Fredrik Präntare, Date: 19/3/2016 */
#include <iostream>
#include <algorithm> // log10, floor
using namespace std;
int main(){
int c = 1, n;
while(scanf("%d", &n) != EOF){
int D_p = 1 + floor((n + 1) * log10(3) - n * log10(2));
printf("Case %d: %d\n", c, D_p);
c++;
}
}

You are overflowing the value of triangels. When you have
long double triangels = pow(3,shrinks);
Where shrinks = 10000 gives: 1.6313501853426258743032567291812e+4771.
The range of a long double where sizeof(long double) == 8 is 1.7E +/- 308.
More than likely you will need to use modular exponentiation to solve this problem.

Related

Function for calculating Pi using taylor series in c++

So I'm at a loss on why my code isn't working, essentially the function I am writing calculates an estimate for Pi using the taylor series, it just crashes whenever I try run the program.
here is my code
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
double get_pi(double accuracy)
{
double estimate_of_pi, latest_term, estimated_error;
int sign = -1;
int n;
estimate_of_pi = 0;
n = 0;
do
{
sign = -sign;
estimated_error = 4 * abs(1.0 / (2*n + 1.0)); //equation for error
latest_term = 4 * (1.0 *(2.0 * n + 1.0)); //calculation for latest term in series
estimate_of_pi = estimate_of_pi + latest_term; //adding latest term to estimate of pi
n = n + 1; //changing value of n for next run of the loop
}
while(abs(latest_term)< estimated_error);
return get_pi(accuracy);
}
int main()
{
cout << get_pi(100);
}
the logic behind the code is the following:
define all variables
set estimate of pi to be 0
calculate a term from the taylor series and calculate the error in
this term
it then adds the latest term to the estimate of pi
the program should then work out the next term in the series and the error in it and add it to the estimate of pi, until the condition in the while statement is satisfied
Thanks for any help I might get
There are several errors in your function. See my comments with lines starting with "//NOTE:".
double get_pi(double accuracy)
{
double estimate_of_pi, latest_term, estimated_error;
int sign = -1;
int n;
estimate_of_pi = 0;
n = 0;
do
{
sign = -sign;
//NOTE: This is an unnecessary line.
estimated_error = 4 * abs(1.0 / (2*n + 1.0)); //equation for error
//NOTE: You have encoded the formula incorrectly.
// The RHS needs to be "sign*4 * (1.0 /(2.0 * n + 1.0))"
// ^^^^ ^
latest_term = 4 * (1.0 *(2.0 * n + 1.0)); //calculation for latest term in series
estimate_of_pi = estimate_of_pi + latest_term; //adding latest term to estimate of pi
n = n + 1; //changing value of n for next run of the loop
}
//NOTE: The comparison is wrong.
// The conditional needs to be "fabs(latest_term) > estimated_error"
// ^^^^ ^^^
while(abs(latest_term)< estimated_error);
//NOTE: You are calling the function again.
// This leads to infinite recursion.
// It needs to be "return estimate_of_pi;"
return get_pi(accuracy);
}
Also, the function call in main is wrong. It needs to be:
get_pi(0.001)
to indicate that if the absolute value of the term is less then 0.001, the function can return.
Here's an updated version of the function that works for me.
double get_pi(double accuracy)
{
double estimate_of_pi, latest_term;
int sign = -1;
int n;
estimate_of_pi = 0;
n = 0;
do
{
sign = -sign;
latest_term = sign * 4 * (1.0 /(2.0 * n + 1.0)); //calculation for latest term in series
estimate_of_pi += latest_term; //adding latest term to estimate of pi
++n; //changing value of n for next run of the loop
}
while(fabs(latest_term) > accuracy);
return estimate_of_pi;
}
Your return statement may be the cause.
Try returning "estimate_of_pi" instead of get_pi(accuracy).
Your break condition can be rewritten as
2*n + 1 < 1/(2*n + 1) => (2*n + 1)^2 < 1
and this will never be true for any positive n. Thus your loop will never end. After fixing this you should change the return statement to
return estimated_error;
You currently are calling the function recursively without an end (assuming you fixed the stop condition).
Moreoever you have a sign and the parameter accuracy that you do not use at all in the calculation.
My advice for such iterations would be to always break on some maximum number of iterations. In this case you know it converges (assuming you fix the maths), but in general you can never be sure that your iteration converges.

Approximating a conical frustum with binary search algorithm

I'm trying to solve this problem.
The description states that some friends have a bottle of coke and they want to equally divide it in cups and I need to help the group to split the Coke bottle.
To solve this I need the height h such that, if each cup is filled with Coke up to the height h, then each person gets the same amount of coke. You may assume that no cup will needed to be filled more than its capacity.
The information given to me is the radius of the top and bottom of the cup with its height.
Input description:
The first line of input contains an integer C that determines the number of test cases. Each test case starts with a line containing two integers, N and L (1 ≤ N ≤ 100, 1 ≤ L ≤ 10^8), the number of friends in the group and the amount of Coke in the bottle, in milliliters. The second line contains three integers b, B and H (1 ≤ b ≤ B ≤ 100, 1 ≤ H ≤ 100), the radius of the smaller and the larger base, and the height of the cups, in centimeters.
The output description :
For each test case, print the value of h such that all cups must be filled up to the height h cm. Print the answer with 2 decimal places.
Example of Input:
2
1 200
5 6 8
2 350
3 3 16
Example of Output:
2.40
6.19
My solution.
With the data given in the question it was necessary to find the radius of the top of the coke amount (like a frustum inside a frustum O.o where the data given correspond to the outside frustum)
With the radius of the coke amount the binary search algorithm can 'guess' the best h.
#include <stdio.h>
#include <math.h>
#define EPS 0.001
typedef long long lld;
int main(){
lld c,n,l,b,B,H; //names are described in the input
scanf("%lld",&c);
for (lld i = 0; i < c; ++i) {
scanf("%lld %lld %lld %lld %lld",&n,&l,&b,&B,&H);
double v = l/n;//volume expected for each cup
double ini = 0,fim = H, mid = 0.0; //mid will be the 'h'
double v_approximate = 0;
while(fabs(v - v_approximate) > EPS){
mid = (ini + fim)/2.0;
double tmp = b + (B-b)*mid/H; //this is the radius of the coke top
v_approximate = (M_PI*mid/3.0)*(tmp*tmp + tmp*b + b*b);
if(v_approximate == v)
break;
else if(v_approximate > v)
fim = mid;
else
ini = mid;
}
printf("%.2lf\n",mid);
}
}
This code gives 10% of wrong answer. This is the first time that i tried to use approximation to solve a math question. What am i missing ?

Sum exceeding permissible value in looping floats

I recently created this simple program to find average velocity.
Average velocity = Δx / Δt
I chose x as a function of t as x = t^2
Therefore v = 2t
also, avg v = (x2 - x1) / (t2 - t1)
I chose the interval to be t = 1s to 4s. Implies x goes from 1 to 16
Therefore avg v = (16 - 1) / (4 - 1) = 5
Now the program :
#include <iostream>
using namespace std;
int main() {
float t = 1, v = 0, sum = 0, n = 0; // t = time, v = velocity, sum = Sigma v, n = Sigma 1
float avgv = 0;
while( t <= 4 ) {
v = 2*t;
sum += v;
t += 0.0001;
n++;
}
avgv = sum/n;
cout << "\n----> " << avgv << " <----\n";
return 0;
}
I used very small increments of time to calculate velocity at many moments. Now, if the increment of t is 0.001, The avg v calculated is 4.99998.
Now if i put increment of t as 0.0001, The avg v becomes 5.00007!
Further decreasing increment to 0.00001 yields avg v = 5.00001
Why is that so?
Thank you.
In base 2 0.0001 and 0.001 are periodic numbers, so they don't have an exact representation. One of them is being rounded up, the other one is rounded down, so when you sum lots of them you get different values.
This is the same thing that happens in decimal representation, if you choose the numbers to sum accordingly (assume each variable can hold 3 decimal digits).
Compare:
a = 1 / 3; // a becomes 0.333
b = a * 6; // b becomes 1.998
with:
a = 2 / 3; // a becomes 0.667
b = a * 3; // b becomes 2.001
both should (theoretically) result into 2 but because of rounding error they give different results
In the decimal system, since 10 is factorised into primes 2 and 5 only fractions whose denominator is divisible only by 2 and 5 can be represented with a finite number of decimal digits (all other fractions are periodic), in base 2 only fractions which have as denominator a power of 2 can be represented exactly. Try using 1.0/512.0 and 1.0/1024.0 as steps in your loop. Also, be careful because if you choose a step that is too small, you may not have enough digits to represent that in the float datatype (i.e., use doubles)

O(N^2) shortest path algorithm

The problem states that we have a set of points with their coordinates and that we have to find the shortest path always beginning at (0,0) reaching a destination and going back again to (0,0) passing all inbetween points only once.
The input looks like this
on the first line are the number of inbetween points, on the second the coordinates of the destination and then the coordinates of all inbetween points. No inbetween points have the same x coordinate and the x coordinate of each inbetween point is less than that of the destination.
5
6 5
1 1
2 3
3 2
4 4
5 3
I have an implementation of the problem in the programming language C++ but the problem is I can't understand it. I've gone through it step by step but I can't understand what it does.
#include <fstream>
#include <cmath>
#include <algorithm>
#include <limits>
using namespace std;
const double inf = numeric_limits<double>::max(); // an infinite number
double dist [205][205] = {0};
double res [205][205] = {0};
int N (0);
struct point {
double x,y;
point(int a,int b):x(a),y(b){}
point(){}
}points[205]; //struct to store inbetween points
inline const bool operator < ( const point &a, const point &b ){
return a.x < b.x;
}
int main()
{
ifstream in ("evripos.in");
ofstream out ("evripos.out");
in>>N;
N+=2;
int t1,t2;
points[0]= point(0,0);
// stores all points
for(int i=1;i<N;++i){
in>>t1>>t2;
points[i]=point(t1,t2);
}
in.close();
sort(points,points+N); // sorts all points according to their x coordinate
// creates a 2 dimensional array of the distances between all points
// called dist
for(int i=0;i<N;++i)
for(int j=0;j<N;++j){
dist [i][j]= sqrt( pow(points[i].x-points[j].x,2) + pow(points[i].y-points[j].y,2));;
res[i][j]=inf;
}
// computes the result, using a 2 dimensional array called res
res[0][0]=0;
for(int i=0;i<N;++i)
for(int j=0;j<N;++j){
res[i+1][i] = min (res[i+1][i], res[i][j] + dist[j][i+1]);
res[i+1][j] = min (res[i+1][j], res[i][j] + dist[i][i+1]);
res[i+1][i+1] = min (res[i+1][i+1], res[i][j] + dist[i][i+1] + dist[i+1][j]);
}
out<<round(res[N-1][N-1])<<endl; //stores the end result
out.close();
}
I've found out that it is a dynamic programming problem and as I understand it the whole logic is in here
res[0][0]=0;
for(int i=0;i<N;++i)
for(int j=0;j<N;++j){
res[i+1][i] = min (res[i+1][i], res[i][j] + dist[j][i+1]);
res[i+1][j] = min (res[i+1][j], res[i][j] + dist[i][i+1]);
res[i+1][i+1]= min (res[i+1][i+1], res[i][j] + dist[i][i+1] + dist[i+1][j]);
}
What exactly is the logic behind this? How is this problem solved with dynamic programming?
This is Bitonic tour problem. You have a list of cities, from 0 to N-1, you need to start from city 0, go through each cities once to reach N-1 and from N-1 go back to 0.
In order to solve the problem, we need to change the way we look at it. Imagine there is not one, but two people starting from city 0, each of them will never be at same city (except 0 and N-1) and they all try to reach city N-1. So if we add the path taken by Person one and Person two, we have the answer for the original problem.
So, we have our int [][]res, with res[i][j] means the minimum total distance for Person one is at city i and Person two is at city j. We observe that this line
res[i+1][i] = min (res[i+1][i], res[i][j] + dist[j][i+1]);
means the Person two starting from city j will go to city i + 1. Notice that i + 1 , not i, which will avoid the case when two persons being at same city. (Also notice that the role of i and j can be interchangeable)
Similarly
res[i+1][j] = min (res[i+1][j], res[i][j] + dist[i][i+1]);
means Person one starting from i go to city i + 1.
Finally, assume that the destination is at i + 1, we have
res[i+1][i+1]= min (res[i+1][i+1], res[i][j] + dist[i][i+1] + dist[i+1][j]);
Note: By the way we increase the index from i to i + 1 in the outer for loop, we also guarantee that all city from 0 to i had been reached (by either Person one or two) before city i + 1 has been reached.
So, the answer for the problem will be at res[N-1][N-1]
Hope that's help!

Distribute prizes for a tournament system

I'm looking for a way to distribute a number across x units. I don't even know how to put this words so I'll give an example:
There's a tournament in which the total prize is $1000. I want that the top 20 winners/entrants will win something out of it.I need a mathematical algorithm/formula which will distibute it across those players, and which gives me the power to control certain other factors of the distribution.
A factor for example is that I want the top #1 winner will get $300. The top #2 winner will get smaller percentage of it. The total distribution must give everyone something, until the top #20 winner (the last one) which will get at least X$.
X$ is another factor I want to control.
Any idea? Does this problem has a name (and what's that name is)? Any code example?
Edit #1 - my first proposal:
#include <conio.h>
#include <vector>
#define TOTAL 100
#define WINNERS 15
#define FIRST_WINNER_PERCENTAGE 0.30
void distribute_1(::std::vector<double> * const prizes)
{
prizes->clear();
double total = TOTAL;
double winning_percentage = FIRST_WINNER_PERCENTAGE;
double slope = 0.5;
int winners = WINNERS;
double winning = 0;
for(int i = 0; i < winners; i++, total -= winning, winning_percentage /= 2)
{
winning = total * winning_percentage;
prizes->push_back(winning);
}
}
void distribute_2(::std::vector<double> * const prizes)
{
prizes->clear();
double total = TOTAL;
double winning_percentage = FIRST_WINNER_PERCENTAGE;
double slope = 0.5;
int winners = WINNERS;
double winning = 0;
for(int i = 0; i < winners; i++, total -= winning/*, winning_percentage /= 2*/)
{
winning = total * winning_percentage;
prizes->push_back(winning);
}
}
void distribute_3(::std::vector<double> * const prizes)
{
prizes->clear();
double total = TOTAL;
double winning_percentage = FIRST_WINNER_PERCENTAGE;
double slope = 0.0005;
int winners = WINNERS;
double winning = 0;
for(int i = 0; i < winners; i++, total -= winning, winning_percentage -= slope)
{
winning = total * winning_percentage;
prizes->push_back(winning);
}
}
void distribute_4(::std::vector<double> * const prizes)
{
prizes->clear();
double total = TOTAL;
double winning_percentage = FIRST_WINNER_PERCENTAGE;
double slope = 1 / WINNERS;
int winners = WINNERS;
double winning = 0;
for(int i = 0; i < winners; i++, total -= winning, winning_percentage -= slope)
{
winning = total * winning_percentage;
prizes->push_back(winning);
}
}
void main()
{
::std::vector<double> prizes;
distribute_1(&prizes);
distribute_2(&prizes);
distribute_3(&prizes);
distribute_4(&prizes);
double total_granted = 0;
for(int i = 0; i < WINNERS; i++)
{
total_granted += prizes[i];
printf("%lf\n", prizes[i]);
}
printf("-\n%lf\n", total_granted);
_getch();
}
This is as far as I could reach. The issue with this one is for example, if that if you set 'WINNERS' to 5 for example, the algorithm doesn't reach the 'TOTAL' amount (100 in this example) or even closer (I get a total of 83).
Cristy's solution:
#include <conio.h>
#include<iostream>
//using arithmetic progression
using namespace std;
int i;
float ratio;
float first_prize;
float s;
int main()
{
float money=1000;
const int total_prizes = 10;
float last_prize = 99;
float prizes[total_prizes+1];
/**/first_prize=2*money/total_prizes-last_prize; //last member of the progresion
ratio=(first_prize-last_prize)/(total_prizes-1);
prizes[total_prizes]=last_prize;
for(i=total_prizes-1;i>=1;i--){
prizes[i]=prizes[i+1]+ratio;
money-=prizes[i];
}
for(i=1;i<=total_prizes;i++){
printf("%d) %.2f\n",i,prizes[i]);
s+=prizes[i];
}
printf("TOTAL SUM:%.2f\n",s);
printf("Ratio: %.2f", ratio);
_getch();
}
It's 1:15 AM here and I'm solving maths :)).
Using arithmetic progression.
I made all using defines so you can easily change them.
#include<iostream>
//using arithmetic progression
using namespace std;
FILE *g=fopen("output.out","w");
#define last_prize 10
#define total_prizes 20
int i;
float prizes[total_prizes+1];
float money=1000;
float ratio;
float first_prize;
float s;
//a1=last_prize
//an=first_prize
int main(){
first_prize=2*money/total_prizes+last_prize; //last member of the progresion
ratio=(first_prize-last_prize)/(total_prizes-1);
prizes[total_prizes]=last_prize;
for(i=total_prizes-1;i>=1;i--)
prizes[i]=prizes[i+1]+ratio;
for(i=1;i<=total_prizes;i++){
fprintf(g,"%d) %.2f\n",i,prizes[i]);
s+=prizes[i];
}
fprintf(g,"TOTAL SUM:%.2f",s);
return 0;
}
OUTPUT:
1) 90.00
2) 85.79
3) 81.58
4) 77.37
5) 73.16
6) 68.95
7) 64.74
8) 60.53
9) 56.32
10) 52.11
11) 47.89
12) 43.68
13) 39.47
14) 35.26
15) 31.05
16) 26.84
17) 22.63
18) 18.42
19) 14.21
20) 10.00
TOTAL SUM:1000.00
As you can see they sum up to exactly 1000.00$ :D
Other results:
INPUT:
#define last_prize 30
#define total_prizes 5
OUTPUT:
1) 370.00
2) 285.00
3) 200.00
4) 115.00
5) 30.00
TOTAL SUM:1000.00
You could make a simple formula like.
#include<iostream>
using namespace std;
FILE *g=fopen("output.out","w");
int i;
int prizes[21];
int money=1000;
int main(){
for(i=1;i<=20;i++){
prizes[i]=(float)(15+(20-i))/100*money;
money-=prizes[i];
fprintf(g,"%d) %d\n",i,prizes[i]);
}
return 0;
}
This will output:
1) 340
2) 217
3) 141
4) 93
5) 62
6) 42
7) 29
8) 20
9) 14
10) 10
11) 7
12) 5
13) 4
14) 3
15) 2
16) 2
17) 1
18) 1
19) 1
20) 0
But you can change the values to anything you would like :).
This is just a fast&easy way to do this.
The starting ideea for this algorithm was:
1st prize: 30% from all the money (1000$) = ~330$
2nd prize: 30% from the rest (670$) = ~201
3rd prize: 30% from the rest... etc...
If you replace (15+(20-i)) with 20 let's say, you get this output:
Just change that value to get diffrent results.
1) 200
2) 160
3) 128
4) 102
5) 82
6) 65
7) 52
8) 42
9) 33
10) 27
11) 21
12) 17
13) 14
14) 11
15) 9
16) 7
17) 6
18) 4
19) 4
20) 3
EDIT:
And one more thing. After splitting all the money using that algorithms there may still be some money left (because the last one gets x% from the rest). You can add the left-over to the first place...
I had this problem for a pool - I wanted the 3 levels of individual prizes to have the same relative ratio (70%/20%/10%) but recognized the likelyhood of ties, so I had to account for that. I didn't want to just split the pot then award prizes since you might end up with ties for second and an individual second place winner getting less than the third place winner.
P(i) = Size of Prize
N(i) = Number of winners
1) Sum (over i) P(i)*N(i) = $1000
2) P(1)/P(2) = 70/20
3) P(2)/P(3) = 20/10
In my case, 3 equations in 3 unknowns - which I solved to get a unique solution.
For your example P(1) = $300. I would just specify successive ratios of prizes and solve the linear system of equations.
Also consider looking here for the distribution of golf prizes at the recent British Open Championship. I'm not saying that the PGA could do a better job than the talent at this website, but it a demonstration of your question in action.
Suppose total money M, you want distribute in n pools such that first person will get k times more than second and second gets k times more than third and so on. Suppose last one get x amount money then
x + k*x + k^2*x ... k^(n-1)*x = M
x(k^n-1)/(k-1) = M
Solve for x from this equation based on value of k you choose and distribute money :-)
Formula in first line of Cristy is wrong.
first_prize=2*money/total_prizes+last_prize;
It should be first_prize=2*money/total_prizes - last_prize;
Here is my solution in python, this will add residual amount to top winners.
starting_amount = (((winnings * 2) / float(no_of_winners)) - last_amount)
difference = (last_amount - starting_amount) / float(no_of_winners - 1)
for rank in range(1, no_of_winners + 1):
reward = starting_amount + difference * (rank - 1)
reward = round_amount(reward)
winnings -= reward
winning_amount[rank] = reward
residual_winnings = winnings
residual_shares = {1: 0.5, 2: 0.3, 3: 0.2}
if no_of_winners < 3:
winning_amount[1] += residual_winnings
else:
for rank in residual_shares:
reward = residual_winnings * residual_shares[rank]
reward = round_amount(reward)
winning_amount[rank] += reward
I spent a few hours trying to come up with an algorithm that will distribute prizes. Here is my solution based off things I saw on various forums. This code is in Ruby. This has worked great for me.
def self.get_prize_array(money,total_prizes)
prizes = []
p = 0.7 # tweek this for distribution of payout
n = total_prizes
l = money
(1..total_prizes).each do |r|
prizes[r-1] = ((1 - p) / (1 - p**n) * p**(r - 1)) * l # p**n is p to the nth power
end
return prizes
end