The Chinese clock problem c++ (giving me time limit error) - c++

I have been trying to solve this problem for an online judge system, which requires a time limit of 1000ms. I have tried a few variations of solutions, but I will post my best draft here. I was able to get my answers right, however, I am exceeding the time limit. The best solution I can come up with is O(n^2).
The Task problem
Once the programmer X was in China and noticed that Russian clocks “Zarya” are 10 times cheaper there than in Russia. X chose to do some shenanigans and bought a huge amount of clocks to bring it to his own country and sell them at half price (which actually means 5x times more expensive than he bought). But as soon as he came back home, he realized that many clocks go discordantly, moreover, they stop from a simple push (or start going if they were stopped before).
Obviously, the clocks were fake, just very accurate copies. To sell them really quickly, X wants to set them all to the same time (so it won’t matter if the time’s correct or not – he can say this is “the time of the manufacturer”) and just shake his bag to make them tick.
To set the time, he has to spin a winding crown that will make clock’s hands move: the hour hand moves 60 times slower than the minute hand and the minute hand is 60 times slower than the second hand. One full spin of a crown makes a full spin of the second hand; and although the spin takes just a second, it will take 6 minutes to change the time to 6 hours. It is allowed to spin a crown only clockwise to save fragile mechanism of a clock.
Help the programmer X minimize the effort put in preparing the clocks to be sold, choosing the optimal time to set all clocks to.
Input:
The first line contains a natural n (1 ≤ n ≤ 50000) – the quantity of clocks.
The next n lines contain the time of each clock in a format “h:mm:ss”, where h (1 ≤ h  ≤ 12) means hours, mm and ss (00 ≤ mm,ss ≤ 59) – minutes and seconds.
Output:
The time all clocks need to be set to in the format presented above.
Example Input
3
11:30:00
12:10:01
6:10:18
Output
12:10:01
#include<iostream>
using namespace std;
struct Clock {
int hours;
int mins;
int secs;
Clock() {
hours = mins = secs = 0;
}
};
void strtotime(string str, Clock& clock) { //converts string input to time
if (str[1] == ':') {
clock.hours = (str[0] - 48);
clock.mins = (str[2] - 48) * 10 + (str[3] - 48);
clock.secs = (str[5] - 48) * 10 + (str[6] - 48);
}
else {
clock.hours = (str[0] - 48) * 10 + (str[1] - 48);
clock.mins = (str[3] - 48) * 10 + (str[4] - 48);
clock.secs = (str[6] - 48) * 10 + (str[7] - 48);
}
}
double calctime(Clock from, Clock to) {//calculates time taken to change one clock time to other's
//calculate time for hours
double minutes;
if (from.hours > to.hours) {
minutes = 12 - (from.hours - to.hours);
}
else {
minutes = to.hours - from.hours;
}
//calculate time for mins
double seconds;
if (from.mins > to.mins) {
seconds = 60 - (from.mins - to.mins);
}
else {
seconds = to.mins - from.mins;
}
//calculate time for secs
double seconds2;
if (from.secs > to.secs) {
seconds2 = 60 - (from.secs - to.secs);
}
else {
seconds2 = to.secs - from.secs;
}
double totalTime = minutes * 60 + seconds + (seconds2 / 60);
return totalTime;
}
int main() {
int n;
string str;
cin >> n;
Clock* clock = new Clock[n];
for (int x = 0; x < n; x++) {
cin >> str;
strtotime(str, clock[x]);
}
double totaltime;
double mintime;
int loc = 0;
bool first = true;
double* timearr = new double[n];
for (int x = 0; x < n; x++) {
totaltime = 0.0;
for (int y = 0; y < n; y++) {
if (x != y) {
totaltime += calctime(clock[y], clock[x]);
}
}
if (first) {
mintime = totaltime;
first = false;
}
else {
if (totaltime < mintime) {
mintime = totaltime;
loc = x;
}
}
}
cout << clock[loc].hours;
cout << ':';
if (clock[loc].mins < 10) {
cout << 0 << clock[loc].mins;
}
else {
cout << clock[loc].mins;
}
cout << ':';
if (clock[loc].secs < 10) {
cout << 0 << clock[loc].secs;
}
else {
cout << clock[loc].secs;
}
}

Sort the times
Calculate the difference between each two neighbors and the first and last element
Find the maximum difference and remove it (the solution is the left neighbor of this difference)

Related

Find One to N is Prime optimization

So I was inspired by a recent Youtube video from the Numberphile Channel. This one to be exact. Cut to around the 5 minute mark for the exact question or example that I am referring to.
TLDR; A number is created with all the digits corresponding to 1 to N. Example: 1 to 10 is the number 12,345,678,910. Find out if this number is prime. According to the video, N has been checked up to 1,000,000.
From the code below, I have taken the liberty of starting this process at 1,000,000 and only going to 10,000,000. I'm hoping to increase this to a larger number later.
So my question or the assistance that I need is optimization for this problem. I'm sure each number will still take very long to check but even a minimal percentage of optimization would go a long way.
Edit 1: Optimize which division numbers are used. Ideally this divisionNumber would only be prime numbers.
Here is the code:
#include <iostream>
#include <chrono>
#include <ctime>
namespace
{
int myPow(int x, int p)
{
if (p == 0) return 1;
if (p == 1) return x;
if (p == 2) return x * x;
int tmp = myPow(x, p / 2);
if (p % 2 == 0) return tmp * tmp;
else return x * tmp * tmp;
}
int getNumDigits(unsigned int num)
{
int count = 0;
while (num != 0)
{
num /= 10;
++count;
}
return count;
}
unsigned int getDigit(unsigned int num, int position)
{
int digit = num % myPow(10, getNumDigits(num) - (position - 1));
return digit / myPow(10, getNumDigits(num) - position);
}
unsigned int getTotalDigits(int num)
{
unsigned int total = 0;
for (int i = 1; i <= num; i++)
total += getNumDigits(i);
return total;
}
// Returns the 'index'th digit of number created from 1 to num
int getIndexDigit(int num, int index)
{
if (index <= 9)
return index;
for (int i = 10; i <= num; i++)
{
if (getTotalDigits(i) >= index)
return getDigit(i, getNumDigits(i) - (getTotalDigits(i) - index));
}
}
// Can this be optimized?
int floorSqrt(int x)
{
if (x == 0 || x == 1)
return x;
int i = 1, result = 1;
while (result <= x)
{
i++;
result = i * i;
}
return i - 1;
}
void PrintTime(double num, int i)
{
constexpr double SECONDS_IN_HOUR = 3600;
constexpr double SECONDS_IN_MINUTE = 60;
double totalSeconds = num;
int hours = totalSeconds / SECONDS_IN_HOUR;
int minutes = (totalSeconds - (hours * SECONDS_IN_HOUR)) / SECONDS_IN_MINUTE;
int seconds = totalSeconds - (hours * SECONDS_IN_HOUR) - (minutes * SECONDS_IN_MINUTE);
std::cout << "Elapsed time for " << i << ": " << hours << "h, " << minutes << "m, " << seconds << "s\n";
}
}
int main()
{
constexpr unsigned int MAX_NUM_CHECK = 10000000;
for (int i = 1000000; i <= MAX_NUM_CHECK; i++)
{
auto start = std::chrono::system_clock::now();
int digitIndex = 1;
// Simplifying this to move to the next i in the loop early:
// if i % 2 then the last digit is a 0, 2, 4, 6, or 8 and is therefore divisible by 2
// if i % 5 then the last digit is 0 or 5 and is therefore divisible by 5
if (i % 2 == 0 || i % 5 == 0)
{
std::cout << i << " not prime" << '\n';
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
PrintTime(elapsed_seconds.count(), i);
continue;
}
bool isPrime = true;
int divisionNumber = 3;
int floorNum = floorSqrt(i);
while (divisionNumber <= floorNum && isPrime)
{
if (divisionNumber % 5 == 0)
{
divisionNumber += 2;
continue;
}
int number = 0;
int totalDigits = getTotalDigits(i);
// This section does the division necessary to iterate through each digit of the 1 to N number
// Example: Think of dividing 124 into 123456 on paper and how you would iterate through that process
while (digitIndex <= totalDigits)
{
number *= 10;
number += getIndexDigit(i, digitIndex);
number %= divisionNumber;
digitIndex++;
}
if (number == 0)
{
isPrime = false;
break;
}
divisionNumber += 2;
}
if (isPrime)
std::cout << "N = " << i << " is prime." << '\n';
else
std::cout << i << " not prime" << '\n';
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
PrintTime(elapsed_seconds.count(), i);
}
}
Its nice to see you are working on the same question I pondered few months ago.
Please refer to question posted in Math Stackexchange for better resources.
TL-DR,
The number you are looking for is called SmarandachePrime.
As per your code, it seems you are dividing with every number that is not a multiple of 2,5. To optimize you can actually check for n = 6k+1 ( 𝑘 ∈ ℕ ).
unfortunately, it is still not a better approach with respect to the number you are dealing with.
The better approach is to use primality test screening to find probable prime numbers in the sequence and then check whether they are prime or not. These tests take a less time ~(O(k log3n)) to check whether a number is prime or not, using mathematical fundamentals, compared to division.
there are several libraries that provide functions for primality check.
for python, you can use gmpy2 library, which uses Miller-Rabin Primality test to find probable primes.
I recommend you to further read about different Primality tests here.
I believe you are missing one very important check, and it's the division by 3:
A number can be divided by 3 is the sum of the numbers can be divided by 3, and your number consists of all numbers from 1 to N.
The sum of all numbers from 1 to N equals:
N * (N+1) / 2
This means that, if N or N+1 can be divided by 3, then your number cannot be prime.
So before you do anything, check MOD(N,3) and MOD(N+1,3). If either one of them equals zero, you can't have a prime number.

Calculate how many days are required for a snail to climb up a wall

I am trying to solve this problem:
Write a program to calculate how many days are required for a snail to climb up a wall. A snail climbs on a wall, it starts at the bottom and climbs up n meters a day. Regretfully, every night it slides m meters down. Given the height of the wall H, write a program to calculate how many days required for the snail to reach the top of the wall.
If the snail will never be able to reach the top of the wall print: Fail.
This is my attempt to solve this problem:
int numDays(int wall_height, int meters_per_day, int meters_down_per_day) {
int current_height = 0;
int days = 0;
while (current_height != wall_height) {
if (current_height + (meters_per_day - meters_down_per_day) >= wall_height) {
break;
}else {
days += 1;
current_height += meters_per_day - meters_down_per_day;
}
}
return days;
}
int main()
{
int wall_height = 30;
int meters_per_day = 3;
int meters_down = 2;
if (meters_down >= meters_per_day) {
cout << "Fail" << endl;
}else {
cout << numDays(wall_height, meters_per_day, meters_down) << endl;
}
return 0;
}
My solution returns 29 days, but the answer is 28 days because once the snail has climbed 27 meters after 27 days, it will simply climb the remaining 3 meters to the top on the 28th day.
What I am doing wrong to generate the wrong output? Thanks!
Your error is that you are only checking if the snail has reached the top of the wall after it has climbed up and down. You even say this yourself. Instead you should check the height after the climb up only
Here's loop that does that.
for (;;) {
current_height += meters_per_day;
if (current_height >= wall_height) {
break;
current_height -= meters_down_per_day;
days += 1;
}
For me, here is the right implementation of your numDays function :
int numDays(int wall_height, int meters_per_day, int meters_down_per_day) {
int current_height = 0;
int days = 1;
while (current_height != wall_height) {
current_height += meters_per_day;
if(current_height >= wall_height)
break;
days += 1;
current_height -= meters_down_per_day;
}
return days;
}
the answer is 28 days because once the snail has climbed 27 meters after 27 days, it will simply climb the remaining 3 meters to the top on the 28th day
To do this, you need to increment first the current_height before testing if the snail is on the top of the wall.
I think the day counter must start at 1 because the first day of iteration is the day 1 (I don't know if the explanation is really clear).
Here's my simple Python program to solve the problem that implements the given conditions:
def num_days(h, n, m):
days = 0
position = 0
while n < h:
if m >= n:
break
days += 1
position += n
if position >= h:
return days
position -= m
if days == 0:
days = 'Fail'
return days
You can call the function num_days with h, n, and m as arguments to get the number of days required for the snail to reach the top of the wall.
For example:
num_days(11, 3, 2)
return
9
num_days(5, 3, 1)
return
2
num_days(5, 0, 1)
return
Fail

Operator overloading logic issues

one of our assignments in the class is to create a program that uses objects to display hours, minutes and seconds. With these numbers we now have to overload various operators that will increase the seconds/minutes by 1, and decrease them using ++ and --. Im having some trouble with the -- operator as its not working as expected, if I put in 0 minutes, and it decreases the minutes it returns values like 128 minutes. As Im starting out in this I would really appreciate some help.
And then the second part is using other operators (> < >= <= == !=) to compare 2 different hours, minutes and seconds and return a bool value if one is more than the other (i.e. h:1 m:5 s:0 vs h:0 m:5 s:0 will return 'true'). I havent gotten to the second part and would appreciate some pointers on how to get this started as Im trying to wrap my head around this whole idea logically.
Main.cpp
#include <iostream>
#include "Time.h"
using namespace std;
int main() {
int hour1, minute1, second1, hour2, minute2, second2;
cout << "Enter time A (hh, mm, ss): ";
cin >> hour1;
cin >> minute1;
cin >> second1;
cout <<endl;
/*cout << "Enter time B(hh, mm, ss): ";
cin >> hour2;
cin >> minute2;
cin >> second;
cout <<endl;*/
Time T1(hour1, minute1, second1);
++T1; //Increases seconds by 1
T1.displayTime();
T1++; //Increases minutes by 1
T1.displayTime();
--T1; //Decreases seconds by 1
T1.displayTime();
T1--; //Decreases minutes by 1
T1.displayTime();
return 0;
}
Time.h
#ifndef TIME_H
#define TIME_H
class Time
{
public:
Time();
Time (int h, int m, int s);
void displayTime();
Time operator++();
Time operator++(int);
Time operator--();
Time operator--(int);
/*Time operator>();
Time operator<();
Time operator>=();
Time operator<=();
Time operator==();
Time operator!=();*/
private:
int hours;
int minutes;
int seconds;
};
#endif // TIME_H
Time.cpp
#include <iostream>
#include "Time.h"
using namespace std;
Time::Time(){
hours = 0;
minutes = 0;
seconds = 0;
}
Time::Time(int h, int m, int s){
hours = h;
minutes = m;
seconds = s;
}
void Time::displayTime(){
cout << "Hours: " << hours <<" Minutes: " << minutes << " Seconds: " <<seconds <<endl;
}
Time Time::operator++(){ //Prefix plus seconds
++seconds;
if (minutes >= 60){
++hours;
minutes -= 60;
}
if (seconds >= 60){
++minutes;
seconds -= 60;
}
return Time(hours, minutes, seconds);
}
Time Time::operator++(int){ //Postfix plus minutes
Time T(hours, minutes, seconds);
++minutes;
if(minutes >=60){
++hours;
minutes -= 60;
}
if (seconds >= 60){
++minutes;
seconds -= 60;
}
return T;
}
Time Time::operator--(){ //PREFIX MINUSS seconds
--seconds;
if (seconds == 0){
--minutes;
seconds += 59;
}
if (minutes == 0){
--hours;
minutes += 59;
}
return Time(hours, minutes, seconds);
}
Time Time::operator--(int){ //POSTFIX MINUSS minutes
Time T(hours, minutes, seconds);
--minutes;
if (minutes == 0){
--hours;
minutes += 59;
}
if (seconds == 0){
--minutes;
seconds += 59;
}
return T;
}
/*Time Time::operator>(){
}
Time Time::operator<(){
}
Time Time::operator>=(){
}
Time Time::operator<=(){
}
Time Time::operator==(){
}
Time Time::operator!=(){
}
*/
If you spot any other mistakes, please do let me know.
So with this the minutes are not subtracting correctly. It seems that it is just taking away from 0, but not adding the necessary seconds back to it (if that makes sense).
Thank you.
Im having some trouble with the -- operator
Actually, you have quite some more trouble! Already operator++ won't work as expected. Try:
Time t(0, 59, 59);
++t;
Once you incremented seconds with overflow, next that can overflow is the minutes, so you need to check these first!
++seconds;
if(seconds == 60)
{
seconds = 0;
++minutes;
// only, if minutes were incremented, they can overflow, so check only here needed
if(minutes == 60)
{
minutes = 0;
// open: how do you want to handle hours overflowing?
// variant 1: just go on, counting 23, 24, 25, ...
++hours;
// variant 2: restart at 0:
hours = (hours + 1) % 24;
// variant 3 (my favourite): rember in a flag that we overflowed
// (and have a getter for so that user can check):
isWrapAround = hours == 23; // new member variable of type bool
hours = (hours + 1) % 24;
}
}
Analogously, you'd handle the operator--, just replacing every occurence of ++ with -- and adjusting the overflow detection to underflow detection. Careful with the latter: Your original code did not do proper underflow detection:
--seconds;
if(seconds == 0)
This would already decrement minutes when we actually have 1 second left, but 00:00:00 is a valid time! So you need to either check for 0 before decrementing (if(seconds-- == 0) or check for negative values afterwards (--seconds; if(seconds == -1) or if (seconds < 0)). With this fix, += 59 won't be correct any more either, you'd need either += 60 or preferrably simply = 59.
Usually, the pre-increment and -decrement operators return a reference to current object. This would allow for e. g. ++(++time):
Time& Time::operator++()
{
// increment as described
return *this;
}
The post-increment and -decrement operators are very strange... Please re-validate if it really is the task to in-/decrement minutes (if so, I can only shake heads over your teacher...). It will be a great surprise for anyone as the operators behave totally differently from what is the usual behaviour! The latter one would be:
Time operator++(int)
{
Time tmp(*this);
++*this;
return tmp;
}
If you really, really shall increment minutes (note the irony: post-X-crement operators actually behave like pre-X-crement, at least as your initial approach looks like): Just leave seconds untouched. All you then need in the post-operators is the body of the outermost if in the respective pre-variants. These then could be re-written (to avoid code duplication) as:
++seconds;
if(seconds == 60)
{
seconds = 0;
*this++; // use post-fix to adjust minutes...
}
Finally: comparison: Unfortunately, we don't yet have C++20 available, otherwise we simply could have implemented the spaceship operator (<=>)... Never mind, we still can use an ordinary function instead and use this one in the operators:
int Time::compare(Time const& other) const
{
// most relevant are hours, if these differ, values of minutes or
// seconds don't matter any more...
int result = hours - other.hours;
if(result == 0)
{
// so hours are the same...
// minutes then are relevant next
result = minutes - other.minutes;
if(result == 0)
result = seconds - other.seconds;
}
return result;
}
Then all the operators to be implemented would look like:
bool Time::operator#(Time const& other) const
{
return compare(other) # 0;
}
where # stands for all of your operators needed (==, !=, <, <=, >, >=).
Bonus: remembering overflow without separate flag:
You won't need another variable any more, but it requires more complex logic.
At first, leaving the -1 (operator--) will indicate that a wrap-around occured. Correspondingly, the getter for wrap-around would return hours == -1;.
At any other place where we previously used hours directly, we'd now use the getter for, which would look like this:
int Time::getHours() const
{
return hours + (hours == -1);
}
Calculating the value for increment is slightly more complex:
hours = (getHours() + 1) % 24 - (hours == 23);

Same random numbers being created everytime the loop goes around.

I am a beginner at C++ and for one of my project involves loop inside loops and creating random numbers. Here is what I have so far:
`
using namespace std;
int main()
{
srand((unsigned int)time(0));
{
cout << "Name of reservoir: ";
string reservior_name;
cin >> reservior_name;
cout << "Capacity in MAF: ";
double capacity;
cin >> capacity;
cout << "Maximum inflow in MAF: ";
int max;
cin>> max;
cout << "minimum inflow in MAF: ";
int min;
cin >> min;
if(min>max)
{cout<<endl<<"Error: The minimum inflow is higher than the maximum inflow."<<endl
<< "Please re-enter your minimum inflow: ";
cin>>min;
}
double inflow_range= max-min;
cout <<"required outflow in MAF: ";
double required;
cin >> required;
if (required > 0.9 * (min + max)/2)
{
cout<<endl<< "Warning: required ouflow is over 90% of the average inflow."<<endl
<< "Returning to main menu ";
}
else
{ const int simulations = 10;
int water_level = 0;
int years = 1;
cout << "Running simulation..." << endl;
for (int i = 1; i <= simulations; i++)
{
int x = (rand()% (max-min + 1)) + min;
while (water_level < capacity)
{
//double r = rand() * 1.0 / RAND_MAX;
//double x = min + inflow_range * r;
//int x = (rand()% (max-min + 1)) + min;
if (water_level + x > required)
{
water_level = water_level + x - required;
}
else
{
water_level= 0;
}
years++;
}
cout <<"Simulation "<< i <<" took " << years <<" years to finish"<< endl;
}
}
}
system ("pause");
return 0;
}
`
So my main question is I'm running into a wall concerning setting up the for loops underneath "Running simulation" where I need to set up the first for loop to run the internal for loop 10 times, with each of those 10 iterations of the internal for loop coming up with random numbers for the range of acceptable results from the query for a random value. I've been told that the idea is to use the Monte Carlo method, i.e. I put in here both the Monte Carlo method and the normal random number generating method. Here it is:
for (int i = 1; i <= simulations; i++)
{
int x = (rand()% (max-min + 1)) + min;
while (water_level < capacity)
{
//double r = rand() * 1.0 / RAND_MAX;
//double x = min + inflow_range * r;
//int x = (rand()% (max-min + 1)) + min;
so the program will create a random value for the inflow. The idea is that the internal for loop will continue to run until the fill_level of the reservoir, which starts at 0, hits the capacity. The process of simulating how many years (each iteration of the internal for loop representing a year) is to be repeated 10 times by the parent for loop of the water_level simulation for loop.
The problem is that the random number that is supposed to created are the same number. THey are different every time I run it, but they are the same every time the loops repeat to make a new simulation. I have tried to figure out what the problem is for hours and still stuck. Any help is very appreciated.
The x is random in your code, the problem is the algorithm and calculation after that. See your code live.
You've forgotten to reset simulation parameter at each iteration, put these inside simulation loop:
--------------------------------------------+
|
for (int i = 1; i <= simulations; i++) |
{ |
int water_level = 0; <--+
int years = 1; <--+
int x = (rand() % (max - min + 1)) + min;
See the code after this edition: live code. The output is
Simulation 1 took 68 years to finish
Simulation 2 took 101 years to finish
Simulation 3 took 8 years to finish
With the code as shown, each iteration (simulation) gets a single value of x for all the years that are simulated. Your commented out code generates a new value of x for each year. Which is the method you want? I'm inclined to think that the inflow varies from year to year, so you should generate a new value of x for each year.
It also looks like you should reset years and water_level for each simulation.
cout << "Running simulation..." << endl;
for (int i = 1; i <= simulations; i++)
{
int water_level = 0;
int years = 1;
while (water_level < capacity)
{
int x = (rand() % (max - min + 1)) + min;
if (water_level + x > required)
water_level += x - required;
else
water_level = 0;
years++;
}
cout <<"Simulation "<< i <<" took " << years <<" years to finish"<< endl;
}
And for debugging, I'd want to print the control parameters (min, max, capacity, required), and then print the key values (year, x, water_level) on each iteration of the inner while loop until I was satisfied it was working correctly.

Determining the difference between dates

I'm trying to figure out a way for my program to take a date (like February 2nd, 2003) and show the difference between the two with another date (like April 2nd, 2012), excluding leap years. So far I've only been able to figure it out if the dates are in the same month, just by subtracting the "day". In this program I use 2 sets of "month", "day" and "year" integers. I'm pretty much at a loss from where to go from here. This is a completely optional part of my assignment but I'd like to get an idea on how to get it to work. It seems like a hassle to me, but maybe there's a simple math formula I'm not thinking about?
Sorry, I don't have any pre-existing code for this part because the rest of the assignment just deals with having the user enter dates and then adding and subtracting a single day.
Using just the standard library, you can convert a moderately insane date structure into a count of seconds since an arbitrary zero point; then subtract and convert into days:
#include <ctime>
// Make a tm structure representing this date
std::tm make_tm(int year, int month, int day)
{
std::tm tm = {0};
tm.tm_year = year - 1900; // years count from 1900
tm.tm_mon = month - 1; // months count from January=0
tm.tm_mday = day; // days count from 1
return tm;
}
// Structures representing the two dates
std::tm tm1 = make_tm(2012,4,2); // April 2nd, 2012
std::tm tm2 = make_tm(2003,2,2); // February 2nd, 2003
// Arithmetic time values.
// On a posix system, these are seconds since 1970-01-01 00:00:00 UTC
std::time_t time1 = std::mktime(&tm1);
std::time_t time2 = std::mktime(&tm2);
// Divide by the number of seconds in a day
const int seconds_per_day = 60*60*24;
std::time_t difference = (time1 - time2) / seconds_per_day;
// To be fully portable, we shouldn't assume that these are Unix time;
// instead, we should use "difftime" to give the difference in seconds:
double portable_difference = std::difftime(time1, time2) / seconds_per_day;
Using Boost.Date_Time is a little less weird:
#include "boost/date_time/gregorian/gregorian_types.hpp"
using namespace boost::gregorian;
date date1(2012, Apr, 2);
date date2(2003, Feb, 2);
long difference = (date1 - date2).days();
It seems like a hassle to me, but maybe there's a simple math formula I'm not thinking about?
It is indeed a hassle, but there is a formula, if you want to do the calculation yourself.
Here is a complete code to calculating date difference in y/m/d.
Assuming that to and from are date types, and that months and days start from 1 (similar to Qt):
static int increment[12] = { 1, -2, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 };
int daysInc = 0;
if (to.day() - from.day() < 0)
{
int month = to.month() - 2; // -1 from zero, -1 previous month.
if (month < 0)
month = 11; // Previous month is December.
daysInc = increment[month];
if ( (month == 1) && (to.year()%4 == 0) )
daysInc++; // Increment days for leap year.
}
int total1 = from.year()*360 + from.month()*30 + from.day();
int total2 = to.year()*360 + to.month()*30 + to.day();
int diff = total2 - total1;
int years = diff/360;
int months = (diff - years*360)/30;
int days = diff - years*360 - months*30 + daysInc;
// Extra calculation when we can pass one month instead of 30 days.
if (from.day() == 1 && to.day() == 31) {
months--;
days = 30;
}
I tried this algorithm and it is working okay. Let me know if you have troubles using/understanding it.
Since you are looking for mathematical formula , it will help you to find a solution to your problem. Let Y be the year,M be the month and D be the day. Do this calculation for both the dates.
Total = Y* 365 + M*30 + D ,then find the difference between 2 totals of the corresponding dates.
While multiplying 30 with M value ,you have to give the number of days in that month. You can do it with #define value or if loop. Similarly you can do for leap year too by multiplying 366 with Y .
Hope this will help u....
New answer for an old question:
chrono-Compatible Low-Level Date Algorithms
has formulas for converting a {year, month, day} triple to a serial count of days and back. You can use it to calculate the number of days between two dates like this:
std::cout << days_from_civil(2012, 4, 2) - days_from_civil(2003, 2, 2) << '\n';
which outputs:
3347
The paper is a how-to manual, not a library. It uses C++14 to demonstrate the formulas. Each formula comes with a detailed description and derivation, that you only have to read if you care about knowing how the formula works.
The formulas are very efficient, and valid over an extremely large range. For example using 32 bit arithmetic, +/- 5 million years (more than enough).
The serial day count is a count of days since (or prior to for negative values) New Years 1970, making the formulas compatible with Unix Time and all known implementations of std::chrono::system_clock.
The days_from_civil algorithm is not novel, and it should look very similar to other algorithms for doing the same thing. But going the other way, from a count of days back to a {year, month, day} triple is trickier. This is the formula documented by civil_from_days and I have not seen other formulations that are as compact as this one.
The paper includes example uses showing typical computations, std::chrono interoperability, and extensive unit tests demonstrating the correctness over +/- 1 million years (using a proleptic Gregorian calendar).
All of the formulas and software are in the public domain.
I'm not sure what platform are you on? Windows, Linux? But let us pretend that you would like to have a platform independent solution and the langugage is standard C++.
If you can use libraries you can use the Boost::Date_Time library (http://www.boost.org/doc/libs/1_49_0/doc/html/date_time.html)
If you cannot use libraries to solve your assignment, you will need to find a common simple ground. Maybe you could convert all the dates to seconds, or days substract them and then convert that back to the data again. Substracting days or months as integers will not help as it will lead to incorrect results unless you do not take into account the rest.
Hope that helps.
Like dbrank0 pointed it out. :)
There is another way round...
Given two dates, take the year of the earlier date as the reference year.
Then calculate no. of days between each of the two given dates and that 1/1/<that year>
Keep a separate function that tells the number of days elapsed till a specific month.
The absolute difference of those two no. of days will give the difference between the two given dates.
Also, do not forget to consider leap years!
The code:
#‎include‬<stdio.h>
#include<math.h>
typedef struct
{
int d, m, y;
} Date;
int isLeap (int y)
{
return (y % 4 == 0) && ( y % 100 != 0) || (y % 400 == 0);
}
int diff (Date d1, Date d2) //logic here!
{
int dd1 = 0, dd2 = 0, y, yref; //dd1 and dd2 store the <i>no. of days</i> between d1, d2 and the reference year
yref = (d1.y < d2.y)? d1.y: d2.y; //that <b>reference year</b>
for (y = yref; y < d1.y; y++)
if (isLeap(y)) //check if there is any leap year between the reference year and d1's year (exclusive)
dd1++;
if (isLeap(d1.y) && d1.m > 2) dd1++; //add another day if the date is past a leap year's February
dd1 += daysTill(d1.m) + d1.d + (d1.y - yref) * 365; //sum up all the tiny bits (days)
for (y = yref; y < d2.y; y++) //repeat for d2
if(isLeap(y))
dd2++;
if (isLeap(y) && d2.m > 2) dd2++;
dd2 += daysTill(d2.m) + d2.d + (d2.y - yref) * 365;
return abs(dd2 - dd1); //return the absolute difference between the two <i>no. of days elapsed past the reference year</i>
}
int daysTill (int month) //some logic here too!!
{
int days = 0;
switch (month)
{
case 1: days = 0;
break;
case 2: days = 31;
break;
case 3: days = 59;
break;
case 4: days = 90; //number of days elapsed before April in a non-leap year
break;
case 5: days = 120;
break;
case 6: days = 151;
break;
case 7: days = 181;
break;
case 8: days = 212;
break;
case 9: days = 243;
break;
case 10:days = 273;
break;
case 11:days = 304;
break;
case 12:days = 334;
break;
}
return days;
}
main()
{
int t; //no. of test cases
Date d1, d2; //d1 is the first date, d2 is the second one! obvious, duh!?
scanf ("%d", &t);
while (t--)
{
scanf ("%d %d %d", &d1.d, &d1.m, &d1.y);
scanf ("%d %d %d", &d2.d, &d2.m, &d2.y);
printf ("%d\n", diff(d1, d2));
}
}
Standard Input:
1
23 9 1960
11 3 2015
Standard Output:
19892
Code in action: https://ideone.com/RrADFR
Better algorithms, optimizations and edits are always welcome!
If you need to do it yourself, then one way to do this pretty easy is by converting dates into a Julian Day. You get formulas at that link, and from conversion on, you only work with floats, where each day is 1 unit.
I've made similar program but it count only days in border of one year or couple years
PS I'm in c++ programming only about two month
#include<iostream>
int calculateDaysInYears(int intYear, int endYear);
int checkYear(int intYear);
int checkMonth(int i, int intYear);
int getUserData()
{
int dayOrMonthOrYear;
std::cin >> dayOrMonthOrYear;
return dayOrMonthOrYear;
}
int calculateMonthInYears(int initialMonth, int endMonth, int initialYear)
{
//Подсчет дней начальной даты для варианта с несколькими годами
int x(0);
initialMonth++;
for (int i = initialMonth; i <= endMonth; i++)
x += checkMonth(i, initialYear);
return x;
}
int calculateMonth(int startMonth, int endMonth, int initialYear)
{
//Формула для подсчета кол-вa дней промежуточных месяцев
//Расчет в пределах года
startMonth++;
int x(0);
for (int i = startMonth; i < endMonth; i++)
x += checkMonth(i, initialYear);
return x;
}
int calculateMonthForEndYear(int endMonth, int endYear)
{
//Подсчет дней в конечном году
int x(0);
//Декремент кол-ва конечных месяцев для компенсации дней последнего месяца
--endMonth;
for (int i = 1; i <= endMonth; i++)
x += checkMonth(i, endYear);
return x;
}
int checkMonth(int i, int intYear)
{
if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12)
return 31;
else
if (i == 2)
{
//Если год високосный, то делится на 4 и 400 без остатка, а на 100 с остатком
if ((intYear % 4 == 0) && (intYear % 100 != 0 ) || (intYear % 400 == 0))
return 29;
else
return 28;
}
else
return 30;
}
int calculateAmountOfDays(int initialDay, int initialMonth, int initialYear)
{
//Подсчет дней до конца стартового месяца
int month = checkMonth(initialMonth, initialYear);
int days = month - initialDay;
return days;
}
int allDays(int initilDays, int endDays, int midleMonth)
{
int totalDays;
//Подсчет всех дней от начала до конца
totalDays = midleMonth + initilDays + endDays;
return totalDays;
}
int checkYear(int intYear)
{
if ((intYear % 4 == 0) && (intYear % 100 != 0) || (intYear % 400 == 0))
return 366;//Високосный год
else
return 365;//Невисокосный год
}
int calculateDaysInYears(int intYear, int endYear)
{
//Начальное кол-во дней. Необходимо для запуска счетчика
int amountDays(0);
//Инкремент начального года для компенсации кол-ва дней промежуточных годов
intYear++;
for (int i = intYear; i < endYear; i++)
amountDays += checkYear(i);
return amountDays;
}
int main()
{
int initialDay;
int initialMonth;
int initialYear;
int endDay;
int endMonth;
int endYear;
std::cout << "Hello! I'm your calendar calculator." << std::endl <<
"Here some rules: " << std::endl <<
"you should enter a data like(d.m.y): 23.8.2020." << std::endl <<
"Also you can ask me to calculate for couple years or in border of one year. Good luck! " << std::endl;
std::cout << "" << std::endl;
//Начальная дата
std::cout << "Enter an initial day: ";
initialDay = getUserData();
std::cout << "Enter an initial month: ";
initialMonth = getUserData();
std::cout << "Enter an initial year: ";
initialYear = getUserData();
std::cout << "" << std::endl;//Пропуск строки
//Конечная дата
std::cout << "Enter an end day: ";
endDay = getUserData();
std::cout << "Enter an end month: ";
endMonth = getUserData();
std::cout << "Enter an end year: ";
endYear = getUserData();
//Проверка кол-ва годов
if ((endYear - initialYear) >= 1)
{
//Подсчет дней до конца начального года
int daysToTheEndOfStartYear = calculateMonthInYears(initialMonth, 12, initialYear) + calculateAmountOfDays(initialDay, initialMonth, initialYear);
//Подсчет дней до конца конечного месяца
int daysToTheEndOfEndYear = calculateMonthForEndYear(endMonth, endYear) + endDay;
//Подсчет дней между годами
int whalDays = calculateDaysInYears(initialYear, endYear);
//Подсчет конечной цыфры
int allDay = whalDays + daysToTheEndOfEndYear + daysToTheEndOfStartYear;
//Вывод в консоль
std::cout << allDay;
}
else
{
//Дни месяцев между начальным и конечным месяцами
int daysInMonths = calculateMonth(initialMonth, endMonth, initialYear);
//Подсчет дней до конца начального месяца
int daysInFirstMonth = calculateAmountOfDays(initialDay, initialMonth, initialYear);
//Подсчет конечной цыфры
int allDay = daysInMonths + daysInFirstMonth + endDay;
//Вывод в консоль
std::cout << allDay;
}
return 0;
}
You should look at the DateTime class.
Also the msdn reference for C++ syntax.