Related
I've been trying for the past hour to get this binary search algorithm to work and by using an example of the algorithm as explained on khan academy, I still can't get it to work, it should output a number but nothing happens. The example on khan academy is like this:
Let min = 0 and max = n-1.
If max < min, then stop: target is not present in array. Return -1.
Compute guess as the average of max and min, rounded down (so that it is an integer).
If array[guess] equals target, then stop. You found it! Return guess.
If the guess was too low, that is, array[guess] < target, then set min = guess + 1.
Otherwise, the guess was too high. Set max = guess - 1.
Go back to step 2.
And the code I wrote according to the steps is:
#include <iostream>
int main() {
int arr[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };
int min = 0;
int max = 24;
int guess;
int targetValue = 73;
while (max > min) {
guess = ((max + min) / 2);
if (arr[guess] == targetValue) {
std::cout << guess;
break;
}
else if (arr[guess] < targetValue) {
min = guess + 1;
}
else {
max = guess - 1;
}
}
return 0;
}
The binary search algorithm states
If L > R, the search terminates as unsuccessful.
In your implementation however, you terminate the search on the condition L >= R. In the case of L == R, the algorithm should do one more iteration, because it did not consider this position in the list yet.
In your case of target value 73, when the algorithm reaches the position of the target, 20, L == R. Your implementation terminates one step too early to recognize the target.
try this:
(max > min) to (max >= min)
Lets say i have:
int array[9][9]= {
{1 , 2 , 3 , 4, 5, 6, 7, 8, 9},
{10, 11, 12, 13, 14, 15, 16, 17, 18},
{19, 20, 21, 22, 23, 24, 25, 26, 27},
{28, 29, 30, 31, 32, 33, 34, 35, 36},
{37, 38, 39, 40, 41, 42, 43, 44, 45},
{46, 47, 48, 49, 50, 51, 52, 53, 54},
{55, 56, 57, 58, 59, 60, 61, 62, 63},
{64, 65, 66, 67, 68, 69, 70, 71, 72},
{73, 74, 75, 76, 77, 78, 79, 80, 81}
};
how can i only apply some function to the first row (value 1 to 9 ) or the first column only (like value 1 to 73). lets say i want to say index 0 to 9 shall all have value 0.
is it possible to save this range in a variable?
Try to do like this:
for (int i = 0; i<10; i++)
array[0][i] = 0;
There are no true multidimensional arrays in C.
In a true multidimensional array, all dimensions are on equal standing. Whatever you can do with rows, you can also do with columns.
This is not the case with C++. The third row of your array is just
array[3]
It's an array on its own in every regard. A range of rows, like any other range, can be represented as a (start, end) pair, e.g. make_pair(array[3], array[7]).
Nothingl like that can be done with columns. The third column, unlike the third row, is not an array, it's just a virtual collection of elements not sitting under any standard data structure umbrella.
The closest thing to a multidimensional array slices are custom iterators, such that ++i moves to either the next element to the right or to the next element below. While you're at it, consider moving away from C style arrays to STL style containers.
To isolate the rows of the array, you could take a reference to a row of the array:
int (&row)[9] = array[2];
For example the above line takes a reference to the 3rd row of the array.
Live Demo
For the columns, is more complicated.
Alternatevely, you could do the following construct that returns a vector of reference wrappers to either a column or a row of a 2D array.
// if flg == true you get row at idx else if flg == false you get column at idx
template<typename T, int N, int M>
std::vector<std::reference_wrapper<T>>
getRange(T (&arr)[N][M], std::size_t const idx, bool const flg = true) {
if(flg) {
return typename std::vector<std::reference_wrapper<T>>(std::begin(arr[idx]), std::end(arr[idx]));
} else {
typename std::vector<std::reference_wrapper<T>> out;
out.reserve(N);
for(int i(0); i < N; ++i) out.push_back(arr[i][idx]);
return out;
}
}
Live Demo
For rows it's easy, as you can pass them like:
void foo(int * row, int cols) {
for (int col = 0; col < cols; ++col) {
int * x = row + col;
}
}
...
foo(array[3], 9);
...
For columns it's more difficult but you can thought about every column as something that have specific offset in the array:
void boo(int * col, int rows, int cols) {
for (int row = 0; row < rows; ++row) {
int * x = col + row * cols;
}
}
....
// process fourth column:
boo(array[0]+4, 9, 9);
Of course using sizeof instead of '9' and C++ vectors/array instead of C-style int[][] will make life more easy and code more readable and supportable.
Another way is to use boost::matrix e.g.:
using namespace boost::numeric::ublas;
matrix<double> m(9, 9);
matrix_row<matrix <double> > row(m, 5);
matrix_column<matrix <double> > col(m, 4);
You can do it by specifying indices (start and end range) with your function and mention whether it should be applied on row or column. Since you are using plain C style array it's trickier to deal with pointers. I recommend you to use vectors and pairs (for ranges).
An example for C style array
void some_function(int array[][9], bool row_or_column, size_t major, size_t start, size_t end){
if (row_or_column = true) {
for (int i = start; i < end; i++) {
cout << array[major][i]; //perform your operation on row
}
}
else {
for (int i = start; i < end; i++) {
cout << array[i][major]; //perform your operation on column
}
}
}
Set row_or_column as either true for row or false for column, major should specify the column number or row number and the ranges in start and end. Note: end is exclusive
For processing second row with range start = 0 and end = 5 i.e 10 to 14
some_function(array, true, 1, 0, 5)
For processing second column with range start = 0 and end = 5 i.e 2 to 38
some_function(array, false, 1, 0, 5)
I'm having an issue with this code,I do not understand how the function works. I need to validate the input from the user, to see if their date that they placed is valid. And if it isn't I set the error code. So in my read function I cin the date then validate the input and call mdays() however, for some reason I don't know how to check in my if statement in the read function if the date is validate or not.
int Date::mdays() const
{
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1};
int mon = _mon >= 1 && _mon <= 12 ? _mon : 13;
mon--;
return days[mon] + int((mon == 1)*((_year % 4 == 0) &&
(_year % 100 != 0)) || (_year % 400 == 0));
}
The code is very clever, written by someone who wanted to demonstrate that they are smart. I hate clever code. (It's also quite slow, I hate code that tries to be clever and fails).
Remember the rules for leapyears:
Every fourth year is a leap year. Except that every 100th year is not a leap year. Except that every 400th year is a leap year.
Most months you can look up from a table, except that February has either 28 or 29 days. So to understand the code, what happens if the month is not February? And what happens if the month is February? mon will be equal to 1. What is the value of (mon == 1) in February? How would you express the rules for leap years?
And the function that you showed calculates the number of days in a month, it doesn't do any validation. Obviously you need to know that April has 30 days to know that April 31st is invalid.
You can change the signature of mdays(), return a boolean to indicate if the date is validate or not, and put an output argument to store the days if the date is validate
bool Date::mdays(int& month_days) const {
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (_mon < 1 || _mon > 12) return false;
mon--;
month_days = days[mon] + int((mon == 1)*((_year % 4 == 0) && (_year % 100 != 0)) || (_year % 400 == 0));
return true;
}
If you can modify the Date class, you should be able to create new method utilizing return value of mdays() like this:
bool Date::validate_day_and_month() const {
int maxday = mdays();
if ( maxday < 0 ) { return false; } // mdays() = -1 if _month is bad
if ( _day <= 0 || _day > maxday ) { return false; }
return true;
}
Here, _day is the day part of the user date input.
I'm trying to write a program that calculates a rental bill. I have most of the program written, but I have to write a function that takes the user input of days rented and the starting rental date to determine the return date. The only requirement is that the function is to be a loop that calls another function (that determines the number of days in the month). The problem I keep running into is that the other function (which is to determine the days in each month) doesn't change depending on the month. So if I put in 1/1/2013, it has the correct number of days for the month and then when the counter changes to Feb, it continues with 31 days. Does anyone know a formula that will satisfy the requirements?
Start with a hard-coded array with the number of days in each month.
Compensate for February's leap day and you should be good.
int daysInMonth(int month, int year)
{
// Check for leap year
bool isLeapYear;
if (year % 400 == 0)
isLeapYear = true;
else if (year % 4 == 0 && year % 100 != 0)
isLeapYear = true;
else
isLeapYear = false;
int numDaysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
if (isLeapYear)
numDaysInMonth[1]++;
return numDaysInMonth[month - 1];
}
Why not considering using Boost.Date_Time ?
int isLeap(int year)
{
return (year > 0) && !(year % 4) && ((year % 100) || !(year % 400));
}
int calcDays(int month, int year)
{
static const int daysInMonth[2][13] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
if (month >= 1 && month <= 12) {
return daysInMonth[isLeap(year)][month - 1];
}
return -1;
}
this will give you the days of the month
I have to print the number of ways you can represent a given number as it's prime number parts.
Let me clarify: Let's say I have been given this number 7. Now, first of all, I have to find all the prime numbers that are less than 7, which are 2, 3 and 5. Now, in how many ways can I summarize those numbers (I can use one number as many times I want) so that the result equals 7? For example, number 7 has five ways:
2 + 2 + 3
2 + 3 + 2
2 + 5
3 + 2 + 2
5 + 2
I'm totally lost with this task. First I figured I'd make an array of usable elements like so: { 2, 2, 2, 3, 3, 5 } (7/2 = 3, so 2 must appear three times. Same goes with 3, which gets two occurences). After that, loop through the array and choose a 'leader' that determines how far in the array we are. I know the explanation is horrible, so here's the code:
#include <iostream>
#include <vector>
int primes_all[25] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
int main()
{
int number;
std::cin >> number;
std::vector<int> primes_used;
for(int i = 0; i < 25; i++) {
if(primes_all[i] < number && number-primes_all[i] > 1) {
for(int k = 0; k < number/primes_all[i]; k++)
primes_used.push_back(primes_all[i]);
}
else break;
}
int result = 0;
for(size_t i = 0; i < primes_used.size(); i++) {
int j = primes_used.size()-1;
int new_num = number - primes_used[i];
while(new_num > 1 && j > -1)
{
if(j > -1) while(primes_used[j] > new_num && j > 0) j--;
if(j != i && j > -1) {
new_num -= primes_used[j];
std::cout << primes_used[i] << " " << primes_used[j] << " " << new_num << std::endl;
}
j--;
}
if(new_num == 0) result++;
}
std::cout << result << std::endl;
system("pause");
return 0;
}
This simply doesn't work. Simply because the idea behind it is wrong. Here's a little details about the limits:
Time limit: 1 second
Memory limit: 128 MB
Also, the biggest number that can be given is 100. That's why I made the array of prime numbers below 100. The result grows very fast as the given number gets bigger, and will need a BigInteger class later on, but that's not an issue.
A few results known:
Input Result
7 5
20 732
80 10343662267187
SO... Any ideas? Is this a combinatory problem? I don't need code, just an idea. I'm still a newbie to C++ but I'll manage
Keep in mind that 3 + 2 + 2 is different than 2 + 3 + 2.
Also, were the given number to be a prime itself, it won't be counted. For example, if the given number is 7, only these sums are valid:
2 + 2 + 3
2 + 3 + 2
2 + 5
3 + 2 + 2
5 + 2
7 <= excluded
Dynamic programming is your friend here.
Consider the number 27.
If 7 has 5 results, and 20 has 732 results, then you know that 27 has at least (732 * 5) results. You can use a two variable system (1 + 26, 2 + 25 ... etc) using the precomputed values for those as you go. You don't have to recompute 25 or 26 because you already did them.
The concept you are searching for is the "prime partitions" of a number. S partition of a number is a way of adding numbers to reach the target; for instance, 1+1+2+3 is a partition of 7. If all the addends are prime, then the partition is a prime partition.
I think your example is wrong. The number 7 is usually considered to have 3 prime partitions: 2+2+3, 2+5, and 7. The order of the addends doesn't matter. In number theory the function that counts prime partitions is kappa, so we would say kappa(7) = 3.
The usual calculation of kappa is done in two parts. The first part is a function to compute the sum of the prime factors of a number; for instance, 42=2·3·7, so sopf(42)=12. Note that sopf(12)=5 because the sum is over only the distinct factors of a number, so even though 12=2·2·3, only one 2 is included in the calculation of the sum.
Given sopf, there is a lengthy formula to calculate kappa; I'll give it in LaTeX form, since I don't know how to enter it here: \kappa(n) = \frac{1}{n}\left(\mathrm{sopf}(n) + \sum_{j=1}^{n-1} \mathrm{sopf}(j) \cdot \kappa(n-j)\right).
If you actually want a list of the partitions, instead of just the count, there is a dynamic programming solution that #corsiKa pointed out.
I discuss prime partitions in more detail at my blog, including source code to produce both the count and the list.
Here's an efficient implementation which uses dynamic programming like corsiKa suggests, but does not use the algorithm he describes.
Simply: if n is reachable via k distinct paths (including the single-step one, if it exists), and p is prime, then we construct k paths to n+p by appending p to all paths to n. Considering all such n < N will produce an exhaustive list of valid paths to N. So we just sum the number of paths so discovered.
#include <iostream>
int primes_all[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
const int N_max = 85;
typedef long long ways;
ways ways_to_reach_N[N_max + 1] = { 1 };
int main()
{
// find all paths
for( int i = 0; i <= N_max; ++i ) {
ways ways_to_reach_i = ways_to_reach_N[i];
if (ways_to_reach_i) {
for( int* p = primes_all; *p <= N_max - i && p < (&primes_all)[1]; ++p ) {
ways_to_reach_N[i + *p] += ways_to_reach_i;
}
}
}
// eliminate single-step paths
for( int* p = primes_all; *p <= N_max && p < (&primes_all)[1]; ++p ) {
--ways_to_reach_N[*p];
}
// print results
for( int i = 1; i <= N_max; ++i ) {
ways ways_to_reach_i = ways_to_reach_N[i];
if (ways_to_reach_i) {
std::cout << i << " -- " << ways_to_reach_i << std::endl;
}
}
return 0;
}
Demo: http://ideone.com/xWZT8v
Replacing the typedef ways with a big integer type is left as an exercise to the reader.