diff --git a/L3/K2/Duomenys.txt b/L3/K2/Duomenys.txt
new file mode 100644
index 0000000..670d33c
--- /dev/null
+++ b/L3/K2/Duomenys.txt
@@ -0,0 +1,5 @@
+Toshiba;123Bąčę;1200.01
+Foobar;AAA;1300.01
+Foobar;AAB;1300.01
+Foobar;BBB;1350.01
+Baz BAAAZ;The FOO - BAZ;1700.12345
\ No newline at end of file
diff --git a/L3/K2/K2.csproj b/L3/K2/K2.csproj
new file mode 100644
index 0000000..ab828a7
--- /dev/null
+++ b/L3/K2/K2.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+
+ Always
+
+
+
+
diff --git a/L3/K2/Program.cs b/L3/K2/Program.cs
new file mode 100644
index 0000000..4061616
--- /dev/null
+++ b/L3/K2/Program.cs
@@ -0,0 +1,372 @@
+using System;
+using System.IO;
+
+namespace K2
+{
+ public interface IBetween
+ {
+ ///
+ /// Indicates whether the value of the certain property of the current instance is in
+ /// [, ] range including range marginal values.
+ /// should always precede in default sort order.
+ ///
+ /// The starting value of the range
+ /// The ending value of the range
+ /// true if the value of the current object property is in range; otherwise,
+ /// false.
+ bool MutuallyInclusiveBetween(T from, T to);
+
+ ///
+ /// Indicates whether the value of the certain property of the current instance is in
+ /// [, ] range excluding range marginal values.
+ /// should always precede in default sort order.
+ ///
+ /// The starting value of the range
+ /// The ending value of the range
+ /// true if the value of the current object property is in range; otherwise,
+ /// false.
+ bool MutuallyExclusiveBetween(T from, T to);
+ }
+
+ ///
+ /// Provides generic container where the data are stored in the linked list.
+ ///
+ /// The type of the data to be stored in the list. Data
+ /// class should implement some interfaces.
+ public class LinkList
+ where T: IComparable
+ {
+ class Node
+ {
+ public T Data { get; set; }
+ public Node Next { get; set; }
+ public Node(T data, Node next)
+ {
+ Data = data;
+ Next = next;
+ }
+ }
+
+ ///
+ /// All the time should point to the first element of the list.
+ ///
+ private Node begin;
+
+ ///
+ /// All the time should point to the last element of the list.
+ ///
+ private Node end;
+
+ ///
+ /// Shouldn't be used in any other methods except Begin(), Next(), Exist() and Get().
+ ///
+ private Node current;
+
+ ///
+ /// Initializes a new instance of the LinkList class with empty list.
+ ///
+ public LinkList()
+ {
+ begin = current = end = null;
+ }
+
+ ///
+ /// One of four interface methods devoted to loop through a list and get value stored in it.
+ /// Method should be used to move internal pointer to the first element of the list.
+ ///
+ public void Begin()
+ {
+ current = begin;
+ }
+
+ ///
+ /// One of four interface methods devoted to loop through a list and get value stored in it.
+ /// Method should be used to move internal pointer to the next element of the list.
+ ///
+ public void Next()
+ {
+ current = current.Next;
+ }
+
+ ///
+ /// One of four interface methods devoted to loop through a list and get value stored in it.
+ /// Method should be used to check whether the internal pointer points to the element of the list.
+ ///
+ /// true, if the internal pointer points to some element of the list; otherwise,
+ /// false.
+ public bool Exist()
+ {
+ return current != null;
+ }
+
+ ///
+ /// One of four interface methods devoted to loop through a list and get value stored in it.
+ /// Method should be used to get the value stored in the node pointed by the internal pointer.
+ ///
+ /// the value of the element that is pointed by the internal pointer.
+ public T Get()
+ {
+ return current.Data;
+ }
+
+ ///
+ /// Method appends new node to the end of the list and saves in it
+ /// passed by the parameter.
+ ///
+ /// The data to be stored in the list.
+ public void Add(T data)
+ {
+ var node = new Node(data, null);
+ if (begin == null)
+ {
+ begin = node;
+ end = node;
+ } else
+ {
+ end.Next = node;
+ end = node;
+ }
+ }
+
+ ///
+ /// Method sorts data in the list. The data object class should implement IComparable
+ /// interface though defining sort order.
+ ///
+ public void Sort()
+ {
+ for (Node nodeA = begin; nodeA != null; nodeA = nodeA.Next)
+ {
+ if (nodeA.Next == null) continue;
+
+ for (Node nodeB = nodeA.Next; nodeB != null; nodeB = nodeB.Next)
+ {
+ if (nodeA.Data.CompareTo(nodeB.Data) < 0)
+ {
+ T tmp = nodeA.Data;
+ nodeA.Data = nodeB.Data;
+ nodeB.Data = tmp;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Provides properties and interface implementations for the storing and manipulating of cars data.
+ ///
+ public class Car : IComparable, IBetween, IBetween
+ {
+ public string Manufacturer { get; set; }
+ public string Model { get; set; }
+ public double Price { get; set; }
+
+ public Car(string manufacturer, string model, double price)
+ {
+ Manufacturer = manufacturer;
+ Model = model;
+ Price = price;
+ }
+
+ ///
+ /// Compares the current instance with another object of the same type and returns an integer
+ /// that indicates whether the current instance precedes, follows, or occurs in the same
+ /// position in the sort order as the other object.
+ ///
+ /// An object to compare with this instance.
+ /// A value that indicates the relative order of the objects being compared.The
+ /// return value has these meanings: -1 when this instance precedes other in the sort order;
+ /// 0 when this instance occurs in the same position in the sort order as other;
+ /// 1 when this instance follows other in the sort order.
+ public int CompareTo(Car other)
+ {
+ if (Price < other.Price)
+ {
+ return -1;
+ } else if (Price == other.Price)
+ {
+ return -Model.CompareTo(other.Model);
+ } else
+ {
+ return 1;
+ }
+ }
+
+ public bool MutuallyInclusiveBetween(double from, double to)
+ {
+ return from <= Price && Price <= to;
+ }
+
+ public bool MutuallyExclusiveBetween(double from, double to)
+ {
+ return from < Price && Price < to;
+ }
+
+ public bool MutuallyInclusiveBetween(string from, string to)
+ {
+ return Manufacturer.CompareTo(from) <= 0 && Manufacturer.CompareTo(to) >= 0;
+ }
+
+ public bool MutuallyExclusiveBetween(string from, string to)
+ {
+ return Manufacturer.CompareTo(from) < 0 && Manufacturer.CompareTo(to) > 0;
+ }
+ }
+
+ public static class InOut
+ {
+ ///
+ /// Creates the list containing data read from the text file.
+ ///
+ /// The name of the text file
+ /// List with data from file
+ public static LinkList ReadFromFile(string fileName)
+ {
+ var cars = new LinkList();
+ foreach (var line in File.ReadAllLines(fileName))
+ {
+ string[] parts = line.Split(';');
+ string manufacturer = parts[0].Trim();
+ string model = parts[1].Trim();
+ double price = double.Parse(parts[2].Trim());
+ cars.Add(new Car(manufacturer, model, price));
+ }
+ return cars;
+ }
+
+ ///
+ /// Appends the table, built from data contained in the list and preceded by the header,
+ /// to the end of the text file.
+ ///
+ /// The name of the text file
+ /// The header of the table
+ /// The list from which the table to be formed
+ public static void PrintToFile(string fileName, string header, LinkList list)
+ {
+ using (var writer = new StreamWriter(fileName, true))
+ {
+ writer.WriteLine(new string('-', 53));
+ writer.WriteLine("| {0, -49} |", header);
+ writer.WriteLine(new string('-', 53));
+
+ // Klausimas: Ar GRIEŽTAI negalima kurtis savo pagalbinių funkcijų?
+ // Nes šitoje situacijoje žemiau labai praverstų tiesiog susikurti `IsEmpty` metodą.
+ // Kartu prie to pačio, man labai nepatinka `Begin`, `Exist` ir `Next`, tai koks `IEnumerable`
+ // manau yra žymiai geresnis sprendimas, kad kaip sukti ciklą per listą.
+ list.Begin();
+ if (list.Exist())
+ {
+ writer.WriteLine("| {0,-20} | {1,-15} | {2,8} |", "Gamintojas", "Modelis", "Kaina");
+ writer.WriteLine(new string('-', 53));
+ for (list.Begin(); list.Exist(); list.Next())
+ {
+ var car = list.Get();
+ writer.WriteLine("| {0,-20} | {1,-15} | {2,8:f2} |", car.Manufacturer, car.Model, car.Price);
+ }
+ } else
+ {
+ writer.WriteLine("| {0, -49} |", "Nėra");
+ }
+ writer.WriteLine(new string('-', 53));
+ writer.WriteLine();
+ }
+ }
+ }
+
+ public static class Task
+ {
+ ///
+ /// The method finds the biggest price value in the given list.
+ ///
+ /// The data list to be searched.
+ /// The biggest price value.
+ public static double MaxPrice(LinkList list)
+ {
+ double maxPrice = -1;
+ for (list.Begin(); list.Exist(); list.Next())
+ {
+ var car = list.Get();
+ maxPrice = Math.Max(maxPrice, car.Price);
+ }
+ return maxPrice;
+ }
+
+ ///
+ /// Filters data from the source list that meets filtering criteria and writes them
+ /// into the new list.
+ ///
+ /// The type of the data objects stored in the list
+ /// The type of criteria
+ /// The source list from which the result would be created
+ /// Lower bound of the interval
+ /// Upper bound of the interval
+ /// The list that contains filtered data
+ public static LinkList Filter(LinkList source, TCriteria from, TCriteria to)
+ where TData : IComparable, IBetween
+ {
+ var filtered = new LinkList();
+ for (source.Begin(); source.Exist(); source.Next())
+ {
+ var item = source.Get();
+ if (item.MutuallyInclusiveBetween(from, to))
+ {
+ filtered.Add(item);
+ }
+ }
+ return filtered;
+ }
+ }
+
+ class Program
+ {
+ // Klausimas: Ar reikia kurti testus `LinkList` klasei?
+ static void Main()
+ {
+ string inputFilename = "Duomenys.txt";
+ string outputFilename = "Rezultatai.txt";
+ File.Delete(outputFilename);
+
+ Console.Write("Įveskite pirmą gamintoją: ");
+ string manufacturer1 = Console.ReadLine();
+ Console.Write("Įveskite antrą gamintoją: ");
+ string manufacturer2 = Console.ReadLine();
+
+ var cars1 = InOut.ReadFromFile(inputFilename);
+ InOut.PrintToFile(outputFilename, "Pradinės mašinos", cars1);
+
+ var cars2 = Task.Filter(cars1, manufacturer1, manufacturer1);
+ var cars3 = Task.Filter(cars1, manufacturer2, manufacturer2);
+ InOut.PrintToFile(outputFilename, string.Format("Mašinos pagal gamintoją '{0}'", manufacturer1), cars2);
+ InOut.PrintToFile(outputFilename, string.Format("Mašinos pagal gamintoją '{0}'", manufacturer2), cars3);
+
+ var maxPrice = Task.MaxPrice(cars1);
+ var cars4 = Task.Filter(cars2, maxPrice * 0.75, maxPrice);
+ var cars5 = Task.Filter(cars3, maxPrice * 0.75, maxPrice);
+ cars4.Sort();
+ cars5.Sort();
+ InOut.PrintToFile(outputFilename, string.Format("Brangios mašinos pagal gamintoją '{0}'", manufacturer1), cars4);
+ InOut.PrintToFile(outputFilename, string.Format("Brangios mašinos pagal gamintoją '{0}'", manufacturer2), cars5);
+
+ // Klausimas: Ar galima įdėti išdemą į failą maine?
+ // Taip, žinau per LD darbus negalima tai daryti. Bet K2 apraše
+ // parašyta, kad negalima pridėti naujų metodų ar keisti egzistuojančių
+ // kamienus.
+ // Bet reikalaujama išvesti surastą didžiausią kainą į failo galą
+ // su paaiškinamu tekstu.
+ // Paradoksas ¯\_(ツ)_/¯
+ using (var writer = new StreamWriter(outputFilename, true))
+ {
+ writer.WriteLine("Didžiausia mašinos kaina: {0:f2}", maxPrice);
+ }
+
+ // Klausimas: KAS SUGALVOJO ŠITĄ UŽDUOTĮ?!?!?!
+ // Niekada nebuvau matęs, kad kas būtų naudojąs interface užklojimiui vieno
+ // lauko palyginimiui pagal tipą. IR DAR tą inteface reikia panaudoti 2 kartus ant `Car`
+ // klasės, kad būtų galima patikrinti skirtingus laukus?!
+ // Čia atrodo, kad kažkas bandė išsisukinėti, kad nereikėtų kurti 2 `Task.Filter`
+ // ir galų gale gavosi, kad reikia aplamai turėti daugiau kodo kad pasiekti tą patį
+ // rezultatą. Ir dar ant viršaus, jeigu to nepakako `MutuallyExclusiveBetween` metodai
+ // lieka nepanaudoti.
+ // Ką galiu pasakyti tai, kad man labai nepatiko šita užduotis.
+ }
+ }
+}
diff --git a/L3/L3.sln b/L3/L3.sln
index 48a6674..8ac655c 100644
--- a/L3/L3.sln
+++ b/L3/L3.sln
@@ -5,7 +5,9 @@ VisualStudioVersion = 17.1.32210.238
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LD_24", "LD_24\LD_24.csproj", "{AE159626-A105-440C-B997-F377C5F8F280}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LD_24Tests", "LD_24Tests\LD_24Tests.csproj", "{39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LD_24Tests", "LD_24Tests\LD_24Tests.csproj", "{39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "K2", "K2\K2.csproj", "{2C869FE9-7C18-4EA6-BE85-B4B10A557F25}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +23,10 @@ Global
{39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2C869FE9-7C18-4EA6-BE85-B4B10A557F25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2C869FE9-7C18-4EA6-BE85-B4B10A557F25}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2C869FE9-7C18-4EA6-BE85-B4B10A557F25}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2C869FE9-7C18-4EA6-BE85-B4B10A557F25}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE