work out how many seconds have expired in total during game play - algorithm

~Why the hell has this had down votes.... you people are weird!
Ok so this is a very simply HTML5 and jQuery and PHP game. Sorry to the people who have answered, I forgot to say this is a php script, i have updated here to reflect.
the first level takes 1 minute. Every level after that takes an extra 10 seconds than the last level. like so;
level 1 = 60 seconds
level 2 = 70 seconds
level 3 = 80 seconds
level 4 = 90 seconds
and so on infinitely.
I need an equation that can figure out what is the total amount of seconds played based on the users level.
level = n
i started with (n * 10) + (n * 60) but soon realized that that doesn't account for the last level already being 10 seconds longer than the last. I have temporarily fixed it using a function calling a foreach loop stopping at the level number and returning the value. but i really want an actual equation.
SO i know you wont let me down :-)
Thanks in advance.
this is what i am using;
function getnumberofsecondsfromlevel($level){
$lastlevelseconds = 60;
while($counter < $level){
$totalseconds = $lastlevelseconds+$totalseconds;
$lastlevelseconds = $lastlevelseconds + 10;
$counter++;
}
return $totalseconds;
}
$level = $_SESSION['**hidden**']['thelevel'];
$totaldureationinseconds = getnumberofsecondsfromlevel($level);
but i want to replace with an actual equation
like so;(of course this is wrong, this is just the example of the format i want it in i.e an equation)
$n = $_SESSION['**hidden**']['thelevel']; (level to get total value of
in seconds)
$s = 60; (start level)
$totaldureationinseconds = ($n * 10) + ($s * $n);
SOLVED by Gopalkrishna Narayan Prabhu :-)
$totalseconds = 60 * $level + 5* (($level-1) * $level);

var total_secs = 0;
for(var i = 1; i<= n ;i++){
total_secs = total_secs + (i*10) + 50;
}
for n= 1, total_secs = 0 + 10 + 50 = 60
for n= 2, total_secs = 60 + 20 + 50 = 130
and so on...
For a single equation:
var n = level_number;
total_secs = 60 * n + 5* ((n-1) * n);
Hope this helps.

It seems as though you're justing looking for the equation
60 + ((levelN - 1) * 10)
Where levelN is the current level, starting at 1. If you make the first level 0, you can get rid of the - 1 part and make it just
60 + (levelN * 10)
Thought process:
What's the base/first number? What's the lowest it can ever be? 60. That means your equation will start with
60 + ...
Every time you increase the level, you add 10, so at some point you'll need something like levelN * 10. Then, it's just some fiddling. In those case, since you don't add any on the first left, and the first level is level 1, you just need to subtract 1 from the level number to fix that.

You can solve this with a really simple mathematical phrase (with factorial).
((n-1)! * 10) + (60 * n)
n is the level ofcourse.

Related

Ruby algorithms loops codewars

I got stuck with below task and spent about 3 hours trying to figure it out.
Task description: A man has a rather old car being worth $2000. He saw a secondhand car being worth $8000. He wants to keep his old car until he can buy the secondhand one.
He thinks he can save $1000 each month but the prices of his old car and of the new one decrease of 1.5 percent per month. Furthermore this percent of loss increases by 0.5 percent at the end of every two months. Our man finds it difficult to make all these calculations.
How many months will it take him to save up enough money to buy the car he wants, and how much money will he have left over?
My code so far:
def nbMonths(startPriceOld, startPriceNew, savingperMonth, percentLossByMonth)
dep_value_old = startPriceOld
mth_count = 0
total_savings = 0
dep_value_new = startPriceNew
mth_count_new = 0
while startPriceOld != startPriceNew do
if startPriceOld >= startPriceNew
return mth_count = 0, startPriceOld - startPriceNew
end
dep_value_new = dep_value_new - (dep_value_new * percentLossByMonth / 100)
mth_count_new += 1
if mth_count_new % 2 == 0
dep_value_new = dep_value_new - (dep_value_new * 0.5) / 100
end
dep_value_old = dep_value_old - (dep_value_old * percentLossByMonth / 100)
mth_count += 1
total_savings += savingperMonth
if mth_count % 2 == 0
dep_value_old = dep_value_old - (dep_value_old * 0.5) / 100
end
affordability = total_savings + dep_value_old
if affordability >= dep_value_new
return mth_count, affordability - dep_value_new
end
end
end
print nbMonths(2000, 8000, 1000, 1.5) # Expected result[6, 766])
The data are as follows.
op = 2000.0 # current old car value
np = 8000.0 # current new car price
sv = 1000.0 # annual savings
dr = 0.015 # annual depreciation, both cars (1.5%)
cr = 0.005. # additional depreciation every two years, both cars (0.5%)
After n >= 0 months the man's (let's call him "Rufus") savings plus the value of his car equal
sv*n + op*(1 - n*dr - (cr + 2*cr + 3*cr +...+ (n/2)*cr))
where n/2 is integer division. As
cr + 2*cr + 3*cr +...+ (n/2)*cr = cr*((1+2+..+n)/2) = cr*(1+n/2)*(n/2)
the expression becomes
sv*n + op*(1 - n*dr - cr*(1+(n/2))*(n/2))
Similarly, after n years the cost of the car he wants to purchase will fall to
np * (1 - n*dr - cr*(1+(n/2))*(n/2))
If we set these two expressions equal we obtain the following.
sv*n + op - op*dr*n - op*cr*(n/2) - op*cr*(n/2)**2 =
np - np*dr*n - np*cr*(n/2) - np*cr*(n/2)**2
which reduces to
cr*(np-op)*(n/2)**2 + (sv + dr*(np-op))*n + cr*(np-op)*(n/2) - (np-op) = 0
or
cr*(n/2)**2 + (sv/(np-op) + dr)*n + cr*(n/2) - 1 = 0
If we momentarily treat (n/2) as a float division, this expression reduces to a quadratic.
(cr/4)*n**2 + (sv/(np-op) + dr + cr/2)*n - 1 = 0
= a*n**2 + b*n + c = 0
where
a = cr/4 = 0.005/4 = 0.00125
b = sv/(np-op) + dr + cr/(2*a) = 1000.0/(8000-2000) + 0.015 + 0.005/2 = 0.18417
c = -1
Incidentally, Rufus doesn't have a computer, but he does have an HP 12c calculator his grandfather gave him when he was a kid, which is perfectly adequate for these simple calculations.
The roots are computed as follows.
(-b + Math.sqrt(b**2 - 4*a*c))/(2*a) #=> 5.24
(-b - Math.sqrt(b**2 - 4*a*c))/(2*a) #=> -152.58
It appears that Rufus can purchase the new vehicle (if it's still for sale) in six years. Had we been able able to solve the above equation for n/2 using integer division it might have turned out that Rufus would have had to wait longer. That’s because for a given n both cars would have depreciated less (or at least not not more), and because the car to be purchased is more expensive than the current car, the difference in values would be greater than that obtained with the float approximation for 1/n. We need to check that, however. After n years, Rufus' savings and the value of his beater will equal
sv*n + op*(1 - dr*n - cr*(1+(n/2))*(n/2))
= 1000*n + 2000*(1 - 0.015*n - 0.005*(1+(n/2))*(n/2))
For n = 6 this equals
1000*6 + 2000*(1 - 0.015*6 - 0.005*(1+(6/2))*(6/2))
= 1000*6 + 2000*(1 - 0.015*6 - 0.005*(1+3)*3)
= 1000*6 + 2000*0.85
= 7700
The cost of Rufus' dream car after n years will be
np * (1 - dr*n - cr*(1+(n/2))*(n/2))
= 8000 * (1 - 0.015*n - 0.005*(1+(n/2))*(n/2))
For n=6 this becomes
8000 * (1 - 0.015*6 - 0.005*(1+(6/2))*(6/2))
= 8000*0.85
= 6800
(Notice that the factor 0.85 is the same in both calculations.)
Yes, Rufus will be able to buy the car in 6 years.
def nbMonths(old, new, savings, percent)
percent = percent.fdiv(100)
current_savings = 0
months = 0
loop do
break if current_savings + old >= new
current_savings += savings
old -= old * percent
new -= new * percent
months += 1
percent += 0.005 if months.odd?
end
[months, (current_savings + old - new).round]
end

Algorithm needed to calculate difference between two times

I have an hour selection drop down 0-23 and minutes selection drop down 0-59 for Start time and End time respectively (so four controls).
I'm looking for an algorithm to calculate time difference using these four values.
Since they're not stored in fancy date/time selection controls, I don't think I can use any standard date/time manipulation functions.
How do I calculate the difference between the two times?
This pseudo-code gives you the algorithm to work out the difference in minutes. It assumes that, if the start time is after the end time, the start time was actually on the previous day.
const MINS_PER_HR = 60, MINS_PER_DAY = 1440
startx = starthour * MINS_PER_HR + startminute
endx = endhour * MINS_PER_HR + endminute
duration = endx - startx
if duration < 0:
duration = duration + MINS_PER_DAY
The startx and endx values are the number of minutes since midnight.
This is basically doing:
Get number of minutes from start of day for start time.
Get number of minutes from start of day for end time.
Subtract the former from the latter.
If result is negative, add number of minutes in a day.
Don't be so sure though that you can't use date/time manipulation functions. You may find that you could easily construct a date/time and calculate differences with something like:
DateTime startx = new DateTime (1, 1, 2010, starthour, startminute, 0);
DateTime endx = new DateTime (1, 1, 2010, endhour , endminute , 0);
Integer duration = DateTime.DiffSecs(endx, startx) / 60;
if (duration < 0)
duration = duration + 1440;
although it's probably not needed for your simple scenario. I'd stick with the pseudo-code I gave above unless you find yourself doing some trickier date/time manipulation.
If you then want to turn the duration (in minutes) into hours and minutes:
durHours = int(duration / 60)
durMinutes = duration % 60 // could also use duration - (durHours * 60)
This will compute duration in minutes including the year as factor
//* Assumptions:
Date is in Julian Format
startx = starthour * 60 + startminute
endx = endhour * 60 + endminute
duration = endx - startx
if duration <= 0:
duration = duration + 1440
end-if
if currday > prevday
duration = duration + ((currday-preday) - 1 * 1440)
end-if
First you need to check to see if the end time is greater than or equal to the start time to prevent any problems. To do this you first check to see if the End_Time_Hour is greater than Start_Time_Hour. If they're equal you would instead check to see if End_Time_Min is greater than or equal to Start_Time_Min.
Next you would subtract Start_Time_Hour from End_Time_Hour. Then you would subtract Start_Time_Min from End_Time_Min. If the difference of the minutes is less than 0 you would decrement the hour difference by one and add the minute difference to 60 (or 59, test that). Concat these two together and you should be all set.
$start_time_hr = 5;
$start_time_mi = 50;
$end_time_hr = 8;
$end_time_mi = 30;
$diff = (($end_time_hr*60)+$end_time_mi) - (($start_time_hr*60)+$start_time_mi);
$diff_hr = (int)($diff / 60);
$diff_mi = (int)($diff) - ($diff_hr*60);
echo $diff_hr . ':' . $diff_mi;
simple equation should help:
mindiff = 60 + endtime.min - starttime.min
hrdiff = ((mindiff/60) - 1) + endtime.hr - starttime.hr
This gives you the duration in hours and minutes
h1 = "hora1"
m1 "min1"
h2 "hora2"
m2 = "min2"
if ( m1 > m2)
{
h3 = (h2 - h1) - 1;
}
else
{
h3 = h2 - h1;
}
m1 = 60 - m1;
if (m1 + m2 >= 60)
{
m3 = 60 - (m1 + m2);
} else if (m3 < 0)
{
m3 = m3 * -1;
}
else
{
m3 = m1 + m2;
}
System.out.println("duration:" + h3 + "h" + m3 + "min");
If you have a function that returns the number of days since some start date (e.g. dayssince1900) you can just convert both dates to seconds since that start date, do the ABS(d1-d2) then convert the seconds back to whatever format you want e.g. HHHH:MM:SS
Simple e.g.
SecondsSince1900(d)
{
return dayssince1900(d)*86400
+hours(d)*3600
+minutes(d)*60
+seconds(d);
}
diff = ABS(SecondsSince1900(d1)-SecondsSince1900(d2))
return format(diff DIV 3600)+':'+format((diff DIV 60) MOD 60)+':'+format(diff MOD 60);
Hum: Not that simple if you have to take into account the leap seconds astronomers are keen to put in from time to time.

Non-linear counter

So I have a counter. It is supposed to calculate the current amount of something. To calculate this, I know the start date, and start amount, and the amount to increment the counter by each second. Easy peasy. The tricky part is that the growth is not quite linear. Every day, the increment amount increases by a set amount. I need to recreate this algorithmically - basically figure out the exact value at the current date based on the starting value, the amount incremented over time, and the amount the increment has increased over time.
My target language is Javascript, but pseudocode is fine too.
Based on AB's solution:
var now = new Date();
var startDate1 = new Date("January 1 2010");
var days1 = (now - startDate1) / 1000 / 60 / 60 / 24;
var startNumber1 = 9344747520;
var startIncrement1 = 463;
var dailyIncrementAdjustment1 = .506;
var currentIncrement = startIncrement1 + (dailyIncrementAdjustment1 * days1);
startNumber1 = startNumber1 + (days1 / 2) * (2 * startIncrement1 + (days1 - 1) * dailyIncrementAdjustment1);
Does that look reasonable to you guys?
It's a quadratic function. If t is the time passed, then it's the usual at2+bt+c, and you can figure out a,b,c by substituting the results for the first 3 seconds.
Or: use the formula for the arithmetic progression sum, where a1 is the initial increment, and d is the "set amount" you refer to. Just don't forget to add your "start amount" to what the formula gives you.
If x0 is the initial amount, d is the initial increment, and e is the "set amount" to increase the incerement, it comes to
x0 + (t/2)*(2d + (t-1)*e)
If I understand your question correctly, you have an initial value x_0, an initial increment per second of d_0 and an increment adjustment of e per day. That is, on day one the increment per second is d_0, on day two the increment per second is d_0 + e, etc.
Then, we note that the increment per second at time t is
d(t) = d_0 + floor(t / S) * e
where S is the number of seconds per day and t is the number of seconds that have elapsed since t = t_0. Then
x = x_0 + sum_{k < floor(t / S)} S * d(k) + S * (t / S - floor(t / S)) * d(t)
is the formula that you are seeking. From here, you can simplify this to
x = x_0 + S * floor(t / S) d_0 + S * e * (floor(t / S) - 1) * floor(t / S) / 2.
use strict; use warnings;
my $start = 0;
my $stop = 100;
my $current = $start;
for my $day ( 1 .. 100 ) {
$current += ($day / 10);
last unless $current < $stop;
printf "Day: %d\tLeft %.2f\n", $day, (1 - $current/$stop);
}
Output:
Day: 1 Left 1.00
Day: 2 Left 1.00
Day: 3 Left 0.99
Day: 4 Left 0.99
Day: 5 Left 0.98
...
Day: 42 Left 0.10
Day: 43 Left 0.05
Day: 44 Left 0.01

Programming an algebra equation

in another post, MSN gave me a good guide on solving my algebra problem (Calculating bid price from total cost). Now, even though I can calculate it by hand, I'm completely stuck on how to write this in pseudocode or code. Anyone could give me a quick hint? By the way, I want to calculate the bid given the final costs .
usage cost(bid) = PIN(bid*0.10, 10, 50)
seller cost(bid) = bid*.02
added cost(bid) = PIN(ceiling(bid/500)*5, 5, 10) + PIN(ceiling((bid - 1000)/2000)*5, 0, 10)
storing cost(bid) = 100
So the final cost is something like:
final cost(bid) = PIN(bid*.1, 10, 50) + pin(ceiling(bid/500)*5, 5, 20) + PIN(ceiling((bid - 1000)/2000)*10, 0, 20) + bid*.02 + 100 + bid
Solve for a particular value and you're done.
For example, if you want the total cost to be $2000:
2000 = PIN(bid*.1, 10, 50) + pin(ceiling(bid/500)*5, 5, 10) + PIN(ceiling((bid - 1000)/2000)*5, 0, 10) + bid*.02 + 100 + bid.
Bid must be at least > 1500 and < 2000, which works out nicely since we can make those PIN sections constant:
2000 = 50 + 10 + 5 + 100 + bid*1.02
1835 = bid*1.02
bid = 1799.0196078431372549019607843137
The function simplifies to:
/ 1.02 * bid + 115 bid < 100
| 1.12 * bid + 105 bid <= 500
final cost(bid) = | 1.02 * bid + 160 bid <= 1000
| 1.02 * bid + 165 bid <= 3000
\ 1.02 * bid + 170 otherwise
If you consider each piece as a separate function, they can be inverted:
bid_a(cost) = (cost - 115) / 1.02
bid_b(cost) = (cost - 105) / 1.12
bid_c(cost) = (cost - 160) / 1.02
bid_d(cost) = (cost - 165) / 1.02
bid_e(cost) = (cost - 170) / 1.02
If you plug your cost into each function you get an estimated bid value for that range. You must check that this value indeed is within that functions valid range.
Example:
cost = 2000
bid_a(2000) = (2000 - 115) / 1.02 = 1848 Too big! Need to be < 100
bid_b(2000) = (2000 - 105) / 1.12 = 1692 Too big! Need to be <= 500
bid_c(2000) = (2000 - 160) / 1.02 = 1804 Too big! Need to be <= 1000
bid_d(2000) = (2000 - 165) / 1.02 = 1799 Good. It is <= 3000
bid_e(2000) = (2000 - 170) / 1.02 = 1794 Too small! Need to be > 3000
Just to check:
final cost(1799) = 1.02 * 1799 + 165 = 2000 Good!
Since the original function is strictly increasing, at most one of those functions will give an acceptable value. But for some inputs none of them will give a good value. This is because the original function jumps over those values.
final cost(1000) = 1.02 * 1000 + 160 = 1180
final cost(1001) = 1.02 * 1001 + 165 = 1186
So no function will give an acceptable value for cost = 1182 for example.
Due to the use of PIN and ceiling, I don't see a easy way to invert the calculation. Assuming that bid has a fixed precision (I'd guess two decimals behind the dot) you can always use a binary search (as the functions are monotone).
Edit: After thinking about it some more, I observed that, taking x = bid*1.02 + 100, we have that the final costs are between x+15 (exclusive) and x+70 (inclusive) (i.e. x+15 < final cost < x+70). Given the size of this range (70-15=55) and the fact that the special values (see note below) for bid are all apart more than this, you can take x+15 = final cost and x+70 = final cost, get the right cases/values of usage and added costs and simply solve that equation (which no longer has either PIN or ceiling in it).
To illustrate, let the final cost be 222. From x+15 = 222 it follows that bid = 107/1.02 = 104.90. Then we have that the usage costs are given by bid*0.1 and that the additional costs are 5. In other words, we get final cost = bid*0.1 + bid*0.02 + 5 + 100 + bid = bid*1.12 + 105 and therefore bid = (222-105)/1.12 = 104.46. As this value of bid means the right values for usage and additional costs were taken, we know that this is the solution.
However, if we would have first looked at x+70 = 222, we would get the following. First we get that for this assumption that bid = 52/1.02 = 50.98. This means that usage costs are 10 and the additional costs are 5. So we get final costs = 10 + bid*0.02 + 5 + 100 + bid = bid*1.02 + 115 and therefore bid = (222-115)/1.02 = 104.90. But if bid is 104.90 then the usage costs are not 10 but bid*0.1, so this isn't the right solution.
I hope I explained it clearly enough. If not, please let me know.
N.B.: With special values I mean those for which the function defining the values of usage and added costs change. For example, for usage cost these values are 100 and 500: below 100 you use 10, above 500 you use 50 and in between you use bid*0.1.

Rounding to nearest 100

First number needs to be rounded to nearest second number. There are many ways of doing this, but whats the best and shortest algorithm? Anyone up for a challenge :-)
1244->1200
1254->1300
123->100
178->200
1576->1600
1449->1400
123456->123500
654321->654300
23->00
83->100
Ruby's round method can consume negative precisions:
n.round(-2)
In this case -2 gets you rounding to the nearest hundred.
For input n:
(n + 50) / 100 * 100
using integer division.
Note that many languages/libraries already have functions to do this.
100 * round(n/100.0)
I know it's late in the game, but here's something I generally set up when I'm dealing with having to round things up to the nearest nTh:
Number.prototype.roundTo = function(nTo) {
nTo = nTo || 10;
return Math.round(this * (1 / nTo) ) * nTo;
}
console.log("roundto ", (925.50).roundTo(100));
Number.prototype.ceilTo = function(nTo) {
nTo = nTo || 10;
return Math.ceil(this * (1 / nTo) ) * nTo;
}
console.log("ceilTo ", (925.50).ceilTo(100));
Number.prototype.floorTo = function(nTo) {
nTo = nTo || 10;
return Math.floor(this * (1 / nTo) ) * nTo;
}
console.log("floorTo ", (925.50).floorTo(100));
I find myself using Number.ceilTo(..) because I'm working with Canvas and trying to get out to determine how far out to scale.
This will do it, given you're using integer math:
n = (n + 50) / 100 * 100
Of course, you didn't specify the behavior of e.g., 1350 and 1450, so I've elected to round up. If you need round-to-even, that'll not work.
As per Pawan Pillai's comment above, rounding to nearest 100th in Javascript:
100 * Math.floor((foo + 50) / 100);
Is this homework?
Generally, mod 100, then if >50 add else subtract.

Resources