-
Notifications
You must be signed in to change notification settings - Fork 0
/
p3solution.cpp
202 lines (150 loc) · 5.55 KB
/
p3solution.cpp
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// Project 3: Heroic Grazblatnik
#include <string>
using namespace std;
const char END_OF_BEAT = '/';
//*************************************
// hasCorrectSyntax
//*************************************
bool hasCorrectSyntax(string song)
{
// An empty song is syntactically correct.
if (song.size() == 0)
return true;
// A non-empty song must end with an end-of-beat marker.
if (song[song.size()-1] != END_OF_BEAT)
return false;
// At this point, we know the song ends properly, so in the following
// loop, we do not have to worry about, say, there not being a character
// following a digit.
// Each iteration of the loop recognizes one beat.
//decouples type from the job (looping thru string
//size_t is the type used to represent sizes (as its names implie//). Its platform (and even potentially implementation) dependent, //and should be used only for this purpose.
An int is signed by default, and even though its size is also platform dependant, it will be a fixed 32bits on most modern machine (and though size_t is 64 bits on 64-bits architecture, int remain 32bits long on those architectures).
size_t k = 0;
while (k != song.size())
{
// The beat might have no note.
if (song[k] == END_OF_BEAT)
{
k++;
continue;
}
// Verify color letter.
char color = tolower(song[k]);
if (color != 'g' && color != 'r' && color != 'y' &&
color != 'b' && color != 'o')
return false;
k++;
// There might be a digit.
//second digit nested in first if
if (isdigit(song[k]))
{
k++;
// There might be a second digit.
if (isdigit(song[k]))
k++;
}
// Verify end of beat.
if (song[k] != END_OF_BEAT)
return false;
k++;
}
// We get here if we got through the song without a problem.
return true;
}
//*************************************
// translateSong
//*************************************
int translateSong(string song, string& instructions, int& badBeat)
{
// Define return values
const int RET_OK = 0;
const int RET_NOT_WELL_FORMED = 1;
const int RET_BAD_SUSTAINED_LENGTH = 2;
const int RET_SUSTAINED_INTERRUPTED = 3;
const int RET_PREMATURE_END = 4;
// A song that is not syntactically correct is not translatable.
if (!hasCorrectSyntax(song))
return RET_NOT_WELL_FORMED;
// We will build the translation in the string named result, and
// modify the instructions parameter only if the entire translation
// succeeds.
string result;
int sustainedRemaining = 0;
// How many beats left in the current
// sustained note
char sustainedColor;
// Color of the current sustained
// note (upper case)
// Each iteration of the loop translates one beat.
int beatNumber;
size_t k = 0;
for (beatNumber = 1; k != song.size(); beatNumber++)
{
// A beat with no note is either a beat with no required action or
// a continuation of a sustained note.
if (song[k] == END_OF_BEAT)
{
if (sustainedRemaining == 0)
result += 'x';
else
{
// Continue current sustained note
result += sustainedColor;
sustainedRemaining--;
}
k++;
continue;
}
// The beat is not empty if we get here, so a sustained note had
// better not still be in effect.
if (sustainedRemaining > 0)
{
badBeat = beatNumber;
return RET_SUSTAINED_INTERRUPTED;
}
// Since we know the song is syntactically correct, we know that
// song[k] is a valid color. Record it and advance past the color.
char color = tolower(song[k]);
k++;
// If there's a digit, this beat specifies a sustained note.
// Determine the sustained note length.
if (isdigit(song[k]))
{
sustainedRemaining = song[k] - '0';
k++;
if (isdigit(song[k]))
{
sustainedRemaining = 10 * sustainedRemaining + song[k] - '0';
k++;
}
// The sustained note length can't be < 2.
if (sustainedRemaining < 2)
{
badBeat = beatNumber;
return RET_BAD_SUSTAINED_LENGTH;
}
// Record the sustained note color and translate this first beat
// of the sustained note.
sustainedColor = toupper(color);
result += sustainedColor;
sustainedRemaining--;
}
else // Not a sustained note, so translate normal note.
{
result += tolower(color);
}
// Advance past the end-of-beat marker.
k++;
}
// We've finished the song, so no sustained note should still be
// in effect.
if (sustainedRemaining > 0)
{
badBeat = beatNumber;
return RET_PREMATURE_END;
}
// We've successfully translated the entire song, so set instructions.
instructions = result;
return RET_OK;
}