How to grow 2d dynamically allocated string array in C++11 ? - string

So, I have been doing this question :
Q. Write a program that lets users keep track of the last time they talked to each of their friends. Users should be able to add new friends (as many as they want!) and store the number of days ago that they last talked to each friend. Let users update this value as well.
I have created pointer to pointer user_friends to store the 2D string array for names of friends and no. of days since last talked. It's a 3x2 array initially for 3 friends. The 2 columns store friend's name and no. of days ( both in string type pointer array ).
My main has this :
int tsize = 3;
string **user_friends = new string*[tsize];
for ( int i = 0; i < tsize; i++ )
{
user_friends[i] = new string[2];
}
Here is the addFriends function to add friends in array.
void addFriends( string **user_f , int tsize )
{
static int next_friend = 0;
int index = 0;
string days;
if ( next_friend >= tsize )
{
cout << "\nGrowing array now...";
user_f = growArray ( user_f, tsize );
}
cout << "\n\nEnter index : ";
cin >> index;
cin.ignore();
cout << "\nEnter friend's name : ";
getline( cin, user_f[index][0] );
cout << "\nEnter days since last talked with this friend : ";
getline (cin, days);
user_f[index][1] = days;
next_friend++;
}
Then there is this growArray function to expand the memory allocated to string array :
string **growArray ( string **ptr, int cur_size )
{
string **new_ptr = new string*[ cur_size*2 ];
for ( int i = 0; i < cur_size; ++i )
{
new_ptr[i] = new string[2];
}
for( int i = 0; i < cur_size; ++i )
{
new_ptr[i] = ptr[i];
}
for ( int i = 0; i < cur_size; ++i )
{
for ( int j = 0; j < 2; ++j)
{
new_ptr[i][j] = ptr[i][j];
}
}
for ( int i = 0; i < cur_size; ++i )
{
delete ptr[i];
}
delete[] ptr;
return new_ptr;
}
Then this display function to print the array.
void displayFriends( string **user_f, int tsize )
{
for ( int i = 0; i < tsize; ++i )
{
for( int j = 0; j < 2; ++j )
{
cout << user_f[i][j] << "\t";
}
cout << endl;
}
}
Now, when I have entered upto 3 friends details, the program runs fine.
When I start to enter the details of friend 4 ( i.e. When I type in index as 3 ) the program crashes. Is there any problem with the growArray function ?
Also, is the display function alright ?

In the growArray function the first for loop should iterate from 0 to 2 * cur_size instead of 0 to cur_size.
for(int i = 0; i< 2 * cur_size; i++)
new_ptr[i] = new string[2]

Related

How to remove K characters from a string such that there is a minimum of each character

I want to remove K characters from a string such that the occurrence of each character is at a minimum.
For example:
String: abcdefghijkllllll
K: 5
Answer: 12 (abcdeghijkl)
String: ababac
K: 4
Answer: 3 (aac)
String: aaaab
K: 4
Answer: 1(b)
I want to remove 5 characters. Those characters would be 5 l's
What I've done so far is count the occurence of each character using a map
But I'm stuck as to what to do next.
#include <bits/stdc++.h>
using namespace std;
string s;
int l, k;
map<char, int> m;
int main() {
getline(cin, s);
scanf("%d %d", &l, &k);
for(int i=0; i<s.length(); i++) {
m[s[i]]++;
}
for(auto &x : m) {
cout << x.second << "\n";
}
return 0;
}
The expected result is the minimum length of a string after removing the characters of any given string (can be sorted or unsorted).
You can remove any character in the String
Update:
#include <bits/stdc++.h>
using namespace std;
string s;
int l, k;
map<char, int> m;
int main() {
getline(cin, s);
cin >> l >> k;
for(int i = 0; i < s.length(); i++) {
m[s[i]]++;
}
for(auto it = m.end(); it != m.begin(); it--) {
// cout << it->second << "\n";
}
vector<pair<int, int>> pairs;
for (auto itr = m.begin(); itr != m.end(); itr++) {
pairs.push_back(*itr);
}
sort(pairs.begin(), pairs.end(), [=](pair<int, int>& a, pair<int, int>& b) { return a.second < b.second; } );
for(auto it = m.end(); it != m.begin(); it--) {
if(it->second - k >= 1) {
it->second-=k;
k -= it->second;
}
}
int sum = 0;
for(auto it = m.end(); it != m.begin(); it--) {
sum += it->second;
// cout << it->second << "\n";
}
cout << sum << "\n";
return 0;
}
The current problem with this is that it doesn't read all the characters and map them correctly to the map.
I'm uncertain from your description and test cases what you're looking for. Your answer is returning the number of characters remaining in the string, and your updated function returns the sum variable. If that's the case why not just return the length of the string minus k?
Your second test case is:
String: ababac
K: 4
Answer: 3 (aac)
Removing 4 characters from "ababac" (length 6) would give it a length of 2, not 3. How does this work?
Can the characters be removed in any order? For the third test case you have:
String: aaaab
K: 4
Answer: 1(b)
Given the description: I want to remove K characters from a string such that the occurrence of each character is at a minimum. Removing 3 characters gives the result "ab". Removing the 4th could result in either "a" or "b". What do you do in this case?
There's a lot of ambiguity in this question, and the test cases are a bit confusing. For example, given "aabbccdddd" k=3, what would be the accepted answer? "abcdddd" or "aabbccd"? "abcdddd" would increase the number of characters that are at a minimum whereas "aabbccd" would reduce the number of the most frequently occurring character.
I've put together an answer using a max priority queue / max-heap (in Java) with the later example from above. This assumes that all your input is good.
import java.util.*;
public class SO {
//Helper class to put in the priority queue.
class CharInt {
char c;
int count;
public CharInt(char c) {
this.c = c;
this.count = 1;
}
void increment() {
this.count++;
}
void decrement() {
this.count--;
}
}
public int minChar(String s, int k) {
Map<Character, CharInt> map = new HashMap<Character, CharInt>();
for (Character c : s.toCharArray()) {
if (map.get(c) == null) {
map.put(c, new CharInt(c));
}else {
map.get(c).increment();
}
}
//Makes a Max-Heap from a PriorityQueue object. The comparator makes sure the top of the PriorityQueue is the character with the highest count.
PriorityQueue<CharInt> maxHeap = new PriorityQueue<CharInt>(new Comparator<CharInt>() {
#Override
public int compare(CharInt o1, CharInt o2) {
return - Integer.compare(o1.count, o2.count);
}
});
//Add all values to the heap.
for (CharInt c : map.values()) {
maxHeap.add(c);
}
//Take the top value off, decrement its count, add it back to the heap. Do this k times.
while (k-- > 0) {
CharInt c = maxHeap.poll();
c.decrement();
maxHeap.add(c);
}
StringBuilder builder = new StringBuilder(); // Used to make output string. Can be left out.
int sum = 0;
//Remove every element from the heap and get its count value.
while(!maxHeap.isEmpty()) {
CharInt c = maxHeap.poll();
for (int i = 0; i < c.count; i++) {
sum += c.count;
builder.append(c.c); // Used to make output string. Can be left out.
}
}
char[] chars = builder.toString().toCharArray(); // Used to make output string. Can be left out.
Arrays.sort(chars); // Used to make output string. Can be left out.
System.out.println(chars); // Used to make output string. Can be left out.
return sum;
}
public static void main(String...bannaa) {
int s = new SO().minChar("abcdefghijkllllll", 5);
int s2 = new SO().minChar("ababac", 4);
int s3 = new SO().minChar("aaaab", 4);
int s4 = new SO().minChar("abbbccc", 4);
System.out.println(s + " " + s2 + " " + s3 + " " + s4);
}
}
Output:
abcdefghijkl
ac
a
abc
12 2 1 3

I'm having trouble formatting the print statement using a nested for loop

I am taking hard coded information of two arrays and creating the Union, Intersection and Difference of them.
My issue is that I can't get the Intersection or Difference to print with the right format.
I have tried a different variety of while loops with for and if statements, but can't quite get it. I know I'm close-ish. (Hopefully)
Main information:
int setA[] = {3,4,9,12,13,15};
int setB[] = {1,3,5,7,9};
int lenA = sizeof(setA) / sizeof(setA[0]);
int lenB = sizeof(setB) / sizeof(setB[0]);
Difference(setA, setB, lenA, lenB);
Intersection(setA, setB, lenA, lenB);
void Intersection(int setA[], int setB[], int lenA, int lenB)
{
cout << "AnB = {";
for (int i = 0; i < lenA; i++)
{
for (int j = 0; j < lenB; j++)
{
while(setA[i] == setB[j] && i < lenA - 1)
{
cout << setA[i++] << ", ";
}
if(i < lenA && setA[i] == setB[j])
{
cout << setA[i++];
}
}
}
cout << "}";
cout << endl;
}
void Difference(int setA[], int setB[], int lenA, int lenB)
{
cout << "A - B = {";
for (int i = 0; i < lenA; i++)
{
bool comp = false;
for (int j = 0; j < lenB; j++)
if (setA[i] == setB[j])
{
comp = true;
break;
}
if(!comp)
{
cout << setA[i] << ",";
}
}
cout << "}";
cout << endl;
}
I want the output to look like:
AnB = {3, 9} (Intersection)
A-B = {4, 12, 13, 15} (Difference)
What I am getting:
AnB = {3, 9, } (Intersection)
A-B = {4, 12, 13, 15, } (Difference)
I just need to get the commas at the end fixed, but don't know how.
Sorry if this question is way too long, I wasn't sure of how to get my issue out.

How to use vector acsess element through function

This code is made for the multiplication of two arrays given by the user
typedef vector<vector<int> > arr ;
void multiply (arr &arr1 ,arr &arr2 )
{
arr res ;
unsigned new_row = arr1.size() ;
unsigned new_col = arr2.at(0).size();
for(int i = 0 ; i < new_row ; i++)
{
vector <int> vec ;
res.push_back(vec ) ;
for(int j = 0 ; j<new_col ;j++)
{
int x = 0 ;
res.at(i).push_back(x);
for(unsigned k =0 ; k <arr2.size();k++)
{
res.at(i).at(j) += arr1.at(i).at(k)*arr2.at(k).at(j);
}
cout<< res.at(i).at(j) ;
}
}
}
int main()
{
unsigned rows_number1 = 0 , columns_number1 = 0 ;
arr arr1 ;
cout<<"MATRIX A "<<endl<<endl ;
cout << "The Rows : " ;
cin >> rows_number1 ;
cout << "The Columns :" ;
cin>> columns_number1 ;
for(int i = 0 ; i<rows_number1;i++)
{
vector<int> newr ;
arr1.push_back(newr);
for(int j = 0; j<columns_number1 ;j++)
{
int x ;
cout<<"The Member ("<<i+1<<","<<j+1 <<") :" ;
cin>>x ;
arr1.at(i).push_back(x);
}
}
unsigned rows_number2 = 0 , columns_number2 = 0 ;
arr arr2 ;
cout<<"MATRIX B "<<endl<<endl ;
cout << "The Rows : " ;
cin >> rows_number2 ;
cout << "The Columns :" ;
cin>> columns_number2 ;
for(int i = 0 ; i<rows_number2;i++)
{
vector<int> newr ;
arr1.push_back(newr);
for(int j = 0; j<columns_number2 ;j++)
{
int x ;
cout<<"The Member ("<<i+1<<","<<j+1 <<") :" ;
cin>>x ;
arr1.at(i).push_back(x);
}
}
system("cls");
if(columns_number1!=rows_number2)
{
cout<<"Error Multiplication Dimensions" <<endl ;
}
else
{
cout << "A * B ="<<endl;
multiply(arr1,arr2);
}
}
why there is an error and what is the other way ??
how i can improve the code to multiplicate two arrays
Edited : i tried with two 2*2 arrays using console input and output and this is my full code
The problem is out_of_range exception but i don't know why
When you mulitply to matrices, there are strict constraints on the input.
The number of columns of the first matrix must be the same as the number of rows of the second matrix.
When your matrix is represented by a std::vector<std::vector<int>>, you'll have to make sure that ALL the nested std::vectors are of the same size.
Also, don't assume that arr2 is non-empty. When it is empty, arr2.at(0) will thrown an exception.
Here's a more robust version of your function.
void multiply (arr &arr1 ,arr &arr2 )
{
arr res;
unsigned num_rows1 = arr1.size();
if ( num_rows1 == 0 )
{
// Can't do much.
// Return.
return res;
}
unsigned num_cols1 = arr1[0].size();
if ( num_cols1 == 0 )
{
// Can't do much.
// Return.
return res;
}
// Inner vector size check of arr1.
for(unsigned int i = 1 ; i < num_rows1 ; i++)
{
if ( num_cols1 != arr1[i].size() )
{
throw std::runtime_error("Bad input");
}
}
// Make sure the number of columns in arr1 is the same as
// number of rows in arr2.
unsigned num_rows2 = arr2.size();
if ( num_cols1 != num_rows2 )
{
throw std::runtime_error("Bad input");
}
unsigned num_cols2 = arr2[0].size();
if ( num_cols2 == 0 )
{
// Can't do much.
// Return.
return res;
}
// Inner vector size check of arr2.
for(unsigned int i = 1 ; i < num_rows2 ; i++)
{
if ( num_cols2 != arr2[i].size() )
{
throw std::runtime_error("Bad input");
}
}
// All inputs appear to be valid.
// Now, do the multiplication.
unsigned new_row = num_rows1;
unsigned new_col = num_cols2;
res.resize(num_rows1);
for(unsigned i = 0 ; i < new_row ; i++)
{
for(unsigned j = 0 ; j<new_col ;j++)
{
int x = 0 ;
res.at(i).push_back(x);
for(unsigned k =0 ; k < num_cols1; k++)
{
res.at(i).at(j) += arr1.at(i).at(k)*arr2.at(k).at(j);
}
cout<< res.at(i).at(j) ;
}
}
}

Stack around the variable A (array) or n (size of the array) was corrupted

This program checks distinctness in an array. (no repeated values in an array I.e if 1 2 3 3 4 is an array it is not distinct). this code Won't compile although (I believe that) index of array did not go out of range in for loop.
theRun-Time Check Failure says stack around variable 'n' was corrupted when I enter n =12. BUT says stack around variable 'A' was corrupted when I enter n = 10. with exactly the same variables entered in the array in the second step. (the error shows up after entering the fourth integer)
#include <iostream>
using namespace std;
int main()
{
int n;
int A[] = {0};
int integer;
cout<<"Enter the size of the array\n";
cin>>n;
cout<<"enter "<<n<<" integers\n";
for (int i = 0 ; i < n ; i++)
{
cin>>A[i];
}
for (int i = 0 ; i < n ; i++)
{
for (int j = 0 ; j < n - i; j++)
{
if(A[j+1] > A[j])
{
int temp;
temp = A[j];
A[j+1] = A[j];
A[j+1] = temp;
}
}
}
for (int i = 0 ; i < n; i++)
{
if (A[i] - A[i+1] ==0 ){
cout<<"\nThe Array Is Not Distinct !\n";
break;
}
else
{
cout<<"\nThe Array Is Distinct !\n";
}
}
system("pause");
return 0;
}

how do i avoid using pointer variables and pointer-based pass-by-reference in this program?

how do i avoid using pointer variables and pointer-based pass-by-reference in this program? as my instructor said there is no need to use pointers. This is a the tortoise and the hare simulator , you will use number generation to develop a simulation of this memorable event.
#include <iostream>
using std::cout;
using std::endl;
#include <cstdlib>
using std::rand;
using std::srand;
#include <ctime>
using std::time;
#include <iomanip>
using std::setw;
const int RACE_END = 70;
// prototypes
void moveTortoise( int *const );
void moveHare( int *const );
void printCurrentPositions( const int *const, const int *const );
int main()
{
int tortoise = 1;
int hare = 1;
int timer = 0;
srand( time( 0 ) );
cout << "ON YOUR MARK, GET SET\nBANG !!!!"
<< "\nAND THEY'RE OFF !!!!\n";
// loop through the events
while ( tortoise != RACE_END && hare != RACE_END )
{
moveTortoise( &tortoise );
moveHare( &hare );
printCurrentPositions( &tortoise, &hare );
timer++;
} // end loop
if ( tortoise >= hare )
cout << "\nTORTOISE WINS!!! YAY!!!\n";
else
cout << "\nHare wins. Yuch.\n";
cout << "\nTIME ELAPSED = " << timer << " seconds" << "\n" << endl;
system("pause");
return 0; // indicates successful termination
} // end main
// progress for the tortoise
void moveTortoise( int * const turtlePtr )
{
int x = 1 + rand() % 10; // random number 1-10
if ( x >= 1 && x <= 5 ) // fast plod
*turtlePtr += 3;
else if ( x == 6 || x == 7 ) // slip
*turtlePtr -= 6;
else // slow plod
++( *turtlePtr );
if ( *turtlePtr < 1 )
*turtlePtr = 1;
else if ( *turtlePtr > RACE_END )
*turtlePtr = RACE_END;
} // end function moveTortoise
// progress for the hare
void moveHare( int * const rabbitPtr )
{
int y = 1 + rand() % 10; // random number 1-10
if ( y == 3 || y == 4 ) // big hop
*rabbitPtr += 9;
else if ( y == 5 ) // big slip
*rabbitPtr -= 12;
else if ( y >= 6 && y <= 8 ) // small hop
++( *rabbitPtr );
else if ( y > 8 ) // small slip
*rabbitPtr -= 2;
if ( *rabbitPtr < 1 )
*rabbitPtr = 1;
else if ( *rabbitPtr > RACE_END )
*rabbitPtr = RACE_END;
} // end function moveHare
// display new position
void printCurrentPositions( const int * const snapperPtr,
const int * const bunnyPtr )
{
if ( *bunnyPtr == *snapperPtr )
cout << setw( *bunnyPtr ) << "OUCH!!!";
else if ( *bunnyPtr < *snapperPtr )
cout << setw( *bunnyPtr ) << 'H'
<< setw( *snapperPtr - *bunnyPtr ) << 'T';
else
cout << setw( *snapperPtr ) << 'T'
<< setw( *bunnyPtr - *snapperPtr ) << 'H';
cout << '\n';
} // end function printCurrentPositions
In C++ you can use references instead of pointers. For example, instead of
void foo(int *x) {
*x = *x + 1;
}
int main() {
int a = 0;
foo(&a);
return 0;
}
you can pass x by reference, like so:
void foo(int &x) {
x = x + 1;
}
int main() {
int a = 0;
foo(a);
return 0;
}
Passing a reference is sort of like passing a pointer, except you don't need to dereference the pointer every time you want to access the value it points to.
You can google "C++ pass by reference" for more information, such as this tutorial: http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/
Alternatively, in your program, you could simply pass int arguments and return the new value:
int moveTortoise(int turtle) {
...
turtle = turtle + 3;
...
return turtle;
}
tortoise = moveTortoise(tortoise)
References& and pointers* are usefull when:
1. you deal with instances of complex classes that passing by reference is resource(CPU time & main memory) consuming operation;
2. when you want to change arguments what are passed(as any function in C++ can return only one value, opposit for ex. to python where multiply values can be returned, you can cope with that restriction by passing using & or *);
3. Other cases...
Built-in(atomic) types can be passed by value (which is you case) without decrease in efficiency.

Resources