Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // https://en.wikipedia.org/wiki/Maximum_flow_problem#Maximum_cardinality_bipartite_matching
- // array of array mapping sport to camps
- // compute another array mapping sport to (sport_slots - requests)
- // sort desc
- // negative values mean some kids will be left aside
- // fill result and decrement second array until each value is negative or zero
- void Main()
- {
- var kids = new []
- {
- new Kid("Ben", "Baseball"),
- new Kid("John", "Baseball"),
- new Kid("Tom", "Baseball"),
- new Kid("Chris", "Soccer"),
- new Kid("Josh", "Soccer"),
- new Kid("Alan", "Basketball"),
- new Kid("Timmy", "Basketball"),
- new Kid("Greg", "Tennis"),
- };
- var camps = new []
- {
- new Camp("Cool Camp", new [] { "Baseball", "Soccer" }),
- new Camp("Fun Camp", new [] { "Baseball" }),
- new Camp("Super Camp", new [] { "Basketball" }),
- new Camp("Sporty Camp", new [] { "Basketball" }),
- new Camp("Nerd Camp", new [] { "Programming" }),
- new Camp("Super Nerd Camp", new [] { "Programming" })
- };
- var sportOpenSlots = camps
- .SelectMany(sc => sc.Sports, (Camp, Sport) => new { Camp, Sport } )
- //.Dump("sportOpenSlots")
- ;
- var requirements = kids
- .GroupBy(x => x.Sport)
- .Select(group => new { Sport = group.Key, SpotRequired = group.Count() })
- //.Dump("requirements")
- ;
- var allocatableSports =
- (
- from sos in sportOpenSlots
- join r in requirements
- on sos.Sport equals r.Sport into unused
- from u in unused.DefaultIfEmpty()
- where u != null
- select new { Sport = sos.Sport, Camp = sos.Camp, Required = u.SpotRequired }
- )
- .OrderByDescending(x => x.Camp.OpenSpots - x.Required)
- ;
- //allocatableSports.Dump("allocatableSports");
- var SportInCamps = (from a in allocatableSports select a.Sport).Distinct();
- //SportInCamps.Dump("SportInCamps");
- var kidsWithAllocatableSports =
- from sic in SportInCamps
- join k in kids
- on sic equals k.Sport into matched
- from m in matched.DefaultIfEmpty()
- where m != null
- select m;
- //kidsWithAllocatableSports.Dump("kidsWithAllocatableSports");
- foreach (var currentSport in allocatableSports)
- {
- var kid = kids.Where(k => k.Camp == null & k.Sport == currentSport.Sport).FirstOrDefault();
- while (kid != null)
- {
- kid.Camp = currentSport.Camp.Name;
- currentSport.Camp.OpenSpots -= 1;
- if (currentSport.Camp.OpenSpots == 0) break;
- kid = kids.Where(k => k.Camp == null & k.Sport == currentSport.Sport).FirstOrDefault();
- }
- }
- //kids.Dump();
- }
- public class Kid
- {
- public string Name { get; set; }
- public string Sport { get; set; }
- public string Camp { get; set; }
- public Kid(string name, string sport, string camp = null)
- {
- this.Name = name;
- this.Sport = sport;
- this.Camp = camp;
- }
- }
- public class Camp
- {
- public string Name { get; set; }
- public string[] Sports { get; set; }
- public int OpenSpots { get; set; }
- public Camp(string name, string[] sports)
- {
- this.Name = name;
- this.Sports = sports;
- this.OpenSpots = 3;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement