|
1 | 1 | package base |
2 | 2 |
|
3 | | -import ( |
4 | | - "sort" |
5 | | -) |
6 | | - |
7 | 3 | type VoteResult string |
8 | 4 |
|
9 | 5 | const ( |
@@ -47,86 +43,56 @@ func (v *VoteResult) UnmarshalText(b []byte) error { |
47 | 43 | return nil |
48 | 44 | } |
49 | 45 |
|
50 | | -// FindMajority finds the majority(over threshold) set between the given sets. |
51 | | -// The returned value means, |
52 | | -// 0-N: index number of set |
53 | | -// -1: not yet majority |
54 | | -// -2: draw |
55 | | -func FindMajority(quorum, threshold uint, set ...uint) int { |
| 46 | +func FindVoteResult(quorum, threshold uint, s []string) (result VoteResult, key string) { |
56 | 47 | th := threshold |
57 | 48 | if th > quorum { |
58 | 49 | th = quorum |
59 | 50 | } |
60 | 51 |
|
61 | | - if len(set) < 1 { |
62 | | - return -1 |
| 52 | + total := uint(len(s)) |
| 53 | + if total == 0 { |
| 54 | + return VoteResultNotYet, "" |
63 | 55 | } |
64 | 56 |
|
65 | | - var sum uint |
66 | | - |
67 | | - for i := range set { |
68 | | - n := set[i] |
69 | | - |
70 | | - if n >= quorum { |
71 | | - return i |
72 | | - } |
73 | | - |
74 | | - if n >= th { |
75 | | - return i |
76 | | - } |
77 | | - |
78 | | - sum += n |
| 57 | + var remain uint |
| 58 | + if total < quorum { |
| 59 | + remain = quorum - total |
79 | 60 | } |
80 | 61 |
|
81 | | - sort.Slice(set, func(i, j int) bool { |
82 | | - return set[i] > set[j] |
83 | | - }) |
84 | | - |
85 | | - if quorum-sum+set[0] < th { |
86 | | - return -2 |
| 62 | + count := make(map[string]uint, len(s)) |
| 63 | + for _, v := range s { |
| 64 | + count[v]++ |
87 | 65 | } |
88 | 66 |
|
89 | | - return -1 |
90 | | -} |
91 | | - |
92 | | -func FindVoteResult(quorum, threshold uint, s []string) (result VoteResult, key string) { |
93 | | - th := threshold |
94 | | - if th > quorum { |
95 | | - th = quorum |
96 | | - } |
97 | | - |
98 | | - if len(s) < 1 { |
99 | | - return VoteResultNotYet, "" |
| 67 | + var ( |
| 68 | + maxCount uint |
| 69 | + topTies uint |
| 70 | + mhs string |
| 71 | + ) |
| 72 | + for hs, cn := range count { |
| 73 | + if cn > maxCount { |
| 74 | + maxCount = cn |
| 75 | + mhs = hs |
| 76 | + topTies = 1 |
| 77 | + } else if cn == maxCount { |
| 78 | + topTies++ |
| 79 | + if hs < mhs { |
| 80 | + mhs = hs |
| 81 | + } |
| 82 | + } |
100 | 83 | } |
101 | 84 |
|
102 | | - keys := map[uint]string{} |
103 | | - defer clear(keys) |
104 | | - |
105 | | - count := map[string]uint{} |
106 | | - defer clear(count) |
107 | | - |
108 | | - for i := range s { |
109 | | - count[s[i]]++ |
| 85 | + if maxCount >= th { |
| 86 | + return VoteResultMajority, mhs |
110 | 87 | } |
111 | 88 |
|
112 | | - set := make([]uint, len(count)) |
113 | | - var i int |
114 | | - |
115 | | - for j := range count { |
116 | | - c := count[j] |
117 | | - keys[c] = j |
118 | | - set[i] = c |
119 | | - i++ |
| 89 | + if remain == 0 { |
| 90 | + return VoteResultDraw, "" |
120 | 91 | } |
121 | 92 |
|
122 | | - sort.Slice(set, func(i, j int) bool { return set[i] > set[j] }) |
123 | | - |
124 | | - switch index := FindMajority(quorum, th, set...); index { |
125 | | - case -1: |
126 | | - return VoteResultNotYet, "" |
127 | | - case -2: |
| 93 | + if maxCount+remain < th { |
128 | 94 | return VoteResultDraw, "" |
129 | | - default: |
130 | | - return VoteResultMajority, keys[set[index]] |
131 | 95 | } |
| 96 | + |
| 97 | + return VoteResultNotYet, "" |
132 | 98 | } |
0 commit comments