Skip to content

Commit 3c31952

Browse files
committed
Added test case for video
Made for video versions of the methods that print to the console instead of creating a results list
1 parent b472b64 commit 3c31952

File tree

1 file changed

+191
-73
lines changed

1 file changed

+191
-73
lines changed

Assignment5/Problem6.cs

+191-73
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ public static void RunTests()
2929
CorrectNREAfterEachRead = new int[]{ 'a', -1, 'b', 'b' },
3030
},
3131
new TestCase
32+
{
33+
InputAsString = "ccaba",
34+
CorrectNREAfterEachRead = new int[]{ 'c', -1, 'a', 'b', 'b' },
35+
},
36+
new TestCase
3237
{
3338
InputAsString = String.Empty,
3439
CorrectNREAfterEachRead = new int[]{ -1 },
@@ -57,40 +62,164 @@ public static void RunTests()
5762
Console.WriteLine($"For the stream: {testCases[i].InputAsString}");
5863
//Console.WriteLine($"The correct result is: {testCases[i].CorrectNREAfterEachRead}");
5964

60-
var testCaseResult = PrintFirstNRE(testCases[i].InputAsStream);
65+
PrintFirstNRE_ForVideo(testCases[i].InputAsStream);
6166

62-
string resultMessage;
67+
//string resultMessage;
6368

64-
if (Enumerable.SequenceEqual(testCaseResult, testCases[i].CorrectNREAfterEachRead))
65-
{
66-
resultMessage = "SUCCESS";
67-
}
68-
else
69-
{
70-
++testOopsCount;
71-
resultMessage = "OOPS";
72-
}
69+
//if (Enumerable.SequenceEqual(testCaseResult, testCases[i].CorrectNREAfterEachRead))
70+
//{
71+
// resultMessage = "SUCCESS";
72+
//}
73+
//else
74+
//{
75+
// ++testOopsCount;
76+
// resultMessage = "OOPS";
77+
//}
7378

74-
Console.WriteLine($"{resultMessage}!");
79+
//Console.WriteLine($"{resultMessage}!");
7580
//Console.WriteLine($"Your answer is: {testCaseResult}");
7681
}
7782

78-
var testCount = testCases.Count;
79-
var testSuccessCount = testCount - testOopsCount;
83+
//var testCount = testCases.Count;
84+
//var testSuccessCount = testCount - testOopsCount;
85+
86+
//Console.WriteLine($"\n\nOut of {testCount} tests total,\n");
87+
//Console.WriteLine($"{testSuccessCount}/{testCount} tests succeeded, and");
88+
//Console.WriteLine($"{testOopsCount}/{testCount} tests oopsed.\n");
89+
90+
//if (testOopsCount == 0)
91+
//{
92+
// Console.WriteLine($"YAY! All tests succeeded! :D\n");
93+
//}
94+
}
95+
96+
97+
const int NO_NRE = -1;
98+
99+
const int LETTER_COUNT = 'z' - 'a';
100+
101+
public static void PrintFirstNRE_ForVideo(StreamReader sr)
102+
{
103+
if (sr == null)
104+
throw new ArgumentNullException("Parameter StreamReader sr is null.");
105+
106+
if (sr.EndOfStream == true)
107+
Console.WriteLine(
108+
$"No letters found in stream.\n" +
109+
$"No non-repeating letters. {NO_NRE}");
110+
111+
var letterTracker = new OrderedLetter_ForVideo[LETTER_COUNT];
112+
113+
for (var i = 0; i < LETTER_COUNT; ++i)
114+
letterTracker[i] = new OrderedLetter_ForVideo();
115+
116+
while (sr.EndOfStream == false)
117+
{
118+
var currLetter = sr.Read();
119+
ValidateLetter(currLetter);
120+
121+
Console.WriteLine(
122+
$"Reading '{Convert.ToChar(currLetter)}' from stream.");
123+
124+
letterTracker[currLetter - 'a'].LogAsRead();
125+
126+
var currFirstNRE = FindCurrentFirstNRE_ForVideo(letterTracker);
127+
128+
if (currFirstNRE == NO_NRE)
129+
Console.WriteLine($"No non-repeating letters. {NO_NRE}");
130+
else
131+
Console.WriteLine($"First non-repeating letter so far is: {Convert.ToChar(currFirstNRE)}");
132+
}
133+
}
134+
public static void ValidateLetter(int letter)
135+
{
136+
if (letter < 'a' || letter > 'z')
137+
throw new ArgumentException(
138+
"Stream may contain only letters between 'a' and 'z', inclusive.");
139+
}
140+
private class OrderedLetter_ForVideo
141+
{
142+
public int FirstSeenOrder { get; private set; }
143+
public bool DoesRepeat { get; private set; }
144+
public OrderedLetter_ForVideo()
145+
{
146+
FirstSeenOrder = NOT_SEEN;
147+
DoesRepeat = false;
148+
}
149+
private const int NOT_SEEN = -2;
150+
151+
private static int nextSeenOrderValue = 0;
152+
public void LogAsRead()
153+
{
154+
if (FirstSeenOrder < 0)
155+
FirstSeenOrder = nextSeenOrderValue++;
156+
else
157+
DoesRepeat = true;
158+
}
159+
}
160+
private static int FindCurrentFirstNRE_ForVideo(OrderedLetter_ForVideo[] letterTracker)
161+
{
162+
var allCurrentNREQuery = letterTracker
163+
.Where(ol => ol.FirstSeenOrder >= 0)
164+
.Where(ol => ol.DoesRepeat == false);
80165

81-
Console.WriteLine($"\n\nOut of {testCount} tests total,\n");
82-
Console.WriteLine($"{testSuccessCount}/{testCount} tests succeeded, and");
83-
Console.WriteLine($"{testOopsCount}/{testCount} tests oopsed.\n");
166+
if (allCurrentNREQuery.Count() == 0)
167+
return NO_NRE;
84168

85-
if (testOopsCount == 0)
169+
var newFirstNRE = allCurrentNREQuery
170+
.OrderBy(ol => ol.FirstSeenOrder)
171+
.First();
172+
173+
for (var i = 0; i < LETTER_COUNT; ++i)
86174
{
87-
Console.WriteLine($"YAY! All tests succeeded! :D\n");
175+
if (ReferenceEquals(letterTracker[i], newFirstNRE))
176+
return 'a' + i;
88177
}
178+
179+
throw new ArgumentException(
180+
"An element in letterTracker met the query criteria," +
181+
"but that element isn't in letterTracker? Wat.");
89182
}
90183

91184

92185

93186

187+
188+
189+
190+
191+
192+
193+
194+
195+
196+
197+
198+
199+
200+
201+
202+
203+
204+
205+
206+
207+
208+
209+
210+
211+
212+
213+
214+
215+
216+
217+
218+
219+
220+
221+
222+
94223
private class OrderedLetter
95224
{
96225
private static int nextSeenOrderValue = 0;
@@ -107,7 +236,7 @@ public OrderedLetter()
107236
// logic handles it seperately
108237
// Returns true if this is a new sighting of the letter
109238
// Returns false if letter has been seen before
110-
public void LogThisLetterAsRead()
239+
public void LogAsRead()
111240
{
112241
if (FirstSeenOrder < 0)
113242
{
@@ -128,18 +257,50 @@ public void LogThisLetterAsRead()
128257
public bool DoesRepeat { get; private set; }
129258
}
130259

131-
public static void ValidateLetter(int letter)
260+
private static int FindCurrentFirstNRE(OrderedLetter[] letterTracker)
132261
{
133-
if (letter < 'a' || letter > 'z')
134-
throw new ArgumentException(
135-
"Stream may contain only letters between 'a' and 'z', inclusive.");
136-
}
262+
var allCurrentNREQuery = letterTracker
263+
.Where(ol => ol.FirstSeenOrder >= 0)
264+
.Where(ol => ol.DoesRepeat == false);
137265

138-
const int NO_NRE = -1;
266+
// I think Count only does a single traversal to check and count the elements, afaik
267+
if (allCurrentNREQuery.Count() == 0)
268+
{
269+
return NO_NRE;
270+
}
271+
272+
273+
// I think that this uses lazy evaluation in that OrderBy remains only as a
274+
// stored instruction until a LINQ "execute" command is added
275+
// it only needs to walk the array once and find the element
276+
// that meets the other criteria with the smallest FirstSeenOrder
277+
// Doesn't need to copy the array or do a full sort, etc.
278+
var newFirstNRE = allCurrentNREQuery
279+
.OrderBy(ol => ol.FirstSeenOrder)
280+
.First();
281+
// That is, First does the least amount of work necessary to figure
282+
// out what is the first element of the sequence
283+
284+
285+
// Reverse lookup to figure out what letter the found newFirstNRE
286+
// corresponds to.
287+
// An alternative to this approach is for each OrderedLetter to also
288+
// store what letter it reprents, which seems silly and can fall out
289+
// of sync. Or we could use use a dictionary instead of an array
290+
// to store the OrderedLetter objects (which is overkill)
291+
// Then we could iterate on the kvps and have access to the keys that way.
292+
for (var i = 0; i < LETTER_COUNT; ++i)
293+
{
294+
if (ReferenceEquals(letterTracker[i], newFirstNRE))
295+
return 'a' + i;
296+
}
297+
298+
throw new ArgumentException(
299+
"An element in letterTracker met the query criteria," +
300+
"but that element isn't in letterTracker? Wat.");
301+
}
139302

140-
const int LETTER_COUNT = 'z' - 'a';
141303

142-
// To the result List<int> for each letter in the stream
143304
public static List<int> PrintFirstNRE(StreamReader sr)
144305
{
145306
if (sr == null)
@@ -151,7 +312,7 @@ public static List<int> PrintFirstNRE(StreamReader sr)
151312
// Console.WriteLine(Convert.ToChar(sr.Read()));
152313
//}
153314

154-
315+
155316
var letterTracker = new OrderedLetter[LETTER_COUNT];
156317
for (var i = 0; i < LETTER_COUNT; ++i)
157318
{
@@ -185,7 +346,7 @@ public static List<int> PrintFirstNRE(StreamReader sr)
185346
var currLetter = sr.Read();
186347
Console.WriteLine($"Reading '{Convert.ToChar(currLetter)}' from stream.");
187348
ValidateLetter(currLetter);
188-
letterTracker[currLetter - 'a'].LogThisLetterAsRead();
349+
letterTracker[currLetter - 'a'].LogAsRead();
189350

190351
var currFirstNRE = FindCurrentFirstNRE(letterTracker);
191352
firstNREList.Add(currFirstNRE);
@@ -213,49 +374,6 @@ public static List<int> PrintFirstNRE(StreamReader sr)
213374
return firstNREList;
214375
}
215376

216-
private static int FindCurrentFirstNRE(OrderedLetter[] letterTracker)
217-
{
218-
var allCurrentNREQuery = letterTracker
219-
.Where(ol => ol.FirstSeenOrder >= 0)
220-
.Where(ol => ol.DoesRepeat == false);
221-
222-
// I think Count only does a single traversal to check and count the elements, afaik
223-
if (allCurrentNREQuery.Count() == 0)
224-
{
225-
return NO_NRE;
226-
}
227-
228-
229-
// I think that this uses lazy evaluation in that OrderBy remains only as a
230-
// stored instruction until a LINQ "execute" command is added
231-
// it only needs to walk the array once and find the element
232-
// that meets the other criteria with the smallest FirstSeenOrder
233-
// Doesn't need to copy the array or do a full sort, etc.
234-
var newFirstNRE = allCurrentNREQuery
235-
.OrderBy(ol => ol.FirstSeenOrder)
236-
.First();
237-
// That is, First does the least amount of work necessary to figure
238-
// out what is the first element of the sequence
239-
240-
241-
// Reverse lookup to figure out what letter the found newFirstNRE
242-
// corresponds to.
243-
// An alternative to this approach is for each OrderedLetter to also
244-
// store what letter it reprents, which seems silly and can fall out
245-
// of sync. Or we could use use a dictionary instead of an array
246-
// to store the OrderedLetter objects (which is overkill)
247-
// Then we could iterate on the kvps and have access to the keys that way.
248-
for (var i = 0; i < LETTER_COUNT; ++i)
249-
{
250-
if (ReferenceEquals(letterTracker[i], newFirstNRE))
251-
return 'a' + i;
252-
}
253-
254-
throw new ArgumentException(
255-
"An element in letterTracker met the query criteria," +
256-
"but that element isn't in letterTracker? Wat.");
257-
}
258-
259377

260378
private class LetterTracker
261379
{

0 commit comments

Comments
 (0)