Checking a date is in an interval given by partial/periodic dates - c++

I can define an interval with start and end in the format YYMMDD, but they can also be partial/periodic - meaning some elements (day, month or year) can be left blank.
For example, start = " 1115" and end = " 0115" the interval is 15th nov to 15th jan every year.
I want to check if a non-partial date is in the interval.
int compareParial(const char* first, const char* second)
{
for (int i = 0; i < 6; ++i)
{
if (first[i] != ' ' && second[i] != ' ' && first[i] != second[i])
return first[i] > second[i] ? 1 : -1;
}
return 0;
}
bool isDateInInterval(const char* start, const char* end, const char* searchDate)
{
int firstCompare = compareParial(start, searchDate);
int endCompare = compareParial(end, searchDate);
if (firstCompare <= 0 && endCompare >= 0)
return true;
// the date can still be in the interval if the start of the interval is in one year, but end in the next year
bool switched = 0 < compareParial(start, end);
if (switched && (firstCompare <= 0) != (endCompare >= 0))
return true;
return false;
}
int main()
{
cout << boolalpha << isDateInInterval(" 1115", " 0115", "251110") << endl;
return 0;
}
Update: If the dates are reversed check again if searchDate is in.
A problem I notice is what if start and end are reversed but the year is provided. For example: isDateInInterval("200105", "190601", "251110") would be true

C++20 contains types which can represent partial dates: year, month, day, year_month, month_day, etc.2
For example:
auto start = November/15;
auto end = January/15;
By using actual calendrical types, as opposed to strings, the logic you have to deal with can be greatly simplified. A complete year_month_day might be compared against an interval defined by a pair of month_day like this:
bool
compare_partial(std::chrono::month_day start, std::chrono::month_day end,
std::chrono::year_month_day searchDate)
{
using namespace std::chrono;
// Guess that both start and end fall in the same year
auto trial_start = start/searchDate.year();
auto trial_end = end/searchDate.year();
if (trial_start <= trial_end)
{
return trial_start <= searchDate && searchDate <= trial_end;
}
// start/y > end/y
// Otherwise guess that searchDate comes after trail_start:
if (trial_start <= searchDate)
{
// trial_end must be in the next year
trial_end += years{1};
return trial_start <= searchDate && searchDate <= trial_end;
}
// Otherwise searchDate < start/y && start/y > end/y
// trial_start must be in the previous year
trial_start -= years{1};
return trial_start <= searchDate && searchDate <= trial_end;
}
Be forewarned that even this answer is somewhat wrong1. However by using actual calendrical types to do things like add/subtract a year, and do the comparisons, one makes the code cleaner, easier to read, and thus less likely to contain errors.
This answer also only addresses the month_day partial date. You might also have a year_month partial date, or a mixture of month_day and year_month.
std::chrono has no type year_day, and I'm not sure what that would mean anyway. If you have an idea of what it would mean, I have no doubt that C++20 chrono could help you model it.
In any event:
cout << boolalpha << compare_partial(November/15, January/15, 2025y/November/10) << endl;
will output:
false
Even if you don't use C++20 chrono (or it's free preview), modeling this using calendrical types (perhaps of your own making), as opposed to strings, is highly recommended for creating a robust, error-free solution.
1 Expressions such as trial_end += years{1}; aren't guaranteed to be valid dates. For example what if trial_end has the value 2020-02-29. Adding a year to that will give you 2021-02-29. To make this correct, you must decide how you want to handle such situations (e.g. map it to 2021-02-28?).
2 There also exists a free, open-source, header-only preview of this part of C++20 which works with C++11/14/17: https://github.com/HowardHinnant/date

If year is set, and the dates are switched, you must return false, since it is an empty interval.
bool switched = 0 < compareParial(start, end);
if (start[0]==' ' && switched && (firstCompare <= 0) != (endCompare >= 0))
return true;
return false;

Related

QtCustomPlot is plotting different times that what im passing in

I am trying to pass in time values on a range of a single day(9:30 - 4:00), i use an api and libcurl to retrieve a .json for me that gives me "date: 2020-06-04" and "minute: 09:30" and i have them read into a vector like so:
//Reads in data from json(historical data 1 day delayed)
for(Json::Value::ArrayIndex i = 0 ; i != chartData.size(); i++)
{
if(chartData[i].isMember("average"))
{
value.push_back(chartData[i]["average"].asDouble());
time.push_back(chartData[i]["date"].asString());
auto timeDate = QDate::fromString(time[i].c_str(), Qt::ISODate);
minute.push_back(chartData[i]["minute"].asString());
auto minuteDate = QTime::fromString(minute[i].c_str(), "hh:mm");
timeInEpoch.push_back(QDateTime(timeDate, minuteDate).toSecsSinceEpoch());
if((value[i] == 0) && (i != chartData.size() - 1))
{
value[i] = value[i-1];
}
if(value[i] > maxAvg)
{
maxAvg = value[i];
}
else if(value[i] < minAvg)
{
minAvg = value[i];
}
}
}
I then have them converted to a date and time so they should be like "2020-06-04 09:30" and then converted into SecsSinceEpoch().
After that they should be plotted but when they are plotted its like all of the times are shifted hours to the right, like so
Does anyone have any ideas what would be causing this? Thank you in advance!
fromString() will give back you the datetime in local time, while toSecsSinceEpoch() is converting the datetime value to UTC. So either you have to set specifically the timezone of the input string (for example to UTC), or you can use offsetFromUtc() (https://doc.qt.io/qt-5/qdatetime.html#offsetFromUtc) to adjust the result of toSecsSinceEpoch()

Checking if reducing iterator points to a valid element

I need to know if I can reduce the iterator and have a valid object. The below errors out because I reduce the iterator by 1 which doesn't exist. How can I know that so I don't get the error?
ticks.push_front(Tick(Vec3(0, 0, 5), 0));
ticks.push_front(Tick(Vec3(0, 0, 8), 100));
ticks.push_front(Tick(Vec3(0, 0, 10), 200));
bool found = false;
list<Tick, allocator<Tick>>::iterator iter;
for (iter = ticks.begin(); iter != ticks.end(); ++iter)
{
Tick t = (*iter);
if (214>= t.timestamp)
{
prior = t;
if (--iter != ticks.end())
{
next = (*--iter);
found = true;
break;
}
}
}
I'm trying to find the entries directly "above" and directly "below" the value 214 in the list. If only 1 exists then I don't care. I need above and below to exist.
After your edits to the question, I think I can write a better answer than what I had before.
First, write a comparison function for Ticks that uses their timestamps:
bool CompareTicks(const Tick& l, const Tick& r)
{
return l.timestamp < r.timestamp;
}
Now use the function with std::upper_bound:
// Get an iterator pointing to the first element in ticks that is > 214
// I'm assuming the second parameter to Tick's ctor is the timestamp
auto itAbove = std::upper_bound(ticks.begin(), ticks.end(), Tick(Vec3(0, 0, 0), 214), CompareTicks);
if(itAbove == ticks.end())
; // there is nothing in ticks > 214. I don't know what you want to do in this case.
This will give you the first element in ticks that is > 214. Next, you can use lower_bound to find the first element that is >= 214:
// get an iterator pointing to the first element in ticks that is >= 214
// I'm assuming the second parameter to Tick's ctor is the timestamp
auto itBelow = std::lower_bound(ticks.begin(), ticks.end(), Tick(Vec3(0, 0, 0), 214), CompareTicks);
You have to do one extra step with itBelow now to get the first element before 214, taking care not to go past the beginning of the list:
if(itBelow == ticks.begin())
; // there is nothing in ticks < 214. I don't know what you want to do in this case.
else
--itBelow;
Now, assuming you didn't hit any of the error cases, itAbove is pointing to the first element > 214, and itBelow is pointing to the last element < 214.
This assumes your Ticks are in order by timestamp, which seems to be the case. Note also that this technique will work even if there are multiple 214s in the list. Finally, you said the list is short so it's not really worth worrying about time complexity, but this technique could get you logarithmic performance if you also replaced the list with a vector, as opposed to linear for iterative approaches.
The answer to your core question is simple. Don't increment if you are at the end. Don't decrement if you are at the start.
Before incrementing, check.
if ( iter == ticks.end() )
Before decrementig, check.
if ( iter == ticks.begin() )
Your particular example
Looking at what you are trying to accomplish, I suspect you meant to use:
if (iter != ticks.begin())
instead of
if (--iter != ticks.end())
Update
It seems you are relying on the contents of your list being sorted by timestamp.
After your comment, I think what you need is:
if (214>= t.timestamp)
{
prior = t;
if (++iter != ticks.end())
{
next = *iter;
if ( 214 <= next.timestep )
{
found = true;
break;
}
}
}
Update 2
I agree with the comment made by #crashmstr. Your logic can be:
if (214 <= t.timestamp)
{
next = t;
if ( iter != ticks.begin())
{
prior = *--(iter);
found = true;
break;
}
}
I think you can do what you want with std::adjacent_find from the standard library <algorithm>. By default std::adjacent_find looks for two consecutive identical elements but you can provide your own function to define the relationship you are interested in.
Here's a simplified example:
#include <algorithm>
#include <iostream>
#include <list>
struct matcher
{
matcher(int value) : target(value) {}
bool operator()(int lo, int hi) const {
return (lo < target) && (target < hi);
}
int target;
};
int main()
{
std::list<int> ticks = { 0, 100, 200, 300 };
auto it = std::adjacent_find(ticks.begin(), ticks.end(), matcher(214));
if (it != ticks.end()) {
std::cout << *it << ' ' << *std::next(it) << '\n';
} else {
std::cout << "not found\n";
}
}
This outputs 200 300, the two "surrounding" values it found.

Why is QMultiMap's find operation not working as I expected?

I have a QMultiMap<QDateTime, SomeOwnDataType> from which I'd like to retrieve all values with a certain timestamp. This is what I do:
QMap<QDateTime, Appointment>::iterator it = _reminders.find(now);
where now has a value of di 6. mrt 12:07:00 2012. This is my loop condition:
while (it != _reminders.end() && it.key() == now) {
This was the state of the _reminders object:
Contrary to my expectations, the loop was skipped entirely. How come?
I believe that the problem is that the two timestamps are not equal. If you check the == operator code of QDateTime you will see that the equality holds if both time and date are equal.
bool QDateTime::operator==(const QDateTime &other) const
{
if (d->spec == other.d->spec && d->utcOffset == other.d->utcOffset)
return d->time == other.d->time && d->date == other.d->date;
else {
QDate date1, date2;
QTime time1, time2;
d->getUTC(date1, time1);
other.d->getUTC(date2, time2);
return time1 == time2 && date1 == date2;
}
}
But the time equal operator compares miliseconds:
bool operator==(const QTime &other) const { return mds == other.mds; }
where mds is the time in miliseconds. In the QTime constructor mds is calculated as follows:
mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
It would be safer if you just checked if the difference between two timestamps is within a limit. For example :
while (it != _reminders.end() && abs(now.msecsTo(it.key())) < aLimitInMsecs) {
How do you initialize now?
QDateTime goes up to the millisecond, so a toString() could display the same value while actually the values are different...
Unless at some point the key _reminders[0] is set to the value of now, they will be different.
If you are constructing an calendar app, you might use a QString as the key to your QMultiMap, with the values being the output of QDateTime::toString() (the format depending on the precision you are willing (day, hours, minute, ...)

Unusual Speed Difference between Python and C++

I recently wrote a short algorithm to calculate happy numbers in python. The program allows you to pick an upper bound and it will determine all the happy numbers below it. For a speed comparison I decided to make the most direct translation of the algorithm I knew of from python to c++.
Surprisingly, the c++ version runs significantly slower than the python version. Accurate speed tests between the execution times for discovering the first 10,000 happy numbers indicate the python program runs on average in 0.59 seconds and the c++ version runs on average in 8.5 seconds.
I would attribute this speed difference to the fact that I had to write helper functions for parts of the calculations (for example determining if an element is in a list/array/vector) in the c++ version which were already built in to the python language.
Firstly, is this the true reason for such an absurd speed difference, and secondly, how can I change the c++ version to execute more quickly than the python version (the way it should be in my opinion).
The two pieces of code, with speed testing are here: Python Version, C++ Version. Thanks for the help.
#include <iostream>
#include <vector>
#include <string>
#include <ctime>
#include <windows.h>
using namespace std;
bool inVector(int inQuestion, vector<int> known);
int sum(vector<int> given);
int pow(int given, int power);
void calcMain(int upperBound);
int main()
{
while(true)
{
int upperBound;
cout << "Pick an upper bound: ";
cin >> upperBound;
long start, end;
start = GetTickCount();
calcMain(upperBound);
end = GetTickCount();
double seconds = (double)(end-start) / 1000.0;
cout << seconds << " seconds." << endl << endl;
}
return 0;
}
void calcMain(int upperBound)
{
vector<int> known;
for(int i = 0; i <= upperBound; i++)
{
bool next = false;
int current = i;
vector<int> history;
while(!next)
{
char* buffer = new char[10];
itoa(current, buffer, 10);
string digits = buffer;
delete buffer;
vector<int> squares;
for(int j = 0; j < digits.size(); j++)
{
char charDigit = digits[j];
int digit = atoi(&charDigit);
int square = pow(digit, 2);
squares.push_back(square);
}
int squaresum = sum(squares);
current = squaresum;
if(inVector(current, history))
{
next = true;
if(current == 1)
{
known.push_back(i);
//cout << i << "\t";
}
}
history.push_back(current);
}
}
//cout << "\n\n";
}
bool inVector(int inQuestion, vector<int> known)
{
for(vector<int>::iterator it = known.begin(); it != known.end(); it++)
if(*it == inQuestion)
return true;
return false;
}
int sum(vector<int> given)
{
int sum = 0;
for(vector<int>::iterator it = given.begin(); it != given.end(); it++)
sum += *it;
return sum;
}
int pow(int given, int power)
{
int original = given;
int current = given;
for(int i = 0; i < power-1; i++)
current *= original;
return current;
}
#!/usr/bin/env python
import timeit
upperBound = 0
def calcMain():
known = []
for i in range(0,upperBound+1):
next = False
current = i
history = []
while not next:
digits = str(current)
squares = [pow(int(digit), 2) for digit in digits]
squaresum = sum(squares)
current = squaresum
if current in history:
next = True
if current == 1:
known.append(i)
##print i, "\t",
history.append(current)
##print "\nend"
while True:
upperBound = input("Pick an upper bound: ")
result = timeit.Timer(calcMain).timeit(1)
print result, "seconds.\n"
For 100000 elements, the Python code took 6.9 seconds while the C++ originally took above 37 seconds.
I did some basic optimizations on your code and managed to get the C++ code above 100 times faster than the Python implementation. It now does 100000 elements in 0.06 seconds. That is 617 times faster than the original C++ code.
The most important thing is to compile in Release mode, with all optimizations. This code is literally orders of magnitude slower in Debug mode.
Next, I will explain the optimizations I did.
Moved all vector declarations outside of the loop; replaced them by a clear() operation, which is much faster than calling the constructor.
Replaced the call to pow(value, 2) by a multiplication : value * value.
Instead of having a squares vector and calling sum on it, I sum the values in-place using just an integer.
Avoided all string operations, which are very slow compared to integer operations. For instance, it is possible to compute the squares of each digit by repeatedly dividing by 10 and fetching the modulus 10 of the resulting value, instead of converting the value to a string and then each character back to int.
Avoided all vector copies, first by replacing passing by value with passing by reference, and finally by eliminating the helper functions completely.
Eliminated a few temporary variables.
And probably many small details I forgot. Compare your code and mine side-by-side to see exactly what I did.
It may be possible to optimize the code even more by using pre-allocated arrays instead of vectors, but this would be a bit more work and I'll leave it as an exercise to the reader. :P
Here's the optimized code :
#include <iostream>
#include <vector>
#include <string>
#include <ctime>
#include <algorithm>
#include <windows.h>
using namespace std;
void calcMain(int upperBound, vector<int>& known);
int main()
{
while(true)
{
vector<int> results;
int upperBound;
cout << "Pick an upper bound: ";
cin >> upperBound;
long start, end;
start = GetTickCount();
calcMain(upperBound, results);
end = GetTickCount();
for (size_t i = 0; i < results.size(); ++i) {
cout << results[i] << ", ";
}
cout << endl;
double seconds = (double)(end-start) / 1000.0;
cout << seconds << " seconds." << endl << endl;
}
return 0;
}
void calcMain(int upperBound, vector<int>& known)
{
vector<int> history;
for(int i = 0; i <= upperBound; i++)
{
int current = i;
history.clear();
while(true)
{
int temp = current;
int sum = 0;
while (temp > 0) {
sum += (temp % 10) * (temp % 10);
temp /= 10;
}
current = sum;
if(find(history.begin(), history.end(), current) != history.end())
{
if(current == 1)
{
known.push_back(i);
}
break;
}
history.push_back(current);
}
}
}
There's a new, radically faster version as a separate answer, so this answer is deprecated.
I rewrote your algorithm by making it cache whenever it finds the number to be happy or unhappy. I also tried to make it as pythonic as I could, for example by creating separate functions digits() and happy(). Sorry for using Python 3, but I get to show off a couple a useful things from it as well.
This version is much faster. It runs at 1.7s which is 10 times faster than your original program that takes 18s (well, my MacBook is quite old and slow :) )
#!/usr/bin/env python3
from timeit import Timer
from itertools import count
print_numbers = False
upperBound = 10**5 # Default value, can be overidden by user.
def digits(x:'nonnegative number') -> "yields number's digits":
if not (x >= 0): raise ValueError('Number should be nonnegative')
while x:
yield x % 10
x //= 10
def happy(number, known = {1}, happies = {1}) -> 'True/None':
'''This function tells if the number is happy or not, caching results.
It uses two static variables, parameters known and happies; the
first one contains known happy and unhappy numbers; the second
contains only happy ones.
If you want, you can pass your own known and happies arguments. If
you do, you should keep the assumption commented out on the 1 line.
'''
# assert 1 in known and happies <= known # <= is expensive
if number in known:
return number in happies
history = set()
while True:
history.add(number)
number = sum(x**2 for x in digits(number))
if number in known or number in history:
break
known.update(history)
if number in happies:
happies.update(history)
return True
def calcMain():
happies = {x for x in range(upperBound) if happy(x) }
if print_numbers:
print(happies)
if __name__ == '__main__':
upperBound = eval(
input("Pick an upper bound [default {0}]: "
.format(upperBound)).strip()
or repr(upperBound))
result = Timer(calcMain).timeit(1)
print ('This computation took {0} seconds'.format(result))
It looks like you're passing vectors by value to other functions. This will be a significant slowdown because the program will actually make a full copy of your vector before it passes it to your function. To get around this, pass a constant reference to the vector instead of a copy. So instead of:
int sum(vector<int> given)
Use:
int sum(const vector<int>& given)
When you do this, you'll no longer be able to use the vector::iterator because it is not constant. You'll need to replace it with vector::const_iterator.
You can also pass in non-constant references, but in this case, you don't need to modify the parameter at all.
This is my second answer; which caches things like sum of squares for values <= 10**6:
happy_list[sq_list[x%happy_base] + sq_list[x//happy_base]]
That is,
the number is split into 3 digits + 3 digits
the precomputed table is used to get sum of squares for both parts
these two results are added
the precomputed table is consulted to get the happiness of number:
I don't think Python version can be made much faster than that (ok, if you throw away fallback to old version, that is try: overhead, it's 10% faster).
I think this is an excellent question which shows that, indeed,
things that have to be fast should be written in C
however, usually you don't need things to be fast (even if you needed the program to run for a day, it would be less then the combined time of programmers optimizing it)
it's easier and faster to write programs in Python
but for some problems, especially computational ones, a C++ solution, like the ones above, are actually more readable and more beautiful than an attempt to optimize Python program.
Ok, here it goes (2nd version now...):
#!/usr/bin/env python3
'''Provides slower and faster versions of a function to compute happy numbers.
slow_happy() implements the algorithm as in the definition of happy
numbers (but also caches the results).
happy() uses the precomputed lists of sums of squares and happy numbers
to return result in just 3 list lookups and 3 arithmetic operations for
numbers less than 10**6; it falls back to slow_happy() for big numbers.
Utilities: digits() generator, my_timeit() context manager.
'''
from time import time # For my_timeit.
from random import randint # For example with random number.
upperBound = 10**5 # Default value, can be overridden by user.
class my_timeit:
'''Very simple timing context manager.'''
def __init__(self, message):
self.message = message
self.start = time()
def __enter__(self):
return self
def __exit__(self, *data):
print(self.message.format(time() - self.start))
def digits(x:'nonnegative number') -> "yields number's digits":
if not (x >= 0): raise ValueError('Number should be nonnegative')
while x:
yield x % 10
x //= 10
def slow_happy(number, known = {1}, happies = {1}) -> 'True/None':
'''Tell if the number is happy or not, caching results.
It uses two static variables, parameters known and happies; the
first one contains known happy and unhappy numbers; the second
contains only happy ones.
If you want, you can pass your own known and happies arguments. If
you do, you should keep the assumption commented out on the 1 line.
'''
# This is commented out because <= is expensive.
# assert {1} <= happies <= known
if number in known:
return number in happies
history = set()
while True:
history.add(number)
number = sum(x**2 for x in digits(number))
if number in known or number in history:
break
known.update(history)
if number in happies:
happies.update(history)
return True
# This will define new happy() to be much faster ------------------------.
with my_timeit('Preparation time was {0} seconds.\n'):
LogAbsoluteUpperBound = 6 # The maximum possible number is 10**this.
happy_list = [slow_happy(x)
for x in range(81*LogAbsoluteUpperBound + 1)]
happy_base = 10**((LogAbsoluteUpperBound + 1)//2)
sq_list = [sum(d**2 for d in digits(x))
for x in range(happy_base + 1)]
def happy(x):
'''Tell if the number is happy, optimized for smaller numbers.
This function works fast for numbers <= 10**LogAbsoluteUpperBound.
'''
try:
return happy_list[sq_list[x%happy_base] + sq_list[x//happy_base]]
except IndexError:
return slow_happy(x)
# End of happy()'s redefinition -----------------------------------------.
def calcMain(print_numbers, upper_bound):
happies = [x for x in range(upper_bound + 1) if happy(x)]
if print_numbers:
print(happies)
if __name__ == '__main__':
while True:
upperBound = eval(input(
"Pick an upper bound [{0} default, 0 ends, negative number prints]: "
.format(upperBound)).strip() or repr(upperBound))
if not upperBound:
break
with my_timeit('This computation took {0} seconds.'):
calcMain(upperBound < 0, abs(upperBound))
single = 0
while not happy(single):
single = randint(1, 10**12)
print('FYI, {0} is {1}.\n'.format(single,
'happy' if happy(single) else 'unhappy'))
print('Nice to see you, goodbye!')
I can see that you have quite a few heap allocations that are unnecessary
For example:
while(!next)
{
char* buffer = new char[10];
This doesn't look very optimized. So, you probably want to have the array pre-allocated and using it inside your loop. This is a basic optimizing technique which is easy to spot and to do. It might become into a mess too, so be careful with that.
You are also using the atoi() function, which I don't really know if it is really optimized. Maybe doing a modulus 10 and getting the digit might be better (you have to measure thou, I didn't test this).
The fact that you have a linear search (inVector) might be bad. Replacing the vector data structure with a std::set might speed things up. A hash_set could do the trick too.
But I think that the worst problem is the string and this allocation of stuff on the heap inside that loop. That doesn't look good. I would try at those places first.
Well, I also gave it a once-over. I didn't test or even compile, though.
General rules for numerical programs:
Never process numbers as text. That's what makes lesser languages than Python slow, so if you do it in C, the program will be slower than Python.
Don't use data structures if you can avoid them. You were building an array just to add the numbers up. Better keep a running total.
Keep a copy of the STL reference open so you can use it rather than writing your own functions.
void calcMain(int upperBound)
{
vector<int> known;
for(int i = 0; i <= upperBound; i++)
{
int current = i;
vector<int> history;
do
{
squaresum = 0
for ( ; current; current /= 10 )
{
int digit = current % 10;
squaresum += digit * digit;
}
current = squaresum;
history.push_back(current);
} while ( ! count(history.begin(), history.end() - 1, current) );
if(current == 1)
{
known.push_back(i);
//cout << i << "\t";
}
}
//cout << "\n\n";
}
Just to get a little more closure on this issue by seeing how fast I could truely find these numbers, I wrote a multithreaded C++ implementation of Dr_Asik's algorithm. There are two things that are important to realize about the fact that this implementation is multithreaded.
More threads does not necessarily lead to better execution times, there is a happy medium for every situation depending on the volume of numbers you want to calculate.
If you compare the times between this version running with one thread and the original version, the only factors that could cause a difference in time are the overhead from starting the thread and variable system performance issues. Otherwise, the algorithm is the same.
The code for this implementation (all credit for the algorithm goes to Dr_Asik) is here. Also, I wrote some speed tests with a double check for each test to help back up those 3 points.
Calculation of the first 100,000,000 happy numbers:
Original - 39.061 / 39.000 (Dr_Asik's original implementation)
1 Thread - 39.000 / 39.079
2 Threads - 19.750 / 19.890
10 Threads - 11.872 / 11.888
30 Threads - 10.764 / 10.827
50 Threads - 10.624 / 10.561 <--
100 Threads - 11.060 / 11.216
500 Threads - 13.385 / 12.527
From these results it looks like our happy medium is about 50 threads, plus or minus ten or so.
Other optimizations: by using arrays and direct access using the loop index rather than searching in a vector, and by caching prior sums, the following code (inspired by Dr Asik's answer but probably not optimized at all) runs 2445 times faster than the original C++ code, about 400 times faster than the Python code.
#include <iostream>
#include <windows.h>
#include <vector>
void calcMain(int upperBound, std::vector<int>& known)
{
int tempDigitCounter = upperBound;
int numDigits = 0;
while (tempDigitCounter > 0)
{
numDigits++;
tempDigitCounter /= 10;
}
int maxSlots = numDigits * 9 * 9;
int* history = new int[maxSlots + 1];
int* cache = new int[upperBound+1];
for (int jj = 0; jj <= upperBound; jj++)
{
cache[jj] = 0;
}
int current, sum, temp;
for(int i = 0; i <= upperBound; i++)
{
current = i;
while(true)
{
sum = 0;
temp = current;
bool inRange = temp <= upperBound;
if (inRange)
{
int cached = cache[temp];
if (cached)
{
sum = cached;
}
}
if (sum == 0)
{
while (temp > 0)
{
int tempMod = temp % 10;
sum += tempMod * tempMod;
temp /= 10;
}
if (inRange)
{
cache[current] = sum;
}
}
current = sum;
if(history[current] == i)
{
if(current == 1)
{
known.push_back(i);
}
break;
}
history[current] = i;
}
}
}
int main()
{
while(true)
{
int upperBound;
std::vector<int> known;
std::cout << "Pick an upper bound: ";
std::cin >> upperBound;
long start, end;
start = GetTickCount();
calcMain(upperBound, known);
end = GetTickCount();
for (size_t i = 0; i < known.size(); ++i) {
std::cout << known[i] << ", ";
}
double seconds = (double)(end-start) / 1000.0;
std::cout << std::endl << seconds << " seconds." << std::endl << std::endl;
}
return 0;
}
Stumbled over this page whilst bored and thought I'd golf it in js. The algorithm is my own, and I haven't checked it thoroughly against anything other than my own calculations (so it could be wrong). It calculates the first 1e7 happy numbers and stores them in h. If you want to change it, change both the 7s.
m=1e7,C=7*81,h=[1],t=true,U=[,,,,t],n=w=2;
while(n<m){
z=w,s=0;while(z)y=z%10,s+=y*y,z=0|z/10;w=s;
if(U[w]){if(n<C)U[n]=t;w=++n;}else if(w<n)h.push(n),w=++n;}
This will print the first 1000 items for you in console or a browser:
o=h.slice(0,m>1e3?1e3:m);
(!this.document?print(o):document.load=document.write(o.join('\n')));
155 characters for the functional part and it appears to be as fast* as Dr. Asik's offering on firefox or v8 (350-400 times as fast as the original python program on my system when running time d8 happygolf.js or js -a -j -p happygolf.js in spidermonkey).
I shall be in awe of the analytic skills anyone who can figure out why this algorithm is doing so well without referencing the longer, commented, fortran version.
I was intrigued by how fast it was, so I learned fortran to get a comparison of the same algorithm, be kind if there are any glaring newbie mistakes, it's my first fortran program. http://pastebin.com/q9WFaP5C
It's static memory wise, so to be fair to the others, it's in a self-compiling shell script, if you don't have gcc/bash/etc strip out the preprocessor and bash stuff at the top, set the macros manually and compile it as fortran95.
Even if you include compilation time it beats most of the others here. If you don't, it's about ~3000-3500 times as fast as the original python version (and by extension >40,000 times as fast as the C++*, although I didn't run any of the C++ programs).
Surprisingly many of the optimizations I tried in the fortran version (incl some like loop unrolling which I left out of the pasted version due to small effect and readability) were detrimental to the js version. This exercise shows that modern trace compilers are extremely good (within a factor of 7-10 of carefully optimized, static memory fortran) if you get out of their way and don't try any tricky stuff.
get out of their way, and trying to do tricky stuff
Finally, here's a much nicer, more recursive js version.
// to s, then integer divides x by 10.
// Repeats until x is 0.
function sumsq(x) {
var y,s=0;
while(x) {
y = x % 10;
s += y * y;
x = 0| x / 10;
}
return s;
}
// A boolean cache for happy().
// The terminating happy number and an unhappy number in
// the terminating sequence.
var H=[];
H[1] = true;
H[4] = false;
// Test if a number is happy.
// First check the cache, if that's empty
// Perform one round of sumsq, then check the cache
// For that. If that's empty, recurse.
function happy(x) {
// If it already exists.
if(H[x] !== undefined) {
// Return whatever is already in cache.
return H[x];
} else {
// Else calc sumsq, set and return cached val, or if undefined, recurse.
var w = sumsq(x);
return (H[x] = H[w] !== undefined? H[w]: happy(w));
}
}
//Main program loop.
var i, hN = [];
for(i = 1; i < 1e7; i++) {
if(happy(i)) { hN.push(i); }
}
Surprisingly, even though it is rather high level, it did almost exactly as well as the imperative algorithm in spidermonkey (with optimizations on), and close (1.2 times as long) in v8.
Moral of the story I guess, spend a bit of time thinking about your algorithm if it's important. Also high level languages already have a lot of overhead (and sometimes have tricks of their own to reduce it) so sometimes doing something more straightforwared or utilizing their high level features is just as fast. Also micro-optimization doesn't always help.
*Unless my python installation is unusually slow, direct times are somewhat meaningless as this is a first generation eee.
Times are:
12s for fortran version, no output, 1e8 happy numbers.
40s for fortran version, pipe output through gzip to disk.
8-12s for both js versions. 1e7 happy numbers, no output with full optimization
10-100s for both js versions 1e7 with less/no optimization (depending on definition of no optimization, the 100s was with eval()) no output
I'd be interested to see times for these programs on a real computer.
I am not an expert at C++ optimization, but I believe the speed difference may be due to the fact that Python lists have preallocated more space at the beginning while your C++ vectors must reallocate and possibly copy every time it grows.
As for GMan's comment about find, I believe that the Python "in" operator is also a linear search and is the same speed.
Edit
Also I just noticed that you rolled your own pow function. There is no need to do that and the stdlib is likely faster.
Here is another way that relies on memorising all the numbers already explored.
I obtain a factor x4-5, which is oddly stable against DrAsik's code for 1000 and 1000000, I expected the cache to be more efficient the more numbers we were exploring. Otherwise, the same kind of classic optimizations have been applied. BTW, if the compiler accepts NRVO (/RNVO ? I never remember the exact term) or rvalue references, we wouldn't need to pass the vector as an out parameter.
NB: micro-optimizations are still possible IMHO, and moreover the caching is naive as it allocates much more memory than really needed.
enum Status {
never_seen,
being_explored,
happy,
unhappy
};
char const* toString[] = { "never_seen", "being_explored", "happy", "unhappy" };
inline size_t sum_squares(size_t i) {
size_t s = 0;
while (i) {
const size_t digit = i%10;
s += digit * digit;
i /= 10;
}
return s ;
}
struct Cache {
Cache(size_t dim) : m_cache(dim, never_seen) {}
void set(size_t n, Status status) {
if (m_cache.size() <= n) {
m_cache.resize(n+1, never_seen);
}
m_cache[n] = status;
// std::cout << "(c[" << n << "]<-"<<toString[status] << ")";
}
Status operator[](size_t n) const {
if (m_cache.size() <= n) {
return never_seen;
} else {
return m_cache[n];
}
}
private:
std::vector<Status> m_cache;
};
void search_happy_lh(size_t upper_bound, std::vector<size_t> & happy_numbers)
{
happy_numbers.clear();
happy_numbers.reserve(upper_bound); // it doesn't improve much the performances
Cache cache(upper_bound+1);
std::vector<size_t> current_stack;
cache.set(1,happy);
happy_numbers.push_back(1);
for (size_t i = 2; i<=upper_bound ; ++i) {
// std::cout << "\r" << i << std::flush;
current_stack.clear();
size_t s= i;
while ( s != 1 && cache[s]==never_seen)
{
current_stack.push_back(s);
cache.set(s, being_explored);
s = sum_squares(s);
// std::cout << " - " << s << std::flush;
}
const Status update_with = (cache[s]==being_explored ||cache[s]==unhappy) ? unhappy : happy;
// std::cout << " => " << s << ":" << toString[update_with] << std::endl;
for (size_t j=0; j!=current_stack.size(); ++j) {
cache.set(current_stack[j], update_with);
}
if (cache[i] == happy) {
happy_numbers.push_back(i);
}
}
}
Here's a C# version:
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp
{
class Program
{
static void Main (string [] args)
{
while (true)
{
Console.Write ("Pick an upper bound: ");
String
input = Console.ReadLine ();
uint
upper_bound;
if (uint.TryParse (input, out upper_bound))
{
DateTime
start = DateTime.Now;
CalcHappyNumbers (upper_bound);
DateTime
end = DateTime.Now;
TimeSpan
span = end - start;
Console.WriteLine ("Time taken = " + span.TotalSeconds + " seconds.");
}
else
{
Console.WriteLine ("Error in input, unable to parse '" + input + "'.");
}
}
}
enum State
{
Happy,
Sad,
Unknown
}
static void CalcHappyNumbers (uint upper_bound)
{
SortedDictionary<uint, State>
happy = new SortedDictionary<uint, State> ();
SortedDictionary<uint, bool>
happy_numbers = new SortedDictionary<uint, bool> ();
happy [1] = State.Happy;
happy_numbers [1] = true;
for (uint current = 2 ; current < upper_bound ; ++current)
{
FindState (ref happy, ref happy_numbers, current);
}
//foreach (KeyValuePair<uint, bool> pair in happy_numbers)
//{
// Console.Write (pair.Key.ToString () + ", ");
//}
//Console.WriteLine ("");
}
static State FindState (ref SortedDictionary<uint, State> happy, ref SortedDictionary<uint,bool> happy_numbers, uint value)
{
State
current_state;
if (happy.TryGetValue (value, out current_state))
{
if (current_state == State.Unknown)
{
happy [value] = State.Sad;
}
}
else
{
happy [value] = current_state = State.Unknown;
uint
new_value = 0;
for (uint i = value ; i != 0 ; i /= 10)
{
uint
lsd = i % 10;
new_value += lsd * lsd;
}
if (new_value == 1)
{
current_state = State.Happy;
}
else
{
current_state = FindState (ref happy, ref happy_numbers, new_value);
}
if (current_state == State.Happy)
{
happy_numbers [value] = true;
}
happy [value] = current_state;
}
return current_state;
}
}
}
I compared it against Dr_Asik's C++ code. For an upper bound of 100000 the C++ version ran in about 2.9 seconds and the C# version in 0.35 seconds. Both were compiled using Dev Studio 2005 using default release build options and both were executed from a command prompt.
Here's some food for thought: If given the choice of running a 1979 algorithm for finding prime numbers in a 2009 computer or a 2009 algorithm on a 1979 computer, which would you choose?
The new algorithm on ancient hardware would be the better choice by a huge margin. Have a look at your "helper" functions.
There are quite a few optimizations possible:
(1) Use const references
bool inVector(int inQuestion, const vector<int>& known)
{
for(vector<int>::const_iterator it = known.begin(); it != known.end(); ++it)
if(*it == inQuestion)
return true;
return false;
}
int sum(const vector<int>& given)
{
int sum = 0;
for(vector<int>::const_iterator it = given.begin(); it != given.end(); ++it)
sum += *it;
return sum;
}
(2) Use counting down loops
int pow(int given, int power)
{
int current = 1;
while(power--)
current *= given;
return current;
}
Or, as others have said, use the standard library code.
(3) Don't allocate buffers where not required
vector<int> squares;
for (int temp = current; temp != 0; temp /= 10)
{
squares.push_back(pow(temp % 10, 2));
}
With similar optimizations as PotatoSwatter I got time for 10000 numbers down from 1.063 seconds to 0.062 seconds (except I replaced itoa with standard sprintf in the original).
With all the memory optimizations (don't pass containers by value - in C++ you have to explicitly decide whether you want a copy or a reference; move operations that allocate memory out of inner loops; if you already have the number in a char buffer, what's the point of copying it to std::string etc) I got it down to 0.532.
The rest of the time came from using %10 to access digits, rather than converting numbers to string.
I suppose there might be another algorithmic level optimization (numbers that you have encountered while finding a happy number are themselves also happy numbers?) but I don't know how much that gains (there is not that many happy numbers in the first place) and this optimization is not in the Python version either.
By the way, by not using string conversion and a list to square digits, I got the Python version from 0.825 seconds down to 0.33 too.
#!/usr/bin/env python
import timeit
upperBound = 0
def calcMain():
known = set()
for i in xrange(0,upperBound+1):
next = False
current = i
history = set()
while not next:
squaresum=0
while current > 0:
current, digit = divmod(current, 10)
squaresum += digit * digit
current = squaresum
if current in history:
next = True
if current == 1:
known.add(i)
history.add(current)
while True:
upperBound = input("Pick an upper bound: ")
result = timeit.Timer(calcMain).timeit(1)
print result, "seconds.\n"
I made a couple of minor changes to your original python code example that make a better than 16x improvement to the performance of the code.
The changes I made took the 100,000 case from about 9.64 seconds to about 3.38 seconds.
The major change was to make the mod 10 and accumulator changes to run in a while loop. I made a couple of other changes that improved execution time in only fractions of hundredths of seconds. The first minor change was changing the main for loop from a range list comprehension to an xrange iterator. The second minor change was substituting the set class for the list class for both the known and history variables.
I also experimented with iterator comprehensions and precalculating the squares but they both had negative effects on the efficiency.
I seem to be running a slower version of python or on a slower processor than some of the other contributers. I would be interest in the results of someone else's timing comparison of my python code against one of the optimized C++ versions of the same algorithm.
I also tried using the python -O and -OO optimizations but they had the reverse of the intended effect.
Why is everyone using a vector in the c++ version? Lookup time is O(N).
Even though it's not as efficient as the python set, use std::set. Lookup time is O(log(N)).

Custom sorting, always force 0 to back of ascending order?

Premise
This problem has a known solution (shown below actually), I'm just wondering if anyone has a more elegant algorithm or any other ideas/suggestions on how to make this more readable, efficient, or robust.
Background
I have a list of sports competitions that I need to sort in an array. Due to the nature of this array's population, 95% of the time the list will be pre sorted, so I use an improved bubble sort algorithm to sort it (since it approaches O(n) with nearly sorted lists).
The bubble sort has a helper function called CompareCompetitions that compares two competitions and returns >0 if comp1 is greater, <0 if comp2 is greater, 0 if the two are equal. The competitions are compared first by a priority field, then by game start time, and then by Home Team Name.
The priority field is the trick to this problem. It is an int that holds a positve value or 0. They are sorted with 1 being first, 2 being second, and so on with the exception that 0 or invalid values are always last.
e.g. the list of priorities
0, 0, 0, 2, 3, 1, 3, 0
would be sorted as
1, 2, 3, 3, 0, 0, 0, 0
The other little quirk, and this is important to the question, is that 95% of the time, priority will be it's default 0, because it is only changed if the user wants to manually change the sort order, which is rarely. So the most frequent case in the compare function is that priorities are equal and 0.
The Code
This is my existing compare algorithm.
int CompareCompetitions(const SWI_COMPETITION &comp1,const SWI_COMPETITION &comp2)
{
if(comp1.nPriority == comp2.nPriority)
{
//Priorities equal
//Compare start time
int ret = comp1.sStartTime24Hrs.CompareNoCase(comp2.sStartTime24Hrs);
if(ret != 0)
{
return ret; //return compare result
}else
{
//Equal so far
//Compare Home team Name
ret = comp1.sHLongName.CompareNoCase(comp2.sHLongName);
return ret;//Home team name is last field to sort by, return that value
}
}
else if(comp1.nPriority > comp2.nPriority)
{
if(comp2.nPriority <= 0)
return -1;
else
return 1;//comp1 has lower priority
}else /*(comp1.nPriority < comp2.nPriority)*/
{
if(comp1.nPriority <= 0)
return 1;
else
return -1;//comp1 one has higher priority
}
}
Question
How can this algorithm be improved?
And more importantly...
Is there a better way to force 0 to the back of the sort order?
I want to emphasize that this code seems to work just fine, but I am wondering if there is a more elegant or efficient algorithm that anyone can suggest. Remember that nPriority will almost always be 0, and the competitions will usually sort by start time or home team name, but priority must always override the other two.
Isn't it just this?
if (a==b) return other_data_compare(a, b);
if (a==0) return 1;
if (b==0) return -1;
return a - b;
You can also reduce some of the code verbosity using the trinary operator like this:
int CompareCompetitions(const SWI_COMPETITION &comp1,const SWI_COMPETITION &comp2)
{
if(comp1.nPriority == comp2.nPriority)
{
//Priorities equal
//Compare start time
int ret = comp1.sStartTime24Hrs.CompareNoCase(comp2.sStartTime24Hrs);
return ret != 0 ? ret : comp1.sHLongName.CompareNoCase(comp2.sHLongName);
}
else if(comp1.nPriority > comp2.nPriority)
return comp2.nPriority <= 0 ? -1 : 1;
else /*(comp1.nPriority < comp2.nPriority)*/
return comp1.nPriority <= 0 ? 1 : -1;
}
See?
This is much shorter and in my opinion easily read.
I know it's not what you asked for but it's also important.
Is it intended that if the case nPriority1 < 0 and nPriority2 < 0 but nPriority1 != nPriority2 the other data aren't compared?
If it isn't, I'd use something like
int nPriority1 = comp1.nPriority <= 0 ? INT_MAX : comp1.nPriority;
int nPriority2 = comp2.nPriority <= 0 ? INT_MAX : comp2.nPriority;
if (nPriority1 == nPriority2) {
// current code
} else {
return nPriority1 - nPriority2;
}
which will consider values less or equal to 0 the same as the maximum possible value.
(Note that optimizing for performance is probably not worthwhile if you consider that there are insensitive comparisons in the most common path.)
If you can, it seems like modifying the priority scheme would be the most elegant, so that you could just sort normally. For example, instead of storing a default priority as 0, store it as 999, and cap user defined priorities at 998. Then you won't have to deal with the special case anymore, and your compare function can have a more straightforward structure, with no nesting of if's:
(pseudocode)
if (priority1 < priority2) return -1;
if (priority1 > priority2) return 1;
if (startTime1 < startTime2) return -1;
if (startTime1 > startTime2) return 1;
if (teamName1 < teamName2) return -1;
if (teamName1 > teamName2) return -1;
return 0; // exact match!
I think the inelegance you feel about your solution comes from duplicate code for the zero priority exception. The Pragmatic Programmer explains that each piece of information in your source should be defined in "one true" place. To the naive programmer reading your function, you want the exception to stand-out, separate from the other logic, in one place, so that it is readily understandable. How about this?
if(comp1.nPriority == comp2.nPriority)
{
// unchanged
}
else
{
int result, lowerPriority;
if(comp1.nPriority > comp2.nPriority)
{
result = 1;
lowerPriority = comp2.nPriority;
}
else
{
result = -1;
lowerPriority = comp1.nPriority;
}
// zero is an exception: always goes last
if(lowerPriority == 0)
result = -result;
return result;
}
I Java-ized it, but the approach will work fine in C++:
int CompareCompetitions(Competition comp1, Competition comp2) {
int n = comparePriorities(comp1.nPriority, comp2.nPriority);
if (n != 0)
return n;
n = comp1.sStartTime24Hrs.compareToIgnoreCase(comp2.sStartTime24Hrs);
if (n != 0)
return n;
n = comp1.sHLongName.compareToIgnoreCase(comp2.sHLongName);
return n;
}
private int comparePriorities(Integer a, Integer b) {
if (a == b)
return 0;
if (a <= 0)
return -1;
if (b <= 0)
return 1;
return a - b;
}
Basically, just extract the special-handling-for-zero behavior into its own function, and iterate along the fields in sort-priority order, returning as soon as you have a nonzero.
As long as the highest priority is not larger than INT_MAX/2, you could do
#include <climits>
const int bound = INT_MAX/2;
int pri1 = (comp1.nPriority + bound) % (bound + 1);
int pri2 = (comp2.nPriority + bound) % (bound + 1);
This will turn priority 0 into bound and shift all other priorities down by 1. The advantage is that you avoid comparisons and make the remainder of the code look more natural.
In response to your comment, here is a complete solution that avoids the translation in the 95% case where priorities are equal. Note, however, that your concern over this is misplaced since this tiny overhead is negligible with respect to the overall complexity of this case, since the equal-priorities case involves at the very least a function call to the time comparison method and at worst an additional call to the name comparator, which is surely at least an order of magnitude slower than whatever you do to compare the priorities. If you are really concerned about efficiency, go ahead and experiment. I predict that the difference between the worst-performing and best-performing suggestions made in this thread won't be more than 2%.
#include <climits>
int CompareCompetitions(const SWI_COMPETITION &comp1,const SWI_COMPETITION &comp2)
{
if(comp1.nPriority == comp2.nPriority)
if(int ret = comp1.sStartTime24Hrs.CompareNoCase(comp2.sStartTime24Hrs))
return ret;
else
return comp1.sHLongName.CompareNoCase(comp2.sHLongName);
const int bound = INT_MAX/2;
int pri1 = (comp1.nPriority + bound) % (bound + 1);
int pri2 = (comp2.nPriority + bound) % (bound + 1);
return pri1 > pri2 ? 1 : -1;
}
Depending on your compiler/hardware, you might be able to squeeze out a few more cycles by replacing the last line with
return (pri1 > pri2) * 2 - 1;
or
return (pri1-pri2 > 0) * 2 - 1;
or (assuming 2's complement)
return ((pri1-pri2) >> (CHAR_BIT*sizeof(int) - 1)) | 1;
Final comment: Do you really want CompareCompetitions to return 1,-1,0 ? If all you need it for is bubble sort, you would be better off with a function returning a bool (true if comp1 is ">=" comp2 and false otherwise). This would simplify (albeit slightly) the code of CompareCompetitions as well as the code of the bubble sorter. On the other hand, it would make CompareCompetitions less general-purpose.