Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5821db2
refactor: run CI only on pull requests with specifics conditions
vbetsch Oct 9, 2026
a6370bd
Merge remote-tracking branch 'origin/master' into develop
vbetsch Oct 9, 2026
97566d9
feat: activate PAIR category
vbetsch Oct 9, 2026
115a6cc
refactor: split categories with chapters
vbetsch Oct 9, 2026
b06342e
feat: create occurrencesByValue hashmap for handlePairScore
vbetsch Oct 9, 2026
1f77b61
feat: create method getOccurrencesByValue and return sum of pairs
vbetsch Oct 9, 2026
cde45eb
refactor: use the right exception to throw in tests
vbetsch Oct 16, 2026
1ed9d68
style: add chapters
vbetsch Oct 16, 2026
d9a2dc7
test: add pair_throwIllegalArgumentException_whenGivenNotPair
vbetsch Oct 16, 2026
291fe25
test: pair_return4Points_whenGivenRollWithOnlyOnePairOfThree
vbetsch Oct 16, 2026
8417544
refactor: remove points numbers in tests names
vbetsch Oct 16, 2026
5149fa0
style: format Yams class
vbetsch Oct 16, 2026
44ff3fa
feat: migrate containsDuplicatesNth to containsAtLeastDuplicatesNth u…
vbetsch Oct 16, 2026
287d5ab
test: if we have more than expected
vbetsch Oct 16, 2026
9999ad5
fix: filter in pair handler
vbetsch Oct 16, 2026
3af7608
docs: update checklist
vbetsch Oct 16, 2026
6ee2138
refactor: rename zero points tests
vbetsch Oct 16, 2026
25e2889
fix: return zero points if duplicates check failed
vbetsch Oct 16, 2026
eb46f5c
fix: categories in tests
vbetsch Oct 16, 2026
bd8dbff
feat: handle two pairs
vbetsch Oct 16, 2026
6e6c1e1
feat: create containsAtLeastXDuplicatesOnYDifferentDices
vbetsch Oct 16, 2026
8fb00da
refactor: merge contains duplicates methods
vbetsch Oct 16, 2026
6a675ea
fix: compute score for two pairs
vbetsch Oct 16, 2026
4f9b509
test: two_pairs_returnPoints_whenGivenRollWithTwoPairsOfFourAndFive
vbetsch Oct 16, 2026
a057590
docs: update checklist
vbetsch Oct 16, 2026
a2a1176
refactor: create getAllPairsOccurrences
vbetsch Oct 16, 2026
952dc18
refactor: rename i to index
vbetsch Oct 16, 2026
5a9f4a6
revert: annotations config
vbetsch Oct 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ The following categories exists:

- [x] Ones, Twos, Threes, Fours, Fives, Sixes: The player scores the sum of the dice that reads one, two, three, four,
five or six, respectively. For example, 1, 1, 2, 4, 4 placed on “fours” gives 8 points.
- [ ] Pair: The player scores the sum of the two highest matching dice. For example, 3, 3, 3, 4, 4 placed on “pair”
- [x] Pair: The player scores the sum of the two highest matching dice. For example, 3, 3, 3, 4, 4 placed on “pair”
gives 8.
- [ ] Two pairs: If there are two pairs of dice with the same number, the player scores the sum of these dice. If not,
- [x] Two pairs: If there are two pairs of dice with the same number, the player scores the sum of these dice. If not,
the player scores 0. For example, 1, 1, 2, 3, 3 placed on “two pairs” gives 8.
- [x] Three of a kind: If there are three dice with the same number, the player scores the sum of these dice. Otherwise,
the player scores 0. For example, 3, 3, 3, 4, 5 places on “three of a kind” gives 9.
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/github/vbetsch/yams/CategoryEnum.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package io.github.vbetsch.yams;

public enum CategoryEnum {
// --- TOP PART ---
ACES,
TWOS,
THREES,
FOURS,
FIVES,
SIXES,
// --- BONUS PART (kata) ---
PAIR,
TWO_PAIRS,
// --- BOTTOM PART ---
THREE_OF_A_KIND,
FOUR_OF_A_KIND,
// FULL_HOUSE,
Expand Down

This file was deleted.

69 changes: 59 additions & 10 deletions src/main/java/io/github/vbetsch/yams/Yams.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,48 @@
package io.github.vbetsch.yams;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Yams {
static final int DICES_COUNT = 5;

// Utils
private Map<Integer, Integer> getOccurrencesByValue(List<Integer> roll) {
Map<Integer, Integer> occurrencesByValue = new HashMap<>();
for (int index = 0; index < roll.size(); index++) {
int diceValue = roll.get(index);
occurrencesByValue.merge(diceValue, 1, Integer::sum);
}
IO.println(occurrencesByValue);
return occurrencesByValue;
}

private boolean containsAtLeastXDuplicatesOnAtLeastYDifferentDices(Map<Integer, Integer> occurrencesByValue, int duplicatesNumber, int differentDices) {
Stream<Map.Entry<Integer, Integer>> matchingOccurrences = occurrencesByValue
.entrySet()
.stream()
.filter(occurrenceByValue -> occurrenceByValue.getValue() >= duplicatesNumber);
return matchingOccurrences.count() >= differentDices;
}

private int calculateSumOfDices(List<Integer> roll) {
return roll
.stream()
.mapToInt(Integer::intValue)
.sum();
}

private Stream<Map.Entry<Integer, Integer>> getAllPairsOccurrences(Map<Integer, Integer> occurrencesByValue) {
return occurrencesByValue
.entrySet()
.stream()
.filter(occurrenceByValue -> occurrenceByValue.getValue() >= 2);
}

// Handlers
private int handleChanceScore(List<Integer> roll) {
return this.calculateSumOfDices(roll);
}
Expand All @@ -38,30 +68,47 @@ private int handleTopPartScores(List<Integer> roll, int target) {
.sum();
}

private boolean containsDuplicatesNth(List<Integer> roll, int duplicatesNumber) {
IntStream reducedRoll = roll
.stream()
private int handlePairScore(List<Integer> roll) throws IllegalArgumentException {
Map<Integer, Integer> occurrencesByValue = this.getOccurrencesByValue(roll);
if (!this.containsAtLeastXDuplicatesOnAtLeastYDifferentDices(occurrencesByValue, 2, 1)) {
return 0;
}
return this.getAllPairsOccurrences(occurrencesByValue)
.map(Map.Entry::getKey)
.max(Integer::compare)
.orElse(0) * 2;
}

private int handleTwoPairsScore(List<Integer> roll) throws IllegalArgumentException {
Map<Integer, Integer> occurrencesByValue = this.getOccurrencesByValue(roll);
if (!this.containsAtLeastXDuplicatesOnAtLeastYDifferentDices(occurrencesByValue, 2, 2)) {
return 0;
}
return this.getAllPairsOccurrences(occurrencesByValue)
.map(occurrenceByValue -> occurrenceByValue.getKey() * 2)
.mapToInt(Integer::intValue)
.distinct();
return reducedRoll.count() == (Yams.DICES_COUNT - duplicatesNumber + 1);
.sum();
}

private int handleThreeOfAKindScore(List<Integer> roll) throws IllegalArgumentException {
if (!this.containsDuplicatesNth(roll, 3)) {
throw new CategoryNotAuthorizedForThisRollError(CategoryEnum.THREE_OF_A_KIND);
Map<Integer, Integer> occurrencesByValue = this.getOccurrencesByValue(roll);
if (!this.containsAtLeastXDuplicatesOnAtLeastYDifferentDices(occurrencesByValue, 3, 1)) {
return 0;
}
return this.calculateSumOfDices(roll);
}

private int handleFourOfAKindScore(List<Integer> roll) throws IllegalArgumentException {
if (!this.containsDuplicatesNth(roll, 4)) {
throw new CategoryNotAuthorizedForThisRollError(CategoryEnum.FOUR_OF_A_KIND);
Map<Integer, Integer> occurrencesByValue = this.getOccurrencesByValue(roll);
if (!this.containsAtLeastXDuplicatesOnAtLeastYDifferentDices(occurrencesByValue, 4, 1)) {
return 0;
}
return this.calculateSumOfDices(roll);
}

// Public method
public int computeScore(List<Integer> roll, CategoryEnum category) throws InvalidRollSizeError {
if(roll.size() != Yams.DICES_COUNT) {
if (roll.size() != Yams.DICES_COUNT) {
throw new InvalidRollSizeError(roll.size());
}
return switch (category) {
Expand All @@ -73,6 +120,8 @@ public int computeScore(List<Integer> roll, CategoryEnum category) throws Invali
case CategoryEnum.FOURS -> this.handleTopPartScores(roll, 4);
case CategoryEnum.FIVES -> this.handleTopPartScores(roll, 5);
case CategoryEnum.SIXES -> this.handleTopPartScores(roll, 6);
case CategoryEnum.PAIR -> this.handlePairScore(roll);
case CategoryEnum.TWO_PAIRS -> this.handleTwoPairsScore(roll);
case CategoryEnum.THREE_OF_A_KIND -> this.handleThreeOfAKindScore(roll);
case CategoryEnum.FOUR_OF_A_KIND -> this.handleFourOfAKindScore(roll);
default -> 1000;
Expand Down
Loading
Loading