malachite_base/strings/
mod.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::named::Named;
10use alloc::string::String;
11use alloc::vec::Vec;
12use core::fmt::{Binary, Debug, LowerHex, Octal, UpperHex};
13use hashbrown::HashSet;
14use itertools::Itertools;
15
16/// Sorts the characters of a string slice and returns them in a new [`String`].
17///
18/// # Worst-case complexity
19/// $T(n) = O(n \log n)$
20///
21/// $M(n) = O(n)$
22///
23/// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`.
24///
25/// # Examples
26/// ```
27/// use malachite_base::strings::string_sort;
28///
29/// assert_eq!(string_sort("Hello, world!"), " !,Hdellloorw");
30/// assert_eq!(string_sort("Mississippi"), "Miiiippssss");
31/// ```
32pub fn string_sort(s: &str) -> String {
33    let mut chars = s.chars().collect_vec();
34    chars.sort_unstable();
35    chars.iter().collect()
36}
37
38/// Takes a string slice's unique characters and returns them in a new [`String`].
39///
40/// The unique characters are output in order of appearance.
41///
42/// # Worst-case complexity
43/// $T(n) = O(n)$
44///
45/// $M(n) = O(n)$
46///
47/// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`.
48///
49/// # Examples
50/// ```
51/// use malachite_base::strings::string_unique;
52///
53/// assert_eq!(string_unique("Hello, world!"), "Helo, wrd!");
54/// assert_eq!(string_unique("Mississippi"), "Misp");
55/// ```
56pub fn string_unique(s: &str) -> String {
57    let mut chars = HashSet::new();
58    let mut nub = String::new();
59    for c in s.chars() {
60        if chars.insert(c) {
61            nub.push(c);
62        }
63    }
64    nub
65}
66
67/// Returns whether all of the first string slice's characters are present in the second string
68/// slice.
69///
70/// Does not take multiplicities into account.
71///
72/// # Worst-case complexity
73/// $T(n) = O(n)$
74///
75/// $M(n) = O(n + m)$
76///
77/// where $T$ is time, $M$ is additional memory, $n$ is `s.len()`, and $m$ is `t.len()`.
78///
79/// # Examples
80/// ```
81/// use malachite_base::strings::string_is_subset;
82///
83/// assert_eq!(string_is_subset("oH, well", "Hello, world!"), true);
84/// assert_eq!(string_is_subset("MMM", "Mississippi"), true);
85/// assert_eq!(string_is_subset("Hello, World!", "Hello, world!"), false);
86/// assert_eq!(string_is_subset("j", "Mississippi"), false);
87/// ```
88pub fn string_is_subset(s: &str, t: &str) -> bool {
89    let t_chars: HashSet<char> = t.chars().collect();
90    s.chars().all(|c| t_chars.contains(&c))
91}
92
93impl_named!(String);
94
95/// A trait that provides an ergonomic way to create the string specified by a [`Debug`]
96/// implementation.
97pub trait ToDebugString: Debug {
98    fn to_debug_string(&self) -> String;
99}
100
101impl<T: Debug> ToDebugString for T {
102    /// Returns the [`String`] produced by `T`s [`Debug`] implementation.
103    ///
104    /// # Examples
105    /// ```
106    /// use malachite_base::strings::ToDebugString;
107    ///
108    /// assert_eq!([1, 2, 3].to_debug_string(), "[1, 2, 3]");
109    /// assert_eq!(
110    ///     [vec![2, 3], vec![], vec![4]].to_debug_string(),
111    ///     "[[2, 3], [], [4]]"
112    /// );
113    /// assert_eq!(Some(5).to_debug_string(), "Some(5)");
114    /// ```
115    #[inline]
116    fn to_debug_string(&self) -> String {
117        ::alloc::format!("{self:?}")
118    }
119}
120
121/// A trait that provides an ergonomic way to create the string specified by a [`Binary`]
122/// implementation.
123pub trait ToBinaryString: Binary {
124    fn to_binary_string(&self) -> String;
125}
126
127impl<T: Binary> ToBinaryString for T {
128    /// Returns the [`String`] produced by `T`s [`Binary`] implementation.
129    ///
130    /// # Examples
131    /// ```
132    /// use malachite_base::strings::ToBinaryString;
133    ///
134    /// assert_eq!(5u64.to_binary_string(), "101");
135    /// assert_eq!((-100i16).to_binary_string(), "1111111110011100");
136    /// ```
137    #[inline]
138    fn to_binary_string(&self) -> String {
139        ::alloc::format!("{self:b}")
140    }
141}
142
143/// A trait that provides an ergonomic way to create the string specified by an [`Octal`]
144/// implementation.
145pub trait ToOctalString: Octal {
146    fn to_octal_string(&self) -> String;
147}
148
149impl<T: Octal> ToOctalString for T {
150    /// Returns the [`String`] produced by `T`s [`Octal`] implementation.
151    ///
152    /// # Examples
153    /// ```
154    /// use malachite_base::strings::ToOctalString;
155    ///
156    /// assert_eq!(50u64.to_octal_string(), "62");
157    /// assert_eq!((-100i16).to_octal_string(), "177634");
158    /// ```
159    #[inline]
160    fn to_octal_string(&self) -> String {
161        ::alloc::format!("{self:o}")
162    }
163}
164
165/// A trait that provides an ergonomic way to create the string specified by a [`LowerHex`]
166/// implementation.
167pub trait ToLowerHexString: LowerHex {
168    fn to_lower_hex_string(&self) -> String;
169}
170
171impl<T: LowerHex> ToLowerHexString for T {
172    /// Returns the [`String`] produced by `T`s [`LowerHex`] implementation.
173    ///
174    /// # Examples
175    /// ```
176    /// use malachite_base::strings::ToLowerHexString;
177    ///
178    /// assert_eq!(50u64.to_lower_hex_string(), "32");
179    /// assert_eq!((-100i16).to_lower_hex_string(), "ff9c");
180    /// ```
181    #[inline]
182    fn to_lower_hex_string(&self) -> String {
183        ::alloc::format!("{self:x}")
184    }
185}
186
187/// A trait that provides an ergonomic way to create the string specified by an [`UpperHex`]
188/// implementation.
189pub trait ToUpperHexString: UpperHex {
190    fn to_upper_hex_string(&self) -> String;
191}
192
193impl<T: UpperHex> ToUpperHexString for T {
194    /// Returns the [`String`] produced by `T`s [`UpperHex`] implementation.
195    ///
196    /// # Examples
197    /// ```
198    /// use malachite_base::strings::ToUpperHexString;
199    ///
200    /// assert_eq!(50u64.to_upper_hex_string(), "32");
201    /// assert_eq!((-100i16).to_upper_hex_string(), "FF9C");
202    /// ```
203    #[inline]
204    fn to_upper_hex_string(&self) -> String {
205        ::alloc::format!("{self:X}")
206    }
207}
208
209/// Generates [`String`]s, given an iterator that generates `Vec<char>`s.
210///
211/// This `struct` is created by [`strings_from_char_vecs`]; see its documentation for more.
212#[derive(Clone, Debug)]
213pub struct StringsFromCharVecs<I: Iterator<Item = Vec<char>>> {
214    css: I,
215}
216
217impl<I: Iterator<Item = Vec<char>>> Iterator for StringsFromCharVecs<I> {
218    type Item = String;
219
220    #[inline]
221    fn next(&mut self) -> Option<String> {
222        self.css.next().map(|cs| cs.into_iter().collect())
223    }
224}
225
226/// Generates [`String`]s, given an iterator that generates `Vec<char>`s.
227///
228/// The elements appear in the same order as they do in the given iterator, but as [`String`]s.
229///
230/// The output length is `css.count()`.
231///
232/// # Examples
233/// ```
234/// use itertools::Itertools;
235/// use malachite_base::strings::strings_from_char_vecs;
236///
237/// let ss =
238///     &strings_from_char_vecs([vec!['a', 'b'], vec!['c', 'd']].iter().cloned()).collect_vec();
239/// assert_eq!(
240///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
241///     &["ab", "cd"]
242/// );
243/// ```
244#[inline]
245pub const fn strings_from_char_vecs<I: Iterator<Item = Vec<char>>>(
246    css: I,
247) -> StringsFromCharVecs<I> {
248    StringsFromCharVecs { css }
249}
250
251/// Iterators that generate [`String`]s without repetition.
252pub mod exhaustive;
253#[cfg(feature = "random")]
254/// Iterators that generate [`String`]s randomly.
255pub mod random;