· 5 months ago · May 08, 2025, 09:40 AM
1//----------------------------------------------------------
2// P175B123. CW2 example task
3//----------------------------------------------------------
4
5using System;
6using System.IO;
7using System.Net.Http.Headers;
8using System.Runtime.InteropServices;
9
10/*
11 * VIDKO:
12 * Module code:
13*/
14
15namespace DummyElements
16{
17
18 /// <summary>
19 /// Enumerator: male, female
20 /// </summary>
21 enum Gender
22 {
23 Male = 1,
24 Female = 2,
25 }
26
27 /// <summary>
28 /// Class to store data about single author
29 /// </summary>
30 class Author
31 {
32 // Auto-properties
33 public string authorName { get; set; }
34 public string bookName { get; set; }
35 public Gender Gender { get; set; }
36 public string publishingHouse { get; set; }
37 public double Price { get; set; }
38
39 /// <summary>
40 /// Default constructor
41 /// </summary>
42 public Author()
43 {
44
45 }
46
47 /// <summary>
48 /// Constructor with parameters
49 /// </summary>
50 public Author(string author, string book,
51 Gender gender, string house, double Price)
52 {
53 authorName = author;
54 bookName = book;
55 Gender = gender;
56 publishingHouse = house;
57 this.Price = Price;
58 }
59
60 public override string ToString()
61 {
62 string line;
63 line = string.Format("{0, -20} {1, 8} {2, -8} {3, -10} {4, 6:f2}",
64 authorName, bookName, Gender, publishingHouse, Price);
65 return line;
66
67 }
68
69 // Overriden method Equals()
70 public override bool Equals(object myObject)
71 {
72 Author author = myObject as Author;
73 return author.authorName == authorName &&
74 author.bookName == bookName;
75 }
76
77 // Overriden method GetHashCode()
78 public override int GetHashCode()
79 {
80 return authorName.GetHashCode() ^
81 bookName.GetHashCode();
82 }
83
84 // Overloaded operator >=
85 public static bool operator >=(Author author1, Author author2)
86 {
87 int poz = String.Compare(author1.bookName, author2.bookName,
88 StringComparison.CurrentCulture);
89 if ((author1.Price > author2.Price) ||
90 (Math.Abs(author1.Price - author2.Price) <= 0.001 && poz < 0))
91 return true;
92 else return false;
93 }
94
95 // Overloaded operator <=
96 public static bool operator <=(Author author1, Author author2)
97 {
98 int poz = String.Compare(author1.bookName, author2.bookName,
99 StringComparison.CurrentCulture);
100 if ((author1.Price < author2.Price) ||
101 (Math.Abs(author1.Price - author2.Price) <= 0.001 && poz > 0))
102 return true;
103 else return false;
104 }
105 }
106
107 /// <summary>
108 /// Container class
109 /// Implemented as singly linked list of authors, without dummy elements
110 /// </summary>
111 sealed class LinkedListOfAuthors
112 {
113
114 // Declaration of pointers
115 private NodeAuthor head; // start address
116 private NodeAuthor tail; // end address
117 private NodeAuthor tailE; // end address (extra)
118 private NodeAuthor iP; // pointer for interface
119
120 // TODO (0.4): implement functionality for node class (stores data of Author and reference to next element)
121 // Define 2 consctructors (with and without parameters)
122 private sealed class NodeAuthor
123 {
124 public Author Author { get; set; }
125 public NodeAuthor Next { get; set; }
126 public NodeAuthor() { }
127 public NodeAuthor(Author Author, NodeAuthor Next)
128 {
129 this.Author = Author;
130 this.Next = Next;
131 }
132 }
133
134 // TODO (0.2): implement consturctor by the given header
135 public LinkedListOfAuthors()
136 {
137 Author temp = new Author();
138 temp.authorName = "MinName";
139 Author temp1 = new Author();
140 temp1.authorName = "MaxName";
141 tail = new NodeAuthor(temp1, null);
142 head = new NodeAuthor(temp, tail);
143 tailE = head;
144 iP = null;
145 }
146
147 // TODO (0.1): implement method by given header
148 // Returns true if linked list is empty; false otherwise
149 public bool IsEmpty()
150 {
151 // TODO: implement method
152 return tailE == head;
153 }
154
155 // TODO (0.1): implement method by given header
156 // Returns data (Author object) of first element in singly linked list
157 public Author First()
158 {
159 // TODO: implement method
160 if (head == tailE)
161 return null;
162 return head.Next.Author;
163 }
164
165 // TODO (0.2): implement method by given header
166 // Returns number of elements in singly linked list
167 public int Count()
168 {
169 // TODO: implement method
170 int cnt = 0;
171 for (NodeAuthor temp = head.Next; temp != tail; temp = temp.Next)
172 cnt++;
173 return cnt;
174 }
175
176 // TODO (0.3): implement method by given header
177 // Adds new element (author) to the FRONT of singly linked list
178 public void AddToFront(Author author)
179 {
180 if (head == tailE)
181 {
182 head.Next = new NodeAuthor(author, head.Next);
183 tailE = head.Next;
184 }
185 else
186 {
187 head.Next = new NodeAuthor(author, head.Next);
188 }
189 }
190
191 // TODO (0.3): implement method by given header
192 // Adds new element (author) to the END of singly linked list
193 public void AddToEnd(Author author)
194 {
195 if (head == tailE)
196 {
197 head.Next = new NodeAuthor(author, tail);
198 tailE = head.Next;
199 }
200 else
201 {
202 tailE.Next = new NodeAuthor(author, tail);
203 tailE = tailE.Next;
204 }
205 }
206
207 //-------------------------------------------------------
208 // Interface methods for navigation
209 //-------------------------------------------------------
210
211 // TODO (0.1): implement method by given header
212 // Start of the list is assigned to the interface pointer
213 public void Start()
214 {
215 if (head == tailE)
216 iP = null;
217 iP = head.Next;
218 }
219
220 // TODO (0.1): implement method by given header
221 // Moves interface pointer to next element
222 public void Next()
223 {
224 iP = iP.Next;
225 }
226
227 // TODO (0.1): implement method by given header
228 // Returns true if the interface pointer is not empty;false - otherwise
229 public bool Exists()
230 {
231 // TODO: implement method
232 return iP != null && iP != tail;
233 }
234
235 // TODO (0.1): implement method by given header
236 // Returns data of interface pointer in linked list
237 public Author GetData()
238 {
239 //TODO: implement method
240 if (iP == null)
241 return null;
242 return iP.Author;
243 }
244
245
246 // TODO (1): implement method by given header
247 // Sorts elements by book price (in descending order) and name of book in alphabetic order
248 // Adapts SelectionSort algorithm
249 public void SelectionSort()
250 {
251 if (head == tailE)
252 return;
253
254 for (NodeAuthor n1 = head.Next; n1.Next != tail; n1 = n1.Next)
255 {
256 NodeAuthor max = n1;
257 for (NodeAuthor n2 = n1.Next; n2 != tail; n2 = n2.Next)
258 {
259 if (n2.Author >= max.Author)
260 max = n2;
261 }
262
263 Author temp = max.Author;
264 max.Author = n1.Author;
265 n1.Author = temp;
266 }
267 }
268
269
270 // TODO (1): implement method by given header
271 // Sorts elements by book price (in descending order) and name of book in alphabetic order
272 // Adapts SelectionSort algorithm
273 public void BubbleSort()
274 {
275 if (head == tailE)
276 return;
277 bool swap = true;
278 while (swap)
279 {
280 swap = false;
281 for (NodeAuthor temp = head.Next; temp.Next != tail; temp = temp.Next)
282 {
283 if (temp.Author <= temp.Next.Author)
284 {
285 swap = true;
286 Author a = temp.Author;
287 temp.Author = temp.Next.Author;
288 temp.Next.Author = a;
289 }
290 }
291 }
292 }
293
294 // TODO (1.5): implement method by given header
295 // Returns the name of first most popular author and number of books published (bookCount)
296 public string MostPopular(out int bookCount)
297 {
298 // TODO: implement method
299 if (head == tailE)
300 {
301 bookCount = -1;
302 return "Not found";
303 }
304
305 int max_cnt = 0;
306 Author a = new Author();
307 for (NodeAuthor n1 = head.Next; n1 != tail; n1 = n1.Next)
308 {
309 int cnt = 0;
310 for (NodeAuthor n2 = head.Next; n2 != tail; n2 = n2.Next)
311 {
312 if (string.Compare(n1.Author.authorName, n2.Author.authorName) == 0)
313 cnt++;
314 }
315
316 if (cnt > max_cnt)
317 {
318 max_cnt = cnt;
319 a = n1.Author;
320 }
321 }
322
323 bookCount = max_cnt;
324 return a.authorName;
325 }
326
327 // TODO (1.5): implement method by the given header
328 // Inserts data of author (stored in object Insertion) before element of author a
329 public void InsertBefore(Author a, Author Insertion)
330 {
331 if (head == tailE)
332 return;
333
334 NodeAuthor temp = head.Next, prev = head;
335 while (temp != tail && temp.Author != a)
336 {
337 prev = temp;
338 temp = temp.Next;
339 }
340
341 if (temp == tail)
342 return;
343 else
344 {
345 prev.Next = new NodeAuthor(Insertion, temp);
346 }
347 }
348
349 // TODO (1.5): implement method by the given header
350 // Inserts data of author (stored in object Insertion) after element of author a
351 public void InsertAfter(Author a, Author Insertion)
352 {
353 if (head == tailE)
354 return;
355
356 NodeAuthor temp = head.Next;
357 while (temp != tail && temp.Author != a)
358 temp = temp.Next;
359
360 if (temp == null)
361 return;
362
363 if (temp == tailE)
364 {
365 tailE.Next = new NodeAuthor(Insertion, tail);
366 tailE = tailE.Next;
367 }
368 else
369 {
370 temp.Next = new NodeAuthor(Insertion, temp.Next);
371 }
372 }
373
374 public void InsertToSorted(Author a)
375 {
376 if (head == tailE)
377 {
378 head.Next = new NodeAuthor(a, tail);
379 tailE = head.Next;
380 return;
381 }
382
383 if (a >= head.Next.Author)
384 {
385 head.Next = new NodeAuthor(a, head.Next);
386 return;
387 }
388
389 NodeAuthor temp = head.Next;
390 while (temp.Next != tail && tail.Author <= a)
391 temp = temp.Next;
392
393 if (temp == tailE)
394 {
395 tailE.Next = new NodeAuthor(a, tail);
396 tailE = tailE.Next;
397 }
398 else
399 {
400 temp.Next = new NodeAuthor(a, temp.Next);
401 }
402 }
403
404 // TODO (1.5): implement method by the given header
405 // Removes data of author (stored in object Insertion)
406 public void Remove(Author a)
407 {
408 if (head == tailE)
409 return;
410
411 NodeAuthor temp = head.Next, prev = head;
412 while (temp != tail && temp.Author != a)
413 {
414 prev = temp;
415 temp = temp.Next;
416 }
417
418 if (temp == tail)
419 return;
420 else
421 {
422 if (temp == tailE)
423 {
424 prev.Next = temp.Next;
425 tailE = prev;
426 }
427 else
428 {
429 prev.Next = temp.Next;
430 }
431 }
432 }
433 }
434
435
436 class Program
437 {
438 const string CFd = "Authors.txt";
439
440 static void Main(string[] args)
441 {
442 // TODO (1): Add required commands
443 // All results are presented to CONSOLE
444 // Create container A
445 LinkedListOfAuthors A = new LinkedListOfAuthors();
446 Read(CFd, A);
447 Print("Initial container A:", A);
448
449 Author temp = new Author();
450 temp.authorName = "Inserted";
451
452 Author temp1 = new Author();
453 temp1.authorName = "Inserted1";
454
455 //********************************************
456 // INSERT BEFORE
457 //********************************************
458 //A.InsertBefore(A.Middle(), temp);
459 //A.InsertBefore(A.First(), temp);
460 //A.InsertBefore(A.First(), temp1);
461 //A.InsertBefore(A.Last(), temp);
462 //Print("Insert before operation testing:", A);
463
464 //********************************************
465 // INSERT AFTER
466 //********************************************
467 //A.InsertAfter(A.Middle(), temp);
468 //A.InsertAfter(A.First(), temp);
469 //A.InsertAfter(A.Last(), temp1);
470 //A.InsertAfter(A.Last(), temp1);
471 //Print("Insert after operation testing:", A);
472
473 //********************************************
474 // INSERT IN SORTED
475 //********************************************
476 //A.SelectionSort();
477 //A.BubbleSort();
478 //temp.Price = 0;
479 //temp.Price = 100;
480 //temp.Price = 5.55;
481 //A.InsertToSorted(temp);
482 //Print("Sorted container A:", A);
483
484 //********************************************
485 // INSERT ALL
486 //********************************************
487 //A.InsertAll(A.First(), temp);
488 //Print("Insert all operation testing:", A);
489
490 //********************************************
491 // REMOVE
492 //********************************************
493 //A.InsertBefore(A.Middle(), temp);
494 //A.InsertBefore(A.First(), temp);
495 //A.InsertBefore(A.Last(), temp);
496 //A.Remove(temp);
497 //A.Remove(temp);
498 //A.Remove(temp);
499 //A.InsertAfter(A.Middle(), temp);
500 //A.InsertAfter(A.First(), temp);
501 //A.InsertAfter(A.First(), temp1);
502 //A.InsertAfter(A.Last(), temp);
503 //Print("Remove operation testing:", A);
504
505 //********************************************
506 // REMOVE ALL
507 //********************************************
508 //A.InsertBefore(A.Middle(), temp);
509 //A.InsertBefore(A.First(), temp);
510 //A.InsertBefore(A.Last(), temp);
511 //A.RemoveAll(temp);
512 //A.InsertBefore(A.Middle(), temp);
513 //A.InsertBefore(A.First(), temp);
514 //A.InsertBefore(A.First(), temp1);
515 //A.InsertBefore(A.Last(), temp);
516 //Print("Remove all operation testing:", A);
517 }
518
519 // Reads initial data from file fv to container A by creating a direct singly linked list
520 // METHOD IS ALREADY IMPLEMENTED
521 static void Read(string fv, LinkedListOfAuthors A)
522 {
523 using (var file = new StreamReader(fv))
524 {
525 string mLine;
526 while ((mLine = file.ReadLine()) != null)
527 {
528 string[] parts = mLine.Split(';'); // line fragments (parts)
529 string authorName = parts[0].Trim();
530 string bookName = parts[1].Trim();
531 Gender gender;
532 Enum.TryParse(parts[2], out gender);
533 string pHouse = parts[3].Trim();
534 double Price = Convert.ToDouble(parts[4]);
535 Author author = new Author(authorName, bookName, gender, pHouse, Price);
536 A.AddToEnd(author);
537 }
538 }
539 }
540
541 // TODO (1): implement method by given header
542 // Prints elements of container A to console using table format;
543 // header – label (note) above the table
544 // Method is implemented in class Program
545 static void Print(string header, LinkedListOfAuthors A)
546 {
547 if (A.Count() == 0)
548 {
549 Console.WriteLine("The container is empty!");
550 return;
551 }
552
553 Console.WriteLine(header);
554 Console.WriteLine(new string('-', 50));
555 Console.WriteLine("{0, -20} {1, -8} {2, -8} {3, -10} {4, -8}", "Name and Surname", "Book", "Gender", "House", "Price");
556 Console.WriteLine(new string('-', 50));
557 for (A.Start(); A.Exists(); A.Next())
558 Console.WriteLine(A.GetData().ToString());
559 Console.WriteLine(new string('-', 50));
560 }
561
562
563 // TODO (1): implement method by given header
564 // Creates a new container B (reverse linked list, deep copy) of authors of specified publishing house p
565 // Uppercase and lowercase letters in filter p are treated as the same (case-insensitive search)
566 // Method is implemented in class Program
567 static void Create(LinkedListOfAuthors A, LinkedListOfAuthors B, string p)
568 {
569 for (A.Start(); A.Exists(); A.Next())
570 {
571 if (string.Compare(A.GetData().publishingHouse, p, StringComparison.OrdinalIgnoreCase) == 0)
572 B.AddToFront(A.GetData());
573 }
574 }
575
576
577 // TODO (1): implement method by given header
578 // Finds and returns last author (null if not found) for specified gender
579 // Method is implemented in class Program
580 static Author Find(LinkedListOfAuthors B, Gender gender)
581 {
582 Author temp = null;
583 for (B.Start(); B.Exists(); B.Next())
584 {
585 if (B.GetData().Gender == gender)
586 {
587 temp = B.GetData();
588 }
589 }
590 return temp;
591 }
592 }
593}
594