What is segmentation fault. How to deal with it [duplicate] - c++11

This question already has answers here:
What is a segmentation fault?
(17 answers)
Closed 2 years ago.
Problem:
A student signed up for workshops and wants to attend the maximum
number of workshops where no two workshops overlap. You must do the
following: Implement structures:
struct Workshop having the following members: The workshop's start time. The workshop's duration. The workshop's end time.
struct Available_Workshops having the following members: An integer, (the number of workshops the student signed up for). An
array of type Workshop array having size . Implement functions:
Available_Workshops* initialize (int start_time[], int duration[], int n) Creates an Available_Workshops object and
initializes its elements using the elements in the and parameters
(both are of size ). Here, and are the respective start time and
duration for the workshop. This function must return a pointer to
an Available_Workshops object.
int CalculateMaxWorkshops(Available_Workshops* ptr) Returns the maximum number of workshops the student can attend—without overlap.
The next workshop cannot be attended until the previous workshop
ends. Note: An array of unkown size ( ) should be declared as
follows: DataType* arrayName = new DataType[n];
Your initialize function must return a pointer to an
Available_Workshops object. Your CalculateMaxWorkshops function
must return maximum number of non-overlapping workshops the student
can attend.
Sample Input
6
1 3 0 5 5 8
1 1 6 2 4 1
Sample Output
4
Explanation The first line denotes , the number of workshops. The next line contains space-separated integers where the integer
is the workshop's start time. The next line contains
space-separated integers where the integer is the workshop's
duration. The student can attend the workshops and without
overlap, so CalculateMaxWorkshops returns to main (which then
prints to stdout).
MY CODE:
#include <iostream>
using namespace std;
class Workshop{
public:
int start_time{},duration{},end_time{};};
class Available_Workshops
{
public:
int n{};
struct Workshop*arr=new struct Workshop[n];
~Available_Workshops()
{
delete [] arr;
}
void arr_sort();
void arr_delete(int i);
};
////////////////////////////////////////////////////////////////////////////////////////////
Available_Workshops * initialize(int start_time[],int duration[],int n)
{
Available_Workshops * x=new Available_Workshops{};
x->n=n;
for(int i=0;i<n;i++)
{
x->arr[i].start_time=start_time[i];
x->arr[i].duration=duration[i];
x->arr[i].end_time=start_time[i]+duration[i];
}
return x;
}
///////////////////////////////////////////////////////////////////////////////////////////
void Available_Workshops:: arr_delete(int i)
{
n-=1;
for(int j=i;j<n;j++)
{
arr[j]=arr[j+1];
}
}
///////////////////////////////////////////////////////////////////////////////////////////
void Available_Workshops:: arr_sort()
{
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(arr[i].start_time>arr[j].start_time)
{
struct Workshop temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int CalculateMaxWorkshops(Available_Workshops * x)
{
x->arr_sort();
for(int i=0;i<x->n-1;i++)
{
for(int j=i+1;j<x->n;j++)
{
if(x->arr[i].end_time>x->arr[j].start_time)
{
if(x->arr[i].duration>=x->arr[j].duration)
x->arr_delete(i);
else x->arr_delete(j);
j--;
}
}
}
int y=x->n;
delete x;
return y;
}
int main(int argc, char *argv[]) {
int n; // number of workshops
cin >> n;
// create arrays of unknown size n
int* start_time = new int[n];
int* duration = new int[n];
for(int i=0; i < n; i++){
cin >> start_time[i];
}
for(int i = 0; i < n; i++){
cin >> duration[i];
}
Available_Workshops * ptr;
ptr = initialize(start_time,duration, n);
cout << CalculateMaxWorkshops(ptr) << endl;
return 0;
}
My code is not running. It has segmentation fault. Please help me find this error

You bug can be seen from the class declaration:
class Available_Workshops
{
public:
int n{};
struct Workshop* arr = new struct Workshop[n];
~Available_Workshops()
{
delete[] arr;
}
void arr_sort();
void arr_delete(int i);
};
Member n gets explicitly initialized to 0. Yet, your initialize function will happily fill in more elements into arr (an array of zero elements) and cause all kinds of undefined behavior.
You really, really want a proper constructor for your class instead of trying to inline initialize the members.
Available_Workshops(int size) :
n(size)
{
arr = new Workshop[n];
}
Another issue, although not related to your crash is inside your arr_delete function.
for (int j = i; j < n; j++)
{
arr[j] = arr[j + 1];
}
When j == n-1 on the last iteration of the loop, it will execute arr[n-1] = arr[n]. Accesing arr[n] is undefined behavior since the only valid indices in the array are from [0..n-1]

Related

Need to find highest non repeating number in custom vector

I'm creating a program, where you input n amount of mushroom pickers, they are in a shroom picking contest, they can find shroomA (worth 5 points), shroomB (worth 3 points) and shroomC (worth 15 points). I need to find the contest winner and print his/her name, but if two or more contestants have the same amount of points they are disqualified, meaning I need to find the highest non repeating result.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class ShroomPicker {
private:
string name;
long long int shroomA, shroomB, shroomC;
public:
void Input() {
char Name[100];
long long int shrooma, shroomb, shroomc;
cin >> Name >> shrooma >> shroomb >> shroomc;
name = Name;
shroomA = shrooma; shroomB = shroomb; shroomC = shroomc;
}
long long int calcPoints() {
return shroomA * 5 + shroomB * 3 + shroomC * 15;
}
string winnersName() {
return name;
}
};
int main() {
int n;
cin >> n;
vector<ShroomPicker> shr;
for (int i = 0; i < n; i++) {
ShroomPicker s;
s.Input();
shr.push_back(s);
}
long long int hiscore = 0;
int num = 0;
for (int i = 0; i < n; i++) {
long long int temp = 0;
temp = shr[i].calcPoints();
if (temp > hiscore) {
hiscore = temp;
num = i;
}
}
cout << shr[num].winnersName();
}
I made this program which finds the highest score even if repeats more than once, could someone suggest how I can find the highest non repeating score?
edit:
for (int i = 0; i < n; i++) {
long long int temp = 0;
temp = shr[i].calcPoints();
if (scoreMap.find(temp) == scoreMap.end()) {
scoreMap[temp] = Info{ i, false };
}
else {
scoreMap[temp] = Info{ i, true };
}
}
I would suggest sorting the list of participants in decreasing number of mushrooms picked (O[nlogn]) and then look through the list from start to finish (O[n] max). The first participant whose number of mushrooms picked is different than those of the adjacent participants (in the sorted list) is the winner.
The fastest (O(N)) way I can think of is to have:
struct Info
{
int picker_index;
bool disqualified;
}
// map from score to the Info object above
std::unordered_map<int, Info> scoreMap;
Iterate through pickers and update the map as follows:
-- If no item in the map, just add scoreMap[score] = Info {picker_index, false};
-- else, set disqualified = true on the existing item;
Once the map is constructed, find the max key in the map for which disqualified = false; similar to what you are doing now.

Hashing using int array or unordered_map in STL?

Which is more efficient in terms of memory and time complexity hashing using int array or unordered_map in STL?
By hashing I mean storing elements formed by the combination of a key value and a mapped value, and fast retrieval of individual elements based on their keys.
Actually I was trying to solve this question.
Here's my solution:-
#include <bits/stdc++.h>
#define MAX 15000005
using namespace std;
/*
* author: vivekcrux
*/
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
int c[MAX];
int n;
int sieve()
{
bitset<MAX> m;
m.set();
int ans = 0;
for(int i=2;i<MAX;i++)
{
if(m[i])
{
int mans = 0;
for(int j=i;j<MAX;j+=i)
{
m[j]=0;
mans += c[j];
}
if(mans<n)
ans = max(ans,mans);
}
}
return ans;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int i,j;
cin>>n;
int a[n+1];
for(i=0;i<n;i++)
{
cin>>a[i];
}
int g = a[0];
for(i=1;i<n;i++)
{
g = gcd(g,a[i]);
}
for(i=0;i<n;i++)
{
a[i] /= g;
if(a[i]!=1) c[a[i]]++;
}
int m = sieve();
if(m==0)
cout<<"-1";
else
cout<<n - m<<endl;
return 0;
}
In this code if I use
unordered_map<int,int> c;
instead of
int c[MAX];
I get a Memory limit exceeded verdict.I have found here that unordered_map has a constant average time complexity on average, but no details about space complexity is mentioned here.I wonder why am I getting MLE with unordered_map.
unordered_map uses bucket to store values. A bucket is a slot in the container's internal hash table to which elements are assigned based on the hash value of their key. Lets see the following code in C++17.
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_map<int,int> mp;
mp[4] = 1;
mp[41] = 5;
mp[67] = 6;
cout<<mp.bucket_count();
}
The output comes out be 7 (depends on compiler). This is the number of buckets used in the above code. But if we use an array of size 67, it will obviously take more memory. Another case would be that if we would had numbers 1, 2 and 3 instead of 4, 41 and 67, the output would have been 7. Here using array was the way to go for saving space. So it depends on the keys you are storing in the hash table. For time complexity, both performs equally same. There is a collision condition in unordered_map which would blow the overall time complexity of the code. Here is the codeforces link of the blog.

Recursive algorithm to find all possible solutions in a nonogram row

I am trying to write a simple nonogram solver, in a kind of bruteforce way, but I am stuck on a relatively easy task. Let's say I have a row with clues [2,3] that has a length of 10
so the solutions are:
$$-$$$----
$$--$$$---
$$---$$$--
$$----$$$-
$$-----$$$
-$$----$$$
--$$---$$$
---$$--$$$
----$$-$$$
-$$---$$$-
--$$-$$$--
I want to find all the possible solutions for a row
I know that I have to consider each block separately, and each block will have an availible space of n-(sum of remaining blocks length + number of remaining blocks) but I do not know how to progress from here
Well, this question already have a good answer, so think of this one more as an advertisement of python's prowess.
def place(blocks,total):
if not blocks: return ["-"*total]
if blocks[0]>total: return []
starts = total-blocks[0] #starts = 2 means possible starting indexes are [0,1,2]
if len(blocks)==1: #this is special case
return [("-"*i+"$"*blocks[0]+"-"*(starts-i)) for i in range(starts+1)]
ans = []
for i in range(total-blocks[0]): #append current solutions
for sol in place(blocks[1:],starts-i-1): #with all possible other solutiona
ans.append("-"*i+"$"*blocks[0]+"-"+sol)
return ans
To test it:
for i in place([2,3,2],12):
print(i)
Which produces output like:
$$-$$$-$$---
$$-$$$--$$--
$$-$$$---$$-
$$-$$$----$$
$$--$$$-$$--
$$--$$$--$$-
$$--$$$---$$
$$---$$$-$$-
$$---$$$--$$
$$----$$$-$$
-$$-$$$-$$--
-$$-$$$--$$-
-$$-$$$---$$
-$$--$$$-$$-
-$$--$$$--$$
-$$---$$$-$$
--$$-$$$-$$-
--$$-$$$--$$
--$$--$$$-$$
---$$-$$$-$$
This is what i got:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef std::vector<bool> tRow;
void printRow(tRow row){
for (bool i : row){
std::cout << ((i) ? '$' : '-');
}
std::cout << std::endl;
}
int requiredCells(const std::vector<int> nums){
int sum = 0;
for (int i : nums){
sum += (i + 1); // The number + the at-least-one-cell gap at is right
}
return (sum == 0) ? 0 : sum - 1; // The right-most number don't need any gap
}
bool appendRow(tRow init, const std::vector<int> pendingNums, unsigned int rowSize, std::vector<tRow> &comb){
if (pendingNums.size() <= 0){
comb.push_back(init);
return false;
}
int cellsRequired = requiredCells(pendingNums);
if (cellsRequired > rowSize){
return false; // There are no combinations
}
tRow prefix;
int gapSize = 0;
std::vector<int> pNumsAux = pendingNums;
pNumsAux.erase(pNumsAux.begin());
unsigned int space = rowSize;
while ((gapSize + cellsRequired) <= rowSize){
space = rowSize;
space -= gapSize;
prefix.clear();
prefix = init;
for (int i = 0; i < gapSize; ++i){
prefix.push_back(false);
}
for (int i = 0; i < pendingNums[0]; ++i){
prefix.push_back(true);
space--;
}
if (space > 0){
prefix.push_back(false);
space--;
}
appendRow(prefix, pNumsAux, space, comb);
++gapSize;
}
return true;
}
std::vector<tRow> getCombinations(const std::vector<int> row, unsigned int rowSize) {
std::vector<tRow> comb;
tRow init;
appendRow(init, row, rowSize, comb);
return comb;
}
int main(){
std::vector<int> row = { 2, 3 };
auto ret = getCombinations(row, 10);
for (tRow r : ret){
while (r.size() < 10)
r.push_back(false);
printRow(r);
}
return 0;
}
And my output is:
$$-$$$----
$$--$$$---
$$---$$$--
$$----$$$--
$$-----$$$
-$$-$$$----
-$$--$$$--
-$$---$$$-
-$$----$$$-
--$$-$$$--
--$$--$$$-
--$$---$$$
---$$-$$$-
---$$--$$$
----$$-$$$
For sure, this must be absolutely improvable.
Note: i did't test it more than already written case
Hope it works for you

how i can pass array argument to C++ function

I want to pass an array from one object, store reference and then work with this array inside my function, but...
I have a terrible misunderstanding of passing an array process: In the class TreeType.
I’m facing with an error and I have tried to resolve that for 3 days, but I couldn’t.
Function:
void AddElements(TreeType& tree, int info[], int fromIndex, int toIndex)
{
int midIndex;
if (fromIndex <= toIndex)
{
midIndex = (fromIndex + toIndex) / 2;
tree.PutItem(info[midIndex]);
AddElements(tree, info, fromIndex, midIndex - 1);
// Complete the left subtree.
AddElements(tree, info, midIndex+1, toIndex);
// Complete the right subtree.
}
}
void MakeTree(TreeType& tree, int info[], int length)
// Creates a binary tree from a sorted array.
{
tree.MakeEmpty();
int arrayb[length];
for(int i = 0; i < length; i++)
{
cout << "Enter Value to make tree:" << endl;
cin >> arrayb[i];
}
AddElements(tree, info, 0, length-1);
}
And invoked in main.cpp.
else if (command == "MakeTree")
{
int length=25;
//int arrayb[length];
int arrayb[]={-1000,-967,-923,-844,-669,-567,-455,-267,-209,-183,-59,-23,68,132,159,170,222,228,233,241,389,479,824,939,985};
tree.MakeTree(tree,arrayb,length);
Error capture

All of the option to replace an unknown number of characters

I am trying to find an algorithm that for an unknown number of characters in a string, produces all of the options for replacing some characters with stars.
For example, for the string "abc", the output should be:
*bc
a*c
ab*
**c
*b*
a**
***
It is simple enough with a known number of stars, just run through all of the options with for loops, but I'm having difficulties with an all of the options.
Every star combination corresponds to binary number, so you can use simple cycle
for i = 1 to 2^n-1
where n is string length
and set stars to the positions of 1-bits of binary representations of i
for example: i=5=101b => * b *
This is basically a binary increment problem.
You can create a vector of integer variables to represent a binary array isStar and for each iteration you "add one" to the vector.
bool AddOne (int* isStar, int size) {
isStar[size - 1] += 1
for (i = size - 1; i >= 0; i++) {
if (isStar[i] > 1) {
if (i = 0) { return true; }
isStar[i] = 0;
isStar[i - 1] += 1;
}
}
return false;
}
That way you still have the original string while replacing the characters
This is a simple binary counting problem, where * corresponds to a 1 and the original letter to a 0. So you could do it with a counter, applying a bit mask to the string, but it's just as easy to do the "counting" in place.
Here's a simple implementation in C++:
(Edit: The original question seems to imply that at least one character must be replaced with a star, so the count should start at 1 instead of 0. Or, in the following, the post-test do should be replaced with a pre-test for.)
#include <iostream>
#include <string>
// A cleverer implementation would implement C++'s iterator protocol.
// But that would cloud the simple logic of the algorithm.
class StarReplacer {
public:
StarReplacer(const std::string& s): original_(s), current_(s) {}
const std::string& current() const { return current_; }
// returns true unless we're at the last possibility (all stars),
// in which case it returns false but still resets current to the
// original configuration.
bool advance() {
for (int i = current_.size()-1; i >= 0; --i) {
if (current_[i] == '*') current_[i] = original_[i];
else {
current_[i] = '*';
return true;
}
}
return false;
}
private:
std::string original_;
std::string current_;
};
int main(int argc, const char** argv) {
for (int a = 1; a < argc; ++a) {
StarReplacer r(argv[a]);
do {
std::cout << r.current() << std::endl;
} while (r.advance());
std::cout << std::endl;
}
return 0;
}

Resources