Comparing two int arrays in C - c++

Is there a better way to compare two int array in C++.
struct integer
{
int *number;
int size;
};
This is my struct and i have used this comparing function. I found this solution but it looks like bulshit.
int BigInteger::biggest(integer number1, integer number2)
{
int biggest = 0;
if (number1.size > number2.size)
{
biggest = 1;
}
else if (number1.size < number2.size)
{
biggest = -1;
}
else
{
for (int i = number1.size; i >=0 ; --i)
{
if (number1.number[i] > number2.number[i])
{
biggest = 1;
return biggest;
}
else if (number1.number[i] < number2.number[i])
{
biggest = -1;
return biggest;
}
else
{
continue;
}
}
}
return biggest;
}
if function turn value as 1 then number1 greater than number2
if function turn value as 0 then number1 equal to number2
if function turn value as -1 then number2 greater than number1

This will not improve anything except, that it's much clearer
int BigInteger::biggest(integer number1, integer number2)
{
if (number1.size != number2.size)
return number1.size - number2.size;
for (int i = 0 ; i < number1.size; ++i) {
if (number1.number[i] == number2.number[i])
continue;
return number1.number[i] - number2.number[i];
}
return 0;
}
This function
Returns > 0 then number1 > number2
Returns < 0 then number1 < number2
And 0 if they are equal
Also, in c++ you can overload operators so implementing > and < should be easy using this code.

There are a few small bugs. You don't need some of this code. It will run slightly faster when it is not part of a class. And with just a bit of modification it will work with qsort() (the parameters need to be pointers) (edit: void pointers)
struct integer
{
int *number;
int size;
};
int biggest(const integer &number1, const integer &number2)
{
int biggest = 0;
if (number1.size > number2.size)
{
biggest = 1;
}
else if (number1.size < number2.size)
{
biggest = -1;
}
else
{
for (int i = number1.size - 1; i >= 0; i--) // or --i, no difference
{
if (number1.number[i] > number2.number[i])
{
biggest = 1;
return biggest;
}
if (number1.number[i] < number2.number[i])
{
biggest = -1;
return biggest;
}
// don't need a continue statement here
}
}
return biggest;
}

You can use the std::mismatch() function like this:
int BigInteger::biggest(integer a, integer b)
{
if (a.size != b.size)
return a.size - a.size;
const auto res = std::mismatch(a.number, a.number + a.size, b.number);
if (res.first == (a.number + a.size))
return 0;
else
return (*res.first) < (*res.second) ? -1 : 1;
}
The name of the function biggest() is quite misleading. compare() would be much better. Also, if the function's return type would be boolean (true: a < b), then you could use std::lexicographical_compare(), and the code would much more simpler.

Related

Floating point exception: 8 on Smith number check

So I have written a code to check if a long int number is Smith, but I keep getting Floating point exception: 8, no matter what size do I fix my variables in. Not quite sure what I am missing.
#include <iostream>
bool isPrime(long int k) {
if (k == 1) return false;
for (long int i = 2; i*i < k; i++)
if (k % i == 0)
return false;
return true;
}
int main(){
long int n;
std::cin >> n;
long int sumPr = 0, sumCif = 0;
while (n > 0) {
sumCif += n % 10;
n = n/10;
}
for (long int i = 0; i*i<=n/2; i++) {
if (isPrime(i)) {
while (n % i == 0){
long int p = i;
while (p > 0) {
sumPr += (p % 10);
p = p/10;
}
n = n/i;
}
}
}
if (sumPr == sumCif) std::cout << "1" ; else std::cout << "0";
return 0;
}
The limits of this loop appear to be flawed:
for (long int i = 0; i*i<=n/2; i++) {
Possibly partly due to copy and paste from isPrime(). But the larger problem is you need to modularize this code so that you can properly test each component. And reuse modules (e.g. you implement sum of digits of a number twice in your code.) Code duplication is a potential source of error.
#include <iostream>
bool isPrime(long number) {
if (number < 2) {
return false;
}
if (number % 2 == 0) {
return (number == 2);
}
for (long divisor = 3; divisor * divisor <= number; divisor += 2) {
if (number % divisor == 0) {
return false;
}
}
return true;
}
long sum_digits(long number) {
long sum = 0;
while (number > 0) {
sum += number % 10;
number /= 10;
}
return sum;
}
long sum_prime_factor_digits(long number) {
long sum = 0;
for (long divisor = 2; divisor <= number; divisor++) {
if (isPrime(divisor)) {
while (number % divisor == 0) {
sum += sum_digits(divisor);
number /= divisor;
}
}
}
return sum;
}
bool is_smith(long number) {
if (isPrime(number)) {
return false; // only composites can play this game
}
return sum_digits(number) == sum_prime_factor_digits(number);
}
int main() {
long number;
std::cin >> number;
if (is_smith(number)) {
std::cout << "1";
} else {
std::cout << "0";
}
std::cout << "\n";
return 0;
}
TESTS
> ./a.out
4
1
> ./a.out
5
0
> ./a.out
6
0
> ./a.out
22
1
> ./a.out
4937775
1
> ./a.out
15966114
1
>
Writing clean code isn't something you do after the fact, it's what you do to help you in the debugging process.

C++ Getting a "Control may reach end of a non-void function on a Johnson-Trotter code

What can I do to silence this warning? Do I need to add another return statement somewhere or do I need to change something within the functions?
Also could someone help me add arrows into the Johnson-Trotter algorithm. It would be nice to have them to show the direction but I am very confused on how to do it; though this isn't the main concern right now I just want the program to run. Thank you in advance.
These are the two functions with the warning:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
return i + 1;
}
}
}
int printOnePerm(int k[], bool dir[], int n)
{
int mobile = getMobile(k, dir, n);
int pos = searchArr(k, n, mobile);
if (dir[k[pos - 1] - 1] == RIGHT_TO_LEFT)
{
swap(k[pos - 1], k[pos -2]);
}
else if (dir[k[pos - 1] - 1] == LEFT_TO_RIGHT)
{
swap(k[pos], k[pos -1]);
}
for(int i = 0; i < n; i++)
{
if (k[i] > mobile)
{
if (dir[k[i] - 1] == LEFT_TO_RIGHT)
{
dir[k[i] - 1] = RIGHT_TO_LEFT;
}
else if(dir[k[i] - 1] == RIGHT_TO_LEFT)
{
dir[k[i] - 1] = LEFT_TO_RIGHT;
}
}
}
for(int i = 0; i < n; i++)
{
cout << k[i];
}
cout << endl;
}
For the first function, searchArr(), one question is what do you expect it to return if the value is not found. Since the return values are in the range [1,n], I'm guessing that zero means not found.
I prefer to design functions which have a single return at the end, whenever possible. A default fail value can be set at the start of the function. I would exit the loop when the value is found, or fall through with the default value set.
Here is what I would write:
int searchArr(int k[], int n, int mobile)
{
int ret = 0; /* not found value */
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
ret = i + 1;
break;
}
}
return ret;
}
Alternately, and perhaps a bit more obscurely, if the value is not found in the array, then i will equal n when the for loop completes. This would be a possible function:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
break;
}
}
if (i < n)
return i + 1;
else
return 0;
}
The for loop can be shrunk to
for(int i = 0; i < n && k[i] != mobile; i++) ;
And the return can be shrunk to
return (i < n) ? i + 1 : 0;
Although I generally discourage using the ?: operator.
As mentioned above, the second function doesn't return any value and should be declared "void".
The first one:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
return i + 1;
}
}
}
will not return anything if for some reason nothing in your array matches. In that case, you need to return a default or error value:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
return i + 1;
}
}
return -1; // not found
}
The second one doesn't seem to want to return anything. In C++, the way to do this is with a void, not an int (That was okay in C. C++ not so much):
// assuming we don't want to return anything
void printOnePerm(int k[], bool dir[], int n)

Dividing an array into the greatest amount of parts with equal sums

The array can hold negative numbers. I've written this code using recursion. First I'm summing the first i elements and then I'm checking for each such sum if the rest of the array (starting from i + 1) can be divided with this sum.
It works for some cases but not for others. I've noticed that it doesn't work if there's a prime somewhere.
It works if I sort the array in descending order beforehand but I don't understand why.
In this case the output is 2, while it should be 0.
#include <iostream>
const int N = 5;
int tab[N] = {1, 2, 3, 3, 4};
// returns the number of partitions with a given sum (or 0 if it can't be partitioned)
int divisions(int tab[N], int p, int sum) {
if (N < 2) return 0;
if (p == N) {
return 1;
}
int s_sum = tab[p++];
while (s_sum != sum && p < N) {
s_sum += tab[p++];
}
if (s_sum == sum) {
return divisions(tab, p, sum) + 1;
} else {
return 0;
}
}
// creates all the possible sums and returns the greatest number of partitions where each partition sums up to some sum
int compareAllDivisions(int tab[N]) {
int maxResult = 0;
for (int i = 0; i < N; ++i) {
int sum = 0;
for (int j = 0; j <= i; ++j) {
sum += tab[j];
}
int result = divisions(tab, i + 1, sum);
if (maxResult < result) {
maxResult = result;
}
}
if (maxResult >= 2) {
return maxResult;
} else {
return 0;
}
}
int main() {
std::cout << compareAllDivisions(tab) << std::endl;
return 0;
}
It is because of return value of if (s_sum == sum) part.
It should be changed like below
if (s_sum == sum) {
int ret = divisions(tab, p, sum);
if(ret == 0) return 0;
else return ret + 1;
} else {
return 0;
}
Your return value of divisions is 0 when can't make and pos number when can make.
So, let's consider when 0 returns in there. It can't make at the back, but it will return pos number!

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

sieve of Eratosthenes C++ algorithm

I am trying to implement this algorithm and I have having a hard time working out the algorithm to work for finding the prime numbers up to 1000. I don't really understand but my code is not giving me the correct output, if you can suggest a way I should change my code I would greatly appreciate it.
#include <iostream>
using namespace std;
bool isPrime(int n);
int main() {
int i;
for(i = 1; i <= 1000; i++){
if( isPrime(i)) cout << "This number " << i << " is a prime. " << endl;
}
}
bool isPrime(int n){
if(n <= 1){
return false;
}
if(n == 2){
return true;
}
for(int i = 2; i < n; i++){
if(n % i == 0){
return false;
}else{
return true;
}
}
}
Your decision inside the for loop inside isPrime() is wrong. This is a criterion to terminate the loop:
if(n % i == 0){
but the elsepart is no reason to terminate. You have to wait until the for loop finished. Like this:
for(int i = 2; i < n; i++){
if(n % i == 0){
// Here, we are sure that n can be divided by any other numbers than 1 and n.
return false;
}
}
// Here, we are sure that n cannot be divided by any number 2 .. (n-1).
return true;
}
By the way, you only have to check until the square root of n. You can spare the rest.
There is problem in your isPrime function
bool isPrime(int n){
if(n <= 1){
return false;
}
if(n == 2){
return true;
}
for(int i = 2; i < n; i++){
if(n % i == 0){
return false;
}
else{
return true; /* this line is very dangerous. When there is odd number it is not divisible by two so the control goes to else block and you get every odd number as your prime number */
}
}
}
Instead use this
bool isPrime(int n){
if(n <= 1){
return false;
}
if(n == 2){
return true;
}
for(int i = 2; i < n; i++){
if(n % i == 0){
return false;
}
}
return true;
}
For Sieve Of Erastosthenes
try this code it may help
int b;
cout << "Enter upper limit" << endl;
cin >> b;
bool *x;
x = new bool[b];
x[2] = true;
for (int i = 2; i < b; i++)
{
int count = 2;
if (x[i])
{
cout << i << endl;
while (i*count < b)
{
x[i*count] = false;
count++;
}
}
}
The problem is in the isPrime function.
Your isPrime function says if the the first value of i (i.e 2) is not divided by n then return true. So for eg. 21, 27 etc are also counted as a prime number.
You can use a flag variable in the isPrime function and used it to determine whether the n is prime or not. Like this
boolean prime = true;
for(int counter = 2; counter <= number / 2; counter++) {
if(number % counter == 0) {
prime = false;
break;
}
}
return prime;
I don't think this is Sieve of Eratosthenes algorithm. If you want to implement this algorithm then you can read from here.