I wondoner is it possible to implement priority query to solve following question: Suppose there is a school which needs to regulate its maximum current students due to the pandemic. For example, there are 4 lessons on some day, which are 9:00-11:00 with 50 students, 10:00-12:00 with 25 students, 14:00-16:00 with 60 students and 17:00-18:00 with 70 students. Then the maximum current students is 75 because when it is 10:00-11:00 there are 75 students in total taking lessons. My initial idea is to create two priority queue, one takes lesson start time as priority and another takes lesson end time. Can some one give any suggestions about this?
You can create an array where each index will represent an hour. And each element will be an integer representing how many MORE students are allowed in the school during this time.
For example array element with index 0 - represents 00:00, 22 - 23:00.
Then the array for your example will look like that:
[0(0:00),0,0,0,0,0,0,0,0,50(9:00),25(10:00),-50(11:00),-25(12:00),0,60(14:00),0,-60(16:00),70(17:00),-70(18:00),0,0,0,0,0]
And then when you need to know the number of students allowed at particular hour, you need to simply sum the array element up to the particular HOUR(index).
For example for 11:00 it will be 0+0+0+0+0+0+0+0+0+50+25=75.
Or when you insert the elements, you can as well update the rest of the array, to calculate the exact capacity for each hour. Then you don't have to calculate sum every time you need to know the number of allowed students. Your data structure will already content precalculated the values.
The array would look like that:
[0(0:00),0,0,0,0,0,0,0,0,50(9:00),75(10:00),25(11:00),0(12:00),0,60(14:00),0,0(16:00),70(17:00),0(18:00),0,0,0,0,0]
This is a trade of to make between slow selects vs slow inserts.
Related
I am trying to write Java code for the following problem.But I am not able to find out a optimized way to solve this .
I have an array list of time and consumption of coffee as follows. I want to calculate the consumption of coffee every hours and if there is no consumption for a particular hour the next hours first entry will be the total consumption for that hour.
For Example :
I have the following array list
Time consumption of coffee
2:15 5 cups
2:30 6 cups
2:45 7 cups
3:05 2 cups
3:45 6 cups
5:05 1 cups
5:30 2 cups
7:15 1 cup
so I want to calculate what is the total consumption for hour 2 which will be in that case 18 cups from 2:00 to 3:00 .again for 3:00 to 4:00 it will be 8 cups. As there is no entry from 4:00 to 5:00 amount of consumption in that case should be amount of coffee consumed at 5:05 which is 1 cup.I want my result till 7 o'clock. As we don't have anything at 6:00 -7 :00 then it will be 1 cup which was value at 7:15.
So I want a final result of total consumption from 2:00 to 7:00 distributed every hour as array list as following object
obj1 = T<2:00,3:00,18>
obj2 = T<3:00,4:00,8>
obj3 = T<4:00,5:00,1>
obj4 = T<5:00,6:00,3>
obj5 = T<6:00,7:00,1>
finalList = <obj1,obj2,obj3,obj4,obj5>
I am not able to get how to chop the list in hourly way and look at the next value as well.
You completely lost me as to the logic of filling an empty hour with first value from the next hour. But I'll give it a shot anyways.
My approach assumes your input data is in chronological order from earlier to later.
Define a CoffeeConsumption class with two members, LocalTime and Integer for your two values.
Create a Map, perhaps a SortedMap such as TreeMap. The key is of type Integer, and represents the hour of the day from 0 to 23. The value is of type Set, perhaps a SortedSet such as TreeSet to store your custom objects defined above.
For each of you custom objects, grab its LocalTime and call getHour. Use that hour number to find the matching key in the Map, retrieve the Set, and add your item.
To get totals, loop the Map, and loop each Set. To save the totals, create a new SortedMap with Integer as key for hour-of-day and Integer as value for the hour’s total number of cups consumed.
Note that there is no need to save explicitly the end-of-hour time as you showed in your Question. You can always calculate that value: call LocalTime::plusHours( 1 ).
To support that move-first-item-to-previous-hour-if-empty feature, follow the logic I just outlined in that hyphenated title. When adding a coffee object to the Map with no existing key yet put there for that hour, first subtract one from the hour and look in the Map for that subtracted number as key. If the subtracted key is not present in the Map, put it, create a fresh empty Set in which to deposit the coffee object that would otherwise have gone to its own hour. Caveat: This feature has a bad smell and suggests something is wrong with your design or the requirement is misunderstood.
I was recently asked a interview question to find Top N(10,20) integers in a List over a period of time. The List is dynamically added elements over a period of regular interval like 5 seconds. Could you please tell how to use the correct data structure and algorithm for this problem..
Such questions normally are not very sophisticated.
10 highest of last 20 entries: An ArrayList of at most 20 elements, adding at the end may remove one at the beginning. Then add them to a new SortedSet (like TreeSet), and take the first 10 on a reversed order. See #iced
If a Queue would fit, nice. (It does not entirely.) But the most important point is correctness. Seeing you cannot sort that ArrayList. That less than 10 top numbers may appear when many duplicates. Points for adding concurrency guards and such.
You can use Java Priority Queue/ Max heap.
I am working with daily stock price time series.
Each day i need to store 4 types of prices (open, high, low, close).
Whatever data structure I use I need to store it sin sequence (preferably a a date or integer as key to later retrieve any of those prices.
Length: variable can be from 2 to 200
I looked into arrays, ArrayLists, Vectors and Maps.
But I still have the problem that they holed pairs, and what I a looking for is to input 1 date or integer and assign to it 4 prices (string each).
Should I use an array and each element would be a class that has 5 members (date plus four kind of prices), then I create ArrayList, instantiate a new class and input is as an element?
Or is there a faster and less complicated way?
You can create a class lets say: price with four members:
open, high, low, close
Create a hash map with date as key and price class as value.
This way all the four members will have unique value for particular day.
All the value can be retrieved with
price.open and so on......
Suppose I have a list of projects with start date and end date. I also have a range of weeks, which varies (could be over months, years, etc)
I would like to display a graph showing 4 values per week:
projects started
projects closed
total projects started
total projects closed
I could loop over the range of weekly values, and for each week iterate through my list of projects and calculate values for each of these 4 trends per week. This would have algorithmic complexity O(nm), n is the length of list of weeks, and m is the length of projects list. That's not so great.
Is there a more efficient approach, and if so, what would it be?
If it's pertinent, I'm coding in Java
While it is true what user yurib has said there is a more efficient solution. Keep two arrays in memory projects_started and projects_ended, both with size 52. Loop through your list of projects and for each project increment corresponding value in both lists. Something like:
projects_started[projects[i].start_week]++;
projects_ended[projects[i].end_week]++;
After the loop you have all the data you need to make a graph. Complexity is O(m).
EDIT: okay, so maximum number of weeks can vary apparently, but if it's smaller than some ludicrous number (more than say a million) then this algorithm still works. Just replace 52 with n. Time complexity is O(m), space complexity is O(n).
EDIT: in order to determine the value of total projects started and ended you have to iterate through the two arrays that you now have and just add up the values. You could do this while populating the graph:
for (int i = 0; i < n)
{
total_started_in_this_week += projects_started[i];
total_ended_in_this_week += projects_ended[i];
// add new item to the graph
}
I'm not sure what the difference between "project" and "total" is, but here's a simple O(n log n) way to calculate the number of projects started and closed in each week:
For each project, add its start and end points to a list.
Sort the list in increasing order.
Walk through the list, pulling out time points until you hit a time point that occurs in a later week. At this point, "projects started" is the total number of start points you have hit, and "projects ended" is the total number of end points you have hit: report these counters, and reset them both to zero. Then continue on to process the next week.
Incidentally, if there are some weeks without any projects that start or end, this procedure will skip them out. If you want to report these weeks as "0, 0" totals, then whenever you output a week that has some nonzero total, make sure you first output as many "0, 0" weeks as it takes to fill in the gap since the last nonzero-total week. (This is easy to do just by setting a lastNonzeroWeek variable each time you output a nonzero-total week.)
First of all, I guess that actually performance won't be an issue; this looks like a case of "premature optimization". You should first do it, then do it right, then do it fast.
I suggest you use maps, which will make your code more readable and outsources implementation details (like performance).
Create a HashMap from int (representing the week number) to Set<Project>, then iterate over your projects and for each one, put it into the map at the right place. After that, iterate over the map's key set (= all non-empty weeks) and do your processing for each one.
I'm new. I'm writing an app for a laser tag place where we've got kids of many ages coming to shoot beams at each other. We're making a highscore screen that'll display the best scores of the day, of the week, and of the month. The idea is that people will feel proud being on the list, and there'll also be prizes once a month.
I'm getting stuck at the whole filtering by date thing.
I basically modified the classic guestbook example to the point where I can add scores and customer info, and sort them by score.
Key guestbookKey = KeyFactory.createKey("Guestbook", guestbookName);
String fornavn = req.getParameter("fornavn");
Integer score = Integer.parseInt(req.getParameter("score"));
String email = req.getParameter("email");
String tlf = req.getParameter("tlf");
Date date = new Date();
Entity highscore = new Entity("Greeting", guestbookKey);
highscore.setProperty("date", date);
highscore.setProperty("fornavn", fornavn);
highscore.setProperty("score", score);
highscore.setProperty("email", email);
highscore.setProperty("tlf", tlf);
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(highscore);
And in the jsp there's a query that grabs the overall top 5.
Query query = new Query("Highscore", highscoreKey).addSort("score", Query.SortDirection.DESCENDING);
List<Entity> greetings = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(5));
And there's a form that sends the user input to the .java. Any tips as far as how I should set up the dates? Saving week # and month # and querying based on that? Seems cumbersome.
From what I can tell, your "HighScore" kind is actually a "Score" kind that keeps track of all scores.
Instead of querying for the high score for the week/month, you're probably better off having a single HighScore entity (that's separate from normal "Score" entities) that you update whenever you enter a score. Every time a new score is entered, check if the high score should be updated.
You never need a fancy query, you just need to fetch the high score entity.
Or you might want a separate high score entity for each month/week etc so you can keep track of the history. In this case you may want to encode week or month into the entity key, so you can get the current week/month's HighScore easily.
There are 2 possible approaches for a requirement like yours where you want to show highscores for a day, week, month, etc:
1, First option is to use your current model where you are storing date and score. Since app engine allows inequality filter only on 1 property, you need to apply an inequality filter on date and then find the n highest number of scores. But since the result will be sorted first for the property with inequality filter and then for any additional property, you cannot do a fetch for only the first n entries to find the top n because the top scores need not be in continuous order. See this post to understand this better. So you will have to fetch all the scores for the date range and then do further sorting of the query result at your client to find the top n. This approach is ok if the total number of scores for a week or a month will not be too high compared to the value of n. If not, this is not a scalable option.
2, Second approach is to redesign your model such that sorting happens on scores so that for getting top n scores for a particular period, you need to fetch only the first n entries. This means the approach is suitable even if number of scores are very large. This then requires converting your date to be suitable for equality filtering like for each entry storing a month number, a week number and calendar year. Then for example if you want to find the top n scores in the 3rd month, then you can query for month=3, sort by scores descending and fetch the first n matching entries. Similarly you can query for a particular week using a week number.
This is very similar to another high-score SO question. I have copied/pasted my answer to it below. Approaching this solution using a database query may cause you to join the ranks of folks who complain about GAE. You will be using a custom index. Your query will likely average 10x miliseconds slower than needed per request. You will need to index thousands, perhaps millions of records. This costs you money -- perhaps lots of it both re: data storage (indices) and instances due to your high latency for what will likely be a highly-called handler function. Think different please. My copy/paste is not as specific to your setup, but it can be easily extended easily. I hope that it might prompt you to think about lower resource, lower cost alternative. As always...HTH. -stevep
Previous high score answer:
You may want to consider an alternate approach. This is a lot of index overhead which will cause your costs to be higher, the response time for the handler executing this function to operate an order of magnitude slower and you will have moments where the eventual consistency of index updates will affect maintenance of this data. If you have a busy site, you will surely not be happy with the latency and costs associated with this approach.
There are a number of alternate approaches. Your expected site transactions per second would affect which you choose. Here is a very simple alternative. Create an ndb entity with a TextProperty. Serialize the top scores entries using a string such as score_userid. Store them in the text field by joining them with a unique character. When a new score comes in, use get_by_id to retrieve this record (ndb automatically handles memcaching for you). Split it into an array. Split the last element of the array, and check against the new score. If it is less than the score, drop it, and append the new score_userid string to the array. Sort the array, join it, and put() the new TextProperty. If you want you could set up an end of the day cron to scan your scores for the day to check to see if your process was affected by the very small chance that two scores arrived at nearly the same time causing one to overwrite the other. HTH. -stevep
Previous SO high score answer link:
GAE datastore query with filter and sort using objectify