See the original problem on HackerRank.
Solutions
A solution consists in finding all the contiguous digits in the string, converting them to integers and putting them in a set for removing duplicates. Finally, outputting the size of the set:
|
|
This solution can be redesigned by using C++ ranges. We note that “contiguous digits” are actually “chunks” of characters that are all digits. This means, we can apply views::chunk_by
to obtain contiguous sequences of characters that are all of the same “alphabeticalness”. Then we just filter out those which are not digits, convert all the remaining ranges to integers, and finally construct a set from of the resulting range of numbers:
|
|
Strictly speaking, isalpha(a) == isalpha(b)
might be false even though both characters are alphabetical because isalpha()
returns any positive number if the input is a letter. However, most implementations just return the very same value for every letter and 0 otherwise. Thus, we should raplace that check with something like (bool)isalpha(a) == (bool)isalpha(b)
.
Paolo Di Giglio noticed that filter
is not necessary if we just iterate 2 “chunks” at a time by introducing stride
:
|
|
If the input starts with a letter, we also drop the very first chunk.
This solution avoids checking every chunk explicitly. The only caveat is that if we introduce other “chunk types” (e.g. we need to distinguish uppercase and lowercase letters for some reason), the positional approach might not work anymore. On the other hand, the filter approach ensures we only consider the chunk containing digits.
An extension of this solution consists in handling numbers that are out of built-in integral bounds (e.g. int
and size_t
). This is possible by removing leading zeros from extracted numbers and store them in a set of strings. In the solution snippet below, we actually used string_view
to avoid copying data every time:
|
|
Here is the same idea with ranges:
|
|
A extension of this exercise consists in handling negative numbers.