Skip to content

Add isomorphism.rs #707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@
* [Burrows Wheeler Transform](https://github.com/TheAlgorithms/Rust/blob/master/src/string/burrows_wheeler_transform.rs)
* [Duval Algorithm](https://github.com/TheAlgorithms/Rust/blob/master/src/string/duval_algorithm.rs)
* [Hamming Distance](https://github.com/TheAlgorithms/Rust/blob/master/src/string/hamming_distance.rs)
* [Isomorphism](https://github.com/TheAlgorithms/Rust/blob/master/src/string/isomorphism.rs)
* [Jaro Winkler Distance](https://github.com/TheAlgorithms/Rust/blob/master/src/string/jaro_winkler_distance.rs)
* [Knuth Morris Pratt](https://github.com/TheAlgorithms/Rust/blob/master/src/string/knuth_morris_pratt.rs)
* [Levenshtein Distance](https://github.com/TheAlgorithms/Rust/blob/master/src/string/levenshtein_distance.rs)
Expand Down
83 changes: 83 additions & 0 deletions src/string/isomorphism.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//! This module provides functionality to determine whether two strings are isomorphic.
//!
//! Two strings are considered isomorphic if the characters in one string can be replaced
//! by some mapping relation to obtain the other string.
use std::collections::HashMap;

/// Determines whether two strings are isomorphic.
///
/// # Arguments
///
/// * `s` - The first string.
/// * `t` - The second string.
///
/// # Returns
///
/// `true` if the strings are isomorphic, `false` otherwise.
pub fn is_isomorphic(s: &str, t: &str) -> bool {
let s_chars: Vec<char> = s.chars().collect();
let t_chars: Vec<char> = t.chars().collect();
if s_chars.len() != t_chars.len() {
return false;
}
let mut s_to_t_map = HashMap::new();
let mut t_to_s_map = HashMap::new();
for (s_char, t_char) in s_chars.into_iter().zip(t_chars) {
if !check_mapping(&mut s_to_t_map, s_char, t_char)
|| !check_mapping(&mut t_to_s_map, t_char, s_char)
{
return false;
}
}
true
}

/// Checks the mapping between two characters and updates the map.
///
/// # Arguments
///
/// * `map` - The HashMap to store the mapping.
/// * `key` - The key character.
/// * `value` - The value character.
///
/// # Returns
///
/// `true` if the mapping is consistent, `false` otherwise.
fn check_mapping(map: &mut HashMap<char, char>, key: char, value: char) -> bool {
match map.get(&key) {
Some(&mapped_char) => mapped_char == value,
None => {
map.insert(key, value);
true
}
}
}

#[cfg(test)]
mod tests {
use super::is_isomorphic;
macro_rules! test_is_isomorphic {
($($name:ident: $inputs:expr,)*) => {
$(
#[test]
fn $name() {
let (s, t, expected) = $inputs;
assert_eq!(is_isomorphic(s, t), expected);
assert_eq!(is_isomorphic(t, s), expected);
assert!(is_isomorphic(s, s));
assert!(is_isomorphic(t, t));
}
)*
}
}
test_is_isomorphic! {
isomorphic: ("egg", "add", true),
isomorphic_long: ("abcdaabdcdbbabababacdadad", "AbCdAAbdCdbbAbAbAbACdAdAd", true),
not_isomorphic: ("egg", "adc", false),
non_isomorphic_long: ("abcdaabdcdbbabababacdadad", "AACdAAbdCdbbAbAbAbACdAdAd", false),
isomorphic_unicode: ("天苍苍", "野茫茫", true),
isomorphic_unicode_different_byte_size: ("abb", "野茫茫", true),
empty: ("", "", true),
different_length: ("abc", "abcd", false),
}
}
2 changes: 2 additions & 0 deletions src/string/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod boyer_moore_search;
mod burrows_wheeler_transform;
mod duval_algorithm;
mod hamming_distance;
mod isomorphism;
mod jaro_winkler_distance;
mod knuth_morris_pratt;
mod levenshtein_distance;
Expand All @@ -30,6 +31,7 @@ pub use self::burrows_wheeler_transform::{
};
pub use self::duval_algorithm::duval_algorithm;
pub use self::hamming_distance::hamming_distance;
pub use self::isomorphism::is_isomorphic;
pub use self::jaro_winkler_distance::jaro_winkler_distance;
pub use self::knuth_morris_pratt::knuth_morris_pratt;
pub use self::levenshtein_distance::{naive_levenshtein_distance, optimized_levenshtein_distance};
Expand Down