-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cxx
142 lines (116 loc) · 3.73 KB
/
main.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <iostream>
#include <string>
#include <algorithm>
#include <exception>
#include <cassert>
#include <ranges>
#include <cstring>
using namespace std;
void validate_input(const char *input, const int n)
{
// handle error and corner cases
if (nullptr == input)
{
throw(std::invalid_argument("null input"));
}
if (!std::strlen(input))
{
throw(std::invalid_argument("empty input"));
}
if (n == 0 || n == 1)
{
throw(std::invalid_argument(std::string("wrong padding, n=").append(std::to_string(n))));
}
if (n < 0)
{
throw(std::invalid_argument(std::string("negative padding value is invald, n=").append(std::to_string(n))));
}
}
std::string left_padded(const char *input, const int n)
{
validate_input(input, n);
std::string result;
result.reserve(std::strlen(input) + n);
string_view str{input};
auto curr_start = begin(str);
while (curr_start != str.end())
{
// append non digits to output
auto first_digit_loc = std::find_if(curr_start, end(str), [](char c)
{ return std::isdigit(c); });
result.append(curr_start, first_digit_loc);
// handle digits
auto first_non_digit_loc = std::find_if(first_digit_loc, end(str), [](char c)
{ return !std::isdigit(c); });
auto dist = std::distance(first_digit_loc, first_non_digit_loc);
// use dist, n and iterstors to pad output if required. Hmm....
if (n - dist > 0 && (first_digit_loc != first_non_digit_loc))
{
result.append(n - dist, '0');
}
// append digits to output.
result.append(first_digit_loc, first_non_digit_loc);
curr_start = first_non_digit_loc;
}
result.shrink_to_fit();
return result;
}
[[nodiscard]] std::string left_padded_ranges(const char *input, const int n)
{
std::string result;
result.reserve(std::strlen(input) + n);
std::string_view sv(input);
size_t offset{0};
while (offset < sv.size())
{
// non digits
std::ranges::copy(sv | std::ranges::views::drop(offset) | std::ranges::views::take_while([](const char &c) -> bool
{ return !std::isdigit(c); }) |
std::ranges::views::transform([&offset](char c)
{ ++offset; return c; }),
std::back_inserter(result));
auto dist = std::ranges::distance(sv | std::ranges::views::drop(offset) | std::views::take_while([](const char &c) -> bool
{ return std::isdigit(c); }));
// only append if there are digits to append
result.append(dist && (n - dist > 0) ? n - dist : 0, '0');
result.append(sv, offset, dist);
// update the offset for next iteration
offset += dist;
}
result.shrink_to_fit();
return result;
}
int main(int argc, char **argv)
{
if (argc != 3)
{
std::cerr << "usage: " << argv[0] << " <input string> <n>" << endl;
return 1;
}
char *input{argv[1]};
try
{
int n = std::stoi(argv[2]);
auto result = left_padded(input, n);
auto result2 = left_padded_ranges(input, n);
assert(result == result2);
cout << result << endl;
}
catch (const std::out_of_range &oor)
{
cerr << "OUT OF RANGE, check parameters " << endl;
}
catch (const std::bad_alloc &ba)
{
cerr << "MEMORY EXCHAUSTED, check parameters " << endl;
}
catch (const std::exception &ex)
{
cerr << "GENERAL EXCEPTION: " << ex.what() << ", check parameters " << endl;
}
catch (...)
{
cerr << "Unknown EXCEPTION DEBUG! " << endl;
}
return 0;
}