Skip to content

Commit c0e100c

Browse files
committed
removed deffinitin and improved speed
1 parent f9d3c69 commit c0e100c

2 files changed

Lines changed: 127197 additions & 279367 deletions

File tree

src/main.rs

Lines changed: 55 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,6 @@ pub mod display;
33
use display::string_input::StringInput;
44
use std::collections::{HashSet, VecDeque};
55

6-
#[derive(Eq, PartialEq, Hash, Clone)]
7-
pub struct Word {
8-
pub word: String,
9-
pub definition: String,
10-
}
11-
12-
impl Word {
13-
pub fn new(word: String, definition: String) -> Word {
14-
Word { word, definition }
15-
}
16-
}
17-
186
fn main() {
197
let starting_word = StringInput::new()
208
.message("Enter starting word")
@@ -28,100 +16,100 @@ fn main() {
2816
.max(starting_word.len() as i32)
2917
.ask();
3018

31-
println!("start: {}", starting_word);
32-
println!("end: {}", ending_word);
19+
if starting_word == ending_word {
20+
eprintln!("The starting word must be different from the ending word");
21+
std::process::exit(1);
22+
}
23+
24+
println!("{} -> {}", starting_word, ending_word);
3325

3426
let file = include_str!("./words.txt");
35-
let mut word_list: Vec<Word> = Vec::new();
27+
let mut word_list: Vec<String> = Vec::new();
3628

37-
let mut start: Option<Word> = None;
38-
let mut end: Option<Word> = None;
29+
let mut has_start = false;
30+
let mut has_end = false;
3931
for line in file.lines() {
40-
let split: Vec<&str> = line.split(" :: ").collect();
41-
if starting_word == split[0] {
42-
start = Some(Word::new(
43-
split[0].trim().to_string(),
44-
split[1].trim().to_string(),
45-
));
32+
if line.len() != starting_word.len() {
33+
continue;
34+
}
35+
36+
if line == starting_word {
37+
has_start = true;
4638
}
4739

48-
if ending_word == split[0] {
49-
end = Some(Word::new(
50-
split[0].trim().to_string(),
51-
split[1].trim().to_string(),
52-
));
40+
if line == ending_word {
41+
has_end = true;
5342
}
5443

55-
word_list.push(Word::new(
56-
split[0].trim().to_string(),
57-
split[1].trim().to_string(),
58-
));
44+
word_list.push(line.to_string());
5945
}
6046

61-
if start.is_none() {
47+
if has_start == false {
6248
eprintln!("Failed to find start word in word list");
6349
std::process::exit(1);
6450
}
6551

66-
if end.is_none() {
52+
if has_end == false {
6753
eprintln!("Failed to find end word in word list");
6854
std::process::exit(1);
6955
}
7056

71-
let ladder = generate_word_ladder(start.unwrap(), end.unwrap(), word_list);
57+
let ladder = generate_word_ladder(starting_word, ending_word, word_list);
7258

7359
if ladder.is_empty() {
7460
println!("Failed to find path between words");
7561
return;
7662
}
7763

7864
for word in ladder {
79-
println!("{} {}", word.word, word.definition);
65+
println!("{}", word);
8066
}
8167
}
8268

83-
fn generate_word_ladder(start_word: Word, end_word: Word, word_list: Vec<Word>) -> Vec<Word> {
84-
let mut queue: VecDeque<Vec<Word>> = VecDeque::new();
85-
let mut visited: HashSet<Word> = HashSet::new();
86-
87-
queue.push_back(vec![start_word.clone()]);
88-
visited.insert(start_word);
69+
fn find_successors(word: &str, word_set: &HashSet<String>) -> Vec<String> {
70+
let mut successors = Vec::new();
71+
let word_chars: Vec<char> = word.chars().collect();
8972

90-
while let Some(path) = queue.pop_front() {
91-
let current_word = path.last().unwrap();
73+
for i in 0..word_chars.len() {
74+
for ch in 'a'..='z' {
75+
if ch != word_chars[i] {
76+
let mut new_word = word_chars.clone();
77+
new_word[i] = ch;
78+
let candidate: String = new_word.into_iter().collect();
9279

93-
if current_word.word == end_word.word {
94-
return path;
95-
}
96-
97-
for word in &word_list {
98-
if differs_by_one_letter(current_word, &word) && !visited.contains(&word) {
99-
visited.insert(word.clone());
100-
let mut new_path = path.clone();
101-
new_path.push(word.clone());
102-
queue.push_back(new_path);
80+
if word_set.contains(&candidate) {
81+
successors.push(candidate);
82+
}
10383
}
10484
}
10585
}
106-
107-
Vec::new()
86+
successors
10887
}
10988

110-
fn differs_by_one_letter(word1: &Word, word2: &Word) -> bool {
111-
if word1.word.len() != word2.word.len() {
112-
return false;
113-
}
89+
fn generate_word_ladder(start: String, end: String, word_list: Vec<String>) -> Vec<String> {
90+
let word_set: HashSet<String> = word_list.iter().cloned().collect();
91+
let mut queue = VecDeque::new();
92+
let mut visited = HashSet::new();
93+
94+
queue.push_back(vec![start.clone()]);
95+
visited.insert(start.clone());
11496

115-
let mut diff_count = 0;
97+
while let Some(ladder) = queue.pop_front() {
98+
let last_word = ladder.last().unwrap();
99+
100+
if last_word == &end {
101+
return ladder;
102+
}
116103

117-
for (c1, c2) in word1.word.chars().zip(word2.word.chars()) {
118-
if c1 != c2 {
119-
diff_count += 1;
120-
if diff_count > 1 {
121-
return false;
104+
for successor in find_successors(last_word, &word_set) {
105+
if !visited.contains(&successor) {
106+
let mut new_ladder = ladder.clone();
107+
new_ladder.push(successor.clone());
108+
queue.push_back(new_ladder);
109+
visited.insert(successor);
122110
}
123111
}
124112
}
125113

126-
diff_count == 1
114+
Vec::new() // Return an empty vector if no ladder is found
127115
}

0 commit comments

Comments
 (0)