Created
March 25, 2020 18:47
-
-
Save david-beckman/98556bc508a305cf1d9df16234889b81 to your computer and use it in GitHub Desktop.
Israeli Parliamentary Coalitions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://ayende.com/blog/190275-C/giving-a-job-candidate-a-hard-problem | |
static var parliment = new Dictionary<string, (int Seats, int Index)> | |
{ | |
["Likud"] = (36, 0), | |
["KahulLaval"] = (33, 1), | |
["JointList"] = (15, 2), | |
["Shas"] = (9, 3), | |
["YahadutHatora"] = (7, 4), | |
["IsrealBeitenu"] = (7, 5), | |
["AvodaGesherMeretz"] = (7, 6), | |
["Yemina"] = (6, 7) | |
}; | |
static var likes = new[,] | |
{ | |
// likud, kahul, joint, shas, yahdut, beitenu, avoda, yemina | |
{ 1.0, -0.5, -1.0, 0.95, 0.95, -0.2, -0.8, 0.95}, // likud | |
{ -0.9, 1.0, -0.6, -0.5, -0.5, 0.5, 0.8, -0.2}, // kahul | |
{ -0.9, -0.3, 1.0, -0.6, -0.6, -1.0, -0.2, -1.0}, // joint | |
{ 0.96, -0.7, -0.6, 1.0, 0.9, -1.0, -0.7, 0.8}, // shas | |
{ 0.97, -0.6, -0.6, 0.92, 1.0, -1.0, -0.6, 0.7}, // yahadut | |
{ -0.4, -0.1, -1.0, -0.99, -0.99, 1.0, -0.6, 0.1}, // beitenu | |
{ -0.95, 0.98, 0.3, -0.89, -0.89, -0.01, 1.0, -0.75}, // avoda | |
{ 0.999, -0.92, -1.0, 0.86, 0.85, -0.3, -0.4, 1.0}, // yemina | |
}; | |
static var target = Math.Ceiling((parliment.Sum(party => party.Value.Seats) + 1) / 2.0); // 61 | |
Coalition.GetAllCoalitions() | |
.Where(coalition => coalition.IsSufficient && coalition.IsLikely) | |
.OrderByDescending(coalition => coalition.Likelyhood) | |
.Select(coalition => coalition.ToString()) | |
.Dump(); | |
public class Coalition | |
{ | |
public Coalition(IReadOnlyCollection<KeyValuePair<string, (int Seats, int Index)>> members) | |
{ | |
this.Members = members ?? throw new ArgumentNullException(nameof(members)); | |
if (this.Members.Count == 0) | |
{ | |
throw new ArgumentOutOfRangeException(nameof(members), "There must be at least 1 member of a coalition."); | |
} | |
} | |
private IReadOnlyCollection<KeyValuePair<string, (int Seats, int Index)>> Members { get; } | |
public IReadOnlyCollection<string> MemberNames => this.Members.Select(party => party.Key).ToArray(); | |
public int Seats => this.Members.Sum(party => party.Value.Seats); | |
public bool IsSufficient => Seats >= target; | |
private double DenormalizedLikelyhood => this.Members.SelectMany(party1 => this.Members.Select(party2 => new {party1, party2})) | |
.Sum(relationship => likes[relationship.party1.Value.Index, relationship.party2.Value.Index]); | |
public double Likelyhood => this.Members.Count == 1 | |
? DenormalizedLikelyhood | |
: 2 * (DenormalizedLikelyhood - this.Members.Count) / (this.Members.Count * (this.Members.Count - 1)); | |
public bool IsLikely => this.Likelyhood > 0.0; | |
public override string ToString() | |
{ | |
return string.Format("Seats: {0} Likelyhood: {1:0.0000} Members: {2}", this.Seats, this.Likelyhood, string.Join(", ", this.MemberNames)); | |
} | |
public static IEnumerable<Coalition> GetAllCoalitions() | |
{ | |
var combo = new bool[parliment.Count]; | |
// Ignore all false... | |
while (GetNextCombo(ref combo, combo.Length - 1)) | |
{ | |
yield return new Coalition(parliment.Where(party => combo[party.Value.Index]).ToArray()); | |
} | |
} | |
private static bool GetNextCombo(ref bool[] combo, int index) | |
{ | |
if (index < 0) return false; | |
if (!combo[index]) | |
{ | |
return combo[index] = true; | |
} | |
combo[index] = false; | |
return GetNextCombo(ref combo, index - 1); | |
} | |
} | |
/* | |
Seats: 65 Likelyhood: 0.6029 Members: Likud, Shas, YahadutHatora, IsrealBeitenu, Yemina | |
Seats: 91 Likelyhood: 0.5989 Members: Likud, KahulLaval, Shas, YahadutHatora, Yemina | |
Seats: 65 Likelyhood: 0.4829 Members: Likud, Shas, YahadutHatora, AvodaGesherMeretz, Yemina | |
Seats: 73 Likelyhood: 0.4509 Members: Likud, JointList, Shas, YahadutHatora, Yemina | |
Seats: 85 Likelyhood: 0.3250 Members: Likud, KahulLaval, Shas, YahadutHatora | |
Seats: 82 Likelyhood: 0.2998 Members: Likud, KahulLaval, YahadutHatora, Yemina | |
Seats: 84 Likelyhood: 0.2998 Members: Likud, KahulLaval, Shas, Yemina | |
Seats: 67 Likelyhood: 0.2250 Members: Likud, JointList, Shas, YahadutHatora | |
Seats: 98 Likelyhood: 0.1193 Members: Likud, KahulLaval, Shas, YahadutHatora, AvodaGesherMeretz, Yemina | |
Seats: 98 Likelyhood: 0.1073 Members: Likud, KahulLaval, Shas, YahadutHatora, IsrealBeitenu, Yemina | |
Seats: 66 Likelyhood: 0.0698 Members: Likud, JointList, Shas, Yemina | |
Seats: 64 Likelyhood: 0.0532 Members: Likud, JointList, YahadutHatora, Yemina | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment