I am supposed to create a quidditch program using arraylists but I am kinda confused and my teacher isn't helpful whatsoever. I know how to create the array list and add them, remove, the basic uses of array list. The way he has the directions worded confuse me, any help about where to start would be great.
I can do most of the work for this program,
the main confusion for me is part a, how to pair the teams to go against each other and how to do the multiple rounds.
Im not asking for anyone to do this program, I'm just asking for some help, explanation and pointers on where to start. Thanks a lot guys.
Directions:
Create an ArrayList of Strings containing the names of your 8 ‘teams’. Use humorous names for your teams (Dwarves, Wizards, Dinosaurs, etc.)
Code a method public void playGame(int teamA, int teamB, ArryList teams)
a. teamA and teamB are the indices (sic. Indexes) of the teams that are playing the current game. You will use these to retrieve the String name of the team.
For our purposes a Quiddich game has four quarters:
b. Each team randomly scores 0 to 4 goals worth 10 points each per quarter (0 – 40 points per quarter.
c. Each quarter, there is a 15% chance that a team will capture the Golden snitch. If that happens the game ends immediately and that team wins.
(First determine if a team got the snitch, then if one did randomize which one wins with even probability.)
d. The method should display the results for each quarter that is played and indicate the final score or if the teams won by capturing the snitch.
e. There are no ties. Play additional sudden death quarters until one team wins.
f. Your method should remove the loosing team from the ArrayList and print a msg that that team (using the String name) has been eliminated from the Tourney.
Code your main program to display the list of teams. Then run the tournament. For each round pit every other team against one another.
a. First round: 4 games reduces teams to 4 remaining.
b. Second round: 2 games reduces teams to final 2
c. Final round: 1 game determines the tournament winner.
Each time show the list of remaining teams and use your method to run the games for that round. (Hint: just use even/odd indices for the pairings: Team index 0 plays team index 1, team index 2 plays team index 3, etc.)
I think the answer is in the last point - the teams shouldn't play in a "league" way (one vs all others) but in a "cup" way (the one that loses won't play anymore). The teams should be divided like this: even vs odd. I believe the simplest way to do this would be:
for(int i = 0; i < teams.size(); i = i + 2) {
playGame(i, i + 1, teams);
}
Assuming, that there will be even number of all teams of course.
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
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 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.
I have been trying to complete the following assignment for my college. So far, I have received help on this assignment a couple of times (which I really appreciate).
Since this is an assignment for college, I would appreciate non-direct answers that explain the concepts with examples that don't directly fix my assignment.
The assignment requires me to check for some things depending on user input.
If the user inputs an order, then inputs the same order with the same code again, it replaces the previous information with the new one. EG, if the user inputs G22 as code and 5 as quantity, then again enters G22 and then 4 as quantity, it forgets about the 5 and replaces that with 4. How can I make it so it remembers the previous one and simply adds the new order and makes it Quantity = 9 (I am using arrays for user input).
If the user enters G22 and quantity 3, but then doesn't enter anything and just hits enter, the counter adds one and upon pressing X (to quit) the shipping charges show up as $2.00 which is for 2 items. How can I avoid the counter from adding 1 in case nothing sensible is entered, i.e. anything else apart from the 4 options available is entered.
I understand that using doubles is not advisable for anything related to money and BigDecimal is recommended (alongwith NumberFormat, maybe). Can I replace my current doubles with BigDecimal with minimal problems, or do I have to replace the whole code? I also do not understand how to implement BigDecimal that easily so I would appreciate layman examples on that (especially on whether I can add/subtract/multiply/divide BigDecimal with ints etc).
I would post the code here but I don't want it copied by anyone else doing the same course and then submit it before I do (not that my code is the most awesome thing in the world, I just put in a lot of effort since its my first ever program).
1) I would use a Map<String, Integer> to store all the quantities for a product code.
2) I would get the total of items ordered by summing the quantities in the map. How the user enters the data shouldn't matter.
3) This advice is project dependant. In your case the option of the marker is what matters. Working in investment banks and trading firms for many years, and I haven't seen anyone use BigDecimal for money. Its not a major rewrite, and at a minimum you should know how to use both double and BigDecimal handling rounding correctly.
I'm making a boggle-like word game. The user is given a grid of letters like this:
O V Z W X
S T A C K
Y R F L Q
The user picks out a word using any adjacent chains of letters, like the word "STACK" across the middle line. The letters used are then replaced by the machine e.g. (new letters in lowercase):
O V Z W X
z e x o p
Y R F L Q
Notice you can now spell "OVeRFLoW" by using the new letters. My problem is: What algorithm can I use to pick new letters that maximizes the number of long words the user can spell? I want the game to be fun and involve spelling e.g. 6 letter words sometimes but, if you pick bad letters, games involve the user just spelling 3 letter words and not getting a chance to find larger words.
For example:
You could just randomly pick new letters from the alphabet. This does not work well.
Likewise, I found picking randomly but using the letter frequencies from Scrabble didn't work well. This works better in Scrabble I think as you are less constrained about the order you use the letters in.
I tried having a set of lists, each representing one of the dies from the Boggle game, and each letter would be picked from a random die side (I also wonder whether I can legally use this data in a product). I didn't notice this working well. I imagine the Boggle dice sides were chosen in some sensible manner, but I cannot find how this was done.
Some ideas I've considered:
Make a table of how often letter pairs occur together in the dictionary. For the sake of argument, say E is seen next to A 30% of the time. When picking a new letter, I would randomly pick a letter based on the frequency of this letter occurring next to a randomly chosen adjacent letter on the grid. For example, if the neighboring letter was E, the new letter would be "A" 30% of the time. The should mean there are lots of decent pairs to use scattered around the map. I could maybe improve this by making probability tables of a letter occurring between two other letters.
Somehow do a search for what words can be spelt on the current grid, taking the new letters to be wildcards. I would then replace the wildcards with letters that allowed the biggest words to be spelt. I'm not sure how you would do this efficiently however.
Any other ideas are appreciated. I wonder if there is a common way to solve this problem and what other word games use.
Edit: Thanks for the great answers so far! I forgot to mention, I'm really aiming for low memory/cpu requirements if possible, I'm probably going to use the SOWPODS dictionary (about 250,000) and my grid will be able 6 x 6.
Here's a simple method:
Write a fast solver for the game using the same word list that the player will use. Generate say 100 different possible boards at random (using letter frequencies is probably a good idea here, but not essential). For each board calculate all the words that can be generated and score the board based on the number of words found or the count weighted by word length (i.e. the total sum of word lengths of all words found). Then just pick the best scoring board from the 100 possibilities and give that to the player.
Also instead of always picking the highest scoring board (i.e. the easiest board) you could have different score thresholds to make the game more difficult for experts.
A minor variation on the letter-pair approach: use the frequency of letter pairs in long words - say 6 letters or longer - since that's your objective. You could also develop a weighting that included all adjacent letters, not just a random one.
This wordgame I slapped up a while back, which behaves very similarly to what you describe, uses English frequency tables to select letters, but decides first whether to generate a vowel or consonant, allowing me to ensure a given rate of vowels on the board. This seems to work reasonably well.
You should look up n-gramming, and Markovian Models.
Your first idea is very losely related to Markovian algorithms.
Basically, if you have a large text corpus, say of 1000 words. What you can do is analyse each letter and create a table to know the probability of a certain letter following the current letter.
For example, I know that the letter Q from my 1000 words ( 4000 letters in total ) is used only 40 times. Then I calculate what probable letters follow using my markov hash table.
For example,
QU happens 100% of the time so I know that should Q be randomly chosen by your application that I need to make sure that the letter U is also included.
Then, the letter "I" is used 50% of the time, and "A" 25% of the times and "O" 25% of the time.
Its actually really complicated to explain and I bet there are other explainations out there which are much better then this.
But the idea is that given a legitmately large text corpus you can create a chain of X letters which are probably consistent with English language and thus should be easy for users to make words out of.
You can choose to look forward on a value of n-gram, the highest the number the easier you could make your game. For example, an n-gram of two would probably make it very hard to create words over 6, but an n-gram of 4 would be very easy.
The Wikipedia explains it really badly, so I wouldn't follow that.
Take a look at this Markov generator:
http://www.haykranen.nl/projects/markov/demo/
I do not know about a precanned algorithm for this, but...
There is a dictionary file in UNIX, and I imagine there is something similar available on other platforms (maybe even in the java libraries? - google it). Anyways, use the files the spell checker uses.
After they spell a word an it drops out, you have existing letters and blank spaces.
1) From each existing letter, go right, left, up, down (you will need to understand recursive algorithms). As long as the string you have built so far is found at the start of words or backwards from the end of words in the dictionary file, continue. When you come across a blank space, count the frequency of the letters you need next. Use the most frequent letters.
It will not guarantee a word as you have not checked the corresponding ending or beginning, but I think it would be much easier to implement than an exhaustive search and get pretty good results.
I think this will get you a step closer to your destination: http://en.wikipedia.org/wiki/Levenshtein_distance
You might look at this Java implementation of the Jumble algorithm to find sets of letters that permute to multiple dictionary words:
$ java -jar dist/jumble.jar | sort -nr | head
11 Orang Ronga angor argon goran grano groan nagor orang organ rogan
10 Elaps Lepas Pales lapse salep saple sepal slape spale speal
9 ester estre reest reset steer stere stree terse tsere
9 caret carte cater crate creat creta react recta trace
9 Easter Eastre asteer easter reseat saeter seater staree teaser
9 Canari Carian Crania acinar arnica canari carina crania narica
8 leapt palet patel pelta petal plate pleat tepal
8 laster lastre rastle relast resalt salter slater stelar
8 Trias arist astir sitar stair stria tarsi tisar
8 Trema armet mater metra ramet tamer terma trame
...