How do I write a pseudocode that identifies the applicants that qualify for admission and outputs their names, student numbers and modes of study - pseudocode

so I'm a math major who has received an assignment regarding pseudocode. Below is what the assignment requires of me:
To qualify for admission, an applicant should have at least 25 points, minimum of B symbol in Mathematics and a Minimum of E symbol in English. If an applicant has a C symbol in Mathematics, then the applicant must write and pass an entrance test to be considered for admission. There are three modes of study: The full-time mode, the part-time mode and the Distance mode. Applicants can choose which mode they want provided there is space in that mode. Each of the full time and part-time modes cannot accommodate more than 30 admitted students. After these two modes are full, every other qualified applicant is admitted in the Distance mode. The admission exercise is first come first served. There are 450 applicants.
Write pseudocode that identifies the applicants that qualify for admission and outputs their names, students numbers and modes of study. Use a For-loop/do while-loop/ do until loop only (I understand this part to mean I can use only those loop structures). You must write only one pseudocode that caters for all modes
So here is my code:
Let M=math, E=english,i=counter,x=number of qualified students, FM=full time, PM=part time, D= distance, N=name of the applicant, SN=student number, P=points, y= students who have a C symbol in math, EX= entrance exam grade, z= number of total students, mo=mode of study
Start
i=0
y=0
x=0
z=0
FM=0
PM=0
D=0
For i 1 to 450
Enter N,SN,P,M,Eng
if(P>=25) AND (M>=B AND Eng>=E)
then
x= x+1
else
If (P>=25) AND (M=C AND Eng>=E)
then
y=y+1
End if
End if
i=i+1
End for
While EX != A
Enter EX, SN, N
If (EX>=50)
then
Display “student admitted”
until EX=A
Endwhile
z=x+y
While (z !=A)
Enter mo
If (mo=FM)
then
FM=FM+1
If (FM>30)
then
D=D+1
Else
If (mo=PM)
then
PM=PM+1
if(PM>30)
then
D=D+1
if(mo=D)
then
D=D+1
Endif
Endif
Endif
Endif
Endif
Endwhile
End

Related

Calculate statistics on numbers entered by user

This was my tutorial given by the lecturer. I don't understand the question. I need guidance into the right direction.
Write an algorithm to read in a list of basketball scores (non-negative integers) one at a time from the user and output the following statistics:
Total number of games.
Total number of games scoring at least 90 points.
Percentage of games scoring at least 90 points.
The user entering a negative sentinel value indicates the end of the input. Note that the sentinel value is not used in computing the highest, lowest or average game score.
Requirements:
Write pseudo code for how you would solve each statistic
Example: total number of games
For each input score, increment
games by one
Determine the variables you will need and figure out the type of each variable
Define and initialize each variable
Determine what type of loop you are going to write
Start with statistic number one (total number of games) and get your loop to compute the total number of games. When you end your loop,
output the total number of games, and then move to problem two.
You only need to write one loop.
Write a complete algorithm for the above problem.
I've tried to understand the requirement and tried googling for some alternative language but unable to find so
n = 0 // number of games
o = 0 // total number of games scoring at least 90 points
for( o = 0; o <= 90; o++ )
{
input =get user input for score
n++
o += input
}
percentage = n/o *100
output percentage
Have I correctly understood the question criteria?
EDIT Answer Attempt 1 :-
int numGames = 0; //number of games
int numTotalPoints = 0; //total number of games scoring
int userInput =0; //to Track input if negative number is enterred
double average = 0.0 //to get average of the game
double gameTo90Points =0.0; //calculate total games to reach 90 points
double percentage 0.0; //to calculate the percentage
Text.put("Input the game score");
userInput = text.getInt;
while(userInput >= 0 )
{
numTotalPoints += userInput;
numGames++;
Text.put("Input the game score");
userInput = text.getInt;
}
if(numGames = 0)
{
Text.put("Not enough score to tabulate");
}
else
{
average = ((double)numTotalPoints)/numGames);
gameTo90Points = 90/average;
percentage = (gameTo90Points/90)*100
Text.put("Total number of games :" +numGames);
Text.put("Total number of games scoring at least 90 points:" +gameTo90Points);
Text.put("Percentage of games scoring at least 90 points:" +percentage);
}
As this is a task you must complete, we should not provide you with the answer to that assignment.
I will provide some comments on your current pseudo-code.
n = 0 // number of games
o = 0 // total number of games scoring at least 90 points
So far this is a good start, but it is better to use variable names that actually tell something about it (e.g. numGames, numHighScoringGames would be good candidates). Also, the assignment asks to "figure out the type of each variable". This is something you have not done yet...
for( o = 0; o <= 90; o++ )
This loop is wrong. After the loop finishes o will be a number greater than 90. But o is supposed to be a particular number of games (with a score of at least 90). This should trigger an alarm... You haven't read any input yet and you already seem to know there will be more than 90 of such games? That's not right.
The value of o should have nothing to do with whether the loop should continue or not.
input =get user input for score
Again, the data type should be determined for the variable input.
n++
This is good, but you did not take into account this part of the assignment:
The user entering a negative sentinel value indicates the end of the input.
Your code should verify if the user entered a negative sentinel value. And if so, you should not ask for more input.
o += input
The variable o is supposed to be a number of games, but now you are adding a score to it... that cannot be right. Also, you add it unconditionally... Should you not first check whether that game is "scoring at least 90 points"?
percentage = n/o *100
Here you use o as it was intended (as a number of games). But think about this... which one of the two will be greater (when not equal)? n or o? Taking that answer into account: Is your formula correct?
Secondly, could the denominator be zero? Should you protect the code from it?
output percentage
OK, but don't forget that the assignment asks for three statistics, not just one.

Searching for proper optimization algorithm

I'm developing a mobile application with an algorithm. It's about food.
So I have a database that contains some meals. A meal contains several foods. A food is an item like an Apple, and it contains the nutrient values of the apple.
A Meal for example could be an apple pie, which contains apples, sugar, etc...
Each Food in a meal has a minimum and maximum amount, to make them more flexible. So when im making pasta with sauce, you can put in 150-250g of pasta and 50-75ml of sauce.
GOAL: The Algorithm is supposed to take in some values for total daily intake of carbohydrates, protein and fats. Then it should do some kind of algorithm to figure out a good combination of meals to best match the expectations of daily carbohydrates, proteins and fats.
While finding a solution, the algorithm can swap out meals, change the scaling of the foods inside the meals, and with n meals per day, and n foods per meal, that's quite a lot of variables.
I've tried a genetic algorithm approach, but I couldn't find a way to properly pair 2 solutions to make a child, and I couldn't figure out a good way for mutation.
Any help is appreciated, I don't want any code, just some inspiration at what i should look at, I'm not afraid of reading something (if it's not a book^^).
Or if anyone has an approach on how to handle this problem, that would be very nice aswell!
You can solve this problem using Mixed Integer Programming (MIP/MILP).
A handy tutorial for this is here.
The idea will be to introduce a binary variable for each meal indicating whether or not that meal is used. For each food item in the meal, there will be a variable indicating what portion of that food item is used.
The portions are constrained by user specified values, as are the health values.
Thus, for two meals m1 and m2 such that m1 has a portion f1 of food 1 and f2 of food 2 and m2 has f3 of food 3 and f4 of food 4, if we take m1 and m2 to be the aforementioned binary variables, then we have constraints like the following:
daily_protein_min<=m1*(f1*protein_f1+f2*protein_f2)+m2*(f3*protein_f3+f4*protein_f4)<=daily_protein_max
f1_min<=f1<=f1_max
f2_min<=f2<=f2_max
f3_min<=f3<=f3_max
f4_min<=f4<=f4_max
We can also constraint the number of meals per day:
m1+m2=1
Since multiplying a variable by a variable produces a potentially non-convex, non-linear result, we refer to the MIP tutorial for a way to transform such constrains into a usable form.
Finally, we use disciplined convex programming to build a model using cvxpy to pass to a solver. GLPK is a free MIP solver. Commercial solvers like Gurobi are generally faster, allow larger problems, are more stable, and quite expensive, though possibly free for students.
Having done all this, putting the problem into code isn't too terrible. Since I wasn't sure what values to use or what sort of food database was reasonable, I've used essentially random inputs (garbage in, garbage out!).
#!/usr/bin/env python3
import cvxpy as cp
import csv
from io import StringIO
import random
#CSV file for food data
#Drawn from: https://think.cs.vt.edu/corgis/csv/food/food.html
food_data = """1st Household Weight,1st Household Weight Description,2nd Household Weight,2nd Household Weight Description,Alpha Carotene,Ash,Beta Carotene,Beta Cryptoxanthin,Calcium,Carbohydrate,Category,Cholesterol,Choline,Copper,Description,Fiber,Iron,Kilocalories,Lutein and Zeaxanthin,Lycopene,Magnesium,Manganese,Monosaturated Fat,Niacin,Nutrient Data Bank Number,Pantothenic Acid,Phosphorus,Polysaturated Fat,Potassium,Protein,Refuse Percentage,Retinol,Riboflavin,Saturated Fat,Selenium,Sodium,Sugar Total,Thiamin,Total Lipid,Vitamin A - IU,Vitamin A - RAE,Vitamin B12,Vitamin B6,Vitamin C,Vitamin E,Vitamin K,Water,Zinc
28.35,1 oz,454,1 lb,0,0.75,0,0,13,0.0,LAMB,68,0,0.12,"LAMB,AUS,IMP,FRSH,RIB,LN&FAT,1/8""FAT,RAW",0.0,1.34,289,0,0,18,0.009,9.765,5.103,17314,0.501,156,0.985,254,16.46,26,0,0.232,11.925,6.9,68,0.0,0.145,24.2,0,0,1.62,0.347,0.0,0.0,0.0,59.01,2.51
0.0,,0,,0,0.9,27,0,141,7.0,SOUR CREAM,35,19,0.01,"SOUR CREAM,REDUCED FAT",0.0,0.06,181,0,0,11,0.0,4.1,0.07,1178,0.0,85,0.5,211,7.0,0,117,0.24,8.7,4.1,70,0.300000012,0.04,14.1,436,119,0.3,0.02,0.9,0.4,0.7,71.0,0.27
78.0,"1 bar, 2.8 oz",0,,0,0.0,0,0,192,46.15,CANDIES,13,0,0.0,"CANDIES,HERSHEY'S POT OF GOLD ALMOND BAR",3.799999952,1.85,577,0,0,0,0.0,0.0,0.0,19130,0.0,0,0.0,0,12.82,0,0,0.0,16.667,0.0,64,38.45999908,0.0,38.46,0,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
425.0,"1 package, yields",228,1 serving,0,1.4,0,0,0,9.5,OLD EL PASO CHILI W/BNS,16,0,0.0,"OLD EL PASO CHILI W/BNS,CND ENTREE",4.300000191,1.18,109,0,0,0,0.0,1.87,0.0,22514,0.0,0,0.985,0,7.7,0,0,0.0,0.904,0.0,258,0.0,0.0,4.5,0,0,0.0,0.0,0.0,0.0,0.0,76.9,0.0
28.0,1 slice,0,,0,3.6,0,0,0,1.31,TURKEY,48,0,0.0,"TURKEY,BREAST,SMOKED,LEMON PEPPER FLAVOR,97% FAT-FREE",0.0,0.0,95,0,0,0,0.0,0.25,0.0,7943,0.0,0,0.19,0,20.9,0,0,0.0,0.22,0.0,1160,0.0,0.0,0.69,0,0,0.0,0.0,0.0,0.0,0.0,73.5,0.0
140.0,"1 cup, diced",113,"1 cup, shredded",0,5.85,63,0,772,2.1,CHEESE,85,36,0.027,"CHEESE,PAST PROCESS,SWISS,W/DI NA PO4",0.0,0.61,334,0,0,29,0.014,7.046,0.038,1044,0.26,762,0.622,216,24.73,0,192,0.276,16.045,15.9,1370,1.230000019,0.014,25.01,746,198,1.23,0.036,0.0,0.34,2.2,42.31,3.61
263.0,"1 piece, cooked, excluding refuse (yield from 1 lb raw meat with refuse)",85,3 oz,0,1.22,0,0,20,0.0,LAMB,91,0,0.108,"LAMB,DOM,SHLDR,WHL (ARM&BLD),LN&FAT,1/8""FAT,CHOIC,CKD,RSTD",0.0,1.97,269,0,0,23,0.022,7.79,6.04,17245,0.7,185,1.56,251,22.7,24,0,0.24,7.98,26.4,66,0.0,0.09,19.08,0,0,2.65,0.13,0.0,0.0,0.0,56.98,5.44
17.0,1 piece,0,,0,0.7,10,0,49,76.44,CANDIES,14,10,0.329,"CANDIES,FUDGE,CHOC,PREPARED-FROM-RECIPE",1.700000048,1.77,411,4,0,36,0.422,2.943,0.176,19100,0.14,71,0.373,134,2.39,0,43,0.085,6.448,2.5,45,73.12000275,0.026,10.41,159,44,0.09,0.012,0.0,0.18,1.4,9.81,1.11
124.0,"1 serving, 1/2 cup",0,,0,1.98,0,0,32,9.68,CAMPBELL SOUP,4,0,0.0,"CAMPBELL SOUP,CAMPBELL'S RED & WHITE,BROCCOLI CHS SOUP,COND",0.0,0.0,81,0,0,0,0.0,0.0,0.0,6014,0.0,0,0.0,0,1.61,0,0,0.0,1.613,0.0,661,1.610000014,0.0,3.63,806,0,0.0,0.0,1.0,0.0,0.0,83.1,0.0
142.0,"1 item, 5 oz",0,,0,3.23,0,0,109,22.26,MCDONALD'S,167,0,0.073,"MCDONALD'S,BACON EGG & CHS BISCUIT",0.899999976,2.13,304,0,0,12,0.137,5.546,1.959,21360,0.642,335,2.625,121,13.45,0,0,0.416,8.262,0.0,863,2.180000067,0.262,18.77,399,0,0.0,0.093,2.1,0.0,0.0,42.29,0.9"""
#Convert to dictionary
food_data = [dict(x) for x in csv.DictReader(StringIO(food_data))]
food_data = [x for x in food_data if float(x['1st Household Weight'])!=0]
#Values to track
quantities = ['Protein', 'Carbohydrate', 'Total Lipid', 'Kilocalories']
#Create random meals
meals = []
for mealnum in range(10):
meal = {"name": "Meal #{0}".format(mealnum), "foods":[]}
for x in range(random.randint(2,4)): #Choose a random number of foods to be in meal
food = random.choice(food_data)
food['min'] = 10 #Use large bounds to ensure we have a feasible solution
food['max'] = 1000
weight = float(food['1st Household Weight']) #Number of units in a standard serving
for q in quantities:
#Convert quantities to per-unit measures
food[q] = float(food[q])/weight
meal['foods'].append(food)
meals.append(meal)
#Create an optimization problem from the meals
total_daily_carbs_min = 225
total_daily_carbs_max = 325
total_daily_protein_min = 46
total_daily_protein_max = 56
total_daily_lipids_min = 44
total_daily_lipids_max = 78
#Construct variables, totals, and some constraints
constraints = []
for meal in meals:
#Create a binary variable indicating whether we are using the variable
meal['use_meal'] = cp.Variable(boolean=True)
for q in quantities:
meal[q] = 0
for food in meal['foods']:
food['portion'] = cp.Variable(pos=True)
#Ensure that we only use an appropriate amount of this food
constraints.append( food['min'] <= food['portion'] )
constraints.append( food['portion'] <= food['max'] )
#Calculate this meal's contributions to the totals.
#Each items contribution is the portion times the per-unit quantity times a
#boolean (0, 1) variable indicating whether or not we use the meal
for q in quantities:
meal[q] += food['portion']*food[q]
#Dictionary with no sums of meals, yet
totals = {q:0 for q in quantities}
#See: "http://www.ie.boun.edu.tr/~taskin/pdf/IP_tutorial.pdf", "Nonlinear Product Terms"
#Since multiplying to variables produces a non-convex, nonlinear function, we
#have to use some trickery
#Let w have the value of `meal['use_meal']*meal['Protein']`
#Let x=meal['use_meal'] and y=meal['Protein']
#Let u be an upper bound on the value of meal['Protein']
#We will make constraints such that
# w <= u*y
# w >=0 if we don't use the meal, `w` is zero
# w <= y if we do use the meal, `w` must not be larger than the meal's value
# w >= u*(x-1)+y if we use the meal, then `w>=y` and `w<=y`, so `w==y`; otherwise, `w>=-u+y`
u = 9999 #An upper bound on the value of any meal quantity
for meal in meals:
for q in quantities:
w = cp.Variable()
constraints.append( w<=u*meal['use_meal'] )
constraints.append( w>=0 )
constraints.append( w<=meal[q] )
constraints.append( w>=u*(meal['use_meal']-1)+meal[q] )
totals[q] += w
#Construct constraints. The totals must be within the ranges given
constraints.append( total_daily_protein_min <= totals['Protein'] )
constraints.append( total_daily_carbs_min <= totals['Carbohydrate'] )
constraints.append( total_daily_lipids_min <= totals['Total Lipid'] )
constraints.append( totals['Protein'] <= total_daily_protein_max)
constraints.append( totals['Carbohydrate'] <= total_daily_carbs_max )
constraints.append( totals['Total Lipid'] <= total_daily_lipids_max )
#Ensure that we're doing three meals because this is the number of meals people
#in some countries eat.
constraints.append( sum([meal['use_meal'] for meal in meals])==3 )
#With an objective value of 1 we are asking the solver to identify any feasible
#solution. We don't care which one.
objective = cp.Minimize(1)
#We could also use:
#objective = cp.Minimize(totals['Kilocalories'])
#to meet nutritional needs while minimizing calories intake
problem = cp.Problem(objective, constraints)
val = problem.solve(solver=cp.GLPK_MI, verbose=True)
if val==1:
for q in quantities:
print("{0} = {1}".format(q, totals[q].value))
for m in meals:
if m['use_meal'].value!=1:
continue
print(m['name'])
for f in m['foods']:
print("\t{0} units of {1} (min={2}, max={3})".format(f['portion'].value, f['Description'], f['min'], f['max']))
The result looks like this:
Protein = 46.0
Carbohydrate = 224.99999999999997
Total Lipid = 69.68255808922696
Kilocalories = 1719.4249142101326
Meal #1
10.0 units of TURKEY,BREAST,SMOKED,LEMON PEPPER FLAVOR,97% FAT-FREE (min=10, max=1000)
10.0 units of MCDONALD'S,BACON EGG & CHS BISCUIT (min=10, max=1000)
1000.0 units of CANDIES,FUDGE,CHOC,PREPARED-FROM-RECIPE (min=10, max=1000)
1000.0 units of OLD EL PASO CHILI W/BNS,CND ENTREE (min=10, max=1000)
Meal #2
999.9999999960221 units of CAMPBELL SOUP,CAMPBELL'S RED & WHITE,BROCCOLI CHS SOUP,COND (min=10, max=1000)
10.0 units of LAMB,AUS,IMP,FRSH,RIB,LN&FAT,1/8"FAT,RAW (min=10, max=1000)
10.0 units of TURKEY,BREAST,SMOKED,LEMON PEPPER FLAVOR,97% FAT-FREE (min=10, max=1000)
10.0 units of MCDONALD'S,BACON EGG & CHS BISCUIT (min=10, max=1000)
Meal #5
1000.0 units of OLD EL PASO CHILI W/BNS,CND ENTREE (min=10, max=1000)
221.06457214122466 units of CHEESE,PAST PROCESS,SWISS,W/DI NA PO4 (min=10, max=1000)
10.0 units of LAMB,DOM,SHLDR,WHL (ARM&BLD),LN&FAT,1/8"FAT,CHOIC,CKD,RSTD (min=10, max=1000)
For reasons that are unclear to me, GLPK fails pretty often, though it does find a solution about 1 out of 20 times. This is disappointing since failing to find a solution looks the same as if it had proven there is no solution.
At the moment, I guess I'd recommend running it a larger number of times to before ruling out the possibility of a solution.
Note that adding more foods and meals should make it easier for the solver to find a solution and reduce the frequency of the problem above.
Another way to approach this problem would be to enumerate subsets of meals, such as all subsets of three meals a day. Determining whether a given subset of meals satisfies portion and nutrient constraints is then a linear programming which can be solved quickly and easily. The downside to this is that there may be a large number of meal combinations to enumerate. MIP solvers may have techniques to reduce the number of combinations that need to be searched.
It sounds like a variation of the theme of the Diet Problem, and Mathematical Programming is an effective approach, as Richard clearly pointed out. However this may not be feasible in your case, since there are not many libraries for mathematical programming on mobile devices (may some can be found here), but I am not aware of any DART libraries for linear programming.
As an alternative, a metaheuristic approach might work well, and you have plenty of alternatives, including Genetic Algorithms.
Independently of the algorithm you are going to adopt, one choice you need to make is how to encode solutions. The most natural choice would be to use non-negative continuous (i.e., real) decision variables: let's call them xfm, representing the amount of food f at meal m (it does not matter whether m is the 3rd meal of the 5th day of the 2nd week: just number them progressively). Two subscripts, so they form a matrix of values of F rows times M columns. One natural way to encode them would be to unroll that matrix into a vector xi, i.e., write each row of the matrix one after the other in an array, so that each subscript i identifies a specific pair (f,m).
Next you need to clearly define what the objective function is and have a procedure for calculating it from your encoded solutions.
Next you need a procedure for generating new solutions to be evaluated (look at point 2 here for some ideas).
If you wish to stick with genetic algorithms, here are some ideas for mutation and crossover, just make sure to preserve non-negativity.

If Random variable is a function

The basic definition of random variable is that it is a function based on random experiment.the question is that if it is a function say f then how can it take numerical values..
Suppose if we toss two coins and X be random variable relating no. of heads with (0,1,2) .For event of two heads say w....we have X(w)=2 is value of function X at w. and not of X itself..
But sometimes it is written that x is a r .v taking values 0,1,2,....
Don't it sound wrong to say function and takes values?
A random variable is a well defined function X: E -> R, whose domain E is a probability space and its codomain is (generally speaking) the set of real numbers.
Intuitively, X is some kind of metric or measurement on the elements of E.
Example 1
Let E be the set of users of Stack Overflow at a given point in time, say right now. And let X be the function that assigns their reputation to every SO user. For example, you could calculate P(X >= 5000) which is the percent of SO users with a reputation of 5000 or more.
Notice that P(X >= 5000) is nothing but a compact notation for the subset of E defined as:
{u in E | X(u) >= 5000}
meaning the subset of SO users u with a reputation of 5000 or more.
Example 2
Let E be the set of questions in SO and X the function that assigns the number of votes (at certain point in time) to each question. If you pick one question q at random, X(q) would be its number of votes and we could ask for the probability of, say, X < 0 (down-voted questions.)
Here the subset of such questions is
{q in E | X(q) < 0}
i.e., the subset of questions q having a negative vote count.
Conclusion
There is nothing random in a Random variable. The randomness is in the way we pick elements (or subsets) from its domain.
Speaking of functions - Yes, it is safe to say that a function can take certain values. Speaking of random variables and probability, the definition I know is:
A random variable assigns a numerical value to each possible outcome of a random experiment
This definition does indeed say that X (aka random variable) is a function. In your case, where it is said that X (as in function) can take values 0,1,2 is basically saying that the subset of the codomain (or even the codomain or target set itself) of function X is the set {0,1,2}, or interval
[0,2] ⊂ ℕ.

Algorithm to calculate sum of points for groups with varying member count [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Let's start with an example. In Harry Potter, Hogwarts has 4 houses with students sorted into each house. The same happens on my website and I don't know how many users are in each house. It could be 20 in one house 50 in another and 100 in the third and fourth.
Now, each student can earn points on the website and at the end of the year, the house with the most points will win.
But it's not fair to "only" do a sum of the points, as the house with a 100 students will have a much higher chance to win, as they have more users to earn points. So I need to come up with an algorithm which is fair.
You can see an example here: https://worldofpotter.dk/points
What I do now is to sum all the points for a house, and then divide it by the number of users who have earned more than 10 points. This is still not fair, though.
Any ideas on how to make this calculation more fair?
Things we need to take into account:
* The percent of users earning points in each house
* Few users earning LOTS of points
* Many users earning FEW points (It's not bad earning few points. It still counts towards the total points of the house)
Link to MySQL dump(with users, houses and points): https://worldofpotter.dk/wop_points_example.sql
Link to CSV of points only: https://worldofpotter.dk/points.csv
I'd use something like Discounted Cumulative Gain which is used for measuring the effectiveness of search engines.
The concept is as it follows:
FUNCTION evalHouseScore (0_INDEXED_SORTED_ARRAY scores):
score = 0;
FOR (int i = 0; i < scores.length; i++):
score += scores[i]/log2(i);
END_FOR
RETURN score;
END_FUNCTION;
This must be somehow modified as this way of measuring focuses on the first result. As this is subjective you should decide on your the way you would modify it. Below I'll post the code which some constants which you should try with different values:
FUNCTION evalHouseScore (0_INDEXED_SORTED_ARRAY scores):
score = 0;
FOR (int i = 0; i < scores.length; i++):
score += scores[i]/log2(i+K);
END_FOR
RETURN L*score;
END_FUNCTION
Consider changing the logarithm.
Tests:
int[] g = new int[] {758,294,266,166,157,132,129,116,111,88,83,74,62,60,60,52,43,40,28,26,25,24,18,18,17,15,15,15,14,14,12,10,9,5,5,4,4,4,4,3,3,3,2,1,1,1,1,1};
int[] s = new int[] {612,324,301,273,201,182,176,139,130,121,119,114,113,113,106,86,77,76,65,62,60,58,57,54,54,42,42,40,36,35,34,29,28,23,22,19,17,16,14,14,13,11,11,9,9,8,8,7,7,7,6,4,4,3,3,3,3,2,2,2,2,2,2,2,1,1,1};
int[] h = new int[] {813,676,430,382,360,323,265,235,192,170,107,103,80,70,60,57,43,41,21,17,15,15,12,10,9,9,9,8,8,6,6,6,4,4,4,3,2,2,2,1,1,1};
int[] r = new int[] {1398,1009,443,339,242,215,210,205,177,168,164,144,144,92,85,82,71,61,58,47,44,33,21,19,18,17,12,11,11,9,8,7,7,6,5,4,3,3,3,3,2,2,2,1,1,1,1};
The output is for different offsets:
1182
1543
1847
2286
904
1231
1421
1735
813
1120
1272
1557
It sounds like some sort of constraint between the houses may need to be introduced. I might suggest finding the person that earned the most points out of all the houses and using it as the denominator when rolling up the scores. This will guarantee the max value of a user's contribution is 1, then all the scores for a house can be summed and then divided by the number of users to normalize the house's score. That should give you a reasonable comparison. It does introduce issues with low numbers of users in a house that are high achievers in which you may want to consider lower limits to the number of house members. Another technique may be to introduce handicap scores for users to balance the scales. The algorithm will most likely flex over time based on the data you receive. To keep it fair it will take some responsive action after the initial iteration. Players can come up with some creative ways to make scoring systems work for them. Here is some pseudo-code in PHP that you may use:
<?php
$mostPointsEarned; // Find the user that earned the most points
$houseScores = [];
foreach ($houses as $house) {
$numberOfUsers = 0;
$normalizedScores = [];
foreach ($house->getUsers() as $user) {
$normalizedScores[] = $user->getPoints() / $mostPointsEarned;
$numberOfUsers++;
}
$houseScores[] = array_sum($normalizedScores) / $numberOfUsers;
}
var_dump($houseScores);
You haven't given any examples on what should be preferred state, and what are situations against which you want to be immune. (3,2,1,1 compared to 5,2 etc.)
It's also a pity you haven't provided us the dataset in some nice way to play.
scala> val input = Map( // as seen on 2016-09-09 14:10 UTC on https://worldofpotter.dk/points
'G' -> Seq(758,294,266,166,157,132,129,116,111,88,83,74,62,60,60,52,43,40,28,26,25,24,18,18,17,15,15,15,14,14,12,10,9,5,5,4,4,4,4,3,3,3,2,1,1,1,1,1),
'S' -> Seq(612,324,301,273,201,182,176,139,130,121,119,114,113,113,106,86,77,76,65,62,60,58,57,54,54,42,42,40,36,35,34,29,28,23,22,19,17,16,14,14,13,11,11,9,9,8,8,7,7,7,6,4,4,3,3,3,3,2,2,2,2,2,2,2,1,1,1),
'H' -> Seq(813,676,430,382,360,323,265,235,192,170,107,103,80,70,60,57,43,41,21,17,15,15,12,10,9,9,9,8,8,6,6,6,4,4,4,3,2,2,2,1,1,1),
'R' -> Seq(1398,1009,443,339,242,215,210,205,177,168,164,144,144,92,85,82,71,61,58,47,44,33,21,19,18,17,12,11,11,9,8,7,7,6,5,4,3,3,3,3,2,2,2,1,1,1,1)
) // and the results on the website were: 1. R 1951, 2. H 1859, 3. S 990, 4. G 954
Here is what I thought of:
def singleValuedScore(individualScores: Seq[Int]) = individualScores
.sortBy(-_) // sort from most to least
.zipWithIndex // add indices e.g. (best, 0), (2nd best, 1), ...
.map { case (score, index) => score * (1 + index) } // here is the 'logic'
.max
input.mapValues(singleValuedScore)
res: scala.collection.immutable.Map[Char,Int] =
Map(G -> 1044,
S -> 1590,
H -> 1968,
R -> 2018)
The overall positions would be:
Ravenclaw with 2018 aggregated points
Hufflepuff with 1968
Slytherin with 1590
Gryffindor with 1044
Which corresponds to the ordering on that web: 1. R 1951, 2. H 1859, 3. S 990, 4. G 954.
The algorithms output is maximal product of score of user and rank of the user within a house.
This measure is not affected by "long-tail" of users having low score compared to the active ones.
There are no hand-set cutoffs or thresholds.
You could experiment with the rank attribution (score * index or score * Math.sqrt(index) or score / Math.log(index + 1) ...)
I take it that the fair measure is the number of points divided by the number of house members. Since you have the number of points, the exercise boils down to estimate the number of members.
We are in short supply of data here as the only hint we have on member counts is the answers on the website. This makes us vulnerable to manipulation, members can trick us into underestimating their numbers. If the suggested estimation method to "count respondents with points >10" would be known, houses would only encourage the best to do the test to hide members from our count. This is a real problem and the only thing I will do about it is to present a "manipulation indicator".
How could we then estimate member counts? Since we do not know anything other than test results, we have to infer the propensity to do the test from the actual results. And we have little other to assume than that we would have a symmetric result distribution (of the logarithm of the points) if all members tested. Now let's say the strong would-be respondents are more likely to actually test than weak would-be respondents. Then we could measure the extra dropout ratio for the weak by comparing the numbers of respondents in corresponding weak and strong test-point quantiles.
To be specific, of the 205 answers, there are 27 in the worst half of the overall weakest quartile, while 32 in the strongest half of the best quartile. So an extra 5 respondents of the very weakest have dropped out from an assumed all-testing symmetric population, and to adjust for this, we are going to estimate member count from this quantile by multiplying the number of responses in it by 32/27=about 1.2. Similarly, we have 29/26 for the next less-extreme half quartiles and 41/50 for the two mid quartiles.
So we would estimate members by simply counting the number of respondents but multiplying the number of respondents in the weak quartiles mentioned above by 1.2, 1.1 and 0.8 respectively. If however any result distribution within a house would be conspicuously skewed, which is not the case now, we would have to suspect manipulation and re-design our member count.
For the sample at hand however, these adjustments to member counts are minor, and yields the same house ranks as from just counting the respondents without adjustments.
I got myself to amuse me a little bit with your question and some python programming with some random generated data. As some people mentioned in the comments you need to define what is fairness. If as you said you don't know the number of people in each of the houses, you can use the number of participations of each house, thus you motivate participation (it can be unfair depending on the number of people of each house, but as you said you don't have this data on the first place).
The important part of the code is the following.
import numpy as np
from numpy.random import randint # import random int
# initialize random seed
np.random.seed(4)
houses = ["Gryffindor","Slytherin", "Hufflepuff", "Ravenclaw"]
houses_points = []
# generate random data for each house
for _ in houses:
# houses_points.append(randint(0, 100, randint(60,100)))
houses_points.append(randint(0, 50, randint(2,10)))
# count participation
houses_participations = []
houses_total_points = []
for house_id in xrange(len(houses)):
houses_total_points.append(np.sum(houses_points[house_id]))
houses_participations.append(len(houses_points[house_id]))
# sum the total number of participations
total_participations = np.sum(houses_participations)
# proposed model with weighted total participation points
houses_partic_points = []
for house_id in xrange(len(houses)):
tmp = houses_total_points[house_id]*houses_participations[house_id]/total_participations
houses_partic_points.append(tmp)
The results of this method are the following:
House Points per Participant
Gryffindor: [46 5 1 40]
Slytherin: [ 8 9 39 45 30 40 36 44 38]
Hufflepuff: [42 3 0 21 21 9 38 38]
Ravenclaw: [ 2 46]
House Number of Participations per House
Gryffindor: 4
Slytherin: 9
Hufflepuff: 8
Ravenclaw: 2
House Total Points
Gryffindor: 92
Slytherin: 289
Hufflepuff: 172
Ravenclaw: 48
House Points weighted by a participation factor
Gryffindor: 16
Slytherin: 113
Hufflepuff: 59
Ravenclaw: 4
You'll find the complete file with printing results here (https://gist.github.com/silgon/5be78b1ea0b55a20d90d9ec3e7c515e5).
You should enter some more rules to define the fairness.
Idea 1
You could set up the rule that anyone has to earn at least 10 points to enter the competition.
Then you can calculate the average points for each house.
Positive: Everyone needs to show some motivation.
Idea 2
Another approach would be to set the rule that from each house only the 10 best students will count for the competition.
Positive: Easy rule to calculate the points.
Negative: Students might become uninterested if they see they can't reach the top 10 places of their house.
From my point of view, your problem is diveded in a few points:
The best thing to do would be to re - assignate the player in the different Houses so that each House has the same number of players. (as explain by #navid-vafaei)
If you don't want to do that because you believe that it may affect your game popularity with player whom are in House that they don't want because you can change the choice of the Sorting Hat at least in the movie or books.
In that case, you can sum the point of the student's house and divide by the number of students. You may just remove the number of student with a very low score. You may remove as well the student with a very low activity because students whom skip school might be fired.
The most important part for me n your algorithm is weather or not you give points for all valuables things:
In the Harry Potter's story, the students earn point on the differents subjects they chose at school and get point according to their score.
At the end of the year, there is a special award event. At that moment, the Director gave points for valuable things which cannot be evaluated in the subject at school suche as the qualites (bravery for example).

Who owes who money optimization

Say you have n people, each who owe each other money. In general it should be possible to reduce the amount of transactions that need to take place. i.e. if X owes Y £4 and Y owes X £8, then Y only needs to pay X £4 (1 transaction instead of 2).
This becomes harder when X owes Y, but Y owes Z who owes X as well. I can see that you can easily calculate one particular cycle. It helps for me when I think of it as a fully connected graph, with the edges being the amount each person owes.
Problem seems to be NP-complete, but what kind of optimisation algorithm could I make, nevertheless, to reduce the total amount of transactions? Doesn't have to be that efficient, as N is quite small for me.
Edit:
The purpose of this problem would be to be able to have in the accounting system something that can say to each person when they log in "You can remove M amount of transactions by simply paying someone X amount, and someone else Y amount". Hence the bank solution (though optimal if everyone is paying at the same time) cannot really be used here.
Are people required to clear their debts by paying somebody that they actually owe money to personally? If not, the following seems to work suspiciously easily:
For each person, work out the net amount they should pay, or should receive.
Have somebody who owes money net pay somebody who should receive money net min(amount owed, amount to be received). After this, at least one of the two participants owes nothing and should receive nothing, and so can be removed from the problem.
Assuming I have missed something, what are the constraints that apply (or gross error made)?
I have created an Android app which solves this problem. You can input expenses during the trip, it even recommends you "who should pay next". At the end it calculates "who should send how much to whom". My algorithm calculates minimum required number of transactions and you can setup "transaction tolerance" which can reduce transactions even further (you don't care about $1 transactions) Try it out, it's called Settle Up:
https://market.android.com/details?id=cz.destil.settleup
Description of my algorithm:
I have basic algorithm which solves the problem with n-1 transactions, but it's not optimal. It works like this: From payments, I compute balance for each member. Balance is what he paid minus what he should pay. I sort members according to balance increasingly. Then I always take the poorest and richest and transaction is made. At least one of them ends up with zero balance and is excluded from further calculations. With this, number of transactions cannot be worse than n-1. It also minimizes amount of money in transactions. But it's not optimal, because it doesn't detect subgroups which can settle up internally.
Finding subgroups which can settle up internally is hard. I solve it by generating all combinations of members and checking if sum of balances in subgroup equals zero. I start with 2-pairs, then 3-pairs ... (n-1)pairs. Implementations of combination generators are available. When I find a subgroup, I calculate transactions in the subgroup using basic algorithm described above. For every found subgroup, one transaction is spared.
The solution is optimal, but complexity increases to O(n!). This looks terrible but the trick is there will be just small number of members in reality. I have tested it on Nexus One (1 Ghz procesor) and the results are: until 10 members: <100 ms, 15 members: 1 s, 18 members: 8 s, 20 members: 55 s. So until 18 members the execution time is fine. Workaround for >15 members can be to use just the basic algorithm (it's fast and correct, but not optimal).
Source code:
Source code is available inside a report about algorithm written in Czech. Source code is at the end and it's in English:
http://settleup.destil.cz/report.pdf
Nominate one person arbitrarily to be the banker.
Each other person transfers the sum of all the outgoing transactions minus the incoming transactions (so either deposits or withdraws) to that person.
There will be a maximum of (n-1) transactions, which is pretty small. It is fast. It is simple.
Given that everyone who transfers money will have to be involved in a transaction anyway*, it is bounded to be at worst twice the optimal case.**
* The exception is the banker themselves. A quick optimisation is to ensure the nominated banker is not someone who holds a neutral position.
** Explaining my upper bound logic further:
Suppose the optimal case is A gives $1 to B, and C gives $1 to D, and E is neutral = two transactions.
Then with this logic, if E is the nominated banker, A gives $1 to E, E gives $1 to B, C gives $1 to E and E gives $1 to D = four transactions.
With the optimisation, making sure you don't choose a neutral person for banker, select A instead.
A gives $1 to B, C gives $1 to A. A gives $1 to D = three transactions.
for each debt in debts
debt.creditor.owed -= debt.amount
debt.deptor.owed += debt.amount
end
for each person in persons
if person.owed > 0 then
deptors.add person
else if person.owed < 0 then
creditors.add person
end
end
deptors.sort_by_owed_desc
creditor.sort_by_owed_asc
for each debtor in deptors
while debtor.owed > 0
creditor = creditors.top
amount = min( debtor.owed, -creditor.owed)
creditor.owed += amount
debtor.owed -= amount
if creditor.owed == 0 then
creditors.remove_top
end
write debtor.name " owes " creditor.name " " amount "€"
end
end
Just thinking about it I'd start by looking at each cycle in the directed graph and reducing each edge in the cycle by the value of the minimum edge in the cycle, then remove the minimum edge altogether. Rinse and repeat.
Here's the Python solution I used; it's the same idea as Gunner's post, with a few line changes:
for i in N:
for j in N:
if i!=j and owes[i][j] > owes[j][i]:
owes[i][j] -= owes[j][i]
owes[j][i] = 0
for k in N:
for i in N:
for j in N:
if k == i or i == j or k == j:
continue
if owes[j][k] > owes[i][j]:
owes[i][k] += owes[i][j]
owes[j][k] -= owes[i][j]
owes[i][j] = 0;
Works a treat.
You can test it with i.e.:
owes = [[0,2,11], [4,0,7], [2,3,0]]
N = range(len(owes))
I think you need to build a different data structure ( a tree, each time one person is the root node) that will check for each person how many "transaction" can you "kill", than, choose the best one, make the cycle, and rebuild it again.it is not o(N), I Think it's N^2 though, and it will not give you the best result. it is just a strategy.
This problem may be tackled with the Warshall algorithm.
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if ( i!= j && owes[i][j] > owes[j][i] )
owes[i][j] -= (owes[i][j] - owes[j][i]), owes[j][i] = 0;
for(k=0;k<n;k++)
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if( k == i || i == j || k == j ) continue;
if ( owes[j][k] > owes[i][j] )
{
int diff = owes[j][k] - owes[i][j];
owes[i][j] = 0;
owes[i][k ] += diff;
owes[j][k] -= diff;
}
}
After the algorithm finishes, the total number of transactions required would be the number of positive entries in the owes table.
I have not verified yet whether the algorithm will work, based on nature of the problem it may work. Solution is O(N^3).
I think you must remove all cicles reducing edges by minimal edge value and removingedges with value 0. After it you will get graph withouth cicles. I think you must find vertexes, wich have no pointers to them (man's wich owes only others money). This man's must pay money, beacouse there is no one to pay the money for them. So my point is that you must find somehow who they must pay.
I have a solution to the problem written in matlab. It is based on a matrix of who owes who what. The number in the (i,j) means that person j owes person i the number. E.g.
B owes A 2
and A owes B 1
of course in this case it is trivial that B should just give A 1
This becomes more complex with more entries. However, with the algorithm i wrote i can guarantee that no more than N-1 transactions occurs where N is the number of persones 2 in this case.
Here is the code i wrote.
function out = whooweswho(matrix)
%input sanitation
if ~isposintscalar(matrix)
[N M] = size(matrix);
if N ~= M
error('Matrix must be square');
end
for i=1:N
if matrix(N,N) ~= 0
error('Matrix must have zero on diagonals');
end
end
else
%construction of example matrix if input is a positive scalar
disp('scalar input: Showing example of NxN matrix randomly filled');
N = matrix;
matrix = round(10*N*rand(N,N)).*(ones(N,N)-eye(N))
end
%construction of vector containing each persons balance
net = zeros(N,1);
for i=1:N
net(i) = sum(matrix(i,:))-sum(matrix(:,i));
end
%zero matrix, so it can be used for the result
matrix = zeros(size(matrix));
%sum(net) == 0 always as no money dissappears. So if min(net) == 0 it
%implies that all balances are zero and we are done.
while min(net) ~= 0
%find the poorest and the richest.
[rec_amount reciever] = max(net);
[give_amount giver] = min(net);
%balance so at least one of them gets zero balance.
amount =min(abs(rec_amount),abs(give_amount));
net(reciever) = net(reciever) - amount;
net(giver) = net(giver) + amount;
%store result in matrix.
matrix(reciever,giver) = amount;
end
%output equivalent matrix of input just reduced.
out = matrix;
end

Resources