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;
}
Related
I'm writing a code to find the last prime number of a given range. Suppose the range is 1 to 50. Then the last prime no. I want to print must be 47. My idea was to maybe reverse the order of prime numbers in the range and then try printing only the first value. Again kinda like if my order was 1 to 50 then I would start printing from 47, 43 and so on and only print 47. But I'm stuck and not getting ideas on how I could do this. here's my code
int prime_bef(int n)
{
int check = 0;
for (int i = 1; i <= n; i++)
{
if (n % i == 0)
{
check++;
}
}
if (check == 2)
{
cout << n << " ";
}
return 0;
}
int main ()
{
int l;
int u;
cin >> l >> u;
for (int i = u; i >= l; i--)
{
prime_bef(i);
}
return 0;
}
You can just use exit() in the place you want to end the program, and it works fine in your case. But by far the best approach is returning a value to test for continuation, it is the most readable.
#include<iostream>
#include <stdlib.h>
using namespace std;
int prime_bef(int n)
{
int check = 0;
for (int i = 1; i <= n; i++)
{
if (n % i == 0)
{
check++;
}
}
if (check == 2)
{
cout << n << " ";
exit(0);
}
return 0;
}
int main ()
{
int l;
int u;
cin >> l >> u;
for (int i = u; i >= l; i--)
{
prime_bef(i);
}
return 0;
}
Same code using bool return type:
#include<iostream>
using namespace std;
bool prime_bef(int n)
{
int check = 0;
for (int i = 1; i <= n; i++)
{
if (n % i == 0)
{
check++;
}
}
if (check == 2)
{
cout << n << " ";
return true;
}
return false;
}
int main ()
{
int l;
int u;
cin >> l >> u;
for (int i = u; i >= l; i--)
{
if(prime_bef(i))
break;
}
return 0;
}
Here is a simple and efficient way to check if the number is prime. I am checking if the number is prime and when it is true I am printing the number and breaking the loop so that only 1 number is printed. You can always remove the break statement and print all prime numbers in range.
#include<iostream>
using namespace std;
bool isPrime(int n){
if(n==2)return true;
if(n%2==0 || n==1)return false;
for(int i=3; i*i<=n; ++i){
if(n%i==0){
return false;
}
}
return true;
}
int main (){
int l, u;
cin>>l>>u;
for (int i = u; i >= l; i--){
if(isPrime(i)){
cout<<i<<"\n";
break;
}
}
return 0;
}
I'll give you a hint... while you are iteratively checking for the prime nature of the number, also check whether the last prime number calculated in the loop is greater than the max term of the range and break the loop when the condition becomes false.
Here a C++17 approach :
#include <cmath>
#include <iostream>
#include <vector>
// type to use for storing primes
using prime_t = unsigned long;
// there is a way to determine an upper bound to the number of primes smaller then a maximum number.
// See : https://primes.utm.edu/howmany.html
// this can be used to estimate the size of the output buffer (vector)
prime_t pi_n(const prime_t max)
{
prime_t pi_n{ max };
if (max > 10)
{
auto ln_n = std::log(static_cast<double>(max));
auto value = static_cast<double>(max) / (ln_n - 1.0);
pi_n = static_cast<prime_t>(value + 0.5);
}
return pi_n;
}
// Calculate prime numbers smaller then max
// https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
auto calculate_primes(const prime_t max)
{
std::vector<bool> is_primes(max, true);
// 0, 1 are not primes
is_primes[0] = false;
is_primes[1] = false;
// sieve
for (prime_t n = prime_t{ 2 }; n < prime_t{ max }; ++n)
{
if (is_primes[n])
{
auto n2 = n * n;
for (prime_t m = n2; m < max; m += n)
{
is_primes[m] = false;
}
}
}
// avoid unnecessary resizes of vector by pre-allocating enough entries to hold result
prime_t n{ 0 };
std::vector<prime_t> primes;
primes.reserve(pi_n(max));
// add all prime numbers found by the sieve
for (const auto is_prime : is_primes)
{
if (is_prime) primes.push_back(n);
n++;
}
return primes;
}
int main()
{
const prime_t max{ 50 };
auto primes = calculate_primes(max);
// max prime is last one in container
auto max_prime = primes.back();
std::cout << "maximum prime number smaller then " << max << ", is " << max_prime << std::endl;
}
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.
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;
}
I am trying to do a program which print all possible palindromes that can be generated rearrangement involves that a character changes its position with maximum 1 index, meaning only interchanges of adjacent characters are allowed.
I tried a lot of codes but the best one I had is the next one.
Only I could get all possible palindromes rearranged but with all changes (not only one)
CODE
#include <bits/stdc++.h>
using namespace std;
#define M 26
bool caNformPalindrome(string str, int* count_array)
{
//Initialize array with zeroes
for (int i = 0; i < 26; ++i)
{
count_array[i] = 0;
}
int length = str.length();
/* Updating frequency according to given string */
for (int i = 0; i < length; i++)
{
count_array[str[i] - 'a']++;
}
int odd_count = 0;
//Find odd_count
for (int i = 0; i < M; i++)
{
if (count_array[i] % 2 == 1)
{
odd_count++;
}
}
//if length is odd_count then only one letter's frequency must be odd_count
if ((length % 2 == 1 && odd_count == 1 ) || (length %2 == 0 && odd_count == 0))
{
return true;
}
else//if length is even no letter should have odd_count frequency
{
return false;
}
}
//Function to reverse the string
string reverse(string str)
{
string rev = str;
reverse(rev.begin(), rev.end());
return rev;
}
//Function to print
void printPalIndromes(string str)
{
int count_array[M];
// checking whether letter can make palindrome or not
if (!caNformPalindrome(str, count_array))
{
return;
}
int length = str.length();
// half will contain half part of all palindromes,
// that is why pushing half count_array of each letter
string half = "";
char mid;//store odd count charcter
for (int i = 0; i < M; i++)
{
if(count_array[i] % 2 == 1)
{
mid = i + 'a';
}
half += string(count_array[i] / 2, i + 'a');
}
string palindrome_string;
do
{
palindrome_string = half;
if (length % 2 == 1)
{
palindrome_string += mid;
}
palindrome_string += reverse(half);
cout<<palindrome_string<<endl;
}
while (next_permutation(half.begin(), half.end()));
}
//Main function
int main()
{
string str = "aabbc";
cout<<"Possible Permutations for Input_string only with 1 change"<<str<<" are: "<<endl;
printPalIndromes(str);
return 0;
}
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;
}