I need to figure out how to solve this problem. I am using Java but it doesn't matter for now. I don't need any codes since I have to do that myself I just need some advices about the algorithm since I can't find any fast ways to do this.(My solution took too long when compiling)
Question is:
There are 4 cities. Each has different routes from one to other(16 routes totally)
Going from City 1 to City 4 is different than going to City 1 from City 4(all routes are one-way) that's why they have different values.
I have the list of required times for each road which is totally 16. Actually the list will be typed by the user when the program initiates but you can assume that I have the list for now.
After we got the required times the user chooses a starting and an ending city and the program has to find the minimum duration for that travel.
Example:
0 18 15 8
18 0 7 3
7 16 0 19
10 14 19 0
This is a table of travel durations. i(row) x j(column) and the values show the travel duration from i to j city.
When the user inputs "4 2" which means from city 4 to city 2, the the output as answer should be 14
But when the user inputs "2 1" the the output as answer should be 13(3+10). First from city 2 to city 4 which is 3 hours and than from city 4 to city 1 which is 10 hours and totally it makes 13 hours.
So the chosen route doesn't need to be the direct route any number of routes can be used between two cities but with the most fastest way.
This 4x4 table was just an example for 4 cities. (Which is all I have also). The algorithm should work for max 100 cities. The user will type the number of cities before filling the table for travel durations between each of them.
I may find a solution for 4 cities but It doesn't work for 100 cities. I also tried permutation method with java but as I said it took too long to compile. However compiling proccess musn't take longer than 4 seconds.
Sorry for the long and boring question of mine but I hope someone can make a useful suggestion.
I have figured out how to do it, so answering this myself. I have managed to make it work by editing the code I have found here. It works really fast and flawless.
Related
I am trying to implement a method in java which takes as input an ArrayList of objects that have a deadline, a score, and object number. Each is accessible as:
game.get(i).number
game.get(i).score
game.get(i).deadline
Where game is the ArrayList and i is the index.
I want to maximize the score I can achieve while considering the deadline for each game. Each game has to be completed before the deadline. e.g. if deadline is 5, it has to be completed at 4 or earlier.
For example, here is a sample ArrayList with it's corresponding data organized in descending order of the score worth:
Index Game number Score Deadline
0 3 76 3
1 4 66 2
2 1 52 2
3 6 51 4
4 5 47 2
5 2 23 1
Then the following ArrayList could be the result:
maximizedScore = [4,1,3,6] -> here each index represents the hour. Even though game 3 has a higher score than game 4 and game 1, we put game 4 in index 0 and game 1 in index 1 as they both have a deadline of 2 so they must be completed before then. However, game 3 has a deadline of 3 so we can do it at hour 2 in order to maximize the total score. Note that game 5 also has the same deadline as game 4 and 1, but it has less points than both so we sacrifice it.
Edit: Each index (0,1,2,3,4,..) represents the hour while the value at the index represents the game number being completed at that hour.
Edit 2: We can only do one game per hour. So if the latest deadline in the data is x, then we can do a max of x games. I.e. 4 in this example.
This provides a maximum score of 245.
The order of games does not matter as long as they are before the deadlines. For example: [1,4,3,6] would also be acceptable as both game 4 and game 1 are being completed before the deadline.
Unfortunately, I have no idea how to go about implementing this. Hopefully I provided a clear idea of what I need.
Any help is appreciated!
I will try to give a general approach without writing any code yet.
I will call the result you are looking for the "schedule". As you explained in your question, the maximum number of games you can place in your schedule is indicated by the maximum value in the "Deadline" column of your input data. I will call this the "time limit".
You are asking for a greedy algorithm. Such an algorithm will generate and check all game schedules to find the one that maximizes your score.
Basic approach
The most basic approach you can take is to generate all permutations of games of length "time limit" or less. For each one of them, you would then check:
is it indeed a valid schedule (is each game in the tentative schedule payable at the time it is placed?),
does this tentative schedule yield a total score greater than the best score obtained so far ? If so, you "keep" this solution and continue trying other schedules
The main difficulty in this first approach is to correctly generate all the possible schedules. I.E:
0
0 1
0 1 2
0 1 2 3
0 1 2 3 4
0 1 2 4
0 1 2 4 3
0 1 3
....
1
1 0
1 0 2
....
Optimizations
Now, the basic approach above has some ineficiencies. For instance, when you are building the possible schedule and you build one that is impossible due to the deadline criteria. For example:
3 5
is an impossible schedule because game "5" has a deadline of 1 (meaning it can only be played as the first game or not a all). If you can recognize this, then you realize that any schedule that starts with 3 5 (3 5 0 ..., 3 5 1 ...) is also impossible.
You can exploit this fact if you generate the schedule in a clever order and skip the generation of the schedules that you know are not going to be possible.
Tips for algorithm
I would suggest generating the schedules in a recursive manner. You have all your game ids (0, 1, etc) in a collection. You start with the lowest index: 0 , remove it from the collection of games and place it in your tentative schedule:
Schedule: 0
You check if it is a valid schedule (i.e. if the game you just placed in your schedule can be played at that time). Let's assume that it is the case (in this specific case as it is the first game on the schedule, it should always be possible). You also check if this tentative schedule yields a better score than anything you found so far.
Then you try to add the lowest game left in your collection of games left to play. In this case, 1. Same thing you remove 1 from the collection of games and place it on your schedule:
Schedule: 0 1
Same thing, you check if this is a valid schedule. You already know that game 0 can be played first, you check if game 1 can be played in second position. Bad luck, the time limit of game 1 prevents you from doing it. It is not worth exploring the schedules that start with 0 1 anymore. You remove 1 from your schedule, but you do not replace it in the games collection: as it is impossible to play in second position, it is not worth checking it further. Instead, I would place it in a collection of games that were "excluded" at the current exploration level.
You then move on to the next game remaining in the game collection, 2 and follow the same routine. If you are able to place a game on your schedule that is compatible with the time limit, you can continue adding games on you schedule with the ones that remain in the games collection. Be careful to recognize that there may be cases where you completely fill your schedule but there are still games left (or vice versa, you still have holes in your schedule but there are no games that can be played left).
When you have run out of options, it is time to remove games from the schedule. Remove the last game you placed on your schedule and place it back in the games collection. Also place the games that you have excluded at the current level back into the games collections. You can continue the schedule generation. Be careful not to take the game you just removed at this level again though.
First thing to do would be to sort your games by their score, because we want a game with a highest score first:
if you have an ArrayList of object say ArrayList<Game> inputData = new ArrayList<>(); you can sort it like this in java:
inputData.sort(Comparator.comparing(Game::getScore));
now the lowest score is first and the highest one is last.
Since we have to keep track of deadlines I would put them into a separate ArrayList and remove them one by one if needed:
ArrayList<Integer> deadlines = new ArrayList<>();
for(Game game : inputData) {
if (!deadlines.contains(game.deadline))
deadlines.add(game.deadline);
}
After that the idea is to iterate through inputData one by one and keep track of previousDeadline and currentDeadline. If we that the currentDeadline is greather than previousDeadline then that means that we can't accept any deadline that is before that. This can be done by checking deadlines list that we created earlier and removing deadlines from it.
int previousDeadline = -1; // initial value because there is no -1 deadline
for(int i = inputData.size()-1; i >= 0; i--) {
int currentDeadline = inputData.get(i).deadline;
// compare previous and currentDeadline and remove from deadlines list
if(previousDeadline != -1 && previousDeadline < currentDeadline) {
for(int j = 1; j < currentDeadline; j++) {
deadlines.remove(Integer.valueOf(j));
}
}
// add to result only if present in deadlines list and update previous deadline
if (deadlines.contains(currentDeadline) ) {
result.add(inputData.get(i).number);
previousDeadline = inputData.get(i).deadline;
}
}
If you give it a input that you provided you will get a list with [3, 4, 1, 6]
Here is a pastebin with code
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.
My English is not very well, BUT I will try my best to explain my issue here.
I am working on an application in which I have to create graph. For now I am using GraphStream.
Requirements for my graph is very complicated, which is :
I have a table named CDR(Call Data Record) in which I have 2 columns ANUMBER and BNUMBER. The structure of table is very clear that it shows that Anumber called Bnumber and there is another column for DATETIME, which shows the date and time of call. BUT I need here only two columns.
Lets say we have 4 numbers here : 123, 456 ,789 ,000 and table structure is like this
Anumber Bnumber
------- -------
123 456
123 789
456 789
789 000
456 000
My table here clearly shows that 123 didn't call 000 But 123 called 456 and 789 and these two numbers called 000 So I have to show the directed graph between 123 and 000 which probably shows like this 123->456->000 and 132->789->000
So the issue is I don't know how to find this path between 123 and 000. There may be more than 2 numbers like 5 or 6 numbers and I have to find the hidden numbers between all the given 5 or 6 numbers AS in the above scenario 456 and 789 are hidden numbers between 132 and 000.
And one thing more my table contains more than 20 million rows and in future obviously the number of rows will grow very fast as user calls each other.
WHAT I HAVE DONE SO FAR:
I have done some R&D on this issue but couldn't found any good library or any solution for this. So far, I think Dijkstra's Algorithm is best for my scenario as GraphStream luckily provides this algorithm here.
What I want from you guys, Give me an idea that Will this algorithm will give me required result OR I have to find any other algo or graph library which will suits best for my problem. I am not good at ALGO's thats why I am here for any help or guideline If you guys can gave me.
Thanks
You don't need Dijkstra's algorithm at all, since you don't have costs on edges. You need simple BFS algorithm.
Here is simple implementation but you should add 'labels' array to mark visited nodes. So after BFS you can restore pass from each node to source node(123 in your case) or say that node cannot be reached from given node(if label for this node remains 0).
You should add label in the following way:
all labels equals 0 on start
when you visit new node you set it's label as current_node_label+1
But Dijkstra's can help you if you set cost of each edge as 1. It's just not efficient way to sole you problem.
I am trying to solve this problem: https://leetcode.com/problems/house-robber-iii/
The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.
Now with this input:
Input: [4,1,null,2,null,3]
That should be this tree:
Now in my opinion the correct output is 4+2 = 6 but leetcode says the correct is 7.
Did I draw wrong the tree? How can you obtain a max 7 rob given that tree?
Number 4 and 3 are also not connected, so 4+3 would also count and would be higher than 4 + 2. It is about nodes that are connected. As long as they are not directly connected, the thief can rob them, thus 4+3 could be robbed.
What's stopping you from robbing 4 + 3 = 7? Those two "houses" are not directly linked.
I have a problem in front of me that I can't grasp, even though I grasp the concept of backtracking well. I have been unable to find any information on this specific problem, and I am unaware if it goes by another name. The problem is to construct a backtracking algorithm that will print out the list of combinations of seating that N number of "presidents" can sit at a round table without sitting next to the same person twice. For example, you give it an input 8, it gives you the output,
1 2 3 4 5 6 7 8
1 3 5 2 6 8 4 7
1 4 2 7 5 8 3 6
Now I have constructed my own backtracking algorithms for simple games (checkers, n-queens, tic-tac-toe), however these that I have worked with have started with a blank canvas and didn't require this type of implementation. What I am asking for is a bit of guidance and insight, or links to more information to this problem as all that was given was about a page and a half, mostly talking about how the combination 1 2 3 4 is effectively the same as 1 4 3 2 in this particular problem. This needs to be done using a backtracking method and that's what is making me confused. If we were give free rein to find solutions I could easily do it. Any help is appreciated.
Thanks!
I'm thinking you'll have to add information about who sat next to who already to the backtracking algorithm state:
You start with, say 1. You seat 2 next to him, and record this "pairing" in the current partial solution. (Literally just an unordered pair of president IDs. An easy way of implementing an unordered pair of numbers is to have the constructor of that class store the smaller ID in the first element of the pair, and the greater ID in the second element.) So you have a partial solution 1 2 …, with the pairing 1-2.
When you reach to a complete solution, you add all its pairings to a "global" list of pairings. This will be used in future searches. I.e. if you get the solution 1 2 3 4 5 6 7 8, you save the pairings 1-2, 2-3, 3-4, 4-5, 5-6, 6-7, 7-8, 1-8.
Now, when doing a search, you have a partial solution x y z … – the last president seated so far is z, and the pairings in this partial solution are x-y and y-z. To seat the next president, you need to look at every president that's:
Not seated so far. (And thus not included in the partial solution's pairings.)
Not paired with z in the global pairings.
If no such president is available, you discard the partial solution and backtrack.
That said, I'm working off the top of my head here, so you'd be well advised to actually doublecheck if I missed any edge cases by using a straightforward brute force implementation and comparing the results.
A very rough pseudocode will look like this:
global flag // I know it is a bad practice but can't think of a better idea at this point
back (PresidentList, chairNumber, computedList)
if (PresidentList.size() == 0)
if (computedList doesn't violate any global distribution)
add computedList to globalList
add distirbution of computedList to global distirbution
set flag;
else return;
else if (flag is set and chairNumber > 2) return;
else if (flag is set and chairNumber = 2) un set flag; return;
else if (chairNumber == maxChairs-1)
// at this point there should be only one president in PresidentList
if (PresidentList.back() can sit with computedList.back() and computedList.front())
remove president from PreseidentList, add president to computedList
back(PresidenList, chairNumber+1,computedList)
else return;
else
for every president in PresidentList
if (president can sit with computedList.back())
remove president from PreseidentList, add president to computedList
back(PresidentList,chairNumber+1,computedList);
You always check if a president can sit near some other president only according to the global distribution variable.
In the main function just run a loop for PresidentList that will start back with that president being as the first one.
The idea of the flag is as follows: when you add a distribution and a list to the global list, back runs already a lot of branches which have the same prefix as the list you just added and hence are already bad. To close all those lists you force the back to stop branching and return to the point when it can set a new 2nd element in the list to compute i.e. get back to the loop if the last else branch of the function.