feat: Complete L3.K2
This commit is contained in:
parent
636d2b21e5
commit
d603b57809
5
L3/K2/Duomenys.txt
Normal file
5
L3/K2/Duomenys.txt
Normal file
@ -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
|
14
L3/K2/K2.csproj
Normal file
14
L3/K2/K2.csproj
Normal file
@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Duomenys.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
372
L3/K2/Program.cs
Normal file
372
L3/K2/Program.cs
Normal file
@ -0,0 +1,372 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace K2
|
||||
{
|
||||
public interface IBetween<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether the value of the certain property of the current instance is in
|
||||
/// [<paramref name="from"/>, <paramref name="to"/>] range including range marginal values.
|
||||
/// <paramref name="from"/> should always precede <paramref name="to"/> in default sort order.
|
||||
/// </summary>
|
||||
/// <param name="from">The starting value of the range</param>
|
||||
/// <param name="to">The ending value of the range</param>
|
||||
/// <returns>true if the value of the current object property is in range; otherwise,
|
||||
/// false.</returns>
|
||||
bool MutuallyInclusiveBetween(T from, T to);
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the value of the certain property of the current instance is in
|
||||
/// [<paramref name="from"/>, <paramref name="to"/>] range excluding range marginal values.
|
||||
/// <paramref name="from"/> should always precede <paramref name="to"/> in default sort order.
|
||||
/// </summary>
|
||||
/// <param name="from">The starting value of the range</param>
|
||||
/// <param name="to">The ending value of the range</param>
|
||||
/// <returns>true if the value of the current object property is in range; otherwise,
|
||||
/// false.</returns>
|
||||
bool MutuallyExclusiveBetween(T from, T to);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides generic container where the data are stored in the linked list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data to be stored in the list. Data
|
||||
/// class should implement some interfaces.</typeparam>
|
||||
public class LinkList<T>
|
||||
where T: IComparable<T>
|
||||
{
|
||||
class Node
|
||||
{
|
||||
public T Data { get; set; }
|
||||
public Node Next { get; set; }
|
||||
public Node(T data, Node next)
|
||||
{
|
||||
Data = data;
|
||||
Next = next;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All the time should point to the first element of the list.
|
||||
/// </summary>
|
||||
private Node begin;
|
||||
|
||||
/// <summary>
|
||||
/// All the time should point to the last element of the list.
|
||||
/// </summary>
|
||||
private Node end;
|
||||
|
||||
/// <summary>
|
||||
/// Shouldn't be used in any other methods except Begin(), Next(), Exist() and Get().
|
||||
/// </summary>
|
||||
private Node current;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the LinkList class with empty list.
|
||||
/// </summary>
|
||||
public LinkList()
|
||||
{
|
||||
begin = current = end = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public void Begin()
|
||||
{
|
||||
current = begin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public void Next()
|
||||
{
|
||||
current = current.Next;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <returns>true, if the internal pointer points to some element of the list; otherwise,
|
||||
/// false.</returns>
|
||||
public bool Exist()
|
||||
{
|
||||
return current != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <returns>the value of the element that is pointed by the internal pointer.</returns>
|
||||
public T Get()
|
||||
{
|
||||
return current.Data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method appends new node to the end of the list and saves in it <paramref name="data"/>
|
||||
/// passed by the parameter.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to be stored in the list.</param>
|
||||
public void Add(T data)
|
||||
{
|
||||
var node = new Node(data, null);
|
||||
if (begin == null)
|
||||
{
|
||||
begin = node;
|
||||
end = node;
|
||||
} else
|
||||
{
|
||||
end.Next = node;
|
||||
end = node;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method sorts data in the list. The data object class should implement IComparable
|
||||
/// interface though defining sort order.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides properties and interface implementations for the storing and manipulating of cars data.
|
||||
/// </summary>
|
||||
public class Car : IComparable<Car>, IBetween<double>, IBetween<string>
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="other">An object to compare with this instance.</param>
|
||||
/// <returns>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.</returns>
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates the list containing data read from the text file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the text file</param>
|
||||
/// <returns>List with data from file</returns>
|
||||
public static LinkList<Car> ReadFromFile(string fileName)
|
||||
{
|
||||
var cars = new LinkList<Car>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the table, built from data contained in the list and preceded by the header,
|
||||
/// to the end of the text file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the text file</param>
|
||||
/// <param name="header">The header of the table</param>
|
||||
/// <param name="list">The list from which the table to be formed</param>
|
||||
public static void PrintToFile(string fileName, string header, LinkList<Car> 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
|
||||
{
|
||||
/// <summary>
|
||||
/// The method finds the biggest price value in the given list.
|
||||
/// </summary>
|
||||
/// <param name="list">The data list to be searched.</param>
|
||||
/// <returns>The biggest price value.</returns>
|
||||
public static double MaxPrice(LinkList<Car> list)
|
||||
{
|
||||
double maxPrice = -1;
|
||||
for (list.Begin(); list.Exist(); list.Next())
|
||||
{
|
||||
var car = list.Get();
|
||||
maxPrice = Math.Max(maxPrice, car.Price);
|
||||
}
|
||||
return maxPrice;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filters data from the source list that meets filtering criteria and writes them
|
||||
/// into the new list.
|
||||
/// </summary>
|
||||
/// <typeparam name="TData">The type of the data objects stored in the list</typeparam>
|
||||
/// <typeparam name="TCriteria">The type of criteria</typeparam>
|
||||
/// <param name="source">The source list from which the result would be created</param>
|
||||
/// <param name="from">Lower bound of the interval</param>
|
||||
/// <param name="to">Upper bound of the interval</param>
|
||||
/// <returns>The list that contains filtered data</returns>
|
||||
public static LinkList<TData> Filter<TData, TCriteria>(LinkList<TData> source, TCriteria from, TCriteria to)
|
||||
where TData : IComparable<TData>, IBetween<TCriteria>
|
||||
{
|
||||
var filtered = new LinkList<TData>();
|
||||
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.
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user