hello i am currently trying to solve hangman and i got a problem with one 1 test(others are running correct) which i cant solve for a while i just paste my solution
import io.reactivex.Observable;
import java.util.*;
public class Hangman {
public Observable<Output> play(Observable<String> words, Observable<String> letters) {
return words.concatMap(word -> letters.scan(Output.empty(), (prevOutput, letter) -> {
String newDiscovered = discover(word, prevOutput.discovered, letter);
Set<String> newGuesses = addGuess(word, prevOutput.guess, letter);
Set<String> newMisses = addMisses(word, prevOutput.misses, letter);
List<Part> newParts = setParts(prevOutput.parts, newMisses);
Status newStatus = setStatus(word, newDiscovered, newMisses);
return new Output(word, newDiscovered, newGuesses, newMisses, newParts, newStatus);
}).startWith(new Output(
word,
newDiscovered(word),
new HashSet<>(),
new HashSet<>(),
new ArrayList<>(),
Status.PLAYING
)).takeUntil(output -> output.status == Status.WIN || output.status == Status.LOSS));
}
String discover(String word, String discovered, String letter){
if (discovered == null){
discovered = newDiscovered(word);
}
char[] wordC = word.toCharArray();
char[] discoveredC = discovered.toCharArray();
if(letter.length() != 1){
throw new IllegalArgumentException("unsuported");
}
char letterC = letter.charAt(0);
for(int i = 0; i < word.length(); i++){
if (discoveredC[i] == letterC){
throw new IllegalArgumentException("Letter " + letter + " was already played");
}
if (wordC[i] == letterC){
discoveredC[i] = letterC;
}
}
return new String(discoveredC);
}
Set<String> addGuess(String word, Set<String> guesses, String letter){
Set<String> newGuesses = new HashSet<>(guesses);
if (newGuesses.contains(letter)){
throw new IllegalArgumentException("Letter " + letter + " was already played");
}
if (word.contains(letter)){
newGuesses.add(letter);
}
return newGuesses;
}
Set<String> addMisses(String word, Set<String> misses, String letter){
Set<String> newMisses = new HashSet<>(misses);
if (word.contains(letter)){
return newMisses;
}
if (!newMisses.add(letter)){
throw new IllegalArgumentException("Letter " + letter + " was already played");
}
return newMisses;
}
Status setStatus(String word, String discovered, Set<String> misses){
if((long) misses.size() >= 6){
return Status.LOSS;
}
if (Objects.equals(word, discovered)){
return Status.WIN;
}
return Status.PLAYING;
}
String newDiscovered(String word){
StringBuilder sb = new StringBuilder();
sb.repeat("_", word.length());
return sb.toString();
}
List<Part> setParts(List<Part> oldParts, Set<String> misses){
List<Part> parts =new ArrayList<>(oldParts);
int size = misses.size();
switch (size){
case 1:
if (!parts.contains(Part.HEAD)){
parts.add(Part.HEAD);
}
break;
case 2:
if (!parts.contains(Part.BODY)){
parts.add(Part.BODY);
}
break;
case 3:
if (!parts.contains(Part.LEFT_ARM)){
parts.add(Part.LEFT_ARM);
}
break;
case 4:
if (!parts.contains(Part.RIGHT_ARM)){
parts.add(Part.RIGHT_ARM);
}
break;
case 5:
if (!parts.contains(Part.LEFT_LEG)){
parts.add(Part.LEFT_LEG);
}
break;
case 6:
if (!parts.contains(Part.RIGHT_LEG)){
parts.add(Part.RIGHT_LEG);
}
break;
}
return parts;
}
}
and problem
@Test
@DisplayName("Handles consecutive games correctly with ordered emissions")
public void consecutiveGames() {
// This test setup is more complex because we have to order the emission of values in the
// different observers.
// 1. Word observable receives the work to guess
// 2. Letter observable receives the various letters tried
// 3. Word observable receives the new word to guess
// 4. Letter observable receiveds the letters for the second word
// Emitters respectively for the word and letter observables
SubscribedEmitters emitters = new SubscribedEmitters();
Runnable emit = () -> {
// Process sending the inputs in the right order
emitters.word.onNext("secret");
Stream.of("a", "e", "o", "s", "c", "r", "g", "t").forEach(emitters.letter::onNext);
emitters.word.onNext("abba");
Stream.of("a", "e", "s", "b").forEach(emitters.letter::onNext);
emitters.word.onComplete();
};
Observable<String> words = createWordObservable(emitters, emit);
Observable<String> letters = createLetterObservable(emitters, emit);
Observable<Output> outputs = hangman.play(words, letters);
// We collect the results of the game
List<Output> results = new ArrayList<>();
Disposable subscription = outputs.filter(output -> output.status != Status.PLAYING).subscribe(results::add);
try {
assertThat(results.size()).isEqualTo(2);
Output first = results.get(0);
assertThat(first.discovered).isEqualTo("secret");
assertThat(first.guess).containsExactlyInAnyOrder("s", "e", "c", "r", "t");
assertThat(first.misses).containsExactlyInAnyOrder("a", "o", "g");
assertThat(first.status).isEqualTo(Status.WIN);
Output second = results.get(1);
assertThat(second.discovered).isEqualTo("abba");
assertThat(second.guess).containsExactlyInAnyOrder("a", "b");
assertThat(second.misses).containsExactlyInAnyOrder("e", "s");
assertThat(first.status).isEqualTo(Status.WIN);
} finally {
subscription.dispose();
}
}
Test Failure
Message:
expected: 2
but was: 0
Exception: org.opentest4j.AssertionFailedError:
expected: 2
but was: 0
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at HangmanTest.consecutiveGames(HangmanTest.java:165)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
i tried to use gemini to solve but it didnt help much, hope anyone knows how to solve it
. You should see something like this in the forum input: