Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Text.RegularExpressions;
- namespace Sort
- {
- public class Sort
- {
- public static List<String> FileNames = new List<string>(); // list of all filenames to iterate through
- public static string OutputFileName = "output.txt"; // default name just in case (although it would never be used)
- public static List<String> ReadFile(List<String> names) // function to read the input file and check if everything is ok with it
- {
- List<String> lines = new List<String>(); // list where all the lines are stored one after another
- foreach (var name in names)
- {
- try
- {
- foreach (string line in File.ReadLines(name))
- {
- lines.Add(line);
- }
- }
- catch (FileNotFoundException) // if file is not found
- {
- Console.WriteLine("I am so sorry to say, but I cannot find such file (" + name +
- "). I know this might be very difficult," +
- " but please check if you have entered the name correctly. I believe in you.");
- lines.Clear(); // returning empty so that the program can exit
- return lines;
- }
- }
- return lines;
- }
- public static async Task Print(bool toFile, List<String> linesArray, string fileName) // function to print the result depending on the flags specified
- {
- if (toFile) // if the user wants the result to be written in a file
- {
- try
- {
- await File.WriteAllLinesAsync(fileName, linesArray); // trying to create the file with filename fileName and write all the lines there
- }
- catch (InvalidOperationException) // catching all the errors that might occur
- {
- Console.WriteLine("Error: the file already exists and is read-only.");
- }
- catch (PathTooLongException)
- {
- Console.WriteLine("Error: the path name may be too long.");
- }
- catch (IOException)
- {
- Console.WriteLine("Error: either the filename is invalid or the disk is full. I don't know, you tell me.");
- }
- }
- else // if the user wants the result to be printed out on the screen
- {
- foreach (var line in linesArray)
- {
- Console.WriteLine(line);
- }
- }
- }
- public static bool IgnoreCase,
- Reverse,
- Unique,
- NumericSort,
- VersionSort,
- FileOutput,
- SymbolSort,
- LengthSort; // all the flags that might be
- public static List<String> SortLines(List<String> lines) // the main sorting algorithm
- {
- if (SymbolSort) // -s flag
- {
- for(int i = 0; i < lines.Count; i++)
- {
- var line = lines[i];
- char[] characters = line.ToArray();
- Array.Sort(characters);
- lines[i] = new string(characters);
- }
- }
- if (LengthSort) // -l flag
- {
- List<Tuple<int, String>> linesWithSizes = new List<Tuple<int, string>>(); // array of tuples where first element is the size of a string and second is the string itself
- foreach (var line in lines)
- {
- linesWithSizes.Add(new Tuple<int, string>(line.Length, line)); // adding size and string
- }
- linesWithSizes.Sort();
- List<String> ans = new List<string>(); // the final list
- foreach (var line in linesWithSizes)
- {
- ans.Add(line.Item2); // adding sorted by size strings to the answer list
- }
- if (Reverse) ans.Reverse();
- if (Unique) ans = ans.Distinct().ToList();
- return ans;
- }
- if (VersionSort) // -V flag
- {
- List<Version> versions = new List<Version>();
- List<String> other = new List<string>(); // we split the initial list into two lists for it to be easier for us
- foreach (var line in lines) // adding to one of the lists depending whether it is a version or not
- {
- try
- {
- versions.Add(Version.Parse(line));
- }
- catch
- {
- other.Add(line);
- }
- }
- versions.Sort(); // sorting the array
- if (Reverse) versions.Reverse(); // the reverse flag
- List<String> mergedList = new List<string>(); // list to merge both parts
- foreach (var version in versions)
- {
- mergedList.Add(version.ToString()); // adding version to the merged list
- }
- mergedList.AddRange(other); // adding the list of other strings
- if (Unique) mergedList = mergedList.Distinct().ToList(); // clearing the -u flag (can't clear it before they are merged)
- return mergedList;
- }
- if (NumericSort) // -n flag. Almost the same as the versionSort
- {
- List<String> nums = new List<string>();
- List<String> other = new List<string>();
- foreach (var line in lines)
- {
- if (new Regex("^[0-9]*$").IsMatch(line)) nums.Add(line);
- else other.Add(line);
- }
- if (Reverse) nums.Reverse();
- nums.AddRange(other);
- if (Unique) nums = nums.Distinct().ToList();
- return nums;
- }
- if (IgnoreCase) // -f flag
- {
- List<Tuple<String, Tuple<int, String>>> indexList = new List<Tuple<string, Tuple<int, String>>>(); // (lowercase string, (its initial position to keep track where same elements were located, initial version to later capitalize))
- int cnt = 0;
- foreach (var line in lines)
- {
- indexList.Add(new Tuple<string, Tuple<int, String>>(line.ToLower(), new Tuple<int, string>(cnt++, line)));
- }
- indexList.Sort(); // sorts. Elements that became same after .ToLower() are sorted depending on their initial position
- List<String> ans = new List<string>();
- foreach (var ansLine in indexList)
- {
- ans.Add(ansLine.Item2.Item2); // inserting initial elements into answer
- }
- if (Reverse) ans.Reverse();
- if (Unique) ans = ans.Distinct().ToList();
- return ans;
- }
- lines.Sort();
- if (Reverse) lines.Reverse();
- if (Unique) lines = lines.Distinct().ToList();
- return lines;
- }
- public static void CheckFlags(string[] args)
- {
- for (int i = 0; i < args.Length; i++) // checking all the flags
- {
- var flag = args[i];
- if (flag == "-f" || flag == "--ignore-case")
- {
- if(!(args.Contains("-V") || args.Contains("--version-sort") || args.Contains("-n") ||
- args.Contains("--numeric-sort") || args.Contains("-l") ||
- args.Contains("--length-sort"))) IgnoreCase = true; // flag can only be added if there are no conflicts
- }
- else if (flag == "-r" || flag == "--reverse") Reverse = true;
- else if (flag == "-u" || flag == "--unique") Unique = true;
- else if (flag == "-s" || flag == "--symbol-sort") SymbolSort = true;
- else if (flag == "-l" || flag == "--length-sort")
- {
- if(!(args.Contains("-V") || args.Contains("--version-sort") || args.Contains("-n")
- || args.Contains("--numeric-sort"))) LengthSort = true; // flag can only be added if there are no conflicts
- }
- else if (flag == "-n" || flag == "--numeric-sort")
- {
- NumericSort = true;
- if (args.Contains("-f") || args.Contains("--ignore-case")) // conflicting flags
- {
- Console.WriteLine("I hope that you understand that asking me to sort the file both ignoring " +
- "the case and processing only numbers basically removes the effect of the ignore case " +
- "flag. You did it just to test me, right? I will sort that anyways though...");
- IgnoreCase = false;
- }
- if (args.Contains("-l") || args.Contains("--length-sort")) // conflicting flags
- {
- Console.WriteLine(
- "Conflict between length and numeric sort detected. I will ignore the length sort. Sad :(");
- LengthSort = false;
- }
- }
- else if (flag == "-o" || Regex.Match(flag, @"--output=.*").Success)
- {
- FileOutput = true;
- if (flag == "-o")
- {
- try // trying to get the output file name
- {
- OutputFileName = args[i + 1];
- i++;
- if (i == args.Length - 1)
- {
- Console.WriteLine("Hmmm... Seems like you didn't specify the output file name.");
- return;
- }
- }
- catch (IndexOutOfRangeException)
- {
- Console.WriteLine("Hmmm... Seems like you didn't specify the output file name.");
- return;
- }
- }
- else // if it is --output=...
- {
- OutputFileName = flag.Substring(9);
- if (OutputFileName == "")
- {
- Console.WriteLine("Hmmm... Seems like you didn't specify the file name.");
- return;
- }
- }
- }
- else if (flag == "-V" || flag == "--version-sort")
- {
- VersionSort = true;
- if (args.Contains("-f") || args.Contains("--ignore-case")) // conflicting flags
- {
- Console.WriteLine("I hope that you understand that asking me to sort the file both ignoring " +
- "the case and processing only versions basically removes the effect of the ignore case " +
- "flag. You did it just to test me, right? I will sort that anyways though...");
- IgnoreCase = false;
- }
- if (args.Contains("-n") || args.Contains("--numeric-sort")) // conflicting flags
- {
- Console.WriteLine(
- "Conflict between version and numeric sort flags detected. As it is stated in the Documentation, " +
- "I will ignore the numeric sort flag and proceed with version sort only.");
- NumericSort = false;
- }
- if (args.Contains("-s") || args.Contains("--symbol-sort")) // conflicting flags
- {
- Console.WriteLine(
- "The symbol sort will leave no chance for versions. I will cancel the version sort flag for you...");
- VersionSort = false;
- }
- if (args.Contains("-l") || args.Contains("--length-sort")) // conflicting flags
- {
- Console.WriteLine(
- "Conflict between length and version sort detected. I will ignore the length sort.");
- LengthSort = false;
- }
- }
- else
- {
- FileNames.Add(flag);
- }
- }
- }
- public static void Main(string[] args)
- {
- CheckFlags(args);
- var linesArray = ReadFile(FileNames); // reading the files
- if (linesArray.Count == 0)
- {
- Console.WriteLine("Unfortunately, I have nothing to read...");
- return;
- }
- linesArray = SortLines(linesArray);
- Print(FileOutput, linesArray, OutputFileName);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement