spoj (Ambiguous Permutations) - c++

I was solving a simple problem on spoj called Ambiguous Permutations(http://www.spoj.com/problems/PERMUT2/), it worked fine when I tested for small inputs, but on submission it shows runtime error - segmentation fault. I'm not able to figure it out (though I've wasted a lot of time, and gained frustration only). Please help.
#include <iostream>
#include <stdlib.h>
#include <string.h>
char arr1[200000];//stores original string.
char arr2[200000];//stores inverse permutation.
long int n;
using namespace std;
int main()
{
while (1)
{
cin >> n;
if (n == 0)
{
exit(0);
}
getchar();
gets(arr1);
//creating inverse permutation.
for (long int i = 0; i < 2 * n - 1; i++)
{
if (i % 2 == 1)
{
arr2[i] = ' ';
}
else
{
arr2[2 * (arr1[i] - '0') - 2] = i / 2 + '1';
}
}
arr2[2 * n - 1] = '\0';
//comparing string with it's inverse permutation.
if (strcmp(arr1, arr2) == 0)
{
cout << endl << "ambiguous";
}
else
{
cout << endl << "not ambiguous";
}
}
return 0;
}

The problem is that you are using a char array to represent integers, and your code assumes that each number is represented by one char (note for example checking i % 2 == 1 to determine whether number or space).
Hence, any number bigger than 9 will cause correctness / memory problems.
If you'll use integer arrays it will be a lot easier.
You'll stop worrying about the space character ' ', won't need to decrement '0' char from the cells, and won't need your loops to run till 2 * n - 1.
I think it is much clearer this way:
#include <iostream>
using namespace std;
const int MAX_SIZE = 1000;
int arr1[MAX_SIZE];
int arr2[MAX_SIZE];
int size = 0;
bool areArrsEqual()
{
for (int i = 0; i < size; ++i)
{
if (arr1[i] != arr2[i])
{
return false;
}
}
return true;
}
int main()
{
cin >> size;
while (size > 0 && size <= MAX_SIZE)
{
for (int i = 0; i < size; ++i)
{
cin >> arr1[i];
}
// creating inverse permutation.
for (int i = 0; i < size; i++)
{
// if (arr[i] - 1 >= size) ==> illegal input.
arr2[arr1[i] - 1] = i + 1;
}
// comparing permutation with it's inverse permutation.
if (areArrsEqual())
{
cout << "ambiguous" << endl;
}
else
{
cout << "not ambiguous" << endl;
}
cin >> size;
}
return 0;
}
Output:
4
1 4 3 2
ambiguous
5
2 3 4 5 1
not ambiguous
1
1
ambiguous
13
1 2 3 4 5 6 7 8 9 10 11 12 13
ambiguous
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";
}

Generation of all sequences of length N from numbers 0.1…k-1 with minimal changes

For example, I have a code that generates all sequences of zeros and ones of length 4. Can I do it using his example?
#define n 2
int x[n];
int main() {
int i, k;
for (i = 0; i < n; i++) {
x[i] = 0;
}
while (1) {
for (i = 0; i < n; i++) {
cout << x[i];
}
cout << endl << endl;
for (k = n - 1; k >= 0 && x[k] == 1; k--) {
x[k] = 0;
}
if (k == -1) {
break;
} else {
x[k] = 1;
}
}
return 0;
}
Example:
Basically your task is to output all N-digit numbers in base K in ascending order.
I encoded two solutions for your task. First solution looks very similar to your code. It is non-recursive, but algorithmical.
Base of this solution is following algorithm - we go from tail of a number while all digits are equal to K - 1 (for example equal to 9 in case of famous base 10) and zeroize them, and first digit smaller than K - 1 we increment. This way we generate next number using previous number. This is also how usually people increment any long number by 1 in their minds.
Try it online!
#include <functional>
#include <vector>
#include <iostream>
void Gen(size_t n, size_t k, auto const & outf) {
std::vector<size_t> a(n);
while (true) {
outf(a);
int i = 0;
for (i = a.size() - 1; i >= 0; --i) {
if (a[i] < k - 1)
break;
a[i] = 0;
}
if (i < 0)
break;
++a[i];
}
}
int main() {
Gen(2, 3, [](auto const & v){
for (auto e: v)
std::cout << e << " ";
std::cout << std::endl;
});
}
Output:
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
Second solution uses approach of Recursive Function.
For those who knows recursive functions this second solution looks simpler and doesn't need invention of any algorithms like in first solution.
Basically in a loop I increment most significant digit (left-most) and recursively with same loop I iterate through all possible numbers in a tail. When tail goes through all possible numbers only then most significant digit is incremented again.
Try it online!
#include <functional>
#include <vector>
#include <iostream>
void Gen(size_t n, size_t k, auto const & outf) {
std::vector<size_t> a(n);
std::function<void(size_t pos)> Rec = [&](auto pos){
if (pos >= n) {
outf(a);
return;
}
for (size_t i = 0; i < k; ++i) {
a[pos] = i;
Rec(pos + 1);
}
};
Rec(0);
}
int main() {
Gen(2, 3, [](auto const & v){
for (auto e: v)
std::cout << e << " ";
std::cout << std::endl;
});
}
Output:
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
If the task is to improve your code with minimal changes, to achieve final goal, then it will be following snippet (see n and K defined at start of program).
Try it online!
#include <iostream>
using namespace std;
#define n 2
#define K 3
int x[n];
int main() {
int i, k;
for (i = 0; i < n; i++) {
x[i] = 0;
}
while (1) {
for (i = 0; i < n; i++) {
cout << x[i] << " ";
}
cout << endl;
for (k = n - 1; k >= 0 && x[k] == K - 1; k--) {
x[k] = 0;
}
if (k == -1) {
break;
} else {
++x[k];
}
}
return 0;
}
Output:
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2

Why my empty string assignment doesn't clear my string

I have an exercise which looks like that:
Problem statement is simple and straight forward . You will be given a non-negative integer P of length N and you need to check whether
it's divisible by Q ?
Integer P will be given in its decimal representation with P0 as leftmost digit and P1 as second digit from left !
Rest of the digit can be generated from the formula :
Pi = ( 4*Pi-1 + Pi-2 ) modulo Q for 2 <= i <= N-1
Input
The first line contains one integer T - denoting the number of test cases.
T lines follow each containing four integers P0 , P1 , Q and N !
Output
For each testcase output YES if the corresponding integer is divisible by Q and NO otherwise.
Constraints
T <= 100000
0 < P0 , P1 , Q < 10
0 < N <= 1018
Example
Input:
4
1 4 2 2
1 4 2 1
4 2 3 2
3 4 7 3
Output:
YES
NO
YES
NO
Explanation
Value of P is 14, 1, 42, 345 in respective cases !
and that's what I came up with
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int t, q, n, p_0, p_1, p_temp, p;
vector<int> digits;
vector<string> answers;
string number = "";
cin >> t;
for (int i = 0; i < t; i++)
{
cin >> p_0 >> p_1 >> q >> n;
if (n == 1)
{
digits.push_back(p_0);
}
else
{
digits.push_back(p_0);
digits.push_back(p_1);
for (int i = 2; i <= (n - 1); i++)
{
p_temp = (4 * digits[i - 1] + digits[i - 2]) % q;
digits.push_back(p_temp);
}
}
for (int i = 0; i < digits.size(); i++)
{
number += to_string(digits[i]);
}
p = stoi(number);
cout << number << endl;
if (p % q == 0)
{
answers.push_back("YES");
}
else
{
answers.push_back("NO");
}
number = "";
}
for (int i = 0; i < answers.size(); i++)
{
cout << answers[i] << endl;
}
}
Everything I have done works fine, except for one thing, this part does not clear my number variable
number = "";
And honestly I don't know why, could someone correct my mistakes and explain me what did I do wrong. Thanks.
Your problem is with the digits vector.
Each loop the number string just gets repopulated with the digits vector which is never cleared.
Use digits.clear() to empty the vector like so:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int t, q, n, p_0, p_1, p_temp, p;
vector<int> digits;
vector<string> answers;
string number = "";
cin >> t;
for (int i = 0; i < t; i++)
{
cin >> p_0 >> p_1 >> q >> n;
if (n == 1)
{
digits.push_back(p_0);
}
else
{
digits.push_back(p_0);
digits.push_back(p_1);
for (int i = 2; i <= (n - 1); i++)
{
p_temp = (4 * digits[i - 1] + digits[i - 2]) % q;
digits.push_back(p_temp);
}
}
for (int i = 0; i < digits.size(); i++)
{
number += to_string(digits[i]);
}
p = stoi(number);
cout << number << endl;
if (p % q == 0)
{
answers.push_back("YES");
}
else
{
answers.push_back("NO");
}
digits.clear();
number = "";
}
for (int i = 0; i < answers.size(); i++)
{
cout << answers[i] << endl;
}
}
To clear a string you can/should use std::string::clear() as:
number.clear();
There may be other logical errors in your program which may be the reason for not getting the output you expect.
Also instead of creating/initializing the string number using string number = "";, you should use
string number;//no need to write = ""

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

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;
}

Program With Array To Check For Increasing/Decreasing Numbers

Beginner C++ student here starting to learn different ways of using arrays. I am trying to put together the program below. It's supposed to ask the user for an input of a set of numbers that will go into an array. This set of numbers may increase or decrease at any point the user wants.
For example:
1 2 3 4 9 8 7 4 5 6 10 11 12 20 19 18 17
The program is to check against that set of numbers and account for every time there is an increase or decrease. Right now the program will return "increase" or "decrease".
For example, running it against the aforementioned set of numbers it returns:
increasing
decreasing
decreasing
However, I have two problems:
I think it is not accounting for all the changes (increases and decreases) occurring in the array correctly. Unsure where I have gone wrong.
I now have to return the number of changes that occur instead of "decrease"/"increase". Meaning, in the example above it would return "3" because there is 1 true value and 2 false.
If anyone can advise I would immensely appreciate the help.
Thank you so very much!!!
#include <iostream>
using namespace std;
bool increasing(int arr[], int n);
int main()
{
int arr[20], n;
cout << "Enter a set of Increasing/Decreasing numbers (ex. 1 2 3 6 5 4 7 8 9 3 2 1)." << endl;
cout << "Press 'Enter' to see results" << endl;
while (cin >> n)
{
for (int i = 0; i <= n; i++)
{
cin >> arr[i];
}
cout << (increasing(arr, n) ? "increasing" : "decreasing") << endl;
}
return 0;
}
bool increasing(int arr[], int n)
{
int x = 0;
for (int i = 0; i < n - 1; i++)
{
if (arr[i] < arr[i + 1])
{
x++;
}
}
if (x == n - 1)
{
return true;
}
else
{
return false;
}
}
For the needs of 1. you have to call the increasing function several times. So you also need an integer advance to remember your advance.
bool increasing(int arr[], int& advance, int n);
You can then call it with (x counts the number of increasing as stated in 2.)
int advance = 0;
do {
int x = 0;
cout << (increasing(arr, advance, n, x) ? "increasing " : "decreasing ") << x << endl;
} while (advance < n-1);
You can implement it with
bool increasing(int arr[], int& advance, int n, int& x)
{ assert(advance < n-1);
x = 0;
bool doesIncrease = arr[advance] < arr[advance + 1];
bool isStable = arr[advance] == arr[advance + 1];
if (doesIncrease) {
for (int i = advance+1; i < n - 1; i++)
{
if (arr[i] < arr[i + 1])
{
x++;
}
}
}
else if (isStable) {
...
}
else { // decreasing
for (int i = advance+1; i < n - 1; i++)
{
if (arr[i] > arr[i + 1])
{
x++;
}
}
};
return doesIncrease;
}