diff options
Diffstat (limited to 'absurdle/Absurdle.java')
| -rw-r--r-- | absurdle/Absurdle.java | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/absurdle/Absurdle.java b/absurdle/Absurdle.java new file mode 100644 index 0000000..61443af --- /dev/null +++ b/absurdle/Absurdle.java @@ -0,0 +1,232 @@ +// Nik Johnson +// 2-11-2024 +// TA: Andy Ruan + +/* +absurd wordle-like game +instead of guessing one word, prolongs game as long as possible by +testing users guess against every word in selected dictionary, and +choosing the largest set of words associated with a possible pattern +for the users guess. the game only ends when the next set to be +considered is narrowed down to one, and the user guesses it. +*/ + +import java.util.*; +import java.io.*; + +public class Absurdle { + public static final String GREEN = "🟩"; + public static final String YELLOW = "🟨"; + public static final String GRAY = "⬜"; + + // [[ ALL OF MAIN PROVIDED ]] + public static void main(String[] args) throws FileNotFoundException { + Scanner console = new Scanner(System.in); + System.out.println("Welcome to the game of Absurdle."); + + System.out.print("What dictionary would you like to use? "); + String dictName = console.next(); + + System.out.print("What length word would you like to guess? "); + int wordLength = console.nextInt(); + + List<String> contents = loadFile(new Scanner(new File(dictName))); + Set<String> words = pruneDictionary(contents, wordLength); + + List<String> guessedPatterns = new ArrayList<>(); + while (!isFinished(guessedPatterns)) { + System.out.print("> "); + String guess = console.next(); + String pattern = record(guess, words, wordLength); + guessedPatterns.add(pattern); + System.out.println(": " + pattern); + System.out.println(); + } + System.out.println("Absurdle " + guessedPatterns.size() + "/∞"); + System.out.println(); + printPatterns(guessedPatterns); + console.close(); + } + + // [[ PROVIDED ]] + // Prints out the given list of patterns. + // - List<String> patterns: list of patterns from the game + public static void printPatterns(List<String> patterns) { + for (String pattern : patterns) { + System.out.println(pattern); + } + } + + // [[ PROVIDED ]] + // Returns true if the game is finished, meaning the user guessed the word. Returns + // false otherwise. + // - List<String> patterns: list of patterns from the game + public static boolean isFinished(List<String> patterns) { + if (patterns.isEmpty()) { + return false; + } + String lastPattern = patterns.get(patterns.size() - 1); + return !lastPattern.contains("⬜") && !lastPattern.contains("🟨"); + } + + // [[ PROVIDED ]] + // Loads the contents of a given file Scanner into a List<String> and returns it. + // - Scanner dictScan: contains file contents + public static List<String> loadFile(Scanner dictScan) { + List<String> contents = new ArrayList<>(); + while (dictScan.hasNext()) { + contents.add(dictScan.next()); + } + return contents; + } + + /* + look through list of words from dictionary, removing words that aren't of + the user specified length. + + takes list of words from user specified dictionary, and user specified word length + + return set of words pruned according to user input + + if the user specified length is less than one, throw IllegalArgumentException + */ + public static Set<String> pruneDictionary(List<String> contents, int wordLength) { + if (wordLength < 1) throw new IllegalArgumentException(); + Set<String> prunedDict = new HashSet<>(); + for (String word : contents) { + if (word.length() == wordLength) { + prunedDict.add(word); + } + } + return prunedDict; + } + + /* + evaluate users guess, looking for the largest set of words that have the pattern + of the guess. if all possible patterns have the same number of words, pick the + first one in alphabetical order. + + takes users guess, set of words determined by pruneDictionary, and length of users guess + + return the pattern associated with the largest set of words + + if the users guess is the wrong length, or there is no words to be guessed, + throw IllegalArgumentException + */ + public static String record(String guess, Set<String> words, int wordLength) { + if (guess.length() != wordLength || words.isEmpty()) { + throw new IllegalArgumentException(); + } + + Map<String, Set<String>> wordMap = new TreeMap<>(); + for (String word : words) { + String nextPattern = patternFor(word, guess); + if (!wordMap.containsKey(nextPattern)) { + wordMap.put(nextPattern, new HashSet<String>()); + } + wordMap.get(nextPattern).add(word); + } + + Boolean allSameSize = true; + int setSize1 = 0; + + for (String pattern : wordMap.keySet()) { + int size = wordMap.get(pattern).size(); + if (setSize1 == 0) setSize1 = size; + if (setSize1 != size) allSameSize = false; + } + + if (allSameSize) { + for (String pattern : wordMap.keySet()) { + removeAllNonMatching(words, wordMap.get(pattern)); + return pattern; + } + } + + String pattern = ""; + int setSize = 0; + for (String word : wordMap.keySet()) { + int nextSetSize = (wordMap.get(word)).size(); + if (nextSetSize > setSize) { + setSize = nextSetSize; + pattern = word; + } + } + removeAllNonMatching(words, wordMap.get(pattern)); + return pattern; + } + + /* + helper method for record, removes words from next considered set that arent in + the largest set determined in record + + takes next set of words to be considered as determined by record, + which will be used to trim the previous set + + no return + */ + public static void removeAllNonMatching(Set<String> words, Set<String> match) { + Iterator<String> iter = words.iterator(); + while(iter.hasNext()) { + if(!match.contains(iter.next())) { + iter.remove(); + } + } + } + + /* + produce pattern for users guess against every word in set of + considered words. + + takes users guess, and the word to generate a pattern against + + return pattern of colored squares for use in record + */ + public static String patternFor(String word, String guess) { + List<String> splitGuess = new ArrayList<>(); + String pattern = new String(); + for (int i = 0;i < guess.length(); i++) { + String nextChar = Character.toString(guess.charAt(i)); + splitGuess.add(nextChar); + } + + Map<Character, Integer> wordMap = new HashMap<>(); + for (int j = 0; j < word.length(); j++) { + char wordChar = word.charAt(j); + if (!wordMap.containsKey(wordChar)) { + wordMap.put(wordChar, 1); + } else { + wordMap.put(wordChar, (wordMap.get(wordChar) + 1)); + } + } + + for (int n = 0; n < splitGuess.size(); n++) { + if ((Character.toString(word.charAt(n))).equals(splitGuess.get(n))) { + int currCount = wordMap.get((splitGuess.get(n)).charAt(0)); + wordMap.put(word.charAt(n), (currCount - 1)); + splitGuess.set(n, GREEN); + } + } + + for (int n = 0; n < splitGuess.size(); n++) { + char charToCheck = (splitGuess.get(n)).charAt(0); + if ((wordMap.keySet()).contains(charToCheck) + && wordMap.get(charToCheck) != 0) { + int currCount2 = wordMap.get(charToCheck); + wordMap.put(charToCheck, (currCount2 - 1)); + splitGuess.set(n, YELLOW); + } + } + + for (int n = 0; n < splitGuess.size(); n++) { + if ((splitGuess.get(n)).length() == 1) { + splitGuess.set(n, GRAY); + } + } + + for (int i = 0; i < splitGuess.size(); i++) { + pattern += splitGuess.get(i); + } + return pattern; + } +} |
