Grouping of 5 items sorted by criteria - java

I want to make a java application, which is addressed for an esports competition. Specifically this application will be for a teamspeak server.
I want users on a channel to be sorted into groups of 5 (they will be identified by a uniqid and a number representing the skill level).
Thus, when 5 users are between skill levels 1 - 3 to be placed in one group, the next ones in another group (each of 5), and until that list / map will no longer be able to be made groups of 5.
Can you help me with an idea? I know how to get the uniqid from the teamspeak server, as well as the skill level, but I don't know how to randomly group them and meet that skill level condition.
I tried a hashmap but it failed.
HashMap<Integer, Integer> teams = new HashMap<>();
for(Client c : api.getClients()){
if(c.getChannelId() == 2170){
if(api.getChannelByNameExact("[LOBBY] Cauta echipa",true).getTotalClients() >= 5) {
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVER1")))) {
teams.put(c.getId(), 1);
}
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVER2")))) {
teams.put(c.getId(), 2);
}
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVER3")))) {
teams.put(c.getId(), 3);
}
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVER4")))) {
teams.put(c.getId(), 4);
}
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVERE")))) {
teams.put(c.getId(), 5);
}
while(teams.size() >= 5){
teams.forEach((key, value) -> {
System.out.println("Key : " + key + " Value : " +value);
if(value > 1 && value < 5){
teams.
}
});
}
teams.clear();
}
}
}
Exemple:
If on a teamspeak channel there are 20 people with skill level in 1 lvl -18 lvl, the robot will build teams of 5 members with similar skill level (with a margin of + - 1 level).
For example, if I have skill level 5, and on the channel there are at least 4 people with skill level between 3-5, the 5 people (including myself) will be added to a list or array or whatever.
After we made the team of 5 people, the program will continue to run and form teams of 5 people with similar skill level, until it will no longer be possible (there will be no 5 people in the main room).

On my mind you should divide on two groups(ArrayLists) hightlevel and lowlevel, for this create function and check skills level(skills>3)=>hight else=>low;
After create HashMap team; where keys - ids; and value - numbers of group;
With operator for and function MathRandom complete first group; value++; Continue while you have available people.
Change value +1(it will be next group) complete HashMap with next Array, using MathRandom();
This is working, if ids - Integer and unique. of course you have to delete from Array element after putting in the map
Also you can try to manage with databases MongoDB:
1.Create two datas: high and low level
2. With Pagebale create page items on page 5; number of page will be your group number. Use method unsorted

Related

Optimal way to solve the below problem based on Data Structure

I was recently asked this in an interview.
Given below are the the candidates and the time at which they got a vote.
Q. Given a time, print the person winning till that time.
Cand. Time
A 4
B 10
C 15
C 18
C 21
B 35
B 40
B 42
E.g In the Qsn above, if we are asked to find the winner at time 20, answer would be C -> Since C has 2 votes.
Tried Solution
Have a Map<String, List> to store Map<Candidate, [Time, votes]>
We can iterate through the array & fetch only the times which are less than 20 (as per the question).
But I believe there will be a more optimum way to solve this type of problem.
Essentially store the given data in a proper Data Structure which will give us the result in optimum time.
Thanks
What I would do is as follows:
First, implement a naive solution, such as the one you thought of, or the one suggested by Pp88 above.
Then, immediately write a test for it, which shows(1) that it works.
Then, implement a more optimal solution, such as the one which follows.
Finally, re-use the previous test to show(1) that the more optimal solution also works.
A more optimal solution could be as follows:
Build a LinkedHashMap where the key is a time coordinate, and the value is one more map, in which the keys are the names of all candidates, and the values are the accumulated vote count of each candidate at that time coordinate.
Traverse this LinkedHashMap and create a new map, where the key is again a time coordinate, and the value is the name of the winning candidate at that time coordinate. Throw away the previous map.
Build an ArrayList containing all the keys in the map.
Once you have done all of the above, any query of the type "who is the winner at time X" can be answered by performing a binary search in the ArrayList to find the time coordinate which is closest to but does not exceed X, and then a look-up of the time coordinate in the map to find the name of the candidate who was winning at that moment.
Ignoring the overhead of preparing the data structures, the time complexity of each query is equal to the time complexity of binary search, which is O(log2 n). This is sub-linear, so it is better than O(N).
(1) At best, we can say that a test "shows that it works"; it does not prove anything. The most accurate way of putting it is that it "gives sufficient reason to believe that it works", but that's too long, so "it shows that it works" is a decent alternative.
This is an O(N) solution, I'm assuming you have in input 2 arrays one for candidates and one for times. Who will win if there are the same amount of votes is not clear so in this case the first wins.
public Optional<Character> findCandidateWithMaxVotes(Character[] candidates, int[] times, int timeLimit) {
Character cadidateWithMaxVotes = null;
int max = 0, count = 0;
Map<Character, Integer> numberOvVotesForCandidate = new HashMap<>();
for(int i = 0; i < times.length; i++) {
if(times[i] <= timeLimit) {
count = numberOvVotesForCandidate.merge(candidates[i], 1, Integer::sum);
if(max < count) {
max = count;
cadidateWithMaxVotes = candidates[i];
}
}
}
return Optional.ofNullable(cadidateWithMaxVotes);
}
It's a bit unclear should we answer just one question ("who is the winner at time 20") or we are
supposed to preprocess the data provided and then answer several queries ("who is the winner at time 20", "who is winner at time 8" etc.).
The first problem is easy:
// Nobody is leading before elections with 0 votes
String leader = null;
int leaderVotes = 0;
HashMap<string, Integer> ballots = new HashMap<string, Integer>();
for (int i = 0; i < candidates.length; ++i) {
// too late, don't count this vote
if (times[i] > givenTime)
continue;
// number of votes
int current = ballots.containsKey(candidates[i])
? ballots.get(candidates[i]) + 1
: 1;
ballots.set(candidates[i], current);
// do we have a leader change?
//TODO: add tie breaking logic here
if (current > leaderVotes) {
leaderVotes = current;
leader = candidates[i];
}
}
// at givenTime we have leader with leaderVotes
The second problem is trickier:
We sort the votes by time
Scan them as we do in the first problem
On every leader change we add a record into (time, leader) list
Having all these done we have a sorted list which is ready for binary search: for given time we are looking for the latest record which is not later than time.

Java classes from database architecture

I have a relatively simple database containing a Player table (a single field username) and a Game (a single field date) one. As a Player can take part in multiple Game and a Game can be played by multiple Player, I use a many-to-many relationship where an extra column score is added to the joined table to store the score of a Player in a Game.
In my Java code, I have obviously a Player class with field username and a Game one with field date. However, I do not know if I should create a third class for the join table or if I should add a List<Player>attribute within the Game class along with a list of List<Integer> to store the score.
EDIT: Example
Player table:
player_id player_name
1 Bob
2 Lea
3 John
Game table:
game_id game_date
1 20/08/2017
2 19/08/2017
Joined table:
game_id player_id score
1 1 50
1 2 35
2 1 50
2 3 29
I would not create a separate class for the joined table. I would go with a Map<Player, Integer> in the Game class to hold the players in the game and their respective scores.
Something like so (simple, no error checks):
class Game {
Map<Player, Integer> playerScores = new HashMap<>();
void addPlayer(Player p) {
playerScores.put(p, 0);
}
void incrementScore(Player p, int increment) {
int newScore = getScore(p) + increment;
playerScores.put(p, newScore);
}
int getScore(Player p) {
return playerScores.get(p);
}
// etc...
}
Why you don't add score attribute to Player class?
1 player probably can't be in 2 games at same time, right?
Reason why I say this is because you would then need only one list, with your approach you end up with 2 lists which are not directly connected. Yes I know that you will place player and his score at same index but this complicates things a lot.
Situation that I can think of just now is showing scoreboard, in other to show which player has highest score you need to sort it, how would you do it with your 2 lists?
In some complicated way for sure, you would first need to connect first and second list in some structure like map or something, probably you would need to use TreeMap<Integer, List<Players>>, where Integer would be the score and for each score you would need List of players because 2 or more players could have same score.
By having score in your Player class you avoid this complications and make accessing score of each player very easy, once they leave game you simply take score, save in database and set back to 0.

Which data structures to use when storing multiple entities with multiple query criteria?

There is a storage unit, with has a capacity for N items. Initially this unit is empty.
The space is arranged in a linear manner, i.e. one beside the other in a line.
Each storage space has a number, increasing till N.
When someone drops their package, it is assigned the first available space. The packages could also be picked up, in this case the space becomes vacant.
Example: If the total capacity was 4. and 1 and 2 are full the third person to come in will be assigned the space 3. If 1, 2 and 3 were full and the 2nd space becomes vacant, the next person to come will be assigned the space 2.
The packages they drop have 2 unique properties, assigned for immediate identification. First they are color coded based on their content and second they are assigned a unique identification number(UIN).
What we want is to query the system:
When the input is color, show all the UIN associated with this color.
When the input is color, show all the numbers where these packages are placed(storage space number).
Show where an item with a given UIN is placed, i.e. storage space number.
I would like to know how which Data Structures to use for this case, so that the system works as efficiently as possible?
And I am not given which of these operations os most frequent, which means I will have to optimise for all the cases.
Please take a note, even though the query process is not directly asking for storage space number, but when an item is removed from the store it is removed by querying from the storage space number.
You have mentioned three queries that you want to make. Let's handle them one by one.
I cannot think of a single Data Structure that can help you with all three queries at the same time. So I'm going to give an answer that has three Data Structures and you will have to maintain all the three DS's state to keep the application running properly. Consider that as the cost of getting a respectably fast performance from your application for the desired functionality.
When the input is color, show all the UIN associated with this color.
Use a HashMap that maps Color to a Set of UIN. Whenever an item:
is added - See if the color is present in the HashMap. If yes, add this UIN to the set else create a new entry with a new set and add the UIN then.
is removed - Find the set for this color and remove this UIN from the set. If the set is now empty, you may remove this entry altogether.
When the input is color, show all the numbers where these packages are placed.
Maintain a HashMap that maps UIN to the number where an incoming package is placed. From the HashMap that we created in the previous case, you can get the list of all UINs associated with the given Color. Then using this HashMap you can get the number for each UIN which is present in the set for that Color.
So now, when a package is to be added, you will have to add the entry to previous HashMap in the specific Color bucket and to this HashMap as well. On removing, you will have to .Remove() the entry from here.
Finally,
Show where an item with a given UIN is placed.
If you have done the previous, you already have the HashMap mapping UINs to numbers. This problem is only a sub-problem of the previous one.
The third DS, as I mentioned at the top, will be a Min-Heap of ints. The heap will be initialized with the first N integers at the start. Then, as the packages will come, the heap will be polled. The number returned will represent the storage space where this package is to be put. If the storage unit is full, the heap will be empty. Whenever a package will be removed, its number will be added back to the heap. Since it is a min-heap, the minimum number will bubble up to the top, satisfying your case that when 4 and 2 are empty, the next space to be filled will be 4.
Let's do a Big O analysis of this solution for completion.
Time for initialization: of this setup will be O(N) because we will have to initialize a heap of N. The other two HashMaps will be empty to begin with and therefore will incur no time cost.
Time for adding a package: will include time to get a number and then make appropriate entries in the HashMaps. To get a number from heap will take O(Log N) time at max. Addition of entries in HashMaps will be O(1). Hence a worst case overall time of O(Log N).
Time for removing a package: will also be O(Log N) at worst because the time to remove from the HashMaps will be O(1) only while, the time to add the freed number back to min-heap will be upper bounded by O(Log N).
This smells of homework or really bad management.
Either way, I have decided to do a version of this where you care most about query speed but don't care about memory or a little extra overhead to inserts and deletes. That's not to say that I think that I'm going to be burning memory like crazy or taking forever to insert and delete, just that I'm focusing most on queries.
Tl;DR - to solve your problem, I use a PriorityQueue, an Array, a HashMap, and an ArrayListMultimap (from guava, a common external library), each one to solve a different problem.
The following section is working code that walks through a few simple inserts, queries, and deletes. This next bit isn't actually Java, since I chopped out most of the imports, class declaration, etc. Also, it references another class called 'Packg'. That's just a simple data structure which you should be able to figure out just from the calls made to it.
Explanation is below the code
import com.google.common.collect.ArrayListMultimap;
private PriorityQueue<Integer> openSlots;
private Packg[] currentPackages;
Map<Long, Packg> currentPackageMap;
private ArrayListMultimap<String, Packg> currentColorMap;
private Object $outsideCall;
public CrazyDataStructure(int howManyPackagesPossible) {
$outsideCall = new Object();
this.currentPackages = new Packg[howManyPackagesPossible];
openSlots = new PriorityQueue<>();
IntStream.range(0, howManyPackagesPossible).forEach(i -> openSlots.add(i));//populate the open slots priority queue
currentPackageMap = new HashMap<>();
currentColorMap = ArrayListMultimap.create();
}
/*
* args[0] = integer, maximum # of packages
*/
public static void main(String[] args)
{
int howManyPackagesPossible = Integer.parseInt(args[0]);
CrazyDataStructure cds = new CrazyDataStructure(howManyPackagesPossible);
cds.addPackage(new Packg(12345, "blue"));
cds.addPackage(new Packg(12346, "yellow"));
cds.addPackage(new Packg(12347, "orange"));
cds.addPackage(new Packg(12348, "blue"));
System.out.println(cds.getSlotsForColor("blue"));//should be a list of {0,3}
System.out.println(cds.getSlotForUIN(12346));//should be 1 (0-indexed, remember)
System.out.println(cds.getSlotsForColor("orange"));//should be a list of {2}
System.out.println(cds.removePackage(2));//should be the orange one
cds.addPackage(new Packg(12349, "green"));
System.out.println(cds.getSlotForUIN(12349));//should be 2, since that's open
}
public int addPackage(Packg packg)
{
synchronized($outsideCall)
{
int result = openSlots.poll();
packg.setSlot(result);
currentPackages[result] = packg;
currentPackageMap.put(packg.getUIN(), packg);
currentColorMap.put(packg.getColor(), packg);
return result;
}
}
public Packg removePackage(int slot)
{
synchronized($outsideCall)
{
if(currentPackages[slot] == null)
return null;
else
{
Packg packg = currentPackages[slot];
currentColorMap.remove(packg.getColor(), packg);
currentPackageMap.remove(packg.getUIN());
currentPackages[slot] = null;
openSlots.add(slot);//return slot to priority queue
return packg;
}
}
}
public List<Packg> getUINsForColor(String color)
{
synchronized($outsideCall)
{
return currentColorMap.get(color);
}
}
public List<Integer> getSlotsForColor(String color)
{
synchronized($outsideCall)
{
return currentColorMap.get(color).stream().map(packg -> packg.getSlot()).collect(Collectors.toList());
}
}
public int getSlotForUIN(long uin)
{
synchronized($outsideCall)
{
if(currentPackageMap.containsKey(uin))
return currentPackageMap.get(uin).getSlot();
else
return -1;
}
}
I use 4 different data structures in my class.
PriorityQueue I use the priority queue to keep track of all the open slots. It's log(n) for inserts and constant for removals, so that shouldn't be too bad. Memory-wise, it's not particularly efficient, but it's also linear, so that won't be too bad.
Array I use a regular Array to track by slot #. This is linear for memory, and constant for insert and delete. If you needed more flexibility in the number of slots you could have, you might have to switch this out for an ArrayList or something, but then you'd have to find a better way to keep track of 'empty' slots.
HashMap ah, the HashMap, the golden child of BigO complexity. In return for some memory overhead and an annoying capital letter 'M', it's an awesome data structure. Insertions are reasonable, and queries are constant. I use it to map between the UIDs and the slot for a Packg.
ArrayListMultimap the only data structure I use that's not plain Java. This one comes from Guava (Google, basically), and it's just a nice little shortcut to writing your own Map of Lists. Also, it plays nicely with nulls, and that's a bonus to me. This one is probably the least efficient of all the data structures, but it's also the one that handles the hardest task, so... can't blame it. this one allows us to grab the list of Packg's by color, in constant time relative to the number of slots and in linear time relative to the number of Packg objects it returns.
When you have this many data structures, it makes inserts and deletes a little cumbersome, but those methods should still be pretty straight-forward. If some parts of the code don't make sense, I'll be happy to explain more (by adding comments in the code), but I think it should be mostly fine as-is.
Query 3: Use a hash map, key is UIN, value is object (storage space number,color) (and any more information of the package). Cost is O(1) to query, insert or delete. Space is O(k), with k is the current number of UINs.
Query 1 and 2 : Use hash map + multiple link lists
Hash map, key is color, value is pointer(or reference in Java) to link list of corresponding UINs for that color.
Each link list contains UINs.
For query 1: ask hash map, then return corresponding link list. Cost is O(k1) where k1 is the number of UINs for query color. Space is O(m+k1), where m is the number of unique color.
For query 2: do query 1, then apply query 3. Cost is O(k1) where k1 is the number of UINs for query color. Space is O(m+k1), where m is the number of unique color.
To Insert: given color, number and UIN, insert in hash map of query 3 an object (num,color); hash(color) to go to corresponding link list and insert UIN.
To Delete: given UIN, ask query 3 for color, then ask query 1 to delete UIN in link list. Then delete UIN in hash map of query 3.
Bonus: To manage to storage space, the situation is the same as memory management in OS: read more
This is very simple to do with SegmentTree.
Just store a position in each place and query min it will match with vacant place, when you capture a place just assign 0 to this place.
Package information possible store in separate array.
Initiall it have following values:
1 2 3 4
After capturing it will looks following:
0 2 3 4
After capturing one more it will looks following:
0 0 3 4
After capturing one more it will looks following:
0 0 0 4
After cleanup 2 it will looks follwong:
0 2 0 4
After capturing one more it will looks following:
0 0 0 4
ans so on.
If you have segment tree to fetch min on range it possible to done in O(LogN) for each operation.
Here my implementation in C#, this is easy to translate to C++ of Java.
public class SegmentTree
{
private int Mid;
private int[] t;
public SegmentTree(int capacity)
{
this.Mid = 1;
while (Mid <= capacity) Mid *= 2;
this.t = new int[Mid + Mid];
for (int i = Mid; i < this.t.Length; i++) this.t[i] = int.MaxValue;
for (int i = 1; i <= capacity; i++) this.t[Mid + i] = i;
for (int i = Mid - 1; i > 0; i--) t[i] = Math.Min(t[i + i], t[i + i + 1]);
}
public int Capture()
{
int answer = this.t[1];
if (answer == int.MaxValue)
{
throw new Exception("Empty space not found.");
}
this.Update(answer, int.MaxValue);
return answer;
}
public void Erase(int index)
{
this.Update(index, index);
}
private void Update(int i, int value)
{
t[i + Mid] = value;
for (i = (i + Mid) >> 1; i >= 1; i = (i >> 1))
t[i] = Math.Min(t[i + i], t[i + i + 1]);
}
}
Here example of usages:
int n = 4;
var st = new SegmentTree(n);
Console.WriteLine(st.Capture());
Console.WriteLine(st.Capture());
Console.WriteLine(st.Capture());
st.Erase(2);
Console.WriteLine(st.Capture());
Console.WriteLine(st.Capture());
For getting the storage space number I used a min heap approach, PriorityQueue. This works in O(log n) time, removal and insertion both.
I used 2 BiMaps, self-created data structures, for storing the mapping between UIN, color and storage space number. These BiMaps used internally a HashMap and an array of size N.
In first BiMap(BiMap1), a HashMap<color, Set<StorageSpace>> stores the mapping of color to the list of storage spaces's. And a String array String[] colorSpace which stores the color at the storage space index.
In the Second BiMap(BiMap2), a HashMap<UIN, storageSpace> stores the mapping between UIN and storageSpace. And a string arrayString[] uinSpace` stores the UIN at the storage space index.
Querying is straight forward with this approach:
When the input is color, show all the UIN associated with this color.
Get the List of storage spaces from BiMap1, for these spaces use the array in BiMap2 to get the corresponding UIN's.
When the input is color, show all the numbers where these packages are placed(storage space number). Use BiMap1's HashMap to get the list.
Show where an item with a given UIN is placed, i.e. storage space number. Use BiMap2 to get the values from the HashMap.
Now when we are given a storage space to remove, both the BiMaps have to be updated. In BiMap1 get the entry from the array, get the corersponding Set, and remove the space number from this set. From BiMap2 get the UIN from the array, remove it and also remove it from the HashMap.
For both the BiMaps the removal and the insert operations are O(1). And the Min heap works in O(Log n), hence the total time complexity is O(Log N)

Select value from arraylist based on its percentage [duplicate]

This question already has answers here:
How to pick an item by its probability?
(13 answers)
Closed 6 years ago.
I got an arraylist of objects. Each objects got 2 values, content and weight. content is just a simple string while weight decides the percentage of how often the string should be used.
If I have 2 objects in the array:
Object 1:
content: hello
weight: 20
Object 2:
content: hey
weight: 80
First objects content should be used 20% of times while the second objects content should be used 80% of all times.
How would I decide which content gets selected based on the weight?
I got the following code so far:
foreach (ContentModels cont in match_array)
{
if (match_array.Count == 1)
{
match = cont.content;
break;
}
}
which pretty much selects the first content if the arraylist only contains one object but I don't know what do to if there are more than one objects?
Alright, I wanted to take a stab at this without looking at someone else's code. Here's what I came up with.
Btw, I hope it was the Java tag that was in error and not the C# tag :D.
Here's the entire program. What follows below is an explanation of each piece
.NET Fiddle
I chose to take each element to be a portion in a ratio. Therefore, in your example, your total is 100 (20 + 80) meaning that the 20 content model should get chosen 20% of the time. If you want to constrain your content models such that their total weights add up to 100, that should be done at the time that you create them.
So here's my solution.
First the content models:
class ContentModel
{
public string Content { get; set; }
public int Weight { get; set; }
}
And then a list of test cases:
static List<ContentModel> contentOptions = new List<ContentModel>
{
new ContentModel
{
Content = "hello",
Weight = 20
},
new ContentModel
{
Content = "hey",
Weight = 80
},
new ContentModel
{
Content = "yo dawg",
Weight = 90
}
};
Given these test cases we would expect to see 'Hello' appear about 10.5% of the time (20 / (80 + 90 + 20)) * 100. And so on for the rest of the test cases.
Here's the generator that makes that happen:
Here all we're going to do is figure out what the total weight is that we're working with. Then we're going to pick a random number and go through each model asking "Is this number from this content model?" If no, then subtract that content model's weight and move to the next one until we get to a model where the selection - weight is < 0. In this case we have the model that was chosen. I hope that makes sense.
(Note: I chose to recalculate the total weight every time in case you change the source list of options. If you make that list readonly, then you could move that .Sum() call outside the while loop.)
static IEnumerable<string> GetGreetings()
{
Random generator = new Random();
while (true)
{
int totalWeight = contentOptions.Sum(x => x.Weight);
int selection = generator.Next(0, totalWeight);
foreach (ContentModel model in contentOptions)
{
if (selection - model.Weight > 0)
selection -= model.Weight;
else
{
yield return model.Content;
break;
}
}
}
}
And finally, here's the main method which will also test this whole thing:
static void Main(string[] args)
{
List<string> selectedGreetings = new List<string>();
/* This will get 1000 greetings,
* which are the Content property of the models, group them by the greeting,
* count them, and then print the count along with the greeting to the Console.
*/
GetGreetings()
.Take(1000)
.GroupBy(x => x)
.Select(x => new { Count = x.Count(), Content = x.Key })
.ToList()
.ForEach(x => Console.WriteLine("{0} : {1}", x.Content, x.Count));
Console.ReadLine();
}
Here are my results from a run through:

different for loops java

I'm having some difficulties with the following problem:
I'm making a little game where you're at a specific spot and each spot has each some possible directions.
The available directions are N(ord),E(ast),S,W . I use the function getPosDirections to get the possible directions of that spot. The function returns the directions into an ArrayList<String> e.g. for spot J3: [E,W]
Now the game goes like this: 2 dice will be rolled so you get a number between 2 and 12, this number represents the number of steps you can make.
What I want is an ArrayList of all the possible routes
clarification of all the possible routes:
When I'm at the current position I check what the possibilities are from there. Let's say that's go East and go West. So we get 2 new positions and from there on we need to check for the next possibilities again for both positions (until we took x directions)
(x equals the number thrown by the dice).
e.g.: I throw 3 and I'm currently at spot J3:
[[E,N,E],[E,N,S],[E,S,E],[E,S,S],[W,N,E],[W,N,S],[W,S,E],[W,S,S]]
How would obtain the last mentioned Array(list)?
First, you might wish to think about your approach some more. In the worst case (a 12 is rolled, and all 4 directions are possible at every location), there will be 4^12 ~= 160 million routes. Is it really necessary to iterate over them all? And is it necessary to fill about 1 GB of memory to store that list?
Next, it is probably a good idea to represent directions in a type-safe manner, for instance using an enum.
That being said, recursion is your friend:
private void iteratePaths(Location currentLoc, List<Direction> currentPath, List<List<Direction>> allPaths, int pathLength) {
if (currentPath.size() >= pathLength) {
allPaths.add(new ArrayList<Direction>(currentPath));
return;
}
for (Direction d : currentLoc.getPosDirections()) {
currentPath.add(d);
Location newLoc = currentLoc.walk(d);
iteratePaths(newLoc, currentPath, allPaths, pathLength);
currentPath.remove(currentPath.size() - 1);
}
}
public void List<List<Direction>> getAllPaths(Location loc, int length) {
List<List<Direction>> allPaths = new ArrayList<List<Direction>>();
List<Direction> currentPath = new ArrayList<Direction>();
iteratePaths(loc, currentPath, allPaths, length);
return allPaths;
}
You can assume that your field of spots is a complete graph. Then you need to implement BFS or DFS with saving pathes.
You can implement all logic in any of these algorithms (like getting a list of possible directions from a certain node).

Categories