cjudge@grandecom.net
BAN USERAnother horribly-worded question.
int windowYear (int y) {
return y < (50 + (DateTime.Now.Year % 100)) ? 2000 + y : 1900 + y;
}
This simplest solution makes a few assumptions:
1. 0 <= y < = 99
2. the current year should always be the center-point on which the window should pivot
3. the centuries in play will always be 1900 and 2000
4. no actual years from the range 0 to 99 will ever be valid
5. there are no better ways to deal with two digit years.
Let's examine these assumptions:
1. To imply that the input values are constrained elsewhere implies that they could just as easily be constrained to four digit years. Of course, this just postpones the problem for the next 7983 years when programmers will have to deal with five-digit years. If these years are coming from user input, it would be better to enforce a four digit year with an input mask. If the data is coming from a database where years were only stored in two digits (did we learn nothing from Y2K?), then we probably need to look at what this year represents in order to pick an appropriate pivot (see point 2).
2. If the two-digit year represents something like a person's birthdate, a much better pivot would be (1 + (currentyear % 100)) so that your 99 year old grandmother's birthday of 6/1/18 will correctly pivot to 6/1/1918 instead of 6/1/2018. The situation is reversed if the date represents something like "expected retirement date."
3. I would hope (but not expect) that a hack like this would be caught in a code review and rejected as the brittle hack that it is. Let's hope code like this won't be needed in the next century.
4. What if a two-digit year is valid and should not be converted? Say you're answering an online quiz which asks, "In what year did the Roman emperor Augustus die?" You type in the correct answer, 14, and the website converts this to 2014 and your answer is scored as incorrect.
5. The only reason to do a year windowing function like this is if you have something like a database that already contains two-digit years. If you're collecting this data on an ongoing basis, fix the problem at the point of data entry.
So, at the very least, modify this function to include the pivot. The pivot basically defines how many years into the future will be windowed into the 2000s
int windowYear (int y, int pivot) {
return y < (pivot + (DateTime.Now.Year % 100)) ? 2000 + y : 1900 + y;
}
Don't reinvent the wheel, put your data into a database and query your data using sql.
- cjudge@grandecom.net May 02, 2017Here's a table lookup that - with 10 million iterations of calculating the count for n = 10,000,000,000,000,000 - shaves about 20% off of my previous algorithm:
// fib starting at 2
static long[] counts = {
2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,
196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,
63245986,102334155,165580141,267914296,433494437,701408733,1134903170,1836311903,2971215073,
4807526976,7778742049,12586269025,20365011074,32951280099,53316291173,86267571272,139583862445,
225851433717,365435296162,591286729879,956722026041,1548008755920,2504730781961,4052739537881,
6557470319842,10610209857723,17167680177565,27777890035288
};
public static long count_TableLookup(long n) {
if (n < 2)
return n + 1;
int e = -1;
int p = 2;
while (p <= n) {
e++;
p <<= 1;
}
long sum = counts [e];
p >>= 1;
n &= ~p;
p >>= 1;
if (n >= p) {
// don't count anything above the midpoint - they all start with 11
n = p - 1;
}
return sum + count_TableLookup (n);
}
A bit more complex (punny!), but orders of magnitude faster for large n:
public static long count_SumOfSeries(long n) {
if (n == 0)
return 1;
if (n == 1)
return 2;
if (n < 4)
return 3;
long sum = 2;
long a = 0;
long b = 1;
long pOf2 = 4;
while (true) {
if (pOf2 <= n) {
long c = a + b;
sum += c;
a = b;
b = c;
pOf2 <<= 1;
}
else {
pOf2 >>= 1;
n &= ~pOf2;
pOf2 >>= 1;
if (n >= pOf2){
// don't count anything above the midpoint - they all start with 11
n = pOf2 - 1;
}
sum += count_SumOfSeries (n);
break;
}
}
return sum;
}
Well, it's ugly and brute-force, but:
- cjudge@grandecom.net May 04, 2017