|
2 | 2 | import java.util.stream.Collectors; |
3 | 3 |
|
4 | 4 | class Hand { |
5 | | - private String input; |
6 | | - private int score; |
| 5 | + private final String original; |
| 6 | + private final List<Card> cards; |
7 | 7 |
|
8 | 8 | Hand(String hand) { |
9 | | - this.input = hand; |
10 | | - this.score = scoreHand(parseCards(hand)); |
| 9 | + this.original = hand; |
| 10 | + this.cards = parseCards(hand); |
11 | 11 | } |
12 | 12 |
|
13 | | - int getScore() { |
14 | | - return score; |
| 13 | + String getOriginal() { |
| 14 | + return original; |
15 | 15 | } |
16 | 16 |
|
17 | | - String getInput() { |
18 | | - return input; |
19 | | - } |
| 17 | + int calculateScore() { |
| 18 | + Map<Integer, Long> rankFrequency = cards.stream() |
| 19 | + .collect(Collectors.groupingBy(Card::getRank, Collectors.counting())); |
20 | 20 |
|
21 | | - private List<Card> parseCards(String hand) { |
22 | | - ArrayList<Card> parsedCards = new ArrayList<>(); |
23 | | - String[] cardsToParse = hand.split(" "); |
24 | | - for (String cardToParse : cardsToParse) { |
25 | | - parsedCards.add(new Card(cardToParse)); |
26 | | - } |
27 | | - return parsedCards; |
28 | | - } |
| 21 | + List<Integer> ranks = rankFrequency.keySet().stream() |
| 22 | + .sorted(Comparator.reverseOrder()) |
| 23 | + .collect(Collectors.toList()); |
29 | 24 |
|
30 | | - private Map<Integer, Integer> getFrequencyMap(List<Card> cards) { |
31 | | - Map<Integer, Integer> frequencyMap = new HashMap<>(); |
32 | | - for (Card c : cards) { |
33 | | - if (frequencyMap.containsKey(c.getRank())) { |
34 | | - frequencyMap.put(c.getRank(), frequencyMap.get(c.getRank()) + 1); |
35 | | - } else { |
36 | | - frequencyMap.put(c.getRank(), 1); |
37 | | - } |
38 | | - } |
39 | | - return frequencyMap; |
40 | | - } |
41 | | - |
42 | | - private int scoreHand(List<Card> cards) { |
43 | | - List<Card> cardsByRank = cards.stream() |
44 | | - .sorted(Comparator.comparing(Card::getRank)) |
45 | | - .unordered() |
46 | | - .collect(Collectors.toList()); |
| 25 | + boolean isFlush = cards.stream() |
| 26 | + .map(Card::getSuit) |
| 27 | + .distinct() |
| 28 | + .count() == 1; |
47 | 29 |
|
48 | | - Map<Integer, Integer> frequencyMap = getFrequencyMap(cards); |
49 | | - List<Integer> ranks = frequencyMap |
50 | | - .entrySet() |
51 | | - .stream() |
52 | | - .map(Map.Entry::getKey) |
53 | | - .sorted(Comparator.reverseOrder()) |
54 | | - .collect(Collectors.toList()); |
55 | | - frequencyMap = frequencyMap |
56 | | - .entrySet() |
57 | | - .stream() |
58 | | - .sorted(Map.Entry.comparingByValue(Collections.reverseOrder())) |
59 | | - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); |
60 | | - List<Integer> rankCounts = frequencyMap |
61 | | - .entrySet() |
62 | | - .stream() |
63 | | - .map(Map.Entry::getValue) |
64 | | - .collect(Collectors.toList()); |
65 | | - List<Integer> suits = cards |
66 | | - .stream() |
67 | | - .map(Card::getSuit) |
68 | | - .collect(Collectors.toList()); |
| 30 | + boolean isStraight = ranks.size() == 5 && |
| 31 | + (ranks.get(0) - ranks.get(4) == 4 || ranks.equals(Arrays.asList(14, 5, 4, 3, 2))); |
69 | 32 |
|
70 | | - return calculatedScore(frequencyMap, cardsByRank, ranks, rankCounts, suits); |
71 | | - } |
72 | | - |
73 | | - private int calculatedScore(Map<Integer, Integer> frequencyMap, List<Card> cardsByRank, List<Integer> ranks, |
74 | | - List<Integer> rankCounts, List<Integer> suits) { |
75 | 33 | if (ranks.equals(Arrays.asList(14, 5, 4, 3, 2))) { |
76 | 34 | ranks = Arrays.asList(5, 4, 3, 2, 1); |
77 | 35 | } |
78 | 36 |
|
79 | | - boolean flush = suits |
80 | | - .stream() |
81 | | - .distinct() |
82 | | - .count() == 1; |
83 | | - boolean straight = ranks.stream().distinct().count() == 5 |
84 | | - && ranks.get(0) - ranks.get(4) == 4; |
85 | | - |
86 | | - Iterator<Integer> iteratorOverFrequencies = frequencyMap.keySet().iterator(); |
87 | | - |
88 | | - int highestFrequency = iteratorOverFrequencies.next(); |
| 37 | + List<Long> frequencies = new ArrayList<>(rankFrequency.values()); |
| 38 | + frequencies.sort(Collections.reverseOrder()); |
89 | 39 |
|
90 | | - if (straight && flush) { |
91 | | - return 800 + highestFrequency; |
92 | | - } |
93 | | - if (rankCounts.equals(Arrays.asList(4, 1))) { |
94 | | - return 700 + cardsByRank.get(0).getRank(); |
95 | | - } |
96 | | - if (rankCounts.equals(Arrays.asList(3, 2))) { |
97 | | - int triplet = 0; |
98 | | - int pair = 0; |
99 | | - for (Integer key : frequencyMap.keySet()) { |
100 | | - if (frequencyMap.get(key) == 2) { |
101 | | - pair = (int) key; |
102 | | - } |
103 | | - if (frequencyMap.get(key) == 3) { |
104 | | - triplet = 3 * (int) key; |
105 | | - } |
106 | | - } |
107 | | - return 600 + 3 * triplet + pair; |
108 | | - } |
109 | | - if (flush) { |
110 | | - return 500 + highestFrequency; |
111 | | - } |
112 | | - if (straight) { |
113 | | - int maxValue = Collections.max(ranks); |
114 | | - return 400 + maxValue; |
115 | | - } |
116 | | - if (rankCounts.equals(Arrays.asList(3, 1, 1))) { |
117 | | - List<Integer> uniqueCards = new ArrayList<Integer>(); |
118 | | - int triplet = 0; |
119 | | - for (Integer key : frequencyMap.keySet()) { |
120 | | - if (frequencyMap.get(key) == 1) { |
121 | | - uniqueCards.add((int) key); |
122 | | - } |
123 | | - if (frequencyMap.get(key) == 3) { |
124 | | - triplet = 3 * (int) key; |
125 | | - } |
126 | | - } |
127 | | - return 300 + triplet + Collections.max(uniqueCards); |
128 | | - } |
129 | | - if (rankCounts.equals(Arrays.asList(2, 2, 1))) { |
130 | | - int productsOfFrequencyAndValue = 0; |
131 | | - for (Integer key : frequencyMap.keySet()) { |
132 | | - int frequencyKey = (int) key; |
133 | | - int frequencyValue = frequencyMap.get(key); |
134 | | - productsOfFrequencyAndValue += frequencyKey * frequencyValue; |
135 | | - } |
136 | | - return 200 + productsOfFrequencyAndValue + 2 * Math.max(highestFrequency, iteratorOverFrequencies.next()); |
137 | | - } |
138 | | - if (rankCounts.equals(Arrays.asList(2, 1, 1, 1))) { |
139 | | - return 100 + highestFrequency; |
140 | | - } |
141 | | - ranks.sort(Comparator.naturalOrder()); |
142 | | - int result = 0; |
143 | | - for (int i = 0; i < ranks.size(); i++) { |
144 | | - result += ranks.get(0) * (i + 1); |
145 | | - } |
146 | | - return result + ranks.get(ranks.size() - 1); |
| 40 | + if (isStraight && isFlush) return 800 + ranks.get(0); |
| 41 | + if (frequencies.equals(Arrays.asList(4L, 1L))) return 700 + ranks.get(0); |
| 42 | + if (frequencies.equals(Arrays.asList(3L, 2L))) return 600 + ranks.get(0) * 10 + ranks.get(1); |
| 43 | + if (isFlush) return 500 + ranks.get(0); |
| 44 | + if (isStraight) return 400 + ranks.get(0); |
| 45 | + if (frequencies.equals(Arrays.asList(3L, 1L, 1L))) return 300 + ranks.get(0) * 10 + ranks.get(1); |
| 46 | + if (frequencies.equals(Arrays.asList(2L, 2L, 1L))) return 200 + ranks.get(0) * 10 + ranks.get(1); |
| 47 | + if (frequencies.equals(Arrays.asList(2L, 1L, 1L, 1L))) return 100 + ranks.get(0); |
| 48 | + |
| 49 | + return ranks.stream().reduce(0, (sum, rank) -> sum * 10 + rank); |
| 50 | + } |
| 51 | + |
| 52 | + private List<Card> parseCards(String hand) { |
| 53 | + return Arrays.stream(hand.split(" ")) |
| 54 | + .map(Card::new) |
| 55 | + .collect(Collectors.toList()); |
147 | 56 | } |
148 | | -} |
| 57 | +} |
0 commit comments