summaryrefslogtreecommitdiff
path: root/absurdle/Absurdle.java
diff options
context:
space:
mode:
Diffstat (limited to 'absurdle/Absurdle.java')
-rw-r--r--absurdle/Absurdle.java232
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;
+ }
+}