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.
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
I need to coordinate the MinMax method using threads. To make it clearer, I will not paste my MinMax.
I use this algorithm to select the best possible moves for the computer in the game of checkers
This is pseudocode from Wikipedia:
1 function minimax(node, depth, maximizingPlayer) is
2 if depth = 0 or node is a terminal node then
3 return the heuristic value of node
4 if maximizingPlayer then
5 value := −∞
6 for each child of node do
7 value := max(value, minimax(child, depth − 1, FALSE))
8 return value
9 else (* minimizing player *)
10 value := +∞
11 for each child of node do
12 value := min(value, minimax(child, depth − 1, TRUE))
13 return value
var value = minimax(origin, depth, TRUE) // call
I need to somehow implement threads into that method to make it faster.
My knowledge of threads is really limited ... And I have to do it by tomorrow. Ultimately, I wrote the function in c#, but I will gladly take advice also in java, because I know it better than c#.
Could someone tell me where should I start?
I think I should call the method through a certain number of threads which would be based on the number of possible moves. Line 7 would probably be a good place? Recursion complicates things a lot and I get lost.
Should I somehow join these threads, or the recursion itself will force the whole method to work like this and not another.
Can anyone edit this pseudocode and show me some example of how I should start this specific number of threads. It can be in c# or java. Each piece of advice is worth its weight in gold. I know that the topic is extensive, but I tried to make it as specific as I can, so please the administrator did not close this topic to me :(
You might want to take a look at Parallel.Foreach. Keep in mind that scheduling work on a thread has some overhead, so just replacing the loops with the parallel equivalent will probably be much slower. A fairly simple approach would be to add a check for the depth and run it in parallel for the first level(s) and synchronous for the deeper levels.
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.
First of all I want to say, that I looked online for a possible or similar solution but did not find anything, might have been looking for the wrong keywords but please excuse my rather simple question.
However, currently I am trying to implement a java function that - on an input of an integer (e.g. 10) gives me every possible solutions on how to divide this by 2 or 1.
And I literally have no clue on how to even start, as there is no pattern to it or anything that I have done is relatable.
However this is an old exam from my professor, so there is a good and short solution I am just not seeing.
Thank you very much for your help and time :)
edit:
The method I am trying to imlement would look as follows:
static void possibilities (int i){ }
I would be able to give an integer (3 for example) and then as output (through Sys.out) all possibilities of all possible combinations of 1 and 2's, for example for 3:
(1,1,1)
(2,1)
(1,2)
Or for 2:
(1,1)
(2)
Here is what I think would work:
say the input is 5 so the very 1st combination will be: (1,1,1,1,1) right? now we add the first two number so it is (2,1,1,1) and store it in a string i.e. "2111" now we find all the permutations of this string (code 4 this is available), now we add the next 1,1 pair so it will look like (2,2,1) i.e "221" and again same process of permutations.
We keep repeating this till the string has just one '1' present or no '1' present, try checking for the number 4, same thing.
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.