Compare commits

...

10 commits
1.0 ... main

Author SHA1 Message Date
458d10e883 Updated LICENSE 2023-04-10 20:11:08 -05:00
SinTan1729
027f303f04
Update README.md 2022-06-10 03:19:11 -05:00
e618253bc0 Improved formatting of output 2022-06-10 03:12:22 -05:00
d0a4506c48 Updated README.md 2022-06-08 11:38:16 -05:00
46fc61bdbf Added build.rs to generate dict files 2022-06-07 23:52:32 -05:00
SinTan1729
2ae84ddf71
Update README.md 2022-06-07 22:37:43 -05:00
cf9e1f7775 Add compression to dictionary data 2022-06-07 19:38:30 -05:00
ade3107107 Updated wordlist and made related changes in code 2022-06-07 17:30:29 -05:00
6192c22c19 Renamed variable 2022-06-07 00:34:39 -05:00
SinTan1729
dbf2a7afc9
Update README.md 2022-06-06 23:57:43 -05:00
11 changed files with 370268 additions and 21 deletions

41
Cargo.lock generated
View file

@ -2,6 +2,47 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "libc"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "lzma-sys"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e06754c4acf47d49c727d5665ca9fb828851cda315ed3bd51edd148ef78a8772"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]] [[package]]
name = "unscrambler" name = "unscrambler"
version = "0.1.0" version = "0.1.0"
dependencies = [
"xz2",
]
[[package]]
name = "xz2"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
dependencies = [
"lzma-sys",
]

View file

@ -6,3 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
xz2 = "0.1.7"
[build-dependencies]
xz2 = "0.1.7"

View file

@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found. the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.> Unscrambler-rust: A simple unscrambler program written in Rust.
Copyright (C) <year> <name of author> Copyright (C) 2023 Sayantan Santra
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode: notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author> Unscrambler-rust Copyright (C) 2023 Sayantan Santra
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.

View file

@ -1,5 +1,15 @@
# Unscrambler written in Rust # Unscrambler written in Rust
I'm learning Rust, so this is just a rewrite of an simple old project in Rust. I'm learning Rust, so this is just a rewrite of a simple old project into Rust.
[Link to old project.](https://github.com/SinTan1729/Unscrambler). [Link to old C++ project.](https://github.com/SinTan1729/Unscrambler)
## Usage
Simply download the `unscrambler` binary from the latest release and run it. The interface is self-explanatory.
### Note
The main `src/wordlist` was pulled from [words_alpha.txt by dwyl](https://github.com/dwyl/english-words/).
In order to use a different `wordlist.txt`, place the file inside `src/` and delete the `*.xz` files there. Then run `cargo build` or `cargo build --release`.

59
build.rs Normal file
View file

@ -0,0 +1,59 @@
use std::{fs, io::Read};
use xz2::read::XzEncoder;
fn main() {
// check if the compressed dictionary files exist, run if missing
// so, in order to rebuild the compressed files, just delete them
if !fs::metadata("src/dict/wordlist.txt.xz").is_ok() {
compress_wordlist();
}
if !fs::metadata("src/dict/wordlist_sorted.txt.xz").is_ok() {
compress_sorted_wordlist();
}
}
fn compress_wordlist() {
// specify location for dictionary files and read wordlist.txt
let dict_dir = "src/dict/";
let wordlist = fs::read_to_string([dict_dir, "wordlist.txt"].join(""))
.expect("The file wordlist.txt is missing!");
// compress wordlist.txt using xz compression and save it
let wordlist_bytes = wordlist.as_bytes();
let mut compressor = XzEncoder::new(wordlist_bytes, 9);
let mut compressed_wordlist = Vec::new();
compressor.read_to_end(&mut compressed_wordlist).unwrap();
fs::write([dict_dir, "wordlist.txt.xz"].join(""), compressed_wordlist).unwrap();
}
fn compress_sorted_wordlist() {
// specify location for dictionary files
let dict_dir = "src/dict/";
// create wordlist_sorted from wordlist.txt
let wordlist = fs::read_to_string([dict_dir, "wordlist.txt"].join(""))
.expect("The file wordlist.txt is missing!");
let mut wordlist_sorted = String::new();
for word in wordlist.split_terminator("\n") {
wordlist_sorted = [wordlist_sorted, sorted(word), "\n".to_string()].join("");
}
//compress wordlist_sorted using xz compression and save it
let wordlist_sorted_bytes = wordlist_sorted.as_bytes();
let mut compressor_sorted = XzEncoder::new(wordlist_sorted_bytes, 9);
let mut compressed_wordlist_sorted = Vec::new();
compressor_sorted
.read_to_end(&mut compressed_wordlist_sorted)
.unwrap();
fs::write(
[dict_dir, "wordlist_sorted.txt.xz"].join(""),
compressed_wordlist_sorted,
)
.unwrap();
}
// function for sorting
fn sorted(word: &str) -> String {
let mut word_chars: Vec<char> = word.chars().collect();
word_chars.sort_by(|a, b| a.cmp(b));
String::from_iter(word_chars)
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

370105
src/dict/wordlist.txt Normal file

File diff suppressed because it is too large Load diff

BIN
src/dict/wordlist.txt.xz Normal file

Binary file not shown.

Binary file not shown.

View file

@ -1,9 +1,27 @@
use std::io::{self, Write}; use std::io::{self, prelude::*, Write};
use xz2::read::XzDecoder;
fn main() { fn main() {
// read the dictionary files // welcome message
let wordlist = include_str!("data/wordlist.txt"); println!("*** Welcome to unscrambler! ***");
let wordlist_sorted = include_str!("data/wordlist_sorted.txt");
// load the compressed dictionary files (embedded in compile-time)
let wordlist_cmp: &[u8] = include_bytes!("dict/wordlist.txt.xz");
let wordlist_sorted_cmp: &[u8] = include_bytes!("dict/wordlist_sorted.txt.xz");
// decompress the dictionary files
let mut decompressor = XzDecoder::new(wordlist_cmp);
let mut decompressor_sorted = XzDecoder::new(wordlist_sorted_cmp);
let mut wordlist = String::new();
let mut wordlist_sorted = String::new();
decompressor.read_to_string(&mut wordlist).unwrap();
decompressor_sorted
.read_to_string(&mut wordlist_sorted)
.unwrap();
// some formatting of the dictionary data
let wordlist = &[" ", &wordlist.replace("\n", " ")[..]].join("")[..];
let wordlist_sorted = &[" ", &wordlist_sorted.replace("\n", " ")[..]].join("")[..];
// get into a loop so that we can run it multiple times // get into a loop so that we can run it multiple times
loop { loop {
@ -37,21 +55,33 @@ fn main() {
if indices.len() == 0 { if indices.len() == 0 {
println!("No matches found!"); println!("No matches found!");
} else { } else {
println!("The matched words are:"); let mut out_list = Vec::new();
for index in indices { for index in indices {
println!( out_list.push(sentence_case(&wordlist[index + 1..index - 1 + input.len()]));
"{}", }
sentence_case(&wordlist[index + 1..index + input.len() - 1]) if out_list.len() == 1 {
); println!("The only matched word is {}.", out_list[0]);
} else {
print!("The {} matched words are ", out_list.len());
out_list.iter().enumerate().for_each(|(pos, word)| {
print!("{}", word);
if pos < out_list.len() - 2 {
print!(", ");
} else if pos < out_list.len() - 1 {
print!(" and ");
}
});
print!(".\n");
io::stdout().flush().unwrap();
} }
} }
// ask if we want to go again // ask if we want to go again
print!("Would you like to do it again? (y/N)"); print!("Would you like to do it again? (y/N): ");
io::stdout().flush().unwrap(); io::stdout().flush().unwrap();
let mut responce = String::new(); let mut response = String::new();
io::stdin().read_line(&mut responce).unwrap(); io::stdin().read_line(&mut response).unwrap();
if !(responce.contains("Y") || responce.contains("y")) { if !(response.contains("Y") || response.contains("y")) {
break; break;
} }
} }
@ -62,6 +92,6 @@ fn sentence_case(s: &str) -> String {
let mut c = s.chars(); let mut c = s.chars();
match c.next() { match c.next() {
None => String::new(), None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + &c.as_str()[..].to_lowercase(), Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
} }
} }