Exercism anagram problems

Hello

I try to solve the anagram problem of exercism where I have to find anagrams of a word where the word itself is not a anagram.

So far I have this :

use std::collections::HashSet;

pub fn anagrams_for<'a>(word: &str, possible_anagrams: &[&str]) -> HashSet<&'a str> {
    possible_anagrams.retain { |&word_to_check| isAnagram word &word_to_check}
}

pub fn isAnagram(word: &str, word_to_check: &str) -> bool {
    
    if word == word_to_check {
        return false 
    }

    if word.sort() == word_to_check.sort {
        return true ; 
    }
    else { 
        return false; 
    }
    

}

but I see 3 compile errors where I have no idea how to solve them :

 Compiling anagram v0.0.0 (C:\Users\rwobb\Exercism\rust\anagram)
error: expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
 --> src\lib.rs:4:30
  |
4 |     possible_anagrams.retain { |&word_to_check| isAnagram word &word_to_check}
  |                              ^ expected one of 7 possible tokens

error: expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
 --> src\lib.rs:4:30
  |
4 |     possible_anagrams.retain { |&word_to_check| isAnagram word &word_to_check}
  |                              ^ expected one of 7 possible tokens

error[E0599]: no method named `sort` found for reference `&str` in the current scope
  --> src\lib.rs:13:13
   |
13 |     if word.sort() == word_to_check.sort {
   |             ^^^^ method not found in `&str`

error[E0609]: no field `sort` on type `&str`
  --> src\lib.rs:13:37
   |
13 |     if word.sort() == word_to_check.sort {
   |                                     ^^^^

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0599, E0609.
For more information about an error, try `rustc --explain E0599`.
error: could not compile `anagram`.
warning: build failed, waiting for other jobs to finish...
error[E0599]: no method named `sort` found for reference `&str` in the current scope
  --> src\lib.rs:13:13
   |
13 |     if word.sort() == word_to_check.sort {
   |             ^^^^ method not found in `&str`

error[E0609]: no field `sort` on type `&str`
  --> src\lib.rs:13:37
   |
13 |     if word.sort() == word_to_check.sort {
   |                                     ^^^^

error: aborting due to 3 previous errors

someone wo can teach me how I can solve them ?

This is, uhh, not valid Rust syntax. A function call with a closure looks like this:

possible_anagrams.retain(|word_to_check| isAnagram(word, word_to_check));

But you can't call retain on a value of type slice. And you certainly can't expect to get a HashSet out of it. You are probably looking for something using iterators:

use std::collections::HashSet;

pub fn anagrams_for<'a>(word: &str, possible_anagrams: &[&'a str]) -> HashSet<&'a str> {
    possible_anagrams.iter()
        .map(|word_to_check| *word_to_check)
        .filter(|word_to_check| is_anagram(word, word_to_check))
        .collect()
}

This first produces an iterator of item type &&str (the use of iter adds an extra &). Then the map turns it into an iterator of item type &str. Then the filter keeps only the anagrams, and finally collect creates the desired collection from the iterator.


That's also not how you use the sort function. Here are a few notes:

  1. The sort functions in Rust don't return anything, rather they modify the thing they are called on.
  2. The &str type cannot be modified as it is immutable, so you can't sort it.
  3. The string types in Rust have no sorting functionality. You need a Vec<char> to sort it.
  4. For your second attempt of sorting, you don't have any parenthesizes. They are not optional.
1 Like

Thanks,

One question : Why do i need to map first ?
and I have to dive into the books to find out how I can make a Vec<char> from a &str

The use of map turns the &&str into a &str by dereferencing it. In this case, the ordering of map and filter is not important, and you can swap them just fine.

As for creating a Vec<char>, you are also going to want an iterator (or for loop).

  1. First create an iterator of item type char from the string.
  2. Call collect to produce a vector.

Thanks
Still struggeling with this one
so far I have this:

use std::collections::HashSet;

pub fn anagrams_for<'a>(word: &str, possible_anagrams: &[&'a str]) -> HashSet<&'a str> {
    possible_anagrams.iter()
        .map(|word_to_check| *word_to_check)
        .filter(|word_to_check| is_anagram(word, word_to_check))
        .collect()
}

pub fn is_anagram(word: &str, word_to_check: &str) -> bool {
    
    if word == word_to_check {
        return false 
    }
    else {
        if word.to_lowercase().chars().collect::<String>() == word_to_check.to_lowercase().chars().collect::<String>(){
            return true
        }
        else{
            return false
        }
    }
}

but a lot of tests are failing

> Executing task: cargo test --package anagram --test anagram -- test_detect_simple_anagram --exact --nocapture <

    Finished test [unoptimized + debuginfo] target(s) in 0.03s
     Running target\debug\deps\anagram-426de6a7af6a850c.exe   

running 1 test
thread 'test_detect_simple_anagram' panicked at 'assertion failed: `(left == right)`
  left: `{}`,
 right: `{"tan"}`', tests\anagram.rs:11:5
stack backtrace:
   0: backtrace::backtrace::trace_unsynchronized
             at C:\Users\VssAdministrator\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.40\src\backtrace\mod.rs:66
   1: std::sys_common::backtrace::_print_fmt
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\sys_common\backtrace.rs:77
   2: std::sys_common::backtrace::_print::{{impl}}::fmt
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\sys_common\backtrace.rs:59
   3: core::fmt::write
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libcore\fmt\mod.rs:1052
   4: std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\io\mod.rs:1426
   5: std::sys_common::backtrace::_print
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\sys_common\backtrace.rs:62
   6: std::sys_common::backtrace::print
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\sys_common\backtrace.rs:49
   7: std::panicking::default_hook::{{closure}}
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\panicking.rs:204
   8: std::panicking::default_hook
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\panicking.rs:224
   9: std::panicking::rust_panic_with_hook
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\panicking.rs:472
  10: std::panicking::begin_panic_handler
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\panicking.rs:380
  11: std::panicking::begin_panic_fmt
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libstd\panicking.rs:334
  12: anagram::process_anagram_case
             at .\tests\anagram.rs:11
  13: anagram::test_detect_simple_anagram
             at .\tests\anagram.rs:33
  14: anagram::test_detect_simple_anagram::{{closure}}
             at .\tests\anagram.rs:26
  15: core::ops::function::FnOnce::call_once<closure-0,()>
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\src\libcore\ops\function.rs:232
  16: alloc::boxed::{{impl}}::call_once<(),FnOnce<()>>
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\src\liballoc\boxed.rs:1015
  17: panic_unwind::__rust_maybe_catch_panic
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libpanic_unwind\lib.rs:86
  18: std::panicking::try
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\src\libstd\panicking.rs:281
  19: std::panic::catch_unwind
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\src\libstd\panic.rs:394
  20: test::run_test_in_process
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libtest\lib.rs:539
  21: test::run_test::run_test_inner::{{closure}}
             at /rustc/b8cedc00407a4c56a3bda1ed605c6fc166655447\/src\libtest\lib.rs:452
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
test test_detect_simple_anagram ... FAILED

failures:

failures:
    test_detect_simple_anagram

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 12 filtered out

error: test failed, to rerun pass '-p anagram --test anagram'

failing test :


#[test]
fn test_detect_simple_anagram() {
    let word = "ant";

    let inputs = ["tan", "stand", "at"];

    let outputs = vec!["tan"];

    process_anagram_case(word, &inputs, &outputs);
}

Did you mean to sort the strings before comparing them?

yes

Try this?

pub fn is_anagram(word: &str, word_to_check: &str) -> bool {
    if word == word_to_check {
        false 
    } else {
        let mut a = word.to_lowercase().chars().collect::<Vec<char>>();
        let mut b = word_to_check.to_lowercase().chars().collect::<Vec<char>>();
        a.sort();
        b.sort();
        a == b
    }
}

Thanks,
This seems to work

use std::collections::HashSet;

pub fn anagrams_for<'a>(word: &str, possible_anagrams: &[&'a str]) -> HashSet<&'a str> {
    possible_anagrams.iter()
        .map(|word_to_check| *word_to_check)
        .filter(|word_to_check| is_anagram(word, word_to_check))
        .collect()
}

pub fn is_anagram(word: &str, word_to_check: &str) -> bool {
    let mut a = word.to_lowercase(); 
    let mut b = word_to_check.to_lowercase(); 
    
    if a == b {
        false 
    } else {
        let mut a = a.chars().collect::<Vec<char>>();
        let mut b = b.to_lowercase().chars().collect::<Vec<char>>();
        a.sort();
        b.sort();
        a == b
    }
}

A little buit ugly code but the tests are all green

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.