Skip to content

Commit

Permalink
Add problem 2182: Construct String With Repeat Limit
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Jul 30, 2024
1 parent 8b46c7b commit 241493a
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,7 @@ pub mod problem_2177_find_three_consecutive_integers_that_sum_to_a_given_number;
pub mod problem_2178_maximum_split_of_positive_even_integers;
pub mod problem_2180_count_integers_with_even_digit_sum;
pub mod problem_2181_merge_nodes_in_between_zeros;
pub mod problem_2182_construct_string_with_repeat_limit;
pub mod problem_2183_count_array_pairs_divisible_by_k;
pub mod problem_2185_counting_words_with_a_given_prefix;
pub mod problem_2186_minimum_number_of_steps_to_make_two_strings_anagram_ii;
Expand Down
82 changes: 82 additions & 0 deletions src/problem_2182_construct_string_with_repeat_limit/greedy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::iter;
use std::num::NonZeroU32;

impl Solution {
pub fn repeat_limited_string(s: String, repeat_limit: i32) -> String {
let mut s = s.into_bytes();
let repeat_limit = NonZeroU32::new(repeat_limit as _).unwrap();
let mut counts = [0_u32; 26];

for &c in &s {
counts[usize::from(c) - usize::from(b'a')] += 1;
}

s.clear();

let mut i = 25;

'outer: while let Some(count) = counts.get(i).copied() {
if count == 0 {
i = i.wrapping_sub(1);

continue;
}

let mut cycles = count / repeat_limit;
let mut extra = count % repeat_limit;

if extra == 0 {
cycles -= 1;
extra = repeat_limit.get();
}

let mut j = i.wrapping_sub(1);

for _ in 0..cycles {
s.extend(iter::repeat(b'a' + i as u8).take(repeat_limit.get() as _));

loop {
if let Some(count_2) = counts.get_mut(j) {
if *count_2 == 0 {
j = j.wrapping_sub(1);
} else {
*count_2 -= 1;

break;
}
} else {
break 'outer;
}
}

s.push(b'a' + j as u8);
}

s.extend(iter::repeat(b'a' + i as u8).take(extra as _));

i = j;
}

String::from_utf8(s).ok().unwrap()
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn repeat_limited_string(s: String, repeat_limit: i32) -> String {
Self::repeat_limited_string(s, repeat_limit)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
72 changes: 72 additions & 0 deletions src/problem_2182_construct_string_with_repeat_limit/greedy_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::num::NonZeroU32;

impl Solution {
pub fn repeat_limited_string(s: String, repeat_limit: i32) -> String {
let mut s = s.into_bytes();
let repeat_limit = NonZeroU32::new(repeat_limit as _).unwrap();
let mut counts = [0_u32; 26];

for &c in &s {
counts[usize::from(c) - usize::from(b'a')] += 1;
}

s.clear();

let mut i = 25;

'outer: while let Some(mut count) = counts.get(i).copied() {
let mut j = i.wrapping_sub(1);
let mut budget = repeat_limit.get();

while count != 0 {
if budget == 0 {
loop {
if let Some(count_2) = counts.get_mut(j) {
if *count_2 == 0 {
j = j.wrapping_sub(1);
} else {
*count_2 -= 1;

break;
}
} else {
break 'outer;
}
}

s.push(b'a' + j as u8);
budget = repeat_limit.get();
}

s.push(b'a' + i as u8);
budget -= 1;

count -= 1;
}

i = j;
}

String::from_utf8(s).ok().unwrap()
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn repeat_limited_string(s: String, repeat_limit: i32) -> String {
Self::repeat_limited_string(s, repeat_limit)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
30 changes: 30 additions & 0 deletions src/problem_2182_construct_string_with_repeat_limit/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
pub mod greedy;
pub mod greedy_2;

pub trait Solution {
fn repeat_limited_string(s: String, repeat_limit: i32) -> String;
}

#[cfg(test)]
mod tests {
use super::Solution;

pub fn run<S: Solution>() {
let test_cases = [
(("cczazcc", 3), "zzcccac"),
(("aababab", 2), "bbabaa"),
(
("robnsdvpuxbapuqgopqvxdrchivlifeepy", 2),
"yxxvvuvusrrqqppopponliihgfeeddcbba",
),
(
("xyutfpopdynbadwtvmxiemmusevduloxwvpkjioizvanetecnuqbqqdtrwrkgt", 1),
"zyxyxwxwvwvuvuvututstrtrtqpqpqponononmlmkmkjigifiededededcbaba",
),
];

for ((s, repeat_limit), expected) in test_cases {
assert_eq!(S::repeat_limited_string(s.to_string(), repeat_limit), expected);
}
}
}

0 comments on commit 241493a

Please sign in to comment.