Skip to content

Commit

Permalink
feat: Implement compare_word functionality (#48)
Browse files Browse the repository at this point in the history
* Implement compare_word Functionality

* feat: handle repeated letters edge case

* fmt

* add comments and add more examples for repeated letters testcase
  • Loading branch information
No-bodyq authored Jan 27, 2025
1 parent e430aa4 commit 6621a0d
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 1 deletion.
73 changes: 72 additions & 1 deletion onchain/src/dewordle.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ mod DeWordle {
MutableVecTrait, VecTrait
};

use dewordle::constants::LetterStates::{CORRECT, PRESENT, ABSENT};

#[storage]
struct Storage {
word_of_the_day: ByteArray, //TODO: hash word
Expand Down Expand Up @@ -53,7 +55,76 @@ mod DeWordle {

// TODO
fn compare_word(ref self: ContractState, guessed_word: ByteArray) -> Span<u8> {
array![0, 1, 2].span()
let guessed_word_len = guessed_word.len();
let word = self.get_daily_word();

assert(guessed_word_len == word.len(), 'Length does not match');

// Initialize tracking arrays
let mut i = 0;
let mut word_states = array![]; // Final letter states
let mut temp_states = array![]; // Temporary states to track exact matches
let mut letter_count_list = array![]; // To track letter frequency in the target word

// Count occurrences of each letter in the daily word
while (i < guessed_word_len) {
let mut count: u32 = 0;
let mut j = 0;
while (j < guessed_word_len) {
if (word[i] == word[j]) {
count += 1; // Count occurrences of the letter
}
j += 1;
};
letter_count_list.append(count);
i += 1;
};

i = 0;

// Identify exact matches and mark temporary state
while (i < guessed_word_len) {
if (guessed_word[i] == word[i]) {
temp_states.append(CORRECT); // Letter is in the correct position
} else {
temp_states.append(ABSENT); // Default to ABSENT for now
}
i += 1;
};

i = 0;

// Identify misplaced letters
while (i < guessed_word_len) {
let prev_word_states = word_states.clone();
// If the letter was marked ABSENT in the temporary states, check for misplaced
// occurrences
if (*temp_states.at(i) == ABSENT) {
let mut j = 0;
while (j < guessed_word_len) {
if (guessed_word[i] == word[j]) {
if (*temp_states.at(j) != CORRECT) {
word_states.append(PRESENT); // Mark as PRESENT (misplaced)
break;
}
}
j += 1;
};

// If no match was found, mark as ABSENT
if (prev_word_states.len() == word_states.len()) {
word_states.append(ABSENT);
}
} else {
// If the letter was previously marked as CORRECT, preserve the state
word_states.append(CORRECT);
}

i += 1;
};

// Return the final array of letter states
word_states.span()
}
}
}
97 changes: 97 additions & 0 deletions onchain/tests/test_dewordle.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,100 @@ fn test_set_daily_word() {
// Verify that the daily word was set correctly
assert(dewordle.get_daily_word() == daily_word, 'Daily word not stored correctly');
}

#[test]
fn test_compare_word_when_all_letters_are_correct() {
let contract_address = deploy_contract();
let dewordle = IDeWordleDispatcher { contract_address: contract_address };

// Define and set the daily word
let daily_word = "test";
dewordle.set_daily_word(daily_word.clone());

// Verify that the daily word was set correctly
assert(dewordle.get_daily_word() == daily_word, 'Daily word not stored correctly');

assert(
dewordle.compare_word("test") == array![0, 0, 0, 0].span(), 'Word not compared correctly'
);
}

#[test]
fn test_compare_word_when_some_letters_are_misplaced() {
let contract_address = deploy_contract();
let dewordle = IDeWordleDispatcher { contract_address: contract_address };

// Define and set the daily word
let daily_word = "test";
dewordle.set_daily_word(daily_word.clone());

// Verify that the daily word was set correctly
assert(dewordle.get_daily_word() == daily_word, 'Daily word not stored correctly');

assert(
dewordle.compare_word("tset") == array![0, 1, 1, 0].span(), 'Word not compared correctly'
);
}

#[test]
fn test_compare_word_when_some_letters_are_absent() {
let contract_address = deploy_contract();
let dewordle = IDeWordleDispatcher { contract_address: contract_address };

// Define and set the daily word
let daily_word = "test";
dewordle.set_daily_word(daily_word.clone());

// Verify that the daily word was set correctly
assert(dewordle.get_daily_word() == daily_word, 'Daily word not stored correctly');

assert(
dewordle.compare_word("tsec") == array![0, 1, 1, 2].span(), 'Word not compared correctly'
);
}

#[test]
#[should_panic(expected: 'Length does not match')]
fn test_compare_word_panics() {
let contract_address = deploy_contract();
let dewordle = IDeWordleDispatcher { contract_address: contract_address };

// Define and set the daily word
let daily_word = "slept";
dewordle.set_daily_word(daily_word.clone());

// Verify that the daily word was set correctly
assert(dewordle.get_daily_word() == daily_word, 'Daily word not stored correctly');

dewordle.compare_word("sweeps");
}

#[test]
fn test_compare_word_when_some_letters_are_repeated() {
let contract_address = deploy_contract();
let dewordle = IDeWordleDispatcher { contract_address: contract_address };

// Define and set the daily word
let daily_word = "slept";
dewordle.set_daily_word(daily_word.clone());

// Verify that the daily word was set correctly
assert(dewordle.get_daily_word() == daily_word, 'Daily word not stored correctly');

assert(
dewordle.compare_word("sweep") == array![0, 2, 0, 2, 1].span(),
'Word not compared correctly'
);

// Define and set another daily word
let daily_word = "test";
dewordle.set_daily_word(daily_word.clone());

// Verify that the daily word was set correctly
assert(dewordle.get_daily_word() == daily_word, 'Daily word not stored correctly');

// verify the word was compared correctly
assert(
dewordle.compare_word("less") == array![2, 0, 0, 2].span(), 'Word not compared correctly'
);
}

0 comments on commit 6621a0d

Please sign in to comment.