Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Thanks in advance.
For my c++ class, i am tasked with representing a polynomial such as (MyPoly= 7x^6*y^4 + 4x^4*y^5 - 8x^5*y^3 – 9x + 8) using linked lists and building Node & Poly classes to help express it.
I don't know how to represent a polynomial with both an X and Y in linked list.
I have an idea of building a linked list to represent the polynomial like 7 6 4 -> 4 4 5 -> -8 5 3 ->-9 1 0 -> 8 0 0 ->NULL
I am new to this so any example code or pseudo code would be of great help.
Attempted setup
I came up with this code here(starting point) but i think it will only work for having a single variable and not two (7x^6*... but not 7x^6*y^4). Thanks again :).
have you thought, or are you allowed to work with the Horner's representation of polynomials? It's not only a much more efficient way to calculate the polynomial values, but can in many cases lead to a more sparse datastructure. For example, the polynom:
is equivalent to the following expression:
So there are 3 things to note:
Actually the one remarkable thing of this schema (although not directly related to your question) is that its calculation is much faster, since you save a lot of multiplications.
The index of the polynom depends directly on the length of the expression
All elements in the expression are isomorph, independently of the degree. This is also true for each arity.
So in this lucky case the polynom I chose could be very easily and efficiently stored as the following list/array:
[7, 5, 1, -4, 1, 8, 1, -7]
or if you want, as a linked list of [x_mult|sum] numbers:
[7|5]->[1|4]->[1|8]->[1|-7]
whereas you know that the elements with even indexes are multiplied by x, and added to the following element, the schema is quite simple.
#include <iostream>
using namespace std;
int main()
{
// the x you want to calculate
int x = 1;
// the horner-representation of your polynom
int A[8] {7, 5, 1, -4, 1, 8, 1, -7};
int partial;
int result = 1;
// run calculations following horner-schema
for (int i = 0; i < 8; i++) {
if (i%2==0){
partial = A[i]*x; // this mult. is only needed at i=0
result *= partial;
} else{
partial = A[i];
result += partial;
}
}
cout << "x=" << x << ", p(x)=" << result << endl;
return 0;
}
Issues: You could greatly improve its performance and memory usage if you supress the odd indexes, and take the "1"'s as granted, storing the first 7 elsewhere. Also since the index depends directly on the list's length, polynoms like
would have a very inefficient representation.
Workaround for the memory issues: A possible workaround would be to inherit your ListElement as ExpandedListElement, so that the numbers in its containers aren't interpreted as factors but as number of repetitions. So the ExpandedListElement [1000|a] would mean, that your list has one thousand ListElements that look like this: [1|a]. So the x^1000+3 given example would have two elements: ExpandedListElement[999|0]-->ListElement[1|3]. You would also need a method to perform the loop, which I omit (if you need this workaround let me know, and I'll post it).
I didn't test it extensively, but I assume it's a good approach also for two or more variables. I left also the rest of the OO-implementation details apart, but the core DS and operations are there and should be easy to embed in classes. If you try it, let me know how it works!
Cheers
Andres
I think, you can represent polynominal with a matrix not a linked list or something.
|X^0|x^1|x^2|x^3
---|---|---|---|---
y^0| | | |
---|---|---|---|---
y^1| | | |
---|---|---|---|---
y^2| | | |
---|---|---|---|---
y^3| | | |
In each cell you should keep the coefficients of x^x' and y^y'. And you can define operations more easily.
You can use Boost.uBLAS for matrix operations.
Fast solution not so clean:
MyPoly= 7x^6*y^4 + 4x^4*y^5 - 8x^5*y^3 – 9x + 8
#include <list>
class factor;
class polynomial{
public:
std::list<factor> factors;
};
class factor{
public:
factor()=default;
factor(int constant,int x_pow,int y_pow):constant(constant),x_pow(x_pow),y_pow(y_pow){}
int constant;
int x_pow;
int y_pow;
};
int main()
{
polynomial MyPoly;
MyPoly.factors.emplace_back(7,6,4);
MyPoly.factors.emplace_back(4,4,5);
MyPoly.factors.emplace_back(8,5,3);
MyPoly.factors.emplace_back(9,1,0);
MyPoly.factors.emplace_back(8,0,0);
}
This would be one way of doing it:
Design Considerations:
1. Consider Polynomial as a list of nodes
2. Each node can consist sub-nodes.
So, your class definitions would be:
class Polynomial
{
list<nodes> termList;
};
class Node
{
list<SubNodes> subnodelist;
};
template<class T>
class subNode
{
int coefficient;
int power;
T variable;
};
Note: Not tested the code for correctness.
Related
Problem Statement:
Given n items with size Ai, an integer m denotes the size of a backpack. How full you can fill this backpack?
Example
Example 1:
Input: [3,4,8,5], backpack size=10
Output: 9
Example 2:
Input: [2,3,5,7], backpack size=12
Output: 12
I have to write solution using memoization , I know bottom up dp will be quite fast ,But can you help me with other optimisation that i can add in this solution.
class Solution {
public:
unordered_map<string,int>m1;
int solve(int m,vector<int>&a,int i){
if(i<0)return 0;
string s = to_string(m)+" "+to_string(i);
if(m1.count(s))return m1[s];
int val=0;
if(m-a[i]>=0)val = a[i] + solve(m-a[i],a,i-1);
return m1[s]=max(val,solve(m,a,i-1));
}
int backPack(int m, vector<int> &a) {
// write your code here
return solve(m,a,int(a.size()-1));
}
};
Consider creating a hash of two integers m and i by following an approach like this
and use that as key in your map. You should see an improvement in runtime although bottom up solution is superior.
In your code, the to_string takes time and also it takes more time to look up for the string than you think as mentioned in the comments.
I am finding it difficult to understand two specific implementations which solve this problem on codeforces link.
I understand this is similar to the knapsack problem. However when i solved it myself, i was not aware of the algorithm. I solved it from my own understanding of dynamic programming. My idea is to regard the remaining length of the ribbon as the next state. Here's my code
#include<iostream>
using namespace std;
int main(){
int n,res1=0,res2,x=0;
int a,b,c;
cin >> n >> a >> b >> c;
for(int i=0;i <= n/a; i++){
res2 = -20000;
for(int j=0; j <= (n-(a*i))/b; j++){
x = (n - (a*i) - (b*j));
res2=max(res2,(j + ((x % c) ? -10000 : x/c)));
}
res1=max(res1,i+res2);
}
cout << res1 << endl;
return 0;
Implementation 1:
1 #include <bits/stdc++.h>
2 using namespace std;
3 int main()
4 {
5 int f[4005],n,a,i,j;
6 fill(f+1,f+4005,-1e9);
7 cin>>n;
8 for(;cin>>a;)
9 for(i=a;i<=n;i++)
10 f[i]=max(f[i],f[i-a]+1);
11 cout<<f[n];
12 }
Implementation 2:
1 #include <bits/stdc++.h>
2 int n, a, b, c, ost;
3 std::bitset<4007> mog;
4 main()
5 {
6 std::cin>>n>>a>>b>>c;
7 mog[0]=1;
8 for (int i=1; i<=n; i++)
9 if ((mog=((mog<<a)|(mog<<b)|(mog<<c)))[n])
10 ost=i;
11 std::cout << ost;
12 }
Though i understand the general idea of solving the knapsack problem. I do not have a clear understanding of how lines 8,9,10 in Implementation 1 achieve this. Specifically irrespective of the input values of a,b,c the inner for loop is a single pass over the array for the corresponding value a received.
Similarly, I can see that lines 8,9,10 in implementation 2 does the same thing. But i have no clue at all how this piece of code works.
Please help me understand this. I feel there is some hidden structure to these two solutions which i am not seeing. Thanks in advance.
Implementation 1
This is quite straightforward implementation of dynamic programming.
Outer loop just goes through three values: a, b, and c
8 for(;cin>>a;)
Inner loop visits every element of an array and updates current best known number of cuts for given ribbon length.
9 for(i=a;i<=n;i++)
10 f[i]=max(f[i],f[i-a]+1);
Implementation 2
I don't think that it can be called dynamic programming, but the trick is quite neat.
It allocates array of bits with length equal to max n. Then sets one bit on the left. It means, that ribbon with length of 0 is a valid solution.
On each iteration algorithm shifts given array to the left by a, b, and c. Result of each such shift can be viewed as the new valid sizes of ribbon. By oring result of all 3 shifts, we get all valid sizes after i'th cut. If n'th bit set we know ribbon of size n can be cut i times without remainder.
n = 10
a = 2
b = 3
c = 5
i=1:
0|0000000001 // mog
0|0000000100 // mog<<a
0|0000001000 // mog<<b
0|0000100000 // mog<<c
0|0000101100 // mog=(mog<<a)|(mog<<b)|(mog<<c)
^ here is a bit checked in 'if' statement '(mog=(...))[n]'
i=2:
0|0000101100 // mog
0|0010110000 // mog<<a
0|0101100000 // mog<<b
1|0110000000 // mog<<c // here we have solution with two pieces of size 5
1|0111110000 // (mog<<a)|(mog<<b)|(mog<<c)
^ now bit set, so we have a solution
We know that there is exactly i cuts at that point, so we set ost=i. But we found the worst solution, we have to keep going until we are sure that there is no more solutions.
Eventually we will reach this state:
i=5:
1|1100000000 // mog
1|0000000000 // mog<<a // 5 pieces of size 2
0|0000000000 // mog<<b
0|0000000000 // mog<<c
1|0000000000 // (mog<<a)|(mog<<b)|(mog<<c)
Here it is the last time when bit at position n will be set. So we will set ost=5 and will do some more iterations.
Algorithm uses n as upper bound of possible cuts, but it's obvious that this bound can be improved. For example n / min({a,b,c}) should be sufficient.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Below is the C++ code for Kruskal's algorithm for finding the minimum cost spanning tree of a graph given by my instructor.
I did not understand the code well. I want to know exactly what part of the code is checking for formation of a cycle in the growing forest of included edges.
I also want to know that what exactly is the purpose of the parent[] array.
Also, is it a better way than checking for cycles using DFS (depth first search)?
Here is the code:
#include<stdio.h>
#include<stdlib.h>
int i, j, k, a, b, u, v, n, ne = 1;
int min, mincost = 0, cost[9][9], parent[9];
int find(int);
int uni(int, int);
int main()
{
printf("\n\tImplementation of Kruskal's algorithm\n");
printf("\nEnter the no. of vertices:");
scanf("%d",&n);
printf("\nEnter the cost adjacency matrix:\n");
for (i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
scanf("%d",&cost[i][j]);
if(cost[i][j] == 0)
cost[i][j] = 999;
}
}
printf("The edges of Minimum Cost Spanning Tree are\n");
while(ne < n)
{
for(i = 1, min = 999; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
if(cost[i][j] < min)
{
min = cost[i][j];
a = u = i;
b = v = j;
}
}
}
u = find(u);
v = find(v);
if(uni(u,v))
{
printf("%d edge (%d, %d) =%d\n", ne++, a, b, min);
mincost += min;
}
cost[a][b] = 999;
}
printf("\n\tMinimum cost = %d\n",mincost);
}
int find(int i)
{
while(parent[i])
i = parent[i];
return i;
}
int uni(int i,int j)
{
if(i!=j)
{
parent[j]=i;
return 1;
}
return 0;
}
Note:
I am aware that the code is messed up a bit and user input will result in failure in case the user enters a value more than 9, but I don't want to focus on that part without understanding how it works. I just know that it selects the minimum cost edge, checks it for the formation of the cycle and then sets its value to infinity (here 999). I don't know how and where it is checking for cycle formation. Please help by explaining.
The code inside the while loop in main finds the lightest edge that has not yet been considered. That edge is between nodes u and v. The edge can form a cycle only if u and v already belong to the same tree.
This:
u=find(u);
v=find(v);
finds the roots of the trees to which u and v belong. Then main passes those two roots to uni:
if(uni(u,v))
...
int uni(int i,int j)
{
if(i!=j)
{
parent[j]=i;
return 1;
}
return 0;
}
If the two roots are the same, the code does nothing, the edge is not used.
I want to know exactly what part of the code is checking for formation of a cycle in the growing forest of included edges. I also want to know that what exactly is the purpose of the parent[] array.
You seem to understand the general idea of Kruskal's algorithm, but not some of the more important details. In particular, I have to assume that you do not understand the central and essential use of a "disjoint set" (a.k.a. "set union" and other names) data structure in this algorithm. For if you did, you would surely recognize that in your code, that is the role served by the parent array. Even if you didn't guess from the name, the find() and uni() functions are a dead giveaway.
The code uses the disjoint set structure to track which groups of vertices are connected by the edges so far added to the graph. The find() function determines which set a given vertex belongs to, and candidate edges are rejected if the two vertices belong to the same set. The uni() function combines two sets into one when two subgraphs are joined by accepting an edge.
Also, is it a better way than checking for cycles using DFS (depth first search)?
Performance details depend somewhat on the implementation of disjoint set. The one here is particularly simple, but more sophisticated ones can reduce the amortized cost of searches, for a better performance bound on the algorithm overall than can be achieved by using DFS instead.
Alright. Before proceeding to the explanation feel free to take a second and read this wonderfully written tutorial on Kruskal's Algorithm over on HackerEarth so that you have a general idea of what to look for.
Now as for the algorithm:
Note: First of all ignore the first three lines, just look at the code in main and assume that all variables are declared before hand.
Now let's begin:
printf("\n\tImplementation of Kruskal's algorithm\n");
printf("\nEnter the no. of vertices:");
scanf("%d",&n);
printf("\nEnter the cost adjacency matrix:\n");
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&cost[i][j]);
if(cost[i][j]==0)
cost[i][j]=999;
}
}
Those first lines ask for the number of vertices and an adjacency matrix with the cost of each vertex to any other vertex. It also looks like that when there isn't any edge connecting 2 vertices the cost is set to 999 so that it doesn't bug the code when set at 0.
Here is what an adjacency matrix looks like.
Assume that your graph looks like this
The adjacency matrix would be the following:
1 2 3
_________
1| 0 0 11
2| 0 0 0
3| 11 6 0
Meaning that 1 is connected to 3 with cost 11. 2 isn't connected with any vertex and 3 is connected to 1 with cost 11 and to 2 with cost 6. The code above would change the above matrix to:
1 2 3
_____________
1| 999 999 11
2| 999 999 999
3| 11 6 999
So that the algorithm doesn't pick 0 as minimum cost. And avoids selecting non-connected vertices.
After that we have:
printf("The edges of Minimum Cost Spanning Tree are\n");
while(ne < n)
{
for(i=1,min=999;i<=n;i++)
{
for(j=1;j <= n;j++)
{
if(cost[i][j] < min)
{
min=cost[i][j];
a=u=i;
b=v=j;
}
}
}
u=find(u);
v=find(v);
if(uni(u,v))
{
printf("%d edge (%d,%d) =%d\n",ne++,a,b,min);
mincost +=min;
}
cost[a][b]=999;
}
printf("\n\tMinimum cost = %d\n",mincost);
Firstly you have to know that Kruskal's algorithm uses Connected Components to figure out whether 2 vertices are connected or not(this is also the reason why kruskal's algorithm doesn't create circles). So let's what the code does.
for(i=1,min=999;i<=n;i++)
{
for(j=1;j <= n;j++)
{
if(cost[i][j] < min)
{
min=cost[i][j];
a=u=i;
b=v=j;
}
}
}
This is somewhat straight forward. What it does is goes through the matrix and finds the smallest value in it. So for the example I gave it would first find 6.
So min=6, u=3(the starting vertex), v=2(the ending vertex). So now in order to understand what will follow you will have to READ about disjoint sets and connected components. Luckily for you there is a 10 min read tutorial again over at HackerEarth which will help you understand how Connected Components work. You can find it here.
So here is what's happening. The algorithm says the smallest cost right now is from 3->2 that costs 6. let's add this to the graph that we are building at the background with connected components and set the cost to 999 so we don't reconsider it. So here: u=find(u);
It goes to the parent array and checks at position 3(arr[3]) who is the parent? The answer is 3 since we haven't connected it to any other component yet. Next it does the same thing for 2(arr[2]) which also stays the same since we haven't connected it. To anything else. And then unifies them to one. That is the array now becomes:
[1, 2, 3] -> [1, 3, 3] (minCost is now equal to 6)
Then it adds min to minCost which is the answer. And changes the cost from 3->2 to 999 so we don't reconsider it.
It repeats that process so that we have:
// min=6, u=3, v=2
[1, 2, 3] -> [1, 3, 3] // minCost = 6
// min=11, u=1, v=3
[1, 3, 3] -> [1, 3, 1] // minCost = 17
// min=11, u=3, v=1 !!! CAREFUL NOW
Moving over to
parent of parent[3] == parent[1] meaning that they have the same parent so they are CONNECTED.
if(uni(u,v)) <-- This won't run since uni(3, 1) will return 0 meaning that they are connected so the min won't be added to minCost this time.
And this is where the algorithm ends. It prints a final cost of 17 and you are done. The ne variable is just there as a counter to make prints easier to understand.
I hope this helps you. Be sure to read the tutorials I linked they will really help you understand the logic because the Wonderful Kruskal's Algorithm.
The links mentioned above:
Kruskal's algorithm: https://www.hackerearth.com/practice/algorithms/graphs/minimum-spanning-tree/tutorial/
Connected Components: https://www.hackerearth.com/practice/data-structures/disjoint-data-strutures/basics-of-disjoint-data-structures/tutorial/
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am self-learning C++ from Sams Teach Yourself C++ In One Hour A Day and on page 150 the author discusses recursive functions using the Fibonacci Series.
He uses the following code:
#include <iostream>
using namespace std;
int GetFibNumber(int FibIndex)
{
if(FibIndex < 2 )
return FibIndex;
else
return GetFibNumber(FibIndex - 1) + GetFibNumber(FibIndex - 2);
}
int main()
{
cout << " Enter 0 based index of desired Fibonacci Number: ";
int Index = 0;
cin >> Index;
cout << " Fibonacci number is: " << GetFibNumber(Index) << endl;
return 0;
}
What is the difference between having
return GetFibNumber(FibIndex - 1) + GetFibNumber(FibIndex - 2);
and
return FibIndex - 1 + FibIndex - 2;
Why do you have to call the function inside itself?
Thank you in advance!
You ask: "Why do you have to call the function inside itself?" Well, strictly, you don't.
The Fibonacci sequence is the sequence of numbers defined by this mathematical recursion:
a0 = 0
a1 = 1
an = an-1 + an-2
The original function does compute this sequence, albeit inefficiently. If Index is 0 it returns 0; if it is 1, it returns 1. Otherwise it returns GetFibNumber(Index - 1) + GetFibNumber(Index - 2), which is precisely what the mathematical definition is. For each element of the sequence, you must add the two previous terms in the sequence.
Your code just returns Index - 1 + Index - 2, which will give a different numerical sequence. Compare:
Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21, 36...
Yours: 0, 1, 1, 3, 5, 7, 9, 11, 13, 17...
But that aside, you do not strictly need a recursive function to compute this mathematical recursion. All you need is a simple for loop:
int GetFibNumber(int FibIndex)
{
if(FibIndex < 2 )
return FibIndex;
int a_n_2 = 0, a_n_1 = 1, a_n;
for (i = 2; i < FibIndex; i++)
{
a_n = a_n_1 + a_n_2;
a_n_2 = a_n_1;
a_n_1 = a_n;
}
return a_n;
}
This approach will be much faster, also.
The code-recursive technique is mathematically correct. It is, however, slower, because it doesn't reuse any computations. It computes an-1 by reworking the recursion all the way back to a1. It then computes an-2, without reusing any of the work that generated an-1. And if you consider this lack-of-reuse happens at every step of the recursion, you'll see that the running time grows exponentially for the recursive function. It grows linearly for the for loop, though.
Advanced topic: There is a way to make the recursive version run faster, and that can be important to know if you run into a programming problem that is most readily defined recursively. Once you're much more comfortable with C++, look up memoization. A memoized recursive Fibonacci gives linear worst-case run-time, and constant run time for repeated lookups (assuming the memo lookup is itself O(1)).
Using the version that does not use recursion is not correct. It will only compute correctly first few Fiboonacci numbers. Try to compute first 10 Fibonacci numbers using the two versions and you will see yourself the two versions compute two different sequences.
The function GetFibNumber calculates the Nth number in the Fibonacci series. If you just take a look the explanation on http://en.wikipedia.org/wiki/Fibonacci_number it is calculated by adding the Nth-1 and Nth-2 numbers in the Fibinacci series. And this is exactly what the function does. You provide the function with an index in the Fibonacci series that you want to calculate (lets say 6; this should have 8 as result).
To calculate the 6th element in the Fibonacci series you need to add the 5th and 4th elements together. So you first need to calculate those. This is where recursion steps in. You can let the function call itself; but instead of calling it again with the value 6 as parameter you now use 5 and 4. This will again lead to the same problem (you need to calc 5th element by adding elements 4 and 3), etc. etc.
With the recursive function you can simply re-use the code to perform the same calculation over and over again until you reach a certain point where you have an answer for the calculation (in this case if N = 1 or N = 0; these cases will result in 1).
I would suggest, since you are still learning, to program this both recursively (like the author did) and using a loop (while, for). It will most likely show you the answer on how this algorithm is built up.
Hint 1: You must know that Fibonnaci sequences are built up upon two initial values...
Hint 2: For when it comes to recursion, you should know how the function results are stored. That will explain your question as well.
They are not equvialent, and it certainly won't calculate the fibonanic sequence. Recursion can be thought of like a tree, so to compute Fib(8) say, by definition we take Fib(7) + Fib(6)
Fib(8)
/ \
Fib(7) Fib(6)
Which in turn require computing Fib(6), Fib(5), Fib(4) as follows:
Fib(8)
/ \
Fib(7) Fib(6)
/ \ / \
Fib(5) Fib(6) Fib(5) Fib(4)
And so on. What you are doing, would produce a different, depth 1 tree:
Fib(8)
/ \
7 6
Because, if you never call the function within the function, it can never go more deep. It should be clear from this and the other answers why it is not correct.
I am trying to write a C++ program that works like the game 24. For those who don't know how it is played, basically you try to find any way that 4 numbers can total 24 through the four algebraic operators of +, -, /, *, and parenthesis.
As an example, say someone inputs 2,3,1,5
((2+3)*5) - 1 = 24
It was relatively simple to code the function to determine if three numbers can make 24 because of the limited number of positions for parenthesis, but I can not figure how code it efficiently when four variables are entered.
I have some permutations working now but I still cannot enumerate all cases because I don't know how to code for the cases where the operations are the same.
Also, what is the easiest way to calculate the RPN? I came across many pages such as this one:
http://www.dreamincode.net/forums/index.php?showtopic=15406
but as a beginner, I am not sure how to implement it.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool MakeSum(int num1, int num2, int num3, int num4)
{
vector<int> vi;
vi.push_back(num1);
vi.push_back(num2);
vi.push_back(num3);
vi.push_back(num4);
sort(vi.begin(),vi.end());
char a1 = '+';
char a2 = '-';
char a3 = '*';
char a4 = '/';
vector<char> va;
va.push_back(a1);
va.push_back(a2);
va.push_back(a3);
va.push_back(a4);
sort(va.begin(),va.end());
while(next_permutation(vi.begin(),vi.end()))
{
while(next_permutation(va.begin(),va.end()))
{
cout<<vi[0]<<vi[1]<<vi[2]<<vi[3]<< va[0]<<va[1]<<va[2]<<endl;
cout<<vi[0]<<vi[1]<<vi[2]<<va[0]<< vi[3]<<va[1]<<va[2]<<endl;
cout<<vi[0]<<vi[1]<<vi[2]<<va[0]<< va[1]<<vi[3]<<va[2]<<endl;
cout<<vi[0]<<vi[1]<<va[0]<<vi[2]<< vi[3]<<va[1]<<va[2]<<endl;
cout<<vi[0]<<vi[1]<<va[0]<<vi[2]<< va[1]<<vi[3]<<va[2]<<endl;
}
}
return 0;
}
int main()
{
MakeSum(5,7,2,1);
return 0;
}
So, the simple way is to permute through all possible combinations. This is slightly tricky, the order of the numbers can be important, and certainly the order of operations is.
One observation is that you are trying to generate all possible expression trees with certain properties. One property is that the tree will always have exactly 4 leaves. This means the tree will also always have exactly 3 internal nodes. There are only 3 possible shapes for such a tree:
A
/ \
N A
/ \ (and the mirror image)
N A
/ \
N N
A
/ \
N A
/ \
A N (and the mirror image)
/ \
N N
A
/` `\
A A
/ \ / \
N N N N
In each spot for A you can have any one of the 4 operations. In each spot for N you can have any one of the numbers. But each number can only appear for one N.
Coding this as a brute force search shouldn't be too hard, and I think that after you have things done this way it will become easier to think about optimizations.
For example, + and * are commutative. This means that mirrors that flip the left and right children of those operations will have no effect. It might be possible to cut down searching through all such flips.
Someone else mentioned RPN notation. The trees directly map to this. Here is a list of all possible trees in RPN:
N N N N A A A
N N N A N A A
N N N A A N A
N N A N N A A
N N A N A N A
That's 4*3*2 = 24 possibilities for numbers, 4*4*4 = 64 possibilities for operations, 24 * 64 * 5 = 7680 total possibilities for a given set of 4 numbers. Easily countable and can be evaluated in a tiny fraction of a second on a modern system. Heck, even in basic on my old Atari 8 bit I bet this problem would only take minutes for a given group of 4 numbers.
You can just use Reverse Polish Notation to generate the possible expressions, which should remove the need for parantheses.
An absolutely naive way to do this would be to generate all possible strings of 4 digits and 3 operators (paying no heed to validity as an RPN), assume it is in RPN and try to evaluate it. You will hit some error cases (as in invalid RPN strings). The total number of possibilities (if I calculated correctly) is ~50,000.
A more clever way should get it down to ~7500 I believe (64*24*5 to be exact): Generate a permutation of the digits (24 ways), generate a triplet of 3 operators (4^3 = 64 ways) and now place the operators among the digits to make it valid RPN(there are 5 ways, see Omnifarious' answer).
You should be able to find permutation generators and RPN calculators easily on the web.
Hope that helps!
PS: Just FYI: RPN is nothing but the postorder traversal of the corresponding expression tree, and for d digits, the number is d! * 4^(d-1) * Choose(2(d-1), (d-1))/d. (The last term is a catalan number).
Edited: The solution below is wrong. We also need to consider the numbers makeable with just x_2 and x_4, and with just x_1 and x_4. This approach can still work, but it's going to be rather more complex (and even less efficient). Sorry...
Suppose we have four numbers x_1, x_2, x_3, x_4. Write
S = { all numbers we can make just using x_3, x_4 },
Then we can rewrite the set we're interested in, which I'll call
T = { all numbers we can make using x_1, x_2, x_3, x_4 }
as
T = { all numbers we can make using x_1, x_2 and some s from S }.
So an algorithm is to generate all possible numbers in S, then use each number s in S in turn to generate part of T. (This will generalise fairly easily to n numbers instead of just 4).
Here's a rough, untested code example:
#include <set> // we can use std::set to store integers without duplication
#include <vector> // we might want duplication in the inputs
// the 2-number special case
std::set<int> all_combinations_from_pair(int a, int b)
{
std::set results;
// here we just use brute force
results.insert(a+b); // = b+a
results.insert(a-b);
results.insert(b-a);
results.insert(a*b); // = b*a
// need to make sure it divides exactly
if (a%b==0) results.insert(a/b);
if (b%a==0) results.insert(b/a);
return results;
}
// the general case
std::set<int> all_combinations_from(std::vector<int> inputs)
{
if (inputs.size() == 2)
{
return all_combinations_from_pair(inputs[0], inputs[1]);
}
else
{
std::set<int> S = all_combinations_from_pair(inputs[0], inputs[1]);
std::set<int> T;
std::set<int> rest = S;
rest.remove(rest.begin());
rest.remove(rest.begin()); // gets rid of first two
for (std::set<int>.iterator i = S.begin(); i < S.end(); i++)
{
std::set<int> new_inputs = S;
new_inputs.insert(*i);
std::set<int> new_outputs = all_combinations_from(new_inputs);
for (std::set<int>.iterator j = new_outputs.begin(); j < new_outputs.end(); j++)
T.insert(*j); // I'm sure you can do this with set_union()
}
return T;
}
}
If you are allowed to use the same operator twice, you probably don't want to mix the operators into the numbers. Instead, perhaps use three 0's as a placeholder for where operations will occur (none of the 4 numbers are 0, right?) and use another structure to determine which operations will be used.
The second structure could be a vector<int> initialized with three 1's followed by three 0's. The 0's correspond to the 0's in the number vector. If a 0 is preceded by zero 1's, the corresponding operation is +, if preceded by one 1, it's -, etc. For example:
6807900 <= equation of form ( 6 # 8 ) # ( 7 # 9 )
100110 <= replace #'s with (-,-,/)
possibility is (6-8)-(7/9)
Advance through the operation possibilities using next_permutation in an inner loop.
By the way, you can also return early if the number-permutation is an invalid postfix expression. All permutations of the above example less than 6708090 are invalid, and all greater are valid, so you could start with 9876000 and work your way down with prev_permutation.
Look up the Knapsack problem (here's a link to get you started: http://en.wikipedia.org/wiki/Knapsack_problem), this problem is pretty close to that, just a little harder (and the Knapsack problem is NP-complete!)
One thing that might make this faster than normal is parallelisation. Check out OpenMP. Using this, more than one check is carried out at once (your "alg" function) thus if you have a dual/quad core cpu, your program should be faster.
That said, if as suggested above the problem is NP-complete, it'll be faster, not necessarily fast.
i wrote something like this before. You need a recursive evaluator. Call evaluate, when you hit "(" call evaluate again otherwise run along with digits and operators till you hit ")", now return the result of the -+*/ operations the the evaluate instance above you