Table reservation given the start and end time - multidimensional-array

Here is a problem that was given to me as part of an online technical screening test on hackerearth. I don't remember the question word to word but will do my best in detailing out the problem
Problem:
Imagine that you own a restaurant. You need to find the number of tables required to accommodate all the reservations. The reservation array consists of start time and end time.
For eg: {{0,10},{5,20}}. So there are 2 reservations. First one starts at time 0 and ends at time 10. Second reservation starts at time 5 and ends at time 20. So in order to accommodate both the reservations we need 2 tables(since both the reservations overlap)
Test Case:
Input: {{5,10},{0,20},{25,40},{35,45}}
Output: 2
Explanation: Table 1 {0,20} {25,40},
Table 2 {5,10} {35,45}
Constraints:
Array is not sorted.
If the end time of one reservation is the same as the start time of some other reservation then consider that extra table is not required
Do not account for a no show scenario
The solution that I came up with looked like this:
I first sorted the array as per the start time
Then I compared the end time with the next remaining start times. If the end time is greater than the start time then increment the number of tables required.
Here is the code:
int[][] reservationStartEndTimes = {{3,7}, {19,23}, {31,41}, {1,9}, {4,16}};
Arrays.sort(reservationStartEndTimes, (a,b) -> Integer.compare(a[0], b[0]));
int tables = 0;
for(int i=0; i<reservationStartEndTimes.length-1; i++) {
for(int j=i+1; j<reservationStartEndTimes.length; j++) {
if(reservationStartEndTimes[i][1] > reservationStartEndTimes[j][0]){
tables++;
}
}
}
System.out.println(tables);
However except for the above test case, all the test cases failed for this logic and the other test cases were hidden. I have tried googling the solution but did not find anything useful. Can someone help in understanding what is wrong here and what the correct solution will be?

I also given same problem in one of the coding round on hacker earth. For me also the hidden test cases did not worked. I had not sorted the array and i believe that could be the reason.
Here is my code.
int[][] reservationStartEndTimes = {{ 0, 20 }, { 25, 40 }, { 5, 10 }, { 35, 25 }};
List<Integer> tables = new ArrayList<>();
Arrays.sort(reservationStartEndTimes, (a, b) -> Integer.compare(a[0], b[0]));
for (int row = 0; row < reservationStartEndTimes.length; row++) {
int startTime = reservationStartEndTimes[row][0];
int endTime = reservationStartEndTimes[row][1];
int time = endTime - startTime;
boolean reserved = false;
for (int i = 0; i < tables.size(); i++) {
if (tables.get(i) < startTime) {
tables.set(i, tables.get(i) + time);
reserved = true;
break;
}
}
if (!reserved)
tables.add(time);
}
System.out.println("Total Table required: "+tables.size());

Related

Finding the row of an object

I'm trying to create a procedural shape made up of quads.
I want to be able to take any quad and use it's index to find the row that it is in.
Take quad 9 from the image. What sort of function can I use to find the row (in this case it is 2 from a 0-index). What about quad 20?
The rows always change in width by 2 quads, one removed from each side.
Sorry it's a bit convoluted but I'm not sure how to approach the problem.
Assume diameter d and quad number q. I claim the rows go 0 to d-1. Moreover, there are (d/2)(2+d) elements. The easier case is if 0<=q<(d/4)(2+d) in which case we are in the first half. Then the index is trunc((-1+sqrt(1+4*q))/2). This comes from using the observation that row n begins with n(n+1) which could be formally shown with the sum of an arithmetic series, then working backwards and solving the quadratic equation.
On the other hand, if we are in the second half (d/4)(2+d)<=q<(d/2)(2*d) and we solve by taking the offset from the end. Let q' be (d/2)(2+d)-1-q. Apply the above index formula to q' instead of q, and subtract the result from d-1 to get the index of q's row.
I may be off by one here or there, but I think this is the gist of it.
I was thinking since this was posted to a programming site, maybe it would be more logical to give a function one could implement without pulling out a lot of math, and instead just relying on addition. I think it would be easier to follow and harder to mess up (though maybe I underestimate my capability to mess up, and I almost did).
var quadRowIndex = function (diameter, quadNumber) {
//diameter should be a positive even number
//quadNumber should be between 0 and index of last number in last row (inclusive)
var quadIndex = 0; //holds the RowIndex, which the function will return once the row contains quadNumber
var rowStartNum = 0;
var rowLength = 2;
//iterate through first half
while (rowLength <= diameter) {
rowStartNum += rowLength;
if (rowStartNum > quadNumber) {
return quadIndex;
}
quadIndex++;
rowLength += 2;
}
rowLength -= 2;
//iterate through second half if still here
while (rowLength >= 2) {
rowStartNum += rowLength;
if (rowStartNum > quadNumber) {
return quadIndex;
}
quadIndex++;
rowLength -= 2;
}
//still here -- number was too high, return error signal
return -1;
};
console.log(quadRowIndex(6, 9));
console.log(quadRowIndex(6, 20));
console.log(quadRowIndex(6, 100));

Function to generate randomly incrementing number over time

I'm trying to make a fake download count. It should increment randomly over time. Some download-count-like patterns would be nice.
Is this possible without using a database, or storing a counter anywhere?
My idea is to check the number of seconds that have passed since my app was released. Then just throw that into a formula which spits out the fake download count. Users can request to see the download count at any time.
Is there a math function that increments randomly? I could just pass my secondsPassed into there and scale it how I'd like.
Something like this: getDownloadCount(secondsPassed)
Edit: here's an example solution. But it gets worse performance over time.
downloadCount = 0
loop secondsPassed/60 times // Loop one more time for every minute passed
downloadCount += seededRandom(0, 10)
Making a fake download count doesn't sound like a nice thing to do. However in designing secure communication protocols, there are legitimate use cases for monotonically growing functions with some randomness in their values.
I am assuming you have:
A growth model given as a monotonically growing function providing approximate values for the desired function.
Access to a time stamp, which never decreases.
Ability to store a constant random seed along with the function definition.
No way to store any updated data upon the function being queried.
First you decide on a window length, which will control how much randomness will be in the final output. I expect you will want this to be on the order of one hour or a few.
Figure out which window the current time is within. Evaluate the reference function at the start and end of this window. Consider the rectangle given by start and end time of the window as well as min and maximum value given by the reference function. Feed the corners of this rectangle and your constant seed into a PRNG. Use the PRNG to choose a random point within the rectangle. This point will be on the final curve.
Perform the same computation for one of the neighbor windows. Which neighbor window to use depend on whether the first computed point on the curve is to the left or the right of the current time.
Now that you have two points on the curve (which are reproducible and consistent), you will have to iterate the following procedure.
You are given two points on the final curve. Consider the rectangle given by those corners. Feed the corners and your constant seed into a PRNG. Use that PRNG to chose a random point within the rectangle. This point will be on the final curve. Discard one of the outer points, which is no longer needed.
Since the Y-values are restricted to integers, this procedure will eventually terminate once your two points on the curve have identical Y-coordinate, and you will know, that the function has to be constant between those two points.
You could implement a Morris Counter.
It works like this: start off by setting the counter to 1. Each time you want to increase the count (which could be every iteration of some loop or every time an event happens, but does not need to be determined randomly), then you do a random procedure to determine the effect it has on the counter.
It can have possibly no effect, or it can have the effect of raising the order of magnitude of the count. The probability is based on whether or not n successive fair coin flips all turn up heads, where n is the number of bits needed to encode the current counter value in binary. As a result, once the counter has gotten pretty high, it's very hard to make it go even higher (the state of the counter models a phenomenon where by you are already way overestimating the count, so now you need lots of nothing-happens events to compensate, making the count more accurate).
This is used as a cheap way to store an approximate count of a very large collection, but there's no reason why you can't use it as your randomly increasing counter device.
If you want better accuracy, or you want the count outputs to be more "normal" numbers instead of always powers of 2, then you can just create several Morris Counters, and at each step average together the set of current counts across them all.
You are after a sequence which always increases by a random amount, depending on how long you last requested the sequence.
This can be done through a random sequence that is always seeded the same.
Then we iterate through the same sequence each time to get the graph.
We need a function that increments our counter, store the new Time and Count and return the count.
Ideally we would model the increases as a poisson process, but a linear one here will do.
class Counter {
private static int counter = 0;
private static int time = 0;
private static double rate = 5.0;
private Random r;
public Counter(int seed){
counter = 0;
r = new Random(seed);
}
private int poisson(double rate, int diff){
// We're gonna cheat here and sample uniformly
return r.Next(0, (int)Math.Round(rate * diff));
}
public int getNext(int t){
var diff = t - time;
time = t;
if (diff <= 0) return counter;
counter += this.poisson(rate, diff);
return counter;
}
}
void Main()
{
var c = new Counter(1024);
for(var i = 0; i< 10; i++){
Console.WriteLine(String.Format("||{0}\t|{1}\t||",i,c.getNext(i)));
}
}
This outputs (for example):
||t |hit||
||0 |0 ||
||1 |3 ||
||2 |4 ||
||3 |6 ||
||4 |6 ||
||5 |8 ||
||6 |10 ||
||7 |13 ||
||8 |13 ||
||9 |16 ||
For some deterministic function f, (perhaps f(x) = x, or if your fake app is REALLY awesome f(x) = 2^x), and a random function r which outputs random number that's sometimes negative and sometimes positive.
Your graphing function g could be:
g(x) = f(x) + r
EDIT
How about this: https://gamedev.stackexchange.com/questions/26391/is-there-a-family-of-monotonically-non-decreasing-noise-functions
Well it's not "random" but you could use A*(X/B + SIN(X/B)) (scaled by some number) to introduce some noise. You can adjust A and B to change the scale of the result and how often the "noise" cycles.
Really, any periodic function that has a first derivative within some bounds could work.
as quick solution you can use something like this (code in java):
static long f(final int x) {
long r = 0; // initial counter
long n = 36969L; // seed
for (int i = 0; i <= x; i++) {
n = 69069L * n + 1234567L; // generate Ith random number
r += (n & 0xf); // add random number to counter
}
return r;
}
by playing with numbers 36969L and 0xf you can achieve different results
numbers 69069L and 1234567L are from standard LCG
the main idea - create simple random, with the same seed and for every passed x (number of seconds) replay random additions to counter
A good model for random events like downloads is the Poisson distribution. You need to estimate the average number of downloads in a given time period (hour, say) and then invert the Poisson distribution to get the number of downloads in a time period given a uniformly distributed random number. For extra realism you can vary the average according to time of day, time of week, etc. Sample algorithms are available at http://en.m.wikipedia.org/wiki/Poisson_distribution#Generating_Poisson-distributed_random_variables.
Here is a javascript implementation of a "fake" download-counter that appears the same to everyone. This always returns the same results for everyone each time and doesn't require database or files to do that. It also gracefully handles the case where you don't ask for new data at the same time, it will still look natural next time you request a day.
https://jsfiddle.net/Lru1tenL/1/
Counter = {
time:Date.now(),
count:0,
rate:0.45
};
Counter.seed = function(seed, startTime)
{
this.time = startTime,
this.count = 0,
this.prng = new Math.seedrandom(seed);
this.prng.getRandomInt = function(min, max) {
return Math.floor(this() * (max - min)) + min;
};
};
Counter.getNext = function(t){
var diff = t - this.time;
console.log(diff);
if(diff <= 0) return this.count;
this.time = t;
var max = Math.ceil(diff/100 * this.rate);
console.log("max: " + max);
this.count += this.prng.getRandomInt(0,max);
return this.count;
};
var results = [];
var today = Date.now();
Counter.seed("My Random Seed", today);
for (var i = 0; i < 7; i++) {
if(i === 4)
{
results.push(null);
} else {
var future = today + 86400000 * i;
results.push(Counter.getNext(future));
}
}
console.log(results);
var data = {
labels: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday","Sunday"],
datasets: [
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: results
}
]
};
var ctx = document.getElementById("myChart").getContext("2d");
var myLineChart = new Chart(ctx).Line(data);
Is the javascript. It creates a counter object that increments when requested based on the time of the previous value asked for. The repeatability comes through a thirdparty library "seedrandom" and the chart is drawn using chartjs.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.0/seedrandom.min.js">
</script>
<body>
<canvas id="myChart" width="600" height="400"></canvas>
</body>
</html>
You can use Unix timestamp. Something like:
Downloads = constant + ( unix time / another constant )
You can vary both constants to get a reasonable number.
P.S: Thats if you want a linear function, otherwise you can do:
Downloads = (unix time) ^ constant
and so on.

Faster database access by index

I have this code
using (var contents = connection.CreateCommand())
{
contents.CommandText = "SELECT [subject],[note] FROM tasks";
var r = contents.ExecuteReader();
int zaehler = 0;
int zielzahl = 5;
while (r.Read())
{
if (zaehler == zielzahl)
{
//access r["subject"].ToString()
}
zaehler++;
}
}
I want to make it faster by accessing zielzahl directly like r[zielzahl] instead of iterating through all entries. But
r[zielzahl]["subject"]
does not work aswell as
r["subject"][zielzahl]
How do I access the column subject of result number zielzahl?
To get only the sixth record, use the OFFSET clause:
SELECT subject, note
FROM tasks
LIMIT 1 OFFSET 5
Please note that the order of returned records is not guaranteed unless you use the ORDER BY clause.

How to calculate this time?

I want to show some effect (animate) with the help of jQuery during the time that should be calculated based on how many results are found for a particular needle. The rule is that the effect should continue no longer than 5 minutes and at the very least be 5 seconds long.
So, here's what I do in particular. I search a database for a particular word the user inputs and count the results. Then I search a myself defined word in the same database and count the results. If there are more the latter results than the former results, I need to calculate how long to show the effect. The more the latter results found, the longer the time the effect should continue. Plus, I need to obey the rule: no longer than 5 minutes, no less than 5 seconds.
I need that to be accurate at best.
That may be a stupid question but I cannot figure out on my own how to calculate the time! :)
http://jsfiddle.net/rCVnv/3/
$(function(){
var firstNum = Math.random()*10000,
secondNum = Math.random()*10000,
result = parseInt(secondNum - firstNum),
milli = 0;
if(result > 0){
if(result < 300000 && result > 5000){
milli = result;
$("#test").fadeOut(result);
}else if(result > 300000){
milli = 300000;
}else if(result < 5000){
milli = 5000;
}
$("#test").fadeOut(milli);
}
$("#result").text("Result : " + result);
});
Im not really sure how you will calculate the milliseconds needed. What I do here is generate 2 random numbers, and subtract the first value from the second value. If the result is between 300000 milliseconds (5 minutes) and 5000 milliseconds, then it just fades it at that number. If it falls beyond those ranges, it sets it to either the high end or low end. Of course, if the result is negative nothing happens because value 1 was larger than value 2.
Also I used fadeOut, which can easily be replaced with animate.
var intSecondsPerResult = 2;
var intAnimationDuration = intSecondsPerResult*{$intResultsCount};
if(intAnimationDuration < 5) {
intAnimationDuration = 5;
} else if(intAnimationDuration > 300) {
intAnimationDuration = 300;
}
PS: $intResultsCount contains the size of your resultset
That is what you want?

display records which exist in file2 but not in file1

log file1 contains records of customers(name,id,date) who visited yesterday
log file2 contains records of customers(name,id,date) who visited today
How would you display customers who visited yesterday but not today?
Constraint is: Don't use auxiliary data structure because file contains millions of records. [So, no hashes]
Is there a way to do this using Unix commands ??
an example, but check the man page of comm for the option you want.
comm -2 <(sort -u yesterday) <(sort -u today)
The other tool you can use is diff
diff <(sort -u yesterday) <(sort -u today)
I was personally going for the creating a data structure and records of visits, but, I can see how you'd do it another way too.
In pseudocode, that looks something like python but could be re-written in perl or shell script or ...
import subprocess
import os
for line in fileinput.input(['myfile'])::
# split out data. For the sake of it I'm assuming name\tid\tdate
fields = line.split("\")
id = fields[1]
grepresult = subprocess.Popen("grep \"" + id + "\" file1", shell=True, bufsize=bufsize, stdout=PIPE).stdout
if len(grepresult) == 0:
print fields # it wasn't in field1
That's not perfect, not tested so treat appropriately but it gives you the gist of how you'd use unix commands. That said, as sfussenegger points out C/C++ if that's what you're using should be able to handle pretty large files.
Disclaimer: this is a not so neat solution (repeatedly calling grep) to match the requirements of the question. If I was doing it, I would use C.
Is a customer identified by id? Is it an int or long? If the answer to both questions is yes, an array with 10,000,000 integers shouldn't take more than 10M*4 = 40MB memory - not a big deal on decent hardware. Simply sort and compare them.
btw, sorting an array with 10M random ints takes less than 2 seconds on my machine - again, nothing to be afraid of.
Here's some very simple Java code:
public static void main(final String args[]) throws Exception {
// elements in each log file
int count = 10000000;
// "read" our log file
Random r = new Random();
int[] a1 = new int[count];
int[] a2 = new int[count];
for (int i = 0; i < count; i++) {
a1[i] = Math.abs(r.nextInt());
a2[i] = Math.abs(r.nextInt());
}
// start timer
long start = System.currentTimeMillis();
// sort logs
Arrays.sort(a1);
Arrays.sort(a2);
// counters for each array
int i1 = 0, i2 = 0, i3 = 0;
// initial values
int n1 = a1[0], n2 = a2[0];
// result array
int[] a3 = new int[count];
try {
while (true) {
if (n1 == n2) {
// we found a match, save value if unique and increment counters
if (i3 == 0 || a3[i3-1] != n1) a3[i3++] = n1;
n1 = a1[i1++];
n2 = a2[i2++];
} else if (n1 < n2) {
// n1 is lower, increment counter (next value is higher)
n1 = a1[i1++];
} else {
// n2 is lower, increment counter (next value is higher)
n2 = a2[i2++];
}
}
} catch (ArrayIndexOutOfBoundsException e) {
// don't try this at home - it's not the pretties way to leave the loop!
}
// we found our results
System.out.println(i3 + " commont clients");
System.out.println((System.currentTimeMillis() - start) + "ms");
}
result
// sample output on my machine:
46308 commont clients
3643ms
as you see, quite efficient for 10M records in each log

Resources