Related
I have to write a program to check if the entered number has these qualifications:
A number that is prime it self, the reverse of that number is also prime, and the number's digits are prime numbers too (Like this number: 7523).
If the needs meet, it has to show "yes" when you enter and run the program otherwise "no".
I know both codes for prime and reverse numbers but I don't know how to merge them.
This is the code:
#include <iostream>
#include <conio.h>
using namespace std;
void prime_check(int x) {
int a, i, flag = 1;
cin >> a;
for (i = 2; i <= a / 2 && flag == 1; i++) {
if (a % i == 0)
flag = 0;
}
if (flag == 1)
cout << "prime";
else
break;
}
int main() {
int a, r, sum = 0;
cin >> a;
while (a != 0) {
r = a % 10;
sum = (sum * 10) + r;
a = a / 10;
}
}
The program has to check each digit of the number entered to see if it is prime or not in every step, then show "yes", but it doesn't work.
Welcome to the site.
I don't know how to merge them.
void prime_check(int n) { /*code*/ }
I'd understand that you don't know how to use this.
It's very easy!
int main()
{
int i = 0;
prime_check(i);
}
If you are confused about how the program executes, you could use a debugger to see where it goes. But since using a debugger can be a bit hard at first, I would suggest to add debug prints to see how the program executes.
This line of code prints the file and line number automatically.
std::cout << __FILE__ << ":" << __LINE__ << "\n";
I'd suggest to add it at the start of every function you wish to understand.
One step further is to make it into a macro, just so that it's easy to use.
#define DEBUGPRINT std::cout << __FILE__ << ":" << __LINE__ << "\n";
Check a working example here:
http://www.cpp.sh/2hpam
Note that it says <stdin>::14 instead of the filename because it's running on a webpage.
I have done some changes to your code, and added comments everywhere I've made changes. Check it out:
#include <iostream>
#include <conio.h>
using namespace std;
bool prime_check(int x) { // I have changed the datatype of this function to bool, because I want to store if all the digits are prime or not
int i, flag = 1; // Removed the variable a, because the function is already taking x as input
for (i = 2; i <= x / 2 && flag == 1; i++) {
if (x % i == 0)
flag = 0;
}
return flag == 1;
}
int main() {
int a, r, sum = 0, original; // added original variable, to store the number added
bool eachDigit = true; // added to keep track of each digit
cin >> a;
original = a;
while (a != 0) {
r = a % 10;
eachDigit = prime_check(r); // Here Each digit of entered number is checked for prime
sum = (sum * 10) + r;
a = a / 10;
}
if (eachDigit && prime_check(original) && prime_check(sum)) // At the end checking if all the digits, entered number and the revered number are prime
cout << "yes";
else
cout<< "no";
}
For optimization, you can check if the entered number is prime or not before starting that loop, and also you can break the loop right away if one of the digits of the entered number is not prime, Like this:
#include <iostream>
#include <conio.h>
using namespace std;
bool prime_check(int x) { // I have changed the datatype of this function to bool, because I want to store if all the digits are prime or not
int i, flag = 1; // Removed the variable a, because the function is already taking x as input
for (i = 2; i <= x / 2 && flag == 1; i++) {
if (x % i == 0)
flag = 0;
}
return flag == 1;
}
int main() {
int a, r, sum = 0;
bool eachDigit = true, entered; // added to keep track of each digit
cin >> a;
entered = prime_check(a);
while (a != 0 && entered && eachDigit) {
r = a % 10;
eachDigit = prime_check(r); // Here Each digit of entered number is checked for prime
sum = (sum * 10) + r;
a = a / 10;
}
if (eachDigit && entered && prime_check(sum)) // At the end checking if all the digits, entered number and the revered number are prime
cout << "yes";
else
cout<< "no";
}
Suppose you have an int variable num which you want to check for your conditions, you can achieve your target by the following:
int rev_num = 0;
bool flag = true; // Assuming 'num' satisfies your conditions, until proven otherwise
if (prime_check(num) == false) {
flag = false;
}
else while (num != 0) {
int digit = num % 10;
rev_num = rev_num * 10 + digit;
// Assuming your prime_check function returns 'true' and 'false'
if (prime_check(digit) == false) {
flag = false;
break;
}
num /= 10;
}
if (prime_check(rev_num) == false) {
flag = false;
}
if (flag) {
cout << "Number satisfies all conditions\n";
}
else {
cout << "Number does not satisfy all conditions\n";
}
The problem is that each of your functions is doing three things, 1) inputting the number, 2) testing the number and 3) outputting the result. To combine these functions you need to have two functions that are only testing the number. Then you can use both functions on the same number, instead of inputting two different numbers and printing two different results. You will need to use function parameters, to pass the input number to the two functions, and function return values to return the result of the test. The inputting of the number and the outputting of the result go in main. Here's an outline
// returns true if the number is a prime, false otherwise
bool prime_check(int a)
{
...
}
// returns true if the number is a reverse prime, false otherwise
bool reverse_prime_check(int a)
{
...
}
int main()
{
int a;
cin >> a;
if (prime_check(a) && reverse_prime_check(a))
cout << "prime\n";
else
cout << "not prime\n";
}
I'll leave you to write the functions themselves, and there's nothing here to do the digit checks either. I'll leave you do to that.
Trying to implement a combination of 4 objects taken 2 at a time without taking into account the arrangement (such must be considered duplicates: so that order is not important) of objects with std::set container:
struct Combination {
int m;
int n;
Combination(const int m, const int n):m(m),n(n){}
};
const auto operator<(const auto & a, const auto & b) {
//explicitly "telling" that order should not matter:
if ( a.m == b.n && a.n == b.m ) return false;
//the case "a.m == b.m && a.n == b.n" will result in false here too:
return a.m == b.m ? a.n < b.n : a.m < b.m;
}
#include <set>
#include <iostream>
int main() {
std::set< Combination > c;
for ( short m = 0; m < 4; ++ m ) {
for ( short n = 0; n < 4; ++ n ) {
if ( n == m ) continue;
c.emplace( m, n );
} }
std::cout << c.size() << std::endl; //12 (but must be 6)
}
The expected set of combinations is 0 1, 0 2, 0 3, 1 2, 1 3, 2 3 which is 6 of those, but resulting c.size() == 12. Also, my operator<(Combination,Combination) does satisfy !comp(a, b) && !comp(b, a) means elements are equal requirement.
What am I missing?
Your code can't work1, because your operator< does not introduce a strict total ordering. One requirement for a strict total ordering is that, for any three elements a, b and c
a < b
and
b < c
imply that
a < c
(in a mathematical sense). Let's check that. If we take
Combination a(1, 3);
Combination b(1, 4);
Combination c(3, 1);
you see that
a < b => true
b < c => true
but
a < c => false
If you can't order the elements you can't use std::set. A std::unordered_set seems to more suited for the task. You just need a operator== to compare for equality, which is trivial and a hash function that returns the same value for elements that are considere identical. It could be as simple as adding m and n.
1 Well, maybe it could work, or not, or both, it's undefined behaviour.
Attached is the working code. The tricky part that you were missing was not adding a section of code to iterate through the already working set to then check the values. You were close! If you need a more thorough answer I will answer questions in the comments. Hope this helps!
#include <set>
#include <iostream>
using namespace std;
struct Combination {
int m;
int n;
Combination(const int m, const int n):m(m),n(n){}
};
const auto operator<(const auto & a, const auto & b) {
//explicitly "telling" that order should not matter:
if ( a.m == b.n && a.n == b.m ) return false;
//the case "a.m == b.m && a.n == b.n" will result in false here too:
return a.m == b.m ? a.n < b.n : a.m < b.m;
}
int main() {
set< Combination > c;
for ( short m = 0; m < 4; ++ m )
{
for ( short n = 0; n < 4; ++ n )
{
//Values are the same we do not add to the set
if(m == n){
continue;
}
else{
Combination s(n,m);
const bool is_in = c.find(s) != c.end();
if(is_in == true){
continue;
}
else{
cout << " M: " << m << " N: " << n << endl;
c.emplace( m, n);
}
}
}
}
cout << c.size() << endl; //16 (but must be 6)
}
Question: How to find, for a given integer n, the first prime number that is larger than n?
My own work so far
I've managed to write a program that checks whether or not a given integer is a prime or not:
#include <iostream>
#include <cmath>
using namespace std;
bool is_prime (int n)
{
int i;
double square_root_n = sqrt(n) ;
for (i = 2; i <= square_root_n ; i++)
{
if (n % i == 0){
return false;
break;
}
}
return true;
}
int main(int argc, char** argv)
{
int i;
while (true)
{
cout << "Input the number and press ENTER: \n";
cout << "To exit input 0 and press ENTER: \n";
cin >> i;
if (i == 0)
{
break;
}
if (is_prime(i))
cout << i << " is prime" << endl;
else
cout << i << " isn't prime'" << endl;
}
return 0;
}
I'm struggling, however, on how to proceed on from this point.
You have a function is_prime(n), and a number n, and you want to return the smallest number q such that is_prime(q)==true and n <= q:
int q = n;
while (!is_prime(q)) {
q++;
}
// here you can be sure that
// 1. q is prime
// 2. q >= n -- unless there was an overflow
If you want to be a bit more efficient, you can check explicitly for the even case, and the increment by 2 each time.
It's a concrete example of a general theme: if you have a test function and a method for generating elements, you can generate the elements that pass the test:
x = initial_value
while (something) {
if (test(x)) {
// found!
// If you only want the first such x, you can break
break;
}
x = generate(x)
}
(note that this is not a valid C++ code, it's pseudocode)
int i;
**int k_koren_od_n = (int)(sqrt(n) + 0.5)**
for (i = 2; i <= k_koren_od_n ; i++){
To get around casting issues, you might want to add this fix.
This question already has answers here:
Compare versions as strings
(5 answers)
Closed 6 years ago.
Our professor want us to write a program to compare two version numbers, like 0.1 < 0.2 or 1 < 1.1. Also there are some trick ones like .0.4 < .1.
So, my idea is first judge if the number start as a dot, if it does, I add a 0 to it. After that I remove other dots except the first one. Then I convert string to number and compare them. Here's what I do in the first step.
string numb1,numb2;
if(numb1[0]=='.')
{
numb1 ="0"+ numb1;
}
I do the same thing to the second number. And now I need help to show me how to remove the dots except the first one.
Our professor want us to use this specific function:
int compareVersions(string ver1, string ver2).
If ver1 > ver2: return 1
if ver1 < ver2: return -1
otherwise return 0.
By the way, some of the vision number may very long like 2.3.2.2.3.1.1.5.3.5.6.2 or 1.1.1.1.1.1.1.
Here's one approach that should work for numerical version numbers:
Split the input strings into pieces using getline(strstream, token, ".")
Convert corresponding pieces to numbers using atoi or stol and compare numerically
Basically, treat the version numbers as sequences of numbers separated by . and compare those sequences lexicographically.
Note that a practical, general version number comparison algorithm probably needs to handle extra trickiness such as letter suffixes (e.g. 1.1e, 2.4b24, 3.5rc1), etc. I'm assuming that this is outside the scope of a class exercise, but the approach is similar: split these parts into sequences of numeric and non-numeric parts and compare each part (e.g. 2.4b7 < 2.4b24 because 4, "b", 7 < 4, "b", 24).
Something like this would work to do the checking and is fairly minimal. It makes use of boost to split the string and then compares the version step by step. It automatically deals with missing leading zeros.
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
#include <iostream>
int version_a_newer_than_b(const std::string& a, const std::string& b)
{
// First, split the string.
std::vector<std::string> va, vb;
boost::split(va, a, boost::is_any_of("."));
boost::split(vb, b, boost::is_any_of("."));
// Compare the numbers step by step, but only as deep as the version
// with the least elements allows.
const int depth = std::min(va.size(), vb.size());
int ia,ib;
for (int i=0; i<depth; ++i)
{
ia = atoi(va[i].c_str());
ib = atoi(vb[i].c_str());
if (ia != ib)
break;
}
// Return the required number.
if (ia > ib)
return 1;
else if (ia < ib)
return -1;
else
{
// In case of equal versions, assumes that the version
// with the most elements is the highest version.
if (va.size() > vb.size())
return 1;
else if (va.size() < vb.size())
return -1;
}
// Everything is equal, return 0.
return 0;
}
int main()
{
std::string a = "0.1.32.8";
std::string b = "0.1";
std::cout << "Is a newer than b: " << version_a_newer_than_b(a, b) << std::endl;
return 0;
}
What you need to do is iterate through the string, ignoring '.' and converting the char representations of numbers into ints. Then compare the two end results.
string numb1 = "4.3.2";
string numb2 = "3.4.5";
int n1 = 0;
int n2 = 0;
for (int i = 0; i < numb1.length(); i++)
{
if (numb1[i] != '.')
{
n1 = n1 * 10;
n2 = n2 * 10;
n1 += (int(numb1[i]) - '0');
n2 += (int(numb2[i]) - '0');
}
}
That will give you 432 and 345, comparing those would give you which is the higher version.
Since you know numb[1] would equal to '.' you can just use
numb1.erase(std::remove(numb1.begin() + 2, numb1.end(), '.'), numb1.end());
Which would remove all dots in numb1 after the second character.
Following example will demonstrates comparison between following version format:
major.minor.revision.build or any shorter version, like only major while it allows you to extend it to fit your needs as of,
"some of the version numbers may be very long like 2.3.2.2.3.1.1.5.3.5.6.2"
Using example bellow, dots in the beginning and end of the version string are taken care of as far .0.4 is considered to be equal to 0.0.4 and .1. is considered to be equal to 0.1.0.
CompareVersion.h
#ifndef COMPAREVERSION_H_
#define COMPAREVERSION_H_
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
struct CompareVersion {
public:
int maj;
int min;
int rev;
int build;
CompareVersion(std::string);
bool operator < (const CompareVersion&);
bool operator <= (const CompareVersion&);
bool operator == (const CompareVersion&);
friend std::ostream& operator << (std::ostream& stream, const CompareVersion& ver) {
stream << ver.maj;
stream << '.';
stream << ver.min;
stream << '.';
stream << ver.rev;
stream << '.';
stream << ver.build;
return stream;
};
void reset();
};
#endif /* COMPAREVERSION_H_ */
CompareVersion.cpp
#include "CompareVersion.h"
CompareVersion::CompareVersion(std::string version)
{
reset();
if (version.compare(0,1,".") == 0)
version = "0"+version;
if (version.compare(version.size()-1,1,".") == 0)
version.append("0");
sscanf(version.c_str(), "%d.%d.%d.%d", &maj, &min, &rev, &build);
if (maj <= 0) maj = 0;
if (min <= 0) min = 0;
if (rev <= 0) rev = 0;
if (build <= 0) build = 0;
}
bool CompareVersion::operator < (const CompareVersion& other)
{
if (maj < other.maj) return true;
if (min < other.min) return true;
if (rev < other.rev) return true;
if (build < other.build) return true;
return false;
}
bool CompareVersion::operator <= (const CompareVersion& other)
{
if (maj >= other.maj) return true;
if (min >= other.min) return true;
if (rev >= other.rev) return true;
if (build >= other.build) return true;
return false;
}
bool CompareVersion::operator == (const CompareVersion& other)
{
return maj == other.maj
&& min == other.min
&& rev == other.rev
&& build == other.build;
}
void CompareVersion::reset()
{
maj = 0;
min = 0;
rev = 0;
build = 0;
}
main.cpp
#include <iostream>
#include "CompareVersion.h"
using namespace std;
int main()
{
if((CompareVersion("1.2.3.4") == CompareVersion("1.2.3.4")) == true)
cout << "Version 1.2.3.4 and version 1.2.3.4 are equal" << endl;
if((CompareVersion("1.2.3.3") < CompareVersion("1.2.3.4")) == true)
cout << "Version 1.2.3.3 is smaller than 1.2.3.4. " << endl;
if((CompareVersion("1.2.3.4") < CompareVersion("1.2.3.4")) == true)
cout << "You won't see that. " << endl;
if((CompareVersion("1.2.3.4") <= CompareVersion("1.2.3.4")) == true)
cout << "Version 1.2.3.4 is smaller or equal to 1.2.3.4" << endl;
if((CompareVersion("1") <= CompareVersion("1.0.0.1")) == true)
cout << "Version 1 is smaller or equal to 1.0.0.1" << endl;
/* THE DOTS */
if((CompareVersion(".0.4") == CompareVersion("0.0.4")) == true)
cout << "Version .0.4 and version 0.0.4 are equal" << endl;
if((CompareVersion(".1.") == CompareVersion("0.1.0")) == true)
cout << "Version .1. and version 0.1.0 are equal" << endl;
if((CompareVersion("1") == CompareVersion("1.0.0.0")) == true)
cout << "Version 1 and version 1.0.0.0 are equal" << endl;
return 0;
}
Output
Version 1.2.3.4 and version 1.2.3.4 are equal
Version 1.2.3.3 is smaller than 1.2.3.4.
Version 1.2.3.4 is smaller or equal to 1.2.3.4
Version 1 is smaller or equal to 1.0.0.1
Version .0.4 and version 0.0.4 are equal
Version .1. and version 0.1.0 are equal
Version 1 and version 1.0.0.0 are equal
I'm trying to implement a function that will look at each element of an array and determine if that particular element is larger than one INT and less than another INT. For example:
Return true if Arr[5] is >i && < u
I have this as a basic algorithm, which works but I want to create a more efficient piece of code, by using the 'divide and conquer' methodology, however I'm having problems using recursion to make it count and all examples I've seen only deal with one point of comparison, not two. can anyone shed some light on the situation.
(http://en.wikipedia.org/wiki/Divide_and_conquer_algorithm)
My original code (linear):
int SimpleSort(int length)
{
int A[] = {25,5,20,10,50};
int i = 25; //Less Than int
u = 2; //Greater Than
for(int Count = 0; Count < length; Count++) //Counter
{
if (A[Count] <= i && A[Count] >= u) //Checker
return true;
} return false;
}
Example code from what I've picked up of this so far(with no luck after many hours of working on various things, and using different example code:
int A[] = {5,10,25,30,50,100,200,500,1000,2000};
int i = 10; //Less Than
int u = 5; //Greater Than
int min = 1;
int max = length;
int mid = (min+max)/2;
if (i < A[mid] && u > A[mid])
{
min = mid + 1;
}
else
{
max = mid - 1;
}
Until i <= A1[mid] && u >= A1[mid])
If this question is not clear I'm sorry, do ask if you need me to elaborate on anything.
Assuming your input vector is always sorted, I think something like this may work for you. This is the simplest form I could come up with, and the performance is O(log n):
bool inRange(int lval, int uval, int ar[], size_t n)
{
if (0 == n)
return false;
size_t mid = n/2;
if (ar[mid] >= std::min(lval,uval))
{
if (ar[mid] <= std::max(lval,uval))
return true;
return inRange(lval, uval, ar, mid);
}
return inRange(lval, uval, ar+mid+1, n-mid-1);
}
This uses implied range differencing; i.e. it always uses the lower of the two values as the lower-bound, and the higher of the two as the upper-bound. If your usage mandates that input values for lval and uval are to be treated as gospel, and therfore any invoke where lval > uval should return false (since it is impossible) you can remove the std::min() and std::max() expansions. In either case, you can further increase performance by making an outter front-loader and pre-checking the order of lval and uval to either (a) returning immediately as false if absolute ordering is required and lval > uval, or (b) predetermine lval and uval in proper order if range-differencing is the requirement. Examples of both such outter wrappers are explored below:
// search for any ar[i] such that (lval <= ar[i] <= uval)
// assumes ar[] is sorted, and (lval <= uval).
bool inRange_(int lval, int uval, int ar[], size_t n)
{
if (0 == n)
return false;
size_t mid = n/2;
if (ar[mid] >= lval)
{
if (ar[mid] <= uval)
return true;
return inRange_(lval, uval, ar, mid);
}
return inRange_(lval, uval, ar+mid+1, n-mid-1);
}
// use lval and uval as an hard range of [lval,uval].
// i.e. short-circuit the impossible case of lower-bound
// being greater than upper-bound.
bool inRangeAbs(int lval, int uval, int ar[], size_t n)
{
if (lval > uval)
return false;
return inRange_(lval, uval, ar, n);
}
// use lval and uval as un-ordered limits. i.e always use either
// [lval,uval] or [uval,lval], depending on their values.
bool inRange(int lval, int uval, int ar[], size_t n)
{
return inRange_(std::min(lval,uval), std::max(lval,uval), ar, n);
}
I have left the one I think you want as inRange. The unit tests performed to hopefully cover main and edge cases are below along with the resulting output.
#include <iostream>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <iterator>
int main(int argc, char *argv[])
{
int A[] = {5,10,25,30,50,100,200,500,1000,2000};
size_t ALen = sizeof(A)/sizeof(A[0]);
srand((unsigned int)time(NULL));
// inner boundary tests (should all answer true)
cout << inRange(5, 25, A, ALen) << endl;
cout << inRange(1800, 2000, A, ALen) << endl;
// limit tests (should all answer true)
cout << inRange(0, 5, A, ALen) << endl;
cout << inRange(2000, 3000, A, ALen) << endl;
// midrange tests. (should all answer true)
cout << inRange(26, 31, A, ALen) << endl;
cout << inRange(99, 201, A, ALen) << endl;
cout << inRange(6, 10, A, ALen) << endl;
cout << inRange(501, 1500, A, ALen) << endl;
// identity tests. (should all answer true)
cout << inRange(5, 5, A, ALen) << endl;
cout << inRange(25, 25, A, ALen) << endl;
cout << inRange(100, 100, A, ALen) << endl;
cout << inRange(1000, 1000, A, ALen) << endl;
// test single-element top-and-bottom cases
cout << inRange(0,5,A,1) << endl;
cout << inRange(5,5,A,1) << endl;
// oo-range tests (should all answer false)
cout << inRange(1, 4, A, ALen) << endl;
cout << inRange(2001, 2500, A, ALen) << endl;
cout << inRange(1, 1, A, 0) << endl;
// performance on LARGE arrays.
const size_t N = 2000000;
cout << "Building array of " << N << " random values." << endl;
std::vector<int> bigv;
generate_n(back_inserter(bigv), N, rand);
// sort the array
cout << "Sorting array of " << N << " random values." << endl;
std::sort(bigv.begin(), bigv.end());
cout << "Running " << N << " identity searches..." << endl;
for (int i=1;i<N; i++)
if (!inRange(bigv[i-1],bigv[i],&bigv[0],N))
{
cout << "Error: could not find value in range [" << bigv[i-1] << ',' << bigv[i] << "]" << endl;
break;
};
cout << "Finished" << endl;
return 0;
}
Output Results:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
Sorting array of 2000000 random values.
Running 2000000 identity searches...
Finished
It's actually pretty straight forward if you assume the array to be sorted. You can get away with logarithmic complexity by always looking at either the respective left or right side of the sequence:
#include <iterator>
template <typename Limit, typename Iterator>
bool inRange(Limit lowerBound, Limit upperBound, Iterator begin, Iterator end) {
if (begin == end) // no values => no valid values
return false;
Iterator mid = begin;
auto const dist = std::distance(begin,end);
std::advance(mid,dist/2); // mid might be equal to begin, if dist == 1
if (lowerBound < *mid && *mid < upperBound)
return true;
if (dist == 1) // if mid is invalid and there is only mid, there is no value
return false;
if (*mid > upperBound)
return inRange(lowerBound, upperBound, begin, mid);
std::advance(mid,1); // we already know mid is invalid
return inRange(lowerBound, upperBound, mid, end);
}
You can invoke this for plain arrays with:
inRange(2,25,std::begin(A),std::end(A));
To my understanding, using divide and conquer for your specific problem
will not yield an andvantage. However, at least in your example, the input is
sorted; is should be possible to improve a bit by skipping values until your lower bound is reached.