Why does the code below causes Segmentation Fault (SIGSEGV)? - c++

PROBLEM STATEMENT
You are given a strictly increasing sequence of integers A1,A2,…,AN. Your task is to compress this sequence.
The compressed form of this sequence is a sequence of ranges separated by commas (characters ','). A range is either an integer or a pair of integers separated by three dots (the string "..."). When each range a...b in the compressed form is decompressed into the subsequence (a,a+1,…,b), we should obtain the (comma-separated) sequence A again.
For each maximal contiguous subsequence (a,a+1,…,b) of A such that b≥a+2, the compressed form of A must contain the range a...b; if b≤a+1, such a sequence should not be compressed into a range. A contiguous subsequence is maximal if it cannot be extended by at least one element of A next to it. It can be proved that the compressed form of any sequence is unique (i.e. well-defined).
Input
The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains a single integer N.
The second line contains N space-separated integers A1,A2,…,AN.
Output
For each test case, print a single line containing one string ― the compressed form of the given sequence.
Constraints
1≤T≤100
1≤N≤100
1 ≤ Ai ≤ 1000 for each valid i
A1 < A2 < …... <AN
Subtasks
Subtask #1 (100 points): Original constraints
Example Input
3
12
1 2 3 5 6 8 9 10 11 12 15 17
4
4 5 7 8
1
4
Example Output
1...3,5,6,8...12,15,17
4,5,7,8
4
MY Code:
#include <bits/stdc++.h>
using namespace std;
bool b[1005];
int a[1005];
int main()
{
int test, i, j, size, count;
cin >> test;
while (test--)
{
for (i = 0; i < 1005; i++)
b[i] = false;
cin >> size;
for (i = 0; i < size; i++)
{
cin >> a[i];
b[a[i]] = true;
}
for (i = 0; i < 1005; i++)
{
if (b[i] == true)
{
cout << i;
j = i;
count = 0;
while (b[j] == true)
{
count++;
j++;
}
if (count > 2)
{
i = j;
if ((j - 1) != a[size - 1])
cout << "..." << i - 1 << ",";
else
cout << "..." << i - 1;
}
if (count == 2)
{
i = j;
if ((j - 1) != a[size - 1])
cout << "," << i - 1 << ",";
else
cout << "," << i - 1;
}
if (count == 1 && ((j - 1) != a[size - 1]))
cout << ",";
}
}
}
return 0;
}
}
MY Question:
Above code runs perfectly on my device giving desired output. But when I am submitting this solution to
Online Judge , it says segmentation fault. It's sure that fundamentally I am accessing the memory incorrectly. Could you please show me where it is?

b is defined a bool[1005]
In this part
for(i=0 ; i<4000 ; i++)
b[i] = false;
You are writing false value 4000 times, exceeding the array size.
Overwriting past the array is allowed on the compiler but will have undefined behaviour in runtime.
In short: it can or can not cause a segfault.

Here is another approach given that the input data is in a file input.txt:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
class Reader {
public:
Reader(const std::string& filename) :
filename_(std::move(filename)), is_(filename_)
{
is_.exceptions( std::ifstream::failbit | std::ifstream::badbit );
}
int get_N() {
int N;
is_ >> N;
return N;
}
std::vector<int> get_ints(int N) {
std::vector<int> v;
v.reserve(N);
for (int i = 0; i < N; i++ ) {
int value;
is_ >> value;
v.push_back(value);
}
return v;
}
int get_num_cases() {
int num_cases;
is_ >> num_cases;
return num_cases;
}
private:
std::string filename_;
std::ifstream is_;
};
bool start_range_cur( std::vector<int> &v, int j, int N )
{
if ( j>= (N - 2) ) return false;
return ((v[j+1] - v[j]) == 1) && ((v[j+2] - v[j+1]) == 1);
}
bool in_range_cur( std::vector<int> &v, int j )
{
return (v[j+1] - v[j]) == 1;
}
void print_range( int min, int max, bool print_comma)
{
std::cout << min << ".." << max;
if (print_comma) std::cout << ",";
}
void print_single(int val, bool print_comma)
{
std::cout << val;
if (print_comma) {
std::cout << ",";
}
}
int main() {
Reader is {"input.txt"};
int num_cases = is.get_num_cases();
for (int i = 0; i < num_cases; i++) {
int N = is.get_N();
std::vector<int> v = is.get_ints(N);
bool in_range = false;
int range_start;
for( int j = 0; j< N; j++ ) {
if (in_range) {
if (j == (N - 1)) {
print_range(range_start, v[j], false);
}
else if (in_range_cur(v, j)) {
continue;
}
else {
print_range(range_start, v[j], true);
in_range = false;
}
}
else {
if (j == (N - 1)) {
print_single(v[j], false);
}
else if (start_range_cur(v, j, N)) {
in_range = true;
range_start = v[j];
}
else {
print_single(v[j], true);
}
}
}
std::cout << '\n';
}
return 0;
}

Related

printing the below pattern using just one loop

ive got the below code to print a pattern (attached below). However i'd like to just use one loop
#include<iostream>
using namespace std;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cout<<"*";
}
for(int j=1;j<=n-i;j++){
if(j%2!=0){
cout<<"_";
}else{
cout<<".";
}
}
cout<<endl;
}
for(int i=1;i<n;i++){
for(int j=1;j<=n-i;j++){
cout<<"*";
}
for(int j=1;j<=i;j++){
if(j%2==0){
cout<<".";
}else{
cout<<"_";
}
}
cout<<endl;
}
}
when n = 5, heres the output.
*_._.
**_._
***_.
****_
*****
****_
***_.
**_._
*_._.
how do i just make this into one single loop
Try this and see how it does what you want to understand the step you did not find on your own:
#include<iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n*2-1; i++) {
if (i <= n)
{
for (int j = 1; j <= i; j++) {
cout << "*";
}
for (int j = 1; j <= n - i; j++) {
if (j % 2 != 0) {
cout << "_";
}
else {
cout << ".";
}
}
cout << endl;
}
else
{
for (int j = 1; j <= n*2 - i; j++) {
cout << "*";
}
for (int j = 1; j <= i-n; j++) {
if (j % 2 == 0) {
cout << ".";
}
else {
cout << "_";
}
}
cout << endl;
}
}
}
I'd like to just use one loop.
I'll take it literally and show a starting point for a possible solution.
// Let's start by figuring out some dimensions.
int n;
std::cin >> n;
int height = 2 * n - 1;
int area = n * height;
// Now we'll print the "rectangle", one piece at a time.
for (int i = 0; i < area; ++i)
{ // ^^^^^^^^
// Extract the coordinates of the char to be printed.
int x = i % n;
int y = i / n;
// Assign a symbol, based on such coordinates.
if ( x <= y and x <= height - y - 1 )
{ // ^^^^^^ ^^^^^^^^^^^^^^^^^^^ Those are the diagonals.
std::cout << '*'; // This prints correctly the triangle on the left...
}
else
{
std::cout << '_'; // <--- But of course, something else should done here.
}
// End of row.
if ( x == n - 1 )
std::cout << '\n';
}
If you look at the pattern, then you can see a sort of "triangles". And this already gives a hint for the solution. Use a triangle function.
Please read about it here.
Then you will notice that always the "aboslute"-function, in C++ std::abs, is involved.
But first of all, it is easily visible that the number rows to print is always the width of a triangle * 2.
And the number of charcters in the pattern, can be calculated by applying the triangle function. Example for width 5:
Number of stars number of dashdot
Row width-abs(row-width) abs(row-width)
1 1 4
2 2 3
3 3 2
4 4 1
5 5 0
6 4 1
7 3 2
8 2 3
9 1 4
And this can be implemented easily now.
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std::string_literals;
int main() {
// Get the max width of the pattern and perform a short input validation
int maxWidth{};
if ((std::cin >> maxWidth) and (maxWidth > 0)) {
// The number of rows for the pattern is dependent on the width. It is a simple relation
const int numberOfRows = 2 * maxWidth;
// Show all rows
for (int row = 1; row < numberOfRows; ++row) {
// Use triangle formular to create star pattern
std::string starPattern(maxWidth - std::abs(row - maxWidth), '*');
// Create dashDot pattern
std::string ddp(std::abs(row - maxWidth), '\0');
std::generate(ddp.begin(), ddp.end(), [i = 0]() mutable { return i++ % 2 ? '.' : '_'; });
// Show output
std::cout << (starPattern+ddp) << '\n';
}
}
else std::cout << "\n*** Error: Invalid input\n\n";
}
Of course you can also create the whole pattern wit std::generate.
Maybe it is too complex for now.
And less understandable.
See:
#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
int main() {
// Get the max width of the pattern and perform a short input validation
if (int width{}; (std::cin >> width) and (width > 0)) {
std::vector<std::string> row(2 * width - 1);
std::for_each(row.begin(), row.end(), [&, r = 1](std::string& s) mutable {
s = std::string(width - std::abs(r - width), '*');
std::string ddp(std::abs(r++ - width),'\0');
std::generate(ddp.begin(), ddp.end(), [&, i = 0]() mutable{ return i++ % 2 ? '.' : '_'; });
s += ddp; std::cout << s << '\n'; });
}
else std::cout << "\n*** Error: Invalid input\n\n";
}

Why am I not able to push a pair after a limit in the vector?

The problem is to find if a given sequence of numbers can form a valid permutation or not. The problem statement is trivial for the real problem. So, I am pushing a pair of integers into the vector. The first part being the number itself and second being 0 or 1.
The code works fine till a sequence 1041 long (specific after debugging a lot). Just to debug I added a print statement after pushing each pair inside the vector. For a length of 1042, the code shows pushed 1040 and then pushed 1 (which is weird) and then just hangs on there.
I am attaching the code as well as the input and terminal output.
You can just check the main function
Code
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
using namespace std;
bool comparator_function(pair<int, int> a, pair<int, int> b) {
return (a.first < b.first);
}
//index_added -> the index at which the latest element was added
void set_r_array(int* r_array_ref, int* per_array_ref, int size, int* count, int index_added) {
for(int i = 1;i <= size; i++) {
count[i] = 0;
}
int temp = index_added;
while(index_added <= size) {
if(index_added == size) {
if(per_array_ref[index_added] == 0) {
r_array_ref[temp] = size;
break;
}
else {
r_array_ref[temp] = -1;
break;
}
}
else {
if(per_array_ref[index_added] == 0) {
r_array_ref[temp] = index_added;
break;
}
else {
index_added++;
}
}
}
for(int i = 1;i <= size; i++) {
if(r_array_ref[i] != -1) {
count[r_array_ref[i]]++;
}
}
}
bool check_max(int* count, int next_element, int size) {
int max_count = -1, index = 0;
for(int i = 1;i <= size; i++) {
int temp_val = count[i];
if(max_count <= temp_val) {
max_count = temp_val;
index = i;
}
}
int num = 0;
for(int i = 1;i <= size; i++) {
if(count[i] == max_count) {
num++;
}
}
//one max
if(num == 1) {
if(next_element == index) {
return true;
}
return false;
}
else {
for(int i = 1;i <= size; i++) {
if(count[i] == max_count) {
if(next_element == i) {
return true;
}
}
}
return false;
}
}
int main() {
int testCases;
cin >> testCases;
cin.ignore();
while(testCases-- > 0) {
int n, result_flag = 0;
cin >> n;
cin.ignore();
vector<pair<int, int>> per;
int temp;
for(int i = 0;i < n; i++) {
cin >> temp;
pair<int, int> temp_pair = make_pair(temp, i+1);
per.push_back(temp_pair);
//debug statement
cout << "pushed " << temp << endl;
}
auto start = std::chrono::high_resolution_clock::now();
cout << "start" << endl;
sort(per.begin(), per.end(), comparator_function);
int permutation_array[n+1], r_array[n+1], count[n+1];
for(int i = 0;i <= n; i++) {
permutation_array[i] = 0;
r_array[i] = i;
count[i] = 1;
}
cout << "end" << endl;
permutation_array[per[0].second] = per[0].first;
set_r_array(r_array, permutation_array, n, count, per[0].second);
//insertion of numbers
for(int i = 1;i < n; i++) {
//check if the next element inserted has the largest count rn or not
int next_element = per[i].second;
if(!check_max(count, next_element, n)) {
cout << "No" << endl;
result_flag = -1;
break;
}
permutation_array[per[i].second] = per[i].first;
set_r_array(r_array, permutation_array, n, count, per[i].second);
}
if(result_flag == 0) {
cout << "Yes" << endl;
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
cout << "Time: " << duration.count() << " microseconds" << endl;
}
}
Input 1
1
5
2 3 4 5 1
Output 1
pushed 2
pushed 3
pushed 4
pushed 5
pushed 1
start
end
Yes
Input 2
1
1042
1 2 3 4 ... so on till 1042
Output 2
pushed 1
pushed 2
.
.
.
pushed 1040
pushed 1
and then hangs, from here on
The complexity of the code is O(n^2). So, I don't think it has to do anything with that. Since the input can be at max 10^4 order. Moreover, according to the print debugging, I think the issue is with the input.
You have issue with input as you reach console line limit.
Put your input into a file should solve that issue.
Then you should be able to debug your algorithm which seems more complicated than needed.

Check whether all the pairs in an array are divisible by k

Given an array of integers and a number k, write a function that returns true if given array can be divided into pairs such that sum of every pair is divisible by k.
This code is producing correct results for all test cases except one I cannot find the glitch in it.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
int arr[n];
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
int k;
cin >> k;
int flag[n] = {0};
int p = 0;
int q = 0;
if (n % 2 != 0) {
cout << "False" << endl;
} else {
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if ((arr[i] + arr[j]) % k == 0 && flag[j] == 0) {
p = 1;
flag[j] = 1;
}
}
if (p == 0) {
q = 1;
cout << "False" << endl;
break;
}
}
if (q == 0) {
cout << "True" << endl;
}
}
}
return 0;
}
One of the big sources of bugs in code is messy code. So how do we clean up code? We modularize it. This means breaking up the code so that each portion of the code does one job well. Let's see what that looks like.
Function to check if something is divisible by k:
bool isDivisible(int number, int divisor) {
return number % divisor == 0;
}
Function to check all pairs:
The logic is as follows:
Take the first number in the list; call in n0.
For every remaining number n1, check if that plus the first number is divisible by k
When we find n1 such that n0 + n1 is divisible by k,
a. If the remaining numbers left over can also be split into divisible pairs, return true
b. Otherwise, continue searching
4.If we've searched through all the numbers, return false.
bool pairsDivisible(int* nums, int count, int k) {
if(count == 0) return true;
if(count % 2 != 0) return false; // count must be even
// 1.
int n0 = nums[0];
// 2.
for(int i = 1; i < count; i++) {
int n1 = nums[i];
// 3.
if(isDivisible(n0 + n1, k)) {
// Move the ith number so it's now nums[1]
std::swap(nums[1], nums[i]);
if(pairsDivisible(nums + 2, count - 2, k)) {
return true; // 3.a
} else {
// Reset the array
std::swap(nums[1], nums[i]);
}
}
}
return false;
}

C++ binary input as a string to a decimal

I am trying to write a code that takes a binary number input as a string and will only accept 1's or 0's if not there should be an error message displayed. Then it should go through a loop digit by digit to convert the binary number as a string to decimal. I cant seem to get it right I have the fact that it will only accept 1's or 0's correct. But then when it gets into the calculations something messes up and I cant seem to get it correct. Currently this is the closest I believe I have to getting it working. could anyone give me a hint or help me with what i am doing wrong?
#include <iostream>
#include <string>
using namespace std;
string a;
int input();
int main()
{
input();
int decimal, x= 0, length, total = 0;
length = a.length();
// atempting to make it put the digits through a formula backwords.
for (int i = length; i >= 0; i--)
{
// Trying to make it only add the 2^x if the number is 1
if (a[i] = '1')
{
//should make total equal to the old total plus 2^x if a[i] = 1
total = total + pow(x,2);
}
//trying to let the power start at 0 and go up each run of the loop
x++;
}
cout << endl << total;
int stop;
cin >> stop;
return 0;
}
int input()
{
int x, x2, count, repeat = 0;
while (repeat == 0)
{
cout << "Enter a string representing a binary number => ";
cin >> a;
count = a.length();
for (x = 0; x < count; x++)
{
if (a[x] != '0' && a[x] != '1')
{
cout << a << " is not a string representing a binary number>" << endl;
repeat = 0;
break;
}
else
repeat = 1;
}
}
return 0;
}
I don't think that pow suits for integer calculation. In this case, you can use shift operator.
a[i] = '1' sets the value of a[i] to '1' and return '1', which is always true.
You shouldn't access a[length], which should be meaningless.
fixed code:
int main()
{
input();
int decimal, x= 0, length, total = 0;
length = a.length();
// atempting to make it put the digits through a formula backwords.
for (int i = length - 1; i >= 0; i--)
{
// Trying to make it only add the 2^x if the number is 1
if (a[i] == '1')
{
//should make total equal to the old total plus 2^x if a[i] = 1
total = total + (1 << x);
}
//trying to let the power start at 0 and go up each run of the loop
x++;
}
cout << endl << total;
int stop;
cin >> stop;
return 0;
}
I would use this approach...
#include <iostream>
using namespace std;
int main()
{
string str{ "10110011" }; // max length can be sizeof(int) X 8
int dec = 0, mask = 1;
for (int i = str.length() - 1; i >= 0; i--) {
if (str[i] == '1') {
dec |= mask;
}
mask <<= 1;
}
cout << "Decimal number is: " << dec;
// system("pause");
return 0;
}
Works for binary strings up to 32 bits. Swap out integer for long to get 64 bits.
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
string getBinaryString(int value, unsigned int length, bool reverse) {
string output = string(length, '0');
if (!reverse) {
for (unsigned int i = 0; i < length; i++) {
if ((value & (1 << i)) != 0) {
output[i] = '1';
}
}
}
else {
for (unsigned int i = 0; i < length; i++) {
if ((value & (1 << (length - i - 1))) != 0) {
output[i] = '1';
}
}
}
return output;
}
unsigned long getInteger(const string& input, size_t lsbindex, size_t msbindex) {
unsigned long val = 0;
unsigned int offset = 0;
if (lsbindex > msbindex) {
size_t length = lsbindex - msbindex;
for (size_t i = msbindex; i <= lsbindex; i++, offset++) {
if (input[i] == '1') {
val |= (1 << (length - offset));
}
}
}
else { //lsbindex < msbindex
for (size_t i = lsbindex; i <= msbindex; i++, offset++) {
if (input[i] == '1') {
val |= (1 << offset);
}
}
}
return val;
}
int main() {
int value = 23;
cout << value << ": " << getBinaryString(value, 5, false) << endl;
string str = "01011";
cout << str << ": " << getInteger(str, 1, 3) << endl;
}
I see multiple misstages in your code.
Your for-loop should start at i = length - 1 instead of i = length.
a[i] = '1' sets a[i] to '1' and does not compare it.
pow(x,2) means and not . pow is also not designed for integer operations. Use 2*2*... or 1<<e instead.
Also there are shorter ways to achieve it. Here is a example how I would do it:
std::size_t fromBinaryString(const std::string &str)
{
std::size_t result = 0;
for (std::size_t i = 0; i < str.size(); ++i)
{
// '0' - '0' == 0 and '1' - '0' == 1.
// If you don't want to assume that, you can use if or switch
result = (result << 1) + str[i] - '0';
}
return result;
}

Working on my own machine but SIGABRT on SPOJ

I'm working on the Next Palindrome problem on SPOJ http://www.spoj.com/problems/PALIN/. My code works fine on my own machine, but SPOJ gives me SIGABRT. I'm using C++ 4.9.2
"A positive integer is called a palindrome if its representation in the decimal system is the same when read from left to right and from right to left. For a given positive integer K of not more than 1000000 digits, write the value of the smallest palindrome larger than K to output. Numbers are always displayed without leading zeros.
Input
The first line contains integer t, the number of test cases. Integers K are given in the next t lines.
Output
For each K, output the smallest palindrome larger than K."
#include<iostream>
#include<vector>
using namespace std;
// turn 9 to 10
void round(vector<int> &input,int index) {
int len = input.size();
input[index] = 0;
input[len-index-1] = 0;
// if it is the first digit, add 1 in the front
if (index == 0) {
input.insert(input.begin(),1);
}
else {
input[index-1] ++;
input[len-index] ++;
}
}
// find the next palindrome
int palin(vector<int> &input) {
int len = input.size();
bool large = true;
bool small = true;
bool eqal = true;
// if it is a single digit
if (len == 1) {
if (input[0] == 9) {
input[0] = 11;
}
else {
input[0] ++;
}
return 1;
}
// start from the one before the middle
int index = len / 2 - 1;
while (index >= 0) {
len = input.size();
// the number supposed to be the same as input[index]
int rfl = len-index-1;
// keep record for if the updated number is smaller/equal to the original
if (input[index] > input[rfl]) {small = false; eqal = false;}
else if (input[index] < input[rfl]) {large = false; small = true; eqal = false;}
else {small = false;}
if (input[index] == 10) {round(input,index);}
else {
input[rfl] = input[index];
}
index --;
};
// restart from the one before the middle
index = (int)input.size() / 2 - 1;
// unless all digits on the left are larger than right/the more left digits are larger but some closer to the middle are smaller or equal, increase the number
if (!large || small || eqal) {
len = input.size();
if (len % 2 == 1) { // odd
if (input[index+1] == 9) {
round(input,index+1);
}
else {input[index+1] ++;}
}
else { // even
if (input[index] == 9) {
round(input,index);
}
else {
input[index-1] ++; input[index + 1] ++;
}
}
// go over the digits again to make sure it is a palindrome
while (index >= 0) {
if (input[index] == 10) {
round(input,index);
}
input[input.size()-index-1] = input[index];
index --;
}
}
return 0;
}
int main() {
int count; // how many numbers are there
cin >> count;
string buffer; // temporary to store each line of input
for (int j=0;j<count;++j) {
vector<int> number;
cin >> buffer;
if (cin.fail() || buffer.size() == 0) { // not a number or length==0
return 1;
}
for (int k=0;k<(int)buffer.size();k++) {
int temp = buffer[k] - '0'; // convert ASCII to int
number.push_back(temp); // construct vector
}
palin(number);
for (int i=0;i<(int)number.size();i++) {
cout << number[i];
}
cout << endl;
}
return 0;
}
Honestly, a brute force method would be inefficient, but would be pretty clear to code. Here, I just keep iterating through numbers until I find a palindrome, for each of the numbers:
http://coliru.stacked-crooked.com/a/2c7ac595d7c2cfa7
#include <iostream>
#include <stack>
#include <string>
#include <vector>
int main() {
int count; // how many numbers are there
std::cin >> count;
std::string buffer;
//two vectors to store output
std::vector<long int> input;
std::vector<long int> output;
//take the inputs
for(int i = 0; i < count; ++i) {
std::cin >> buffer;
input.push_back(std::stoi(buffer));
buffer.clear();
}
//check that we have the inputs
for(auto it : input) {
std::cout << it << std::endl;
}
//lambda to test for palindromes
auto is_palindrome = [](long int n) {
auto str = std::to_string(n);
std::stack<char> stack;
//Load each character into the stack
for(auto it : str) {
stack.push(it);
}
//Use the property of a stack to take out in a reverse order
for(size_t i = 0; !stack.empty(); stack.pop()) {
if (stack.top() != str[i])
return false;
else
++i;
}
return true;
};
//test for the palindromes; iterate
for(auto it : input) {
int n;
for (n = it+1; ; ++n) {
if(is_palindrome(n))
break;
else
continue;
}
output.push_back(n);
}
//output the outputs
for(auto it : output) {
std::cout << "next palindrome: " << it << '\n';
}
return 0;
}