|
10 | 10 | /// Format vector of numbers into a compressed range
|
11 | 11 |
|
12 | 12 | #include <algorithm>
|
13 |
| -#include <cassert> |
| 13 | +#include <sstream> |
14 | 14 | #include <string>
|
15 | 15 |
|
| 16 | +#include "invariant.h" |
| 17 | + |
16 | 18 | #include "format_number_range.h"
|
17 | 19 |
|
18 | 20 | /// create shorter representation for output
|
19 |
| -/// \param parameters: vector of numbers |
| 21 | +/// \param input_numbers: vector of numbers |
20 | 22 | /// \return string of compressed number range representation
|
21 |
| -std::string format_number_range(std::vector<unsigned> &numbers) |
| 23 | +std::string format_number_range(const std::vector<unsigned> &input_numbers) |
22 | 24 | {
|
23 |
| - std::string number_range; |
| 25 | + PRECONDITION(!input_numbers.empty()); |
| 26 | + |
| 27 | + std::vector<unsigned> numbers(input_numbers); |
24 | 28 | std::sort(numbers.begin(), numbers.end());
|
25 | 29 | unsigned end_number=numbers.back();
|
26 | 30 | if(numbers.front()==end_number)
|
27 |
| - number_range=std::to_string(end_number); // only single number |
28 |
| - else |
| 31 | + return std::to_string(end_number); // only single number |
| 32 | + |
| 33 | + std::stringstream number_range; |
| 34 | + |
| 35 | + auto start_number = numbers.front(); |
| 36 | + |
| 37 | + for(std::vector<unsigned>::const_iterator it = numbers.begin(); |
| 38 | + it != numbers.end(); |
| 39 | + ++it) |
29 | 40 | {
|
30 |
| - bool next=true; |
31 |
| - bool first=true; |
32 |
| - bool range=false; |
33 |
| - unsigned start_number=numbers.front(); |
34 |
| - unsigned last_number=start_number; |
| 41 | + const auto number = *it; |
| 42 | + const auto next = std::next(it); |
| 43 | + |
| 44 | + // advance one forward |
| 45 | + if(next != numbers.end() && *next <= number + 1) |
| 46 | + continue; |
| 47 | + |
| 48 | + // end this block range |
| 49 | + if(start_number != numbers.front()) |
| 50 | + number_range << ','; |
35 | 51 |
|
36 |
| - for(const auto &number : numbers) |
| 52 | + if(number == start_number) |
37 | 53 | {
|
38 |
| - if(next) |
39 |
| - { |
40 |
| - next=false; |
41 |
| - start_number=number; |
42 |
| - last_number=number; |
43 |
| - } |
44 |
| - // advance one forward |
45 |
| - else |
46 |
| - { |
47 |
| - if(number==last_number+1 && !(number==end_number)) |
48 |
| - { |
49 |
| - last_number++; |
50 |
| - if(last_number>start_number+1) |
51 |
| - range=true; |
52 |
| - } |
53 |
| - // end this block range |
54 |
| - else |
55 |
| - { |
56 |
| - if(first) |
57 |
| - first=false; |
58 |
| - else |
59 |
| - number_range+=","; |
60 |
| - if(last_number>start_number) |
61 |
| - { |
62 |
| - if(range) |
63 |
| - { |
64 |
| - if(number==end_number && number==last_number+1) |
65 |
| - number_range+= |
66 |
| - std::to_string(start_number)+"-"+std::to_string(end_number); |
67 |
| - else if(number==end_number) |
68 |
| - number_range+= |
69 |
| - std::to_string(start_number)+"-"+std::to_string(last_number)+ |
70 |
| - ","+std::to_string(end_number); |
71 |
| - else |
72 |
| - number_range+= |
73 |
| - std::to_string(start_number)+"-"+std::to_string(last_number); |
74 |
| - } |
75 |
| - else |
76 |
| - { |
77 |
| - if(number!=end_number) |
78 |
| - number_range+= |
79 |
| - std::to_string(start_number)+","+std::to_string(last_number); |
80 |
| - else |
81 |
| - { |
82 |
| - if(start_number+1==last_number && last_number+1==number) |
83 |
| - number_range+= |
84 |
| - std::to_string(start_number)+"-"+std::to_string(end_number); |
85 |
| - else |
86 |
| - number_range+= |
87 |
| - std::to_string(start_number)+ |
88 |
| - ","+std::to_string(last_number)+ |
89 |
| - ","+std::to_string(end_number); |
90 |
| - } |
91 |
| - } |
92 |
| - start_number=number; |
93 |
| - last_number=number; |
94 |
| - range=false; |
95 |
| - continue; |
96 |
| - } |
97 |
| - else |
98 |
| - { |
99 |
| - if(number!=end_number) |
100 |
| - number_range+=std::to_string(start_number); |
101 |
| - else |
102 |
| - number_range+=std::to_string(start_number)+","+ |
103 |
| - std::to_string(end_number); |
104 |
| - start_number=number; |
105 |
| - last_number=number; |
106 |
| - range=false; |
107 |
| - continue; // already set next start number |
108 |
| - } |
109 |
| - next=true; |
110 |
| - } |
111 |
| - } |
| 54 | + number_range << number; |
112 | 55 | }
|
| 56 | + else if(number == start_number + 1) |
| 57 | + { |
| 58 | + number_range << start_number << ',' << number; |
| 59 | + } |
| 60 | + else |
| 61 | + { |
| 62 | + number_range << start_number << '-' << number; |
| 63 | + } |
| 64 | + |
| 65 | + if(next != numbers.end()) |
| 66 | + start_number = *next; |
113 | 67 | }
|
114 |
| - assert(!number_range.empty()); |
115 |
| - return number_range; |
| 68 | + |
| 69 | + CHECK_RETURN(!number_range.str().empty()); |
| 70 | + return number_range.str(); |
116 | 71 | }
|
0 commit comments