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.
Related
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.
How to efficiently store RPG Item properties in Java?
I'm designing a text based RPG where random items are spawned in when looting chests for example.
Currently I'm storing my Item data in a textfile. When a random item has to be generated a scanner reads the file, collects the values, takes probability in account, and then creates a new object accordingly.
Here is an example of some items of the 'Consumable' class.
The values are listed accordingly:
name, probability, level at which the item gets added to the itempool, weight, value, +health, +damage, Effect
example of textfile:
Twinkie 10 1 1 10 10 10 0
Banana 10 1 1 5 5 0 0
Potato 20 1 1 5 5 0 0
Protein_Shake 5 5 1 30 10 10 1
Beer 5 5 1 5 10 10 1
If the Effect value equals 0, a new default Consumable gets created with effect 'null'.
if the Effect value is 1, a function uses a switch(name) statement to find the effect belonging to the item and then
passes the effect as an argument in the 'Consumable constructor'.
I'm certain that this is a very unoriganized and inefficient way to go about this sort of thing. Anyone has a suggestion on how to handle this? I want to do it right.
Should I maybe create an ConsumablePool class where I just create all the items immediatly or store the item information elsewhere?
There are a few ways to optimize your current task, which seems to be:
Consumable nextItem = getRandomConsumable(List<Consumable> candidates);
Perhaps you must also choose based on the current level:
Consumable nextItem = getRandomConsumable(int level, List<Consumable> candidates);
Currently, you state that each time you call getRandomConsumable() you generate the list of candidates from a disk file (you seem to have already written this code). Your instinct is correct. The 'cost' of this operation is relatively high. Reading from disk compared to reading from a memory cache of objects will cause poor performance. Assuming that the disk file does not change during the game, your application should be creating the candidate list once (at startup), and using this List each time the next item must be chosen.
In the case where candidates are based on level, further optimizations can be done. Consider dividing the candidates by level, such as:
List<Consumable> candidates = createCacheFromDisk(); // Run at startup
Map<Integer, List<Consumable>> itemsByLevelMap = candidates .stream().collect(Collectors.groupingBy(Consumable::getLevel));
This will further break out the list of candidates into Lists by level, allowing
List<Consumable> level1Items = itemsByLevelMap.get(1);
This general approach of caching will greatly improve the performance of your application; choosing a random item from a List which has already been generated/cached performs far greater than generating a new List (from disk) each time.
I have an arrayList of size N that contains a class with time stored in it based on System millis. I want to go through the whole arrayList and split it up into one hour chunks. It can only be the last 24 hours starting from now and going back 24 hours. There may be items that fall out of the last 24 hour window though.
I can't believe I'm asking an algorithm question on SO. Thanks for the help.
The large arrayList is made up of basically this item:
public class Item {
private long date;
private long otherData;
}
I'm saving the date in the Item using:
System.currentTimeMillis()
Again, I would like to split up the arrayList of Items into 24 separate arrayLists of Items based on their "save date" that used currentTimeMillis() at the time they were saved.
It would be even cooler if the first/newest/most recent bucket ended exactly on the next hour mark then every hour after that. In other words, if I do a request at 7:25PM...it would awesome if the first Item "bucket" only contained entries that were saved in the last 25 minutes. Then, the next 23 "bucket of Items" were broken down on the hour(6:00PM, 5:00PM...).
Thanks again.
I would convert the current system time to a Date or Calendar object. Using that I can get the minutes of the current hour. I can then go back to the start of the hour, and iterate on down through each hour. You can go between Date and milliseconds easily using myDate.getTime() and new Date(milliseconds)
Figure out how many milliseconds you need for each section and subtract.
One way you could break up the blocks is by converting the times into a Calendar and checking the HOUR_OF_DAY. Create a HashMap of hours corresponding with an arrayList of the bucket items then simply loop through and place them in the corresponding list.
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.