From f9f8f326740644f24bcb14132cd37d6c0e3decba Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Thu, 16 May 2024 20:19:07 +0200 Subject: [PATCH] strfry a string --- .gitignore | 1 + Cargo.lock | 7 +++++++ Cargo.toml | 8 ++++++++ LICENSE | 20 ++++++++++++++++++ README.md | 10 +++++++++ src/lib.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 106 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..4d92684 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "strfry" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d13cb3f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "strfry" +version = "0.1.0" +edition = "2021" +description = "randomize a string" +license = "MIT" + +[dependencies] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e4be788 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2024 Jan-Erik Rediger + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5be10af --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Randomize a string + +Randomizes the contents of string by randomly swapping characters in the string. +The result is an anagram of string. + +```rust +use strfry::strfry; + +let anagram = strfry("i am a weakish speller"); +``` diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..9e8356f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,60 @@ +//! Randomize a string +//! +//! Randomizes the contents of string by randomly swapping characters in the string. +//! The result is an anagram of string. +//! +//! ```rust +//! # use strfry::strfry; +//! let anagram = strfry("i am a weakish speller"); +//! ``` + +use std::collections::hash_map::RandomState; +use std::hash::{BuildHasher, Hasher}; + +fn random() -> usize { + RandomState::new().build_hasher().finish() as usize +} + +/// randomize a string +/// +/// Randomizes the contents of string by randomly swapping characters in the string. +/// Panics when the string contains non-ASCII characters. +/// The result is an anagram of string. +pub fn strfry(string: &str) -> String { + assert!(string.is_ascii()); + + let mut output = string.to_string(); + { + // SAFETY: It's all ASCII and we just gonna swap around things. + let string = unsafe { output.as_bytes_mut() }; + let len = string.len(); + + for i in 0..len { + let j = random() % (len - i) + i; + string.swap(i, j); + } + } + + output +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn it_works() { + let input = "hello world!"; + assert_eq!(input.len(), strfry(&input).len()); + } + + #[test] + fn randomizes() { + for _ in 0..100 { + assert!(matches!( + &*strfry("abc"), + "abc" | "acb" | "bac" | "bca" | "cab" | "cba" + )); + } + } +}