Skip to content

Commit 1bd27f5

Browse files
mengfansheng-gitchangweidalaifu6vil02sozelfist
authored
Add isomorphism.rs (#707)
* isomorphic strings * modify the code as suggested * modify DIRECTORY.md * modify docstring * tests: add test cases with longer inputs --------- Co-authored-by: mengfansheng <[email protected]> Co-authored-by: Piotr Idzik <[email protected]> Co-authored-by: SOZEL <[email protected]>
1 parent 20c92d7 commit 1bd27f5

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@
303303
* [Burrows Wheeler Transform](https://github.com/TheAlgorithms/Rust/blob/master/src/string/burrows_wheeler_transform.rs)
304304
* [Duval Algorithm](https://github.com/TheAlgorithms/Rust/blob/master/src/string/duval_algorithm.rs)
305305
* [Hamming Distance](https://github.com/TheAlgorithms/Rust/blob/master/src/string/hamming_distance.rs)
306+
* [Isomorphism](https://github.com/TheAlgorithms/Rust/blob/master/src/string/isomorphism.rs)
306307
* [Jaro Winkler Distance](https://github.com/TheAlgorithms/Rust/blob/master/src/string/jaro_winkler_distance.rs)
307308
* [Knuth Morris Pratt](https://github.com/TheAlgorithms/Rust/blob/master/src/string/knuth_morris_pratt.rs)
308309
* [Levenshtein Distance](https://github.com/TheAlgorithms/Rust/blob/master/src/string/levenshtein_distance.rs)

src/string/isomorphism.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! This module provides functionality to determine whether two strings are isomorphic.
2+
//!
3+
//! Two strings are considered isomorphic if the characters in one string can be replaced
4+
//! by some mapping relation to obtain the other string.
5+
use std::collections::HashMap;
6+
7+
/// Determines whether two strings are isomorphic.
8+
///
9+
/// # Arguments
10+
///
11+
/// * `s` - The first string.
12+
/// * `t` - The second string.
13+
///
14+
/// # Returns
15+
///
16+
/// `true` if the strings are isomorphic, `false` otherwise.
17+
pub fn is_isomorphic(s: &str, t: &str) -> bool {
18+
let s_chars: Vec<char> = s.chars().collect();
19+
let t_chars: Vec<char> = t.chars().collect();
20+
if s_chars.len() != t_chars.len() {
21+
return false;
22+
}
23+
let mut s_to_t_map = HashMap::new();
24+
let mut t_to_s_map = HashMap::new();
25+
for (s_char, t_char) in s_chars.into_iter().zip(t_chars) {
26+
if !check_mapping(&mut s_to_t_map, s_char, t_char)
27+
|| !check_mapping(&mut t_to_s_map, t_char, s_char)
28+
{
29+
return false;
30+
}
31+
}
32+
true
33+
}
34+
35+
/// Checks the mapping between two characters and updates the map.
36+
///
37+
/// # Arguments
38+
///
39+
/// * `map` - The HashMap to store the mapping.
40+
/// * `key` - The key character.
41+
/// * `value` - The value character.
42+
///
43+
/// # Returns
44+
///
45+
/// `true` if the mapping is consistent, `false` otherwise.
46+
fn check_mapping(map: &mut HashMap<char, char>, key: char, value: char) -> bool {
47+
match map.get(&key) {
48+
Some(&mapped_char) => mapped_char == value,
49+
None => {
50+
map.insert(key, value);
51+
true
52+
}
53+
}
54+
}
55+
56+
#[cfg(test)]
57+
mod tests {
58+
use super::is_isomorphic;
59+
macro_rules! test_is_isomorphic {
60+
($($name:ident: $inputs:expr,)*) => {
61+
$(
62+
#[test]
63+
fn $name() {
64+
let (s, t, expected) = $inputs;
65+
assert_eq!(is_isomorphic(s, t), expected);
66+
assert_eq!(is_isomorphic(t, s), expected);
67+
assert!(is_isomorphic(s, s));
68+
assert!(is_isomorphic(t, t));
69+
}
70+
)*
71+
}
72+
}
73+
test_is_isomorphic! {
74+
isomorphic: ("egg", "add", true),
75+
isomorphic_long: ("abcdaabdcdbbabababacdadad", "AbCdAAbdCdbbAbAbAbACdAdAd", true),
76+
not_isomorphic: ("egg", "adc", false),
77+
non_isomorphic_long: ("abcdaabdcdbbabababacdadad", "AACdAAbdCdbbAbAbAbACdAdAd", false),
78+
isomorphic_unicode: ("天苍苍", "野茫茫", true),
79+
isomorphic_unicode_different_byte_size: ("abb", "野茫茫", true),
80+
empty: ("", "", true),
81+
different_length: ("abc", "abcd", false),
82+
}
83+
}

src/string/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod boyer_moore_search;
55
mod burrows_wheeler_transform;
66
mod duval_algorithm;
77
mod hamming_distance;
8+
mod isomorphism;
89
mod jaro_winkler_distance;
910
mod knuth_morris_pratt;
1011
mod levenshtein_distance;
@@ -30,6 +31,7 @@ pub use self::burrows_wheeler_transform::{
3031
};
3132
pub use self::duval_algorithm::duval_algorithm;
3233
pub use self::hamming_distance::hamming_distance;
34+
pub use self::isomorphism::is_isomorphic;
3335
pub use self::jaro_winkler_distance::jaro_winkler_distance;
3436
pub use self::knuth_morris_pratt::knuth_morris_pratt;
3537
pub use self::levenshtein_distance::{naive_levenshtein_distance, optimized_levenshtein_distance};

0 commit comments

Comments
 (0)