Repeated String

See the original problem on HackerRank.

Solutions

Let’s call l the length of the string. Thus, we have copies = n / l copies of the string.

Let’s call occ the number of occurrences of a in the string. Thus, we have at least occ * l occurrences of a.

The extra number of a is calculated from the possible remainder of the first n / l characters in the string. So we calculate the number of a in the first n%l characters.

Here is a C++ solution:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
string s; long n; 
cin >> s >> n;
int l = s.size();

auto occ = count(begin(s), end(s), 'a');
auto copies = n/l;

const auto remainder = n % l;
const auto aInFirstPart = count(begin(s), next(begin(s), remainder), 'a');

cout << (copies*occ + aInFirstPart);

An alternative solution in Python:

1
2
s, n = input().strip(), int(input().strip())
print(s.count("a") * (n // len(s)) + s[:n % len(s)].count("a"))

This simple exercise gives us the opportunity to find “perturbations” (variations) on the problem. Basically, we start from the problem as-is and we make it more or less complicated.

For example:

  • count other letters (take this information from the input)
  • search the infinite string with generators
  • don’t use loops (only use standard functions or constructs, instead)
  • don’t use the module operator

An alternative solution in Haskell:

1
2
3
4
5
6
7
solve :: String -> Int -> Int
solve s n = rep * ( countA s ) + countA las
  where
    l = length s
    rep = div n l
    las = take ( rem n l ) s
    countA = length . filter (== 'a')

An alternative solution in Rust:

1
2
3
4
5
6
7
8
fn solve(s: &str, n: usize) -> usize {
    let chars_count = s.chars().count();
    let remainder = n % chars_count;
    let repeat = n / chars_count;
    let a_in_s = s.chars().filter(|&c| c == 'a').count();
    let a_in_remainder = s.chars().take(remainder).filter(|&c| c == 'a').count();
    repeat * a_in_s + a_in_remainder
}

In Rust, chars and bytes are different things. If we know the input is an ASCII string, we can optimize the code by iterating the raw buffer:

1
2
3
4
5
6
7
8
fn solve(s: &[u8], n: usize) -> usize {
    let chars_count = s.len();
    let remainder = n % chars_count;
    let repeat = n / chars_count;
    let a_in_s = s.iter().filter(|&&c| c == b'a').count();
    let a_in_remainder = s.iter().take(remainder).filter(|&&c| c == b'a').count();
    repeat * a_in_s + a_in_remainder
}
We've worked on this challenge in these gyms: modena 
comments powered by Disqus