Messed up srand() and vector::iterator - c++

I have written a practice code for a 'battle' that allows you to select number of combatants, number of rounds and number of dice-rolls per fighter per round storing the result into a 3D vector array. The storage part is working; however, the printResult() function is botched (i have put a // before it in main() ) and the srand() isnt working either. The complete program is below for convenience:
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <ctime>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
class Combat{
private:
int numberOfRounds;
int numberOfCombatants;
int numberOfRolls;
int sidesDie;
vector <int> rollz;
vector <vector <int> >combatant;
vector <vector <vector <int> > > round;
public:
void printMenu();
void battle();
void printResult();
Combat(int, int , int, int );
Combat(int );
Combat();
int roll();
int roll(int die);
};
void Combat::printMenu()
{
cout<<setw (10)<<"Welcome to the Combat Menu";
cout<<'\n'<<setw (10)<<"Choose:";
cout<<'\n'<<setw (10)<<"Number of combatants: ";
cin>>numberOfCombatants;
cout<<'\n'<<setw (10)<<"Die sides:";
cin>>sidesDie;
cout<<'\n'<<setw (10)<<"Enter number of rounds: ";
cin>>numberOfRounds;
cout<<setw(10)<<"Enter number of rolls (per combatant per round):";
cin>>numberOfRolls;
}
Combat::Combat(){
numberOfRounds=8;
}
Combat::Combat(int x){
x=numberOfRounds;
}
Combat::Combat(int rnds,int cmb,int rll, int sides){
numberOfRounds=rnds;
numberOfCombatants=cmb;
numberOfRolls=rll;
sidesDie=sides;
}
int Combat::roll(int die)
{
die=sidesDie;
srand(time(0));
int r=(1+rand()%die);
return r;
}
int Combat::roll(){
srand(time(0));
int r=(1+rand()%6);
return r;
}
void Combat::battle(){
cout<<setw(10)<<" Computing results of battle ...\n";
int i,j,k;
for (i=0;i<numberOfRounds;++i){
cout<<"\nRound number "<<i+1;
round.push_back(combatant);
for(j=0;j<numberOfCombatants;++j){
cout<<"\nCombatant number "<<j+1;
combatant.push_back(rollz);
cout<<endl;
for(k=0;k<numberOfRolls;++k){
rollz.push_back(roll(sidesDie));
cout<<rollz.at(k)<<'\t';
}
}
cout<<endl<<endl;
}
cout<<endl;
}
void Combat::printResult(){
cout<<endl;
vector< vector <vector<int> > >::const_iterator it1;
int combt, counter=0;
for (it1=round.begin();it1 !=round.end();++it1){
++counter;
cout<<"\nRound number "<<counter<<endl;
for(vector<vector<int> >::const_iterator it2=combatant.begin();it2!=combatant.end();++it2){
++combt;
cout<<"\nCombatant "<<combt<<" hits ";
for(vector<int>::const_iterator it3=rollz.begin();it3!=rollz.end();++it3){
cout<<*it3<<'\t';
}
}
}
}
int main ()
{
Combat fight;
fight.printMenu();
fight.battle();
//fight.printResult();
cout<<endl;
}

You have two problems you should tackle separately (and which you should have solved separately before you put them together into one code base). Loki Asteri has already addressed the problem with srand().
It looks as if round is a vector of Combatant, which is a vector of something else, but look here:
void Combat::printResult(){
...
for (it1=round.begin();it1 !=round.end();++it1){
++counter;
cout<<"\nRound number "<<counter<<endl;
// You never use counter or it1 again.
// You iterate over the same combatant for each it1:
for(vector<vector<int> >::const_iterator it2=combatant.begin();
it2!=combatant.end();++it2){
++combt;
cout<<"\nCombatant "<<combt<<" hits "; // bad variable name at best
// And now you iterate over the same rollz
// for every entry in combatant.
for(vector<int>::const_iterator it3=rollz.begin();
it3!=rollz.end();++it3){
cout<<*it3<<'\t';
}
}
}
}

Only call srand() once in an application.
int main()
{
srand(time(0));
// STUFF
}

Related

Merge Sort with no output what am I doing wrong?

I am struggling to understand why I am getting no output?
I am trying to learn how to implement a merge-sort algorithm. The way I went about this is first concatenating the two vectors and then implementing a function to sort the concatenated vector.
I am new to C++ programming.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
void merge(vector<int> &array1, vector<int> &array2){
vector<int> mergeArray;
mergeArray.insert(mergeArray.end(), array1.begin(), array1.end());
mergeArray.insert(mergeArray.end(), array2.begin(), array2.end());
}
void sort(vector<int> &mergeArray, vector<int> &sortedArray, int n, int i){
if(n==0){
return;
}
if(mergeArray[i]>mergeArray[i+1]){
sort(mergeArray,sortedArray,n-1,i+1);
sortedArray.push_back(mergeArray[i+1]);
}
else{
sort(mergeArray,sortedArray,n-1,i+1);
sortedArray.push_back(mergeArray[i]);
}
for(int x=0; x<sortedArray.size(); x++){
cout << sortedArray[x];
}
}
int main()
{
vector<int> array1 = {5,4,2};
vector<int> array2 = {3,7,1};
vector<int> mergeArray;
vector<int> sortedArray;
merge(array1,array2);
sort(mergeArray,sortedArray,mergeArray.size() + sortedArray.size(),0);
return 0;
}
The mergeArray vector in merge is local to the function, and main has no way of seeing the changes to mergeArray.
You could pass the array in as a reference parameter, instead of declaring it as a local variable:
void merge(vector<int> &mergeArray, vector<int> &array1, vector<int> &array2) {
// ...
}
and call merge like this:
merge(mergeArray, array1,array2);
Notice that you are already doing this in your sort function. You need to do a similar thing for merge.
Here's a demo.

Why did this TSP code fail in the case mentioned but worked else where?

I am implementing Travelling Salesman Problem with Dynamic approach. I have added my attempt below. The code compiled and gave correct output for most of the cases. However, it failed when I had matrix representation: [[0,10,1],[1,0,10],[10,1,0]]. I expect the result to be 3 but it is showing me 30 as the output.
I have done recursion calls and dict map stores the keys for memorization.
#include<bits/stdc++.h>
using namespace std;
int v;
int G[10][10];
int parent[10];
map<pair<int,set<int> >, int > dict;
void solve(int,set<int>);
int tsp(int,set<int>);
int main(){
set<int> s,s_o;
set<int>::iterator it;
cout<<"Give number of vertices"<<endl;
cin>>v;
for(int i=0;i<v;i++)
s.insert(i);
//cout<<"Give number of edges"<<endl;
//cin>>e;
s_o=s;
cout<<"Give edges"<<endl;
for(int i=0;i<v;i++){
for(int j=0;j<v;j++){
cin>>G[i][j];
}
}
solve(0,s);
return 0;
}
void solve(int i,set<int> s){
parent[i]=-1;
set<int>::iterator it;
it=s.find(i);
s.erase(it);
// for(it=s.begin();it!=s.end();++it)
// cout<<*it<<" ";
int ans=tsp(0,s);
cout<<ans<<endl;
for(int i=0;i<v;i++)
cout<<parent[i]<<" ";
cout<<endl;
}
int tsp(int a,set<int>s){
set<int>::iterator it;
int min_cost=1000000;
int k,min_k;
if(s.empty()){
return G[a][0];
}
for(it=s.begin();it!=s.end();++it){
k=*it;
s.erase(it);
if(dict.find(pair<int, set<int> >(k,s))!=dict.end()){
//cout<<"here"<<endl;
return G[a][k]+ dict.at(pair<int, set<int> >(k,s));
}
else{
if(tsp(k,s)<min_cost){
min_cost=tsp(k,s);
min_k=k;
}
pair<int,set<int> > x(k,s);
dict.insert(pair<pair<int, set<int> >,int >(x,min_cost));
parent[a]=min_k; //i must admit that this is accidental, but
//it worked xD
return G[a][k]+min_cost;
}
}
}
Also the parent array I expect to hold parent of vertex and -1 for source(0 in case).
Is there anything wrong in the tsp() function? If not, why did it give answer as 30?
Also, what is wrong in the parent array use?
Thank you for your help! :)

unresolved overloaded function type [int] when implementing graph

I try to implement graph bfs but get compiler error
error:
invalid types '<unresolved overloaded function type>[int]' for array subscript|
My questions:
Is my approach making array of vector of struct is right approach? And how can I solve the compiler error?
How to initialize array value to infinity?
When making undirected graph, should I push back 2 times?
My code:
#include <iostream>
#include <deque>
#include <vector>
#define INT_MAX 21422
using namespace std;
int distancee[10]={4,4,4,4,4,4,4,4,4,4}; //want to intialize all to infinity
struct bfss{
int firstt;
int secondd;
};
vector<bfss>bfs[10];
void bfsfunc(int start){
deque<int> q;
q.push_back(start);
distancee[start]=0;
while(!q.empty()){
int v=q.front();
q.pop_front();
for(int i=0;i<bfs[v].size();i++){
if(distance[bfs[v][i].firstt]>(distance[v]+bfs[v][i].secondd)){ // got error in this line
distance[bfs[v][i].firstt]=distance[v]+bfs[v][i].secondd;
if(bfs[v][i].second==0)
{
q.push_front(bfs[v][i].first);
} else {
q.push_back(bfs[v][i].second);
}
}
}
}
}
int main()
{
int edges,nodes,x,y,z;
cin>>edges>>nodes;
for(int i=0;i<edges;i++){
cin>>x>>y>>z; //x is array subscript , y is node(x-y is edge) , z is weight
bfss newbfs;
newbfs.firstt=y;
newbfs.secondd=z;
bfs[x].push_back(newbfs);
bfss newbfs;
newbfs.firstt=x;
newbfs.secondd=z;
bfs[y].push_back(newbfs); // when making undirected graph, should i push back 2 times?
}
bfsfunc(0);
return 0;
}
As mentioned, you had a few typos on distancee, firstt and secondd. Fix those and the errors goes away. For an int the closest you'll come to infinity is it's max value. With that and a few other minor changes (comments in the code), this is what I came up with:
#include <iostream>
#include <deque>
#include <vector>
#include <array>
#include <limits> // std::numeric_limits
// removed using namespace std;
// max distance: not infinity, but hopefully large enough
constexpr int md = std::numeric_limits<int>::max();
// replaced the C array with a standard C++ array
std::array<int, 10> distancee={md,md,md,md,md,md,md,md,md,md};
struct bfss { // shouldn't these be unsigned?
int firstt;
int secondd;
};
std::vector<std::vector<bfss>> bfs(10); // replaced C array with a standard C++ vector
void bfsfunc(int start) {
std::deque<int> q;
q.push_back(start);
distancee[start]=0;
while(!q.empty()) {
int v=q.front();
q.pop_front();
// using size_t intstead of int for array subscript
for(size_t i=0;i<bfs[v].size();i++) {
if(distancee[bfs[v][i].firstt]>(distancee[v]+bfs[v][i].secondd)) {
distancee[bfs[v][i].firstt]=distancee[v]+bfs[v][i].secondd;
if(bfs[v][i].secondd==0) {
q.push_front(bfs[v][i].firstt);
} else {
q.push_back(bfs[v][i].secondd);
}
}
}
}
}
int main()
{
int edges,nodes,x,y,z;
std::cin>>edges>>nodes;
for(int i=0;i<edges;i++) {
std::cin>>x>>y>>z; //x is array subscript , y is node(x-y is edge) , z is weight
// using emplace_back to let the vector create the bfss in place
bfs[x].emplace_back(bfss{y, z});
bfs[y].emplace_back(bfss{x, z});
}
bfsfunc(0);
return 0;
}
I don't know the answer to the question about pushing twice since I don't know the algorithm.

Newbie - matrix addition implementation in c++

Hello i'm trying to program the addition of 2 matrices into a new one (and it does when i run the program step by step) but for some reason VS 2010 gives me an access error after it does the addition.
Here is the code.
#include <iostream>
#include <cstdio>
#include <conio>
using namespace std;
class operatii
{
typedef double mat[5][5];
mat ms,m1,m2;
int x1,x2,y1,y2;
public:
void preg();
int cit_val();
void cit_mat(int&,int&,double[5][5]);
void suma();
void afisare(int&,int&,double[5][5]);
};
void operatii::preg()
{
cit_mat(x1,y1,m1);
cit_mat(x2,y2,m2);
suma();
afisare(x1,y1,ms);
}
int operatii::cit_val()
{
int n;
cin>>n;
return n;
}
void operatii::cit_mat(int& x,int& y,double m[5][5])
{
char r;
cout<<"Matrice patratica? Y/N ";
cin>>r;
if ((r=='y')||(r=='Y'))
{
cout<<"Numar linii si coloane: ";
x=cit_val();
y=x;
}
else
{
cout<<"Numar linii: ";
x=cit_val();
cout<<"Numar coloane: ";
y=cit_val();
}
for (int i=1;i<=x;i++)
for (int j=1;j<=y;j++)
cin>>m[i][j];
}
void operatii::suma()
{
if ((x1==x2)&&(y1==y2))
for (int i=1;i<=x1;i++)
for (int j=1;i<=y1;j++)
ms[i][j]=m1[i][j]+m2[i][j];
else cout<<"Eroare";
}
void operatii::afisare(int& x,int& y,double m[5][5])
{
cout<<endl;
for (int i=1;i<=x;i++)
{
for (int j=1;j<=y;j++)
cout<<m[i][j];
cout<<endl;
}
}
void main()
{
operatii matrice;
matrice.preg();
system("PAUSE");
}
Any kind of help would be apreciated.
Arrays are 0-based in c++.
Change your various variants of for (somevar=1; somevar<=something) to for (somevar=0; somevar<something)
You're writing past the end of your arrays, which overwrites stack return address, leading to a return to nonexecutable code, again leading to an access violation.
Also,
for (int j=1;i<=y1;j++)
I think you want to use j not i here. Such errors are much easier to see if you use longer and more distinct variable names than "i" and "j", such as e.g. "Line" and "Column"

Code Crashes Immediately After Running

Even at the bare minimum of 10 numbers to input, I get no errors but my code crashes immediately on running. I was also wondering, what should I do if I have a question similar to another question that I've already asked, but on another new problem?
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
#include <vector>
using namespace std;
int primer(int max);
int main()
{
primer(5);
system("pause");
return 0;
}
int primer(int max){
vector<int> a;
a[1]=2;
for (int i=2;i<=max;i++){
bool prime=true;
for (int ii=0;ii<a.size();ii++) {
if (i/a[ii]==floor(i/a[ii])) {
prime=false;
}
}
if (prime==true) {
a.push_back(i);
}
}
for (int iii=0;iii<=a.size();iii++) {
cout << a[iii] << endl;
}
}
I get no errors but the compiled code crashes immediately.
I changed it to
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
#include <vector>
using namespace std;
int primer(int max);
int main()
{
primer(5);
system("pause");
return 0;
}
int primer(int max){
vector<int> a;
a.push_back(2);
for (double i=2;i<=max;i++){
bool prime=true;
for (int ii=0;ii<a.size();ii++) {
if (i/a[ii]==floor(i/a[ii])) {
prime=false;
}
}
if (prime) {
a.push_back(i);
}
}
for (int iii=0;iii<=a.size();iii++) {
cout << a[iii] << endl;
return a.size();
}
}
I addressed all of your problems. It still returns no errors and still crashes.
What makes you think you can do this?
vector<int> a;
a[1]=2;
vector<int> a;
a[1]=2;
You can't access a[1] until you've reserved space for it. You should probably use a.push_back(2) to append 2 to the end of a.
You have declared primer to return int, yet it returns nothing. Either make it void or return the number of primes.
i/a[ii]==floor(i/a[ii]) isn't going to do what you expect. i/a[ii] performs integer division. You should cast i to double before dividing.
if (prime==true) can be changed to simply if (prime), no need to compare a boolean to true.
Please improve your coding style. Use proper indentation and more commonly used variable names: i, j, k instead of i, ii, iii.
Here is another bug:
for (int iii=0;iii<=a.size();iii++) {
cout << a[iii] << endl;
return a.size();
}
My understanding is that you can only return once from a function, main included. The execution will not loop here because of the return statement.
Did you really want a return statement inside a for loop?