I'm really sorry, I would search my question but I don't know how to word it correctly, I have a big problem with mental math and I've been trying to think of a solution. I'm trying to build a program for my guild that will add names to a list. This list has a parallel struct for each entry that holds the person's name and number of donations to a raffle.
I want to randomize through all the names and have the results positively influenced by the amount of donations people have put in. likes 1 or 1% increase in possibility * number of donations. I've done randomization before but I've never had to influence the odds slightly. help me please? I would post code but I don't have ANY randomization at the time. I can give you some other stuff though:
I made a struct to hold each user's entry:
public struct pEntry
{
public string Name;
public int Entries;
}
I made a list to hold all the entries:
public List<pEntry> lEntries = new List<pEntry>();
I want my randomization to be positively influenced by the number of entries(donations) they've made. This has no cap on how high it can go but if I need to maybe I can make it like.. 255.After it randomizes it will pick display a message saying that, that user has won and it will remove that entry from the list and pick a few more. This program will be used for multiple raffles and things like it but all use the same system.
You need to know how much donations increase the chance of winning. Does 1 = 1 more chance than someone that hasn't donated? Once you have a base and a bonus, you can just generate a "chart", see what your top number is, and generate a random number. After that, you can remove that person or reset their chances by whatever fraction you want, regenerate your chance list, and generate a new number.
For instance, if you want 1 donation unit to give 10% more chance for that person, then you could generate a list of all the guild, and each person gets 10 "lots" + 1 lot per donation unit. So if you had 3 people, where:
Ann gave 5 donation units
Tom gave 2 donation units
Bob didn't give any
The resulting list would be:
Ann lot count: 10 (base) + 5 (donations) = 15 lots
Tom lot count: 10 (base) + 2 (donations) = 12 lots
Bob lot count: 10 (base) + 0 (no donations) = 10 lots
Then you generate a number between 1 and 37 (15 + 12 + 10) to determine the winner.
Figure out what each donation should improve their odds (increases in their lots) and then you can start building your ranges and generate your numbers.
Related
I have a situation where i have to create a C# routine which has the following logic to take a list of people and divide them into 2 teams based on preferences:
I have an array of 20 names:
var names = new List(){"Joe", "Bill", "Scott", "Jonathan", . . .}
Each name can give 0 to 3 preferences, so for each name, I have is an array of 0 to 3 length and is an array of strings with other names in the list (they are people they want to be on their team)
I now need to solve for taking the list of 20 people and dividing them into 2 teams and creating the teams (sub lists) based on optimizing for people's preferences. So each person should get AT LEAST one person that they included in their preference on their team (if mathematically possible). There is no priority of one person above anyone else, just trying to optimize for the top number of matches.
I can convert the string lists into a list of objects
List<Person> list = CreateList(array)
where Person class is the following
public class Person
{
public string Name;
public List<Person> Preferences;
}
but now i am trying to figure out how to use this data structure to generate the 2 teams where i end up with 2 lists of teams that are set of 10 people.
The optimal flow method can solve your problem - maximizing flow in a graph which branches capacity express preferences. There is a N^3 algorithm.
See here for an example : Algorithm for optimal matching with choices and ranking
Instead of setting up an adjacency matrix and trying to extract some meaningful vector solution via linear algebra, I think you might get some mileage out of an iterative "team captain" type model.
I would start by representing each individual's preferences as a row vector, mimicking the rows of an adjacency matrix.
For ease of explanation, I'll use an example with 4 people: A, B, C, and D. A and D want to be together, B wants to be with C, and C wants to be with A.
The rows of the adjacency matrix are [1,0,0,1],[0,1,1,0],[1,0,1,0],[1,0,0,1]. So I would carry on representing each individual as their row in the adjacency matrix. A is [1,0,0,1], B is [0,1,1,0], C is [1,0,1,0], and D is [1,0,0,1].
Now I would create team captains. I'm going to look for two vectors whose dot product is minimal. A zero dot product is not guaranteed to exist by your requirements. For instance, everyone could want to be with one particular individual. But you can still find two vectors whose dot product is minimal, and entirely orthogonal is likely in practice.
Now make those two people team captains. In this example, that means A=[1,0,0,1] and B=[0,1,1,0] are viable team captains.
Now iteratively allow them to start picking their teams. A can find his optimal new member by taking dot products with C, and D, and observing D yields the maximum dot product, resulting in the teams {A,D}, {B,C}.
Of course, in your case, it doesn't stop there. So let's consider what would happen if there were also an E, F, G, and H waiting to get picked. In that case, the team {A,D} would multiply the (column) matrix [A][D] with the (column) vectors [E],[F],[G], and [H], and see which product has maximal norm, selecting it and allowing team {B,C} to select its newest member through the same process: max{norm([B][C]*[candidate])}.
I am given a csv of employee schedules with columns:
employee ID, first last name, sunday schedule, monday schedule, ... , saturday schedule
1 week schedule for each employee. I've attached a screenshot of a portion of the csv file. The total file has around 300 rows.
I need to generate teams of 15 based on the employees' schedules (locations don't matter) so that the employees on each team have the closest schedules to each other. Pseudocode of what I have tried:
parse csv file into array of schedules (my own struct definition)
match employees who have the same exact schedule into teams (creates ~5 full sized teams, 20 - 25 half filled teams, leaves ~50 schedules who don't match with anyone)
for i = 1 to 14, for each member of teams of size i, find the team with the closest schedule (as a whole) and add the member to that team. Once a team reaches size 15, mark them as "done".
This worked somewhat but definitely did not give me the best teams. My question is does anyone know a better way to do this? Pseudocode or just a general idea will help, thanks.
EDIT: Here is an example of the formula of comparison
The comparison is based on half hour blocks of difference between the agents schedules. Agent 25 has a score of 16 because he has a difference of 8 half hours with Agent 23 and 24. The team's total score is 32 based on everyone's scores added together.
Not all agents work 8 hour days, and many have different days off, which have the greatest effect on their "closeness" score. Also, a few agents have a different schedule on a certain day than their normal schedule. For example, one agent might work 7am - 3pm on mondays but work 8am - 4pm on tuesday - friday.
Unless you find a method that gets you an exact best answer, I would add a hill-climbing phase at the end that repeatedly checks to see if swapping any pair of agents between teams would improve things, and swaps them if this is the case, only stopping when it has rechecked every pair of agents and there are no more improvements to be made.
I would do this for two reasons:
1) Such hill-climbing finds reasonably good solutions surprisingly often.
2) People are good at finding improvements like this. If you produce a computer-generated schedule and people can find simple improvements (perhaps because they notice they are often scheduled at the same time as somebody from another team) then you're going to look silly.
Thinking about (2) another way to find local improvements would be to look for cases where a small number of people from different teams are scheduled at the same time and see if you can swap them all onto the same team.
Can't say for sure about the schedules, but in string algorithms you can find an edit distance calculation. The idea is to define number of operations you need to perform to get one string from another. For example, distance between kitten and sitting is 3, 2 for substitutions and 1 for deletion. I think that you can define a metric between two employees' schedule in similar way.
Now, after you have a distance function, you may start a clusterization. The k-means algorithm may be a good start for you, but it's main disadvantage is that the number of groups is fixed initially. But I think that you can easily adjust general logic for your needs. After that, you may try some additional ways to cluster your data, but you really should start with your distance function, and then simply optimize it on your employee records.
I've created a Restaurant POS that sells Sandwiches, I'm trying to figure out how to create a calculation which does the following as an example
Hotdog Sandwich chosen -----> substract from inventory the following
1 Bread
50gm Ketchup
25gm Mayo
2 Hotdog pieces
etc.
Currently the client enters purchases as follows, 5 packs of Hotdogs by typing Hotdog and 5 in quantity, but the hotdog pack contains 6 hotdog pieces
while when he types Ketchup, and 5 in quantity it means 5 bottles.
what I'm asking is the best way to do this, what should I do?
make a DB table that holds the detail of each ingredient? like 1 bottle of Ketchup = 300gm and 1 Hotdog pack = 6 pieces?
Or
make the code in C# converts what the client enters into grams and units? like when he chooses Ketchup from comboBox and enters 1 bottle, the code converts it to 300gm?
the reason for doing this is for the client to know exactly the amount of ingredients in the inventory, and also to make the program calculate the exact cost of the Sandwich, so he code get the net profit displayed in the reports section
Or is there a better way to do this?
I would store the information in the database (solution 1) because you don't have to change your source code when he e.g. want's to use bottles of ketchup with 350 g.
I have a List of salesmen with the fields, name, district and sales. I have sorted them by amount of articles sold but I need a way to separate them into levels and print it out. For example:
James - 12 Sales
Billy - 25 Sales
2 salesmen have reached level 1: under 50 sales
and so on. What's the easiest and best way to do this?
The loop I'm currently using for sorting looks like this:
foreach (salesman n in salesmen.OrderBy(s=>s.sales))
{
Console.WriteLine(n.name);
Console.WriteLine(n.sales);
}
Since you don't specify code, or how you fill your objects, an approach would be:
Employees.ForEach(e => Console.WriteLine("{0} - {1} Sale/s",e.Name, e.Sales.Count().ToString()));
int[] levels = new int[1];
levels[0] = 50;
for (int i = 0; i < levels.Length; i++)
{
var emps = Employees.Where(e => e.Sales.Count() <= levels[i]);
emps.ForEach(Console.WriteLine("{0} salesmen have reachead level {1}: under {2} sales", emps.Count(), i.ToString(), levels[i]);
// Remove employees from the list that already achived the level (so they won't be counted again).
Employess.RemoveAll(e=> e.Sales.Count() <= levels[i]);
}
This is just pseudo code, it might not compile but it's the general idea.
I have a List of salesmen with the fields, name, district and sales. I have sorted them by amount of articles sold but I need a way to separate them into levels and print it out. For example:
James - 12 Sales
Billy - 25 Sales
2 salesmen have reached level 1: under 50 sales
and so on. What's the easiest and best way to do this?
The loop I'm currently using for sorting looks like this:
foreach (salesman n in salesmen.OrderBy(s=>s.sales))
{
Console.WriteLine(n.name);
Console.WriteLine(n.sales);
}
There are no secrets in coding, and there are no shortcuts either. We first develop business logic "If a salesman makes so many sales, they are in this level, that many sales, that level" and then we turn that into computer logic. That's the art of programming, finding the best way to turn people statements into math statements. Sometimes the math statements are very verbose, sometimes they're terse. Doesn't change the end of the day, where all you can do is write the code.
The only way to get all the people in a list sorted into buckets is to go over every single part of the list. That's an iteration, or a loop. You're doing that. Then we test (.OrderBy(s...) for certain keywords or values.
The easiest and best way to do what you're asking is to define the business rules, then encapsulate them in logic as you're doing, with loops. You may find you end up with one list per business rule, which isn't a bad thing.
The only problem here is it sounds like you're looking for a "this is always the best way to store this data" answer, and that doesn't exist here. Until we know your entire use-case, the best we can do is to say "yes, this is appropriate". Each situation calls for a different answer. I realize this isn't much of an answer, but sometimes it's the answer you need to hear. You're doing fine, have a little confidence in yourself.
I'm trying implement a bracket in my program (using C#/.NET MVC) and I am stuck trying to figure out some algorithm.
For example, I have a bracket like this with 8 entries (A,B,C,D,E,F,G,H)
I'm trying to figure out if there's an algorithmic way to
depending on # of entries, find # of
games per round
depending on # of entries, for a
specific game #, what is the
corresponding game # in the next
round?
For example, in this case, for 8 entries, the example are:
for round 1, there are 4 games. Round 2, 2 games. Round 3, 1 game
game 2 in round 1 corresponds to game 5 in round 2.
I also thought about storing this info in a table, but it seems overkill since it never changes, but here it is anyway:
Any help will be greatly appreciated!
Cheers,
Dean
C# code for the first part of your question:
// N = Initial Team Count
// R = Zero-Based Round #
// Games = (N / (2 ^ R)) / 2
public double GamesPerRound(int totalTeams, int currentRound) {
var result = (totalTeams / Math.Pow(2, currentRound)) / 2;
// Happens if you exceed the maximum possible rounds given number of teams
if (result < 1.0F) throw new InvalidOperationException();
return result;
}
The next step in solving part (2) is to know the minimum game number for a given round. An intuitive way to do that would be through a for loop, but there's probably a better method:
var totalTeams = 8;
var selectedRound = 2;
var firstGame = 1;
// If we start with round 1, this doesn't execute and firstGame remains at 1
for (var currentRound = 1; currentRound < selectedRound; currentRound++) {
var gamesPerRound = GamesPerRound(totalTeams, currentRound);
firstGame += gamesPerRound;
}
Quoting #Yuck who answered the first question perfectly.
C# code for the first part of your question:
// N = Initial Team Count
// R = Zero-Based Round #
// Games = (N / (2 ^ R)) / 2
public double GamesPerRound(int totalTeams, int currentRound) {
var result = (totalTeams / Math.Pow(2, currentRound)) / 2;
// Happens if you exceed the maximum possible rounds given number of teams
if (result < 1.0F) throw new InvalidOperationException();
return result;
}
Moving on to the second question:
//G = current game.
//T = total teams
//Next round game = (T / 2) + RoundedUp(G / 2)
//i. e.: G = 2, T = 8
//Next round game = (8 / 2) + RoundedUp(2 / 2) = 5
public int NextGame(int totalTeams, int currentGame) {
return (totalTeams / 2) + (int)Math.Ceiling((double)currentGame / 2);
}
I actually worked this out myself fairly recently and stumbled on (that is, I worked it out, but it has probably been discovered before) a neat recursive solution.
You start with your list of players, in a list that is sorted in seed order. This will be important later.
The overall algorithm consists of splitting the list of players into two and then creating two sub-tournaments. The winners of the two sub-tournaments will end up the grand final of the overall tournament.
Required Objects
Player
Name
Seed
Match
Home Player
Away Player
Next Match (pointer to the Match the winner goes to)
Splitting the Lists
Most tournaments put the top seeded player against the bottom seeded player in round one. In order to do this I used the following algorithm, but you could just put the first n / 2 players in one list and the rest in the other list to create a tournament where seeds 1 and 2 play off in round one (and seed 3 plays 4, 5 plays 6 etc).
I'll note here that the neat thing about having top seed play bottom seed is that with this algorithm if you don't have a power of two number of players, the top seed(s) will get a bye in the early rounds.
Take the first player and put them in the "left" list
Take the next two players (or the last player) and put them in the "right" list
Take the next two player and put them in the "left" list
Repeat from step 2 until there are no more players.
Of course, if there are only two players in the list you simply create a match between them and return.
Building the Tournament
So you start out with a list of say, 64 players. You split it into two lists of 32 players and recursively create two sub tournaments. The methods that you call recursively should return the Matches that represent the sub-tournament's grand final match (the semi-final of your overall tournament). You can then create a match to be the grand final of your overall tournament and set the nextMatch of the semi final matches to be this grand final.
Things to Consider
You'll need to break out of recursing if there are only two players in the list that's passed in.
If your split gives you a list of one, shouldn't recurse with it. Just create a sub-tournament with the other list (it should only have two players so will return with a match immediately), set the home team to be the single player and the nextMatch of the sub-tournament.
If you want to be able to keep track of rounds, you'll need to pass a recursion depth integer - increment it when you create a sub-tournament.
Hope this helps, let me know if you need any clarification :)
So basically its a elimination contest.
So just have List.
The algorithm will always put the first and second teams together if the number of teams is even. You then increase the counter by two and repeat.
If the number of teams is odd do pretty much the samething except you randomly select a winner of the "first around" and put it against the odd team.
After the first round you repeat the algorithm the same way.
A+1
C+1
...
For example, I have a bracket like
this with 8 entries (A,B,C,D,E,F,G,H)
You should be able to figure out how to parse this. This seems like a homework question.
Consider renumbering the games (you can always renumber them back afterwards)
if the final is 1
semis are 2,3
the problem is then has well-published solutions: ahnentafel (German for ancestor table) has been used for a long time by genealogists - http://en.wikipedia.org/wiki/Ahnentafel
one interesting part of this is the binary notation of the game # gives a lot of information as to the structure of the tournament and where in the tree the match is.
Also note that as every match knocks out 1 competitor, for n competitors there will be n-1 matches