Best way to find difference between two values in a cyclic system? - c++

Take for example time: if we have the starting hour and ending hour, what's the best way to find the number of hours between them?
If we take a 12-hour clock, we'd get the following results
from 1 to 5 = 4
from 11 to 1 = 2
What is the most efficient way to do that?

Assuming a 12 hour clock, the number of hours from a to b can be calculated as:
difference = ((b + 12) - a) % 12;
This also assumes that a and b are both in the range [1, 12]. In case they are not, you can do:
a %= 12;
b %= 12;
before doing the difference calculation.

Assuming input already in range 1-12, you might do
return b - a + (b < a) * 12;
benchmark showing a 2 times performance gain over cigien's solution.

Related

How do I go about getting the real result for 50%60 in C++

I please check this problem I'm creating a Time Base app but I'm having problem getting to work around the modulus oper (%) I want the remainder of 50%60 which I'm expecting to output 10 but it just give me the Lhvalues instead i.e 50. How do I go about it.
Here is a part review of the code.
void setM(int m){
if ((m+min)>59){
hour+=((min+m)/60);
min=0;
min=(min+m)%60;
}
else min+=m;
}
In the code m is passed in as 50 and min is passed in as 10
How do I get the output to be 10 for min in this equation min=(min+m)%60; without reversing the equation i.e
60%(min+m)
in C++ expression a % b returns remainder of division of a by b (if they are positive. For negative numbers sign of result is implementation defined).
you should do : 60 % 50 if you want to divide by 50
Or, if you want to get mins, i think you don't need to make min=0.
When you do 50 % 60, you get a remiainder of 50 since 50 cannot be divided by 60.
To get around this error, you can try doing do something like 70 % 60 to get the correct value as a result, since you do not want to use 60 % 50
This would follow the following logic:
Find the difference between 60 and min + m after min is set to zero if min + mis less than 60. Store it in a variable var initially set to zero.
check if the result is negative; if it is, then set it to positive by multiplying it by -1
When you do the operation, do min = ((min + m) + var) % 60; instead.
***Note: As I am unfamiliar with a Time Base App and what its purpose is, this solution may or may not be required, hence please inform me in the comments before downvoting if I there is anything wrong with my answer. Thanks!
It looks like you are trying to convert an integral number of minutes to an hour/minute pair. That would look more like this instead:
void setM(int m)
{
hour = m / 60;
min = m % 60;
}
If you are trying to add an integral number of minutes to an existing hour/minute pair, it would look more like this:
void addM(int m)
{
int value = (hour * 60) + min;
value += m;
hour = value / 60;
min = value % 60;
}
Or
void addM(int m)
{
setM(((hour * 60) + min) + m);
}

Not understanding mathematical solution to implementation task

The problem sounds like that:
Kevin has N friends and one building. He wants to organize a
party in that building and he invites exacly 1 friend / day. Kevin
unfortunately has grumpy neighbors which aren't too happy with the
noise that Kevin's party does. For that, Kevin wants to minimize the
noise level of his party. (the noise level is equal to the number of
friends in the building) In order to do that, after some day he can
clear the building by asking his friends to leave (he can do that K times, for K different days). (ex: he clears the
building after day 2 so at day 3 when he invites another friend, for
day 3 the noise level will be 1 because the past day he cleared the
building; if he didn't clear the building at day 2, the noise level
for day 3 will have been 3 (1 from day 2, 1 from day 1 and the new invited friend) and the total noise level for day 1, 2 and 3 would have been 1+2+3=6).
For better understanding the task:
Input:
5 2 (N, K)
Output:
7
Explanation:
In the input example, N friends will be invited at the party, in the following order:
1 (day 1) 1 (day 1)
1 (day 2) so in the building for each day will be present 2 (day 2)
1 (day 3) -------------------------------------------------> 3 (day 3)
1 (day 4) (without clearing the building) 4 (day 4)
1 (day 5) 5 (day 5)
-----(+)
15
So, clearing the building 0 times (K=0), the noise level will be 15.
Clearing the building 1 time (K=1), the sum will be:
(0 times)
1 1
__ 2 __ clearing the building after day 2 2
3 -----------------------------------> 1
4 2
5 3
----(+)
9
At this case (K=1), another solution could be to clear after day 3, same sum.
Clearing 2 times (K=2):
(0 times)
1 1
__ 2 __ clearing the building after day 2 & 3 2
__ 3 __ --------------------------------------> 1
4 1
5 2
----(+)
7
I have the solution but I don't understand it!
I tried, took some other cases but still nothing, maybe you guys can explain me why the solution is the way it is.
This is how sum(N, K) is calculated:
sum(N, K) = minimum noise level clearing the building K times (K>=0)
C++ code:
int sum(int n)
{
return n * (n + 1) / 2;
}
int solve(int n, int k)
{
int p = k + 1;
int mp = n/p;
int bp = (n+p-1)/p;
int nmaj = n%p;
int nmic = p-nmaj;
return nmic * sum(mp) + nmaj*sum(bp);
}
What is the purpose of each variable?
What does nmic * sum(mp) and nmaj*sum(bp) computes?
!!!!
For the example above (at the beginning - N=5, K=2), I debugged the code and wrote for N=5, K=0..2 the value for each variable, hoping to get the idea but no succes. I am going to post them for you, maybe you'll get the idea and then explain to me (I am a novice in algorithmic problems).
Here is it:
variable values for each case
I repeat, I tried for some hours to understand but no succes. And it's not a homework. Thank you!
The code goes like this:
int p = k+1;
p is the number of "parts" in which you divide the days (Ex: Day1 + Day2 = part1, Day 3 + Day4 = part2, Day 5 = part3)
int mp = n/p;
mp is the amount of days the minor part has, in the example is 1 (Day5). It's calculated as the floor of the number of days over the number of parts.
int bp = (n+p-1)/p;
bp is the amount of days in the bigger part, in the example is 2 (Day1 + Day2 or Day3 + Day4). I don't really get the exact math behind but that's what it calculates
int nmaj = n%p;
int nmic = p-nmaj;
nmaj is the number of major parts, in the example is 2 (Day1 + Day2 and Day3 + Day4), the nmic is the number of minor parts (1 for Day5).
nmic * sum(mp) + nmaj*sum(bp);
This just returns the number of minor parts * the accumulated value in minor parts + number of major parts * the accumulated value in major parts
The sum function is just the formula for arithmetic series (Or summation of arithmetic progressions) for the special case of initial element = 1

For Loops for a Time Class

I am trying to write a for loop for a time class. Where if the minutes entered are over 60, 60 is subtracted from the total minutes and hours is incremented by 1 until the final minutes left is less than 60 . I was doing if statements like
if (m > 59){
m = m - 60;
h++;
if (m > 59)... etc..
but that doesn't cover every case and I feel like I should know how to do this for loop but I can't figure it out. Any help would be appreciated, thanks
Well if it doesn't have to be implemented using loops, you could do simply
h = m / 60;
m = m % 60;
It is the fastest and cleanest way to do that, I suppose.
Not really sure whether you want to do anything else inside the loops. If so, this won't help you very much.
Edit:
Here is some explanation of how it works.
What m / 60 does is called integer division. It returns floor of the expression. So for example if m = 131 than m / 60 = 2.
The second expression uses the modulo operator. Basically it finds the reminder after division. Back to our example, m % 60 = 11 since m can be written as m = 60 * 2 + 11 = 131. For further information please refer to wiki.
#Jendas has a good simple answer to the overall problem, but if you want to keep with this format but fix your issue with loops, you could put the whole thing in a while loop instead of individual if statements:
while(m >59)
{
m = m - 60;
h++;
// do anything else you need to take care of
}
// finishing statements
h = 0;
while (m >= 60)
{
m = m - 60;
h++;
}
You probably want to use >= 60 instead of 59.
Also, as Jendas rightly suggested you might want to research a little about the modulus operator '%'

Does opening a file related to the program also stop the program?

I have this program that is supposed to search for perfect numbers.
(X is a perfect number if the sum of all numbers that divide X, divided by 2 is equal to X)
sum/2 = x
Now It has found the first four, which were known in Ancient Greece, so it's not really a anything awesome.
The next one should be 33550336.
I know it is a big number, but the program has been going for about 50 minutes, and still hasn't found 33550336.
Is it because I opened the .txt file where I store all the perfect numbers while the program was running, or is it because I don't have a PC fast enough to run it*, or because I'm using Python?
*NOTE: This same PC factorized 500 000 in 10 minutes (while also running the perfect number program and Google Chrome with 3 YouTube tabs), also using Python.
Here is the code to the program:
i = 2
a = open("perfect.txt", 'w')
a.close()
while True:
sum = 0
for x in range(1, i+1):
if i%x == 0:
sum += x
if sum / 2 == i:
a = open("perfect.txt", 'a')
a.write(str(i) + "\n")
a.close()
i += 1
The next one should be 33550336.
Your code (I fixed the indentation so that it does in principle what you want):
i = 2
a = open("perfect.txt", 'w')
a.close()
while True:
sum = 0
for x in range(1, i+1):
if i%x == 0:
sum += x
if sum / 2 == i:
a = open("perfect.txt", 'a')
a.write(str(i) + "\n")
a.close()
i += 1
does i divisions to find the divisors of i.
So to find the perfect numbers up to n, it does
2 + 3 + 4 + ... + (n-1) + n = n*(n+1)/2 - 1
divisions in the for loop.
Now, for n = 33550336, that would be
Prelude> 33550336 * (33550336 + 1) `quot` 2 - 1
562812539631615
roughly 5.6 * 1014 divisions.
Assuming your CPU could do 109 divisions per second (it most likely can't, 108 is a better estimate in my experience, but even that is for machine ints in C), that would take about 560,000 seconds. One day has 86400 seconds, so that would be roughly six and a half days (more than two months with the 108 estimate).
Your algorithm is just too slow to reach that in reasonable time.
If you don't want to use number-theory (even perfect numbers have a very simple structure, and if there are any odd perfect numbers, those are necessarily huge), you can still do better by dividing only up to the square root to find the divisors,
i = 2
a = open("perfect.txt", 'w')
a.close()
while True:
sum = 1
root = int(i**0.5)
for x in range(2, root+1):
if i%x == 0:
sum += x + i/x
if i == root*root:
sum -= x # if i is a square, we have counted the square root twice
if sum == i:
a = open("perfect.txt", 'a')
a.write(str(i) + "\n")
a.close()
i += 1
that only needs about 1.3 * 1011 divisions and should find the fifth perfect number in a couple of hours.
Without resorting to the explicit formula for even perfect numbers (2^(p-1) * (2^p - 1) for primes p such that 2^p - 1 is prime), you can speed it up somewhat by finding the prime factorisation of i and computing the divisor sum from that. That will make the test faster for all composite numbers, and much faster for most,
def factorisation(n):
facts = []
multiplicity = 0
while n%2 == 0:
multiplicity += 1
n = n // 2
if multiplicity > 0:
facts.append((2,multiplicity))
d = 3
while d*d <= n:
if n % d == 0:
multiplicity = 0
while n % d == 0:
multiplicity += 1
n = n // d
facts.append((d,multiplicity))
d += 2
if n > 1:
facts.append((n,1))
return facts
def divisorSum(n):
f = factorisation(n)
sum = 1
for (p,e) in f:
sum *= (p**(e+1) - 1)/(p-1)
return sum
def isPerfect(n):
return divisorSum(n) == 2*n
i = 2
count = 0
out = 10000
while count < 5:
if isPerfect(i):
print i
count += 1
if i == out:
print "At",i
out *= 5
i += 1
would take an estimated 40 minutes on my machine.
Not a bad estimate:
$ time python fastperf.py
6
28
496
8128
33550336
real 36m4.595s
user 36m2.001s
sys 0m0.453s
It is very hard to try and deduce why this has happened. I would suggest that you run your program either under a debugger and test several iteration manually to check if the code is really correct (I know you have already calculated 4 numbers but still). Alternatively it would be good to run your program under a python profiler just to see if it hasn't accidentally blocked on a lock or something.
It is possible, but not likely that this is an issue related to you opening the file while it is running. If it was an issue, there would have probably been some error message and/or program close/crash.
I would edit the program to write a log-type output to a file every so often. For example, everytime you have processed a target number that is an even multiple of 1-Million, write (open-append-close) the date-time and current-number and last-success-number to a log file.
You could then Type the file once in a while to measure progress.

How do you use the "%" operator in C++?

I have to take a number of days and convert them into weeks and days.
I know I have to use the % operator, but how do I use it?
% is the modulo (remainder) operator. In your case, try:
int weeks = total_days / 7;
int remaining_days = total_days % 7;
Odd how when people asking a question say "I know", they're often wrong. You don't need modulus (%) at all.
int weeks = total_days / 7;
printf("%d days is equal to %d weeks and %d days.\n",
total_days, weeks, total_days - weeks*7);
Actually you can divide the total number of days by 7 and you will get the weeks.
THen you can perform modulo on total number of days with 7 and you get the days remaining.
Is this not enough
% (modulus operator) gives you the remainder. So days % 7 will give you the amount of days left after converting to weeks. i.e. if days = 15, then days % 7 would equal 1.