using System; using System.Text; using System.Text.RegularExpressions; using System.Collections.Generic; using System.IO; using System.Linq; namespace Lab4.ChainedWords { static class TaskUtils { /// /// Return anything that matches a word in given text, depending on punctuation /// /// Target text /// Target punctuation /// Word matches private static MatchCollection MatchByWords(string text, string punctuation) { string pattern = string.Format(@"[^{0}\n]+", Regex.Escape(punctuation)); return Regex.Matches(text, pattern, RegexOptions.IgnoreCase); } /// /// Return anything that matches a positive integer in text /// /// Target text /// Integer matches private static MatchCollection MatchByIntegers(string text) { return Regex.Matches(text, @"\d+"); } /// /// Find all chains of words in given text. A chain is a sequence of words where every words /// last letter matches the next words first letter. And split the text into words using punctuation /// /// Target text /// Target punctuation /// A list of chains with line number where it was found public static List> FindChains(string text, string punctuation) { List> chains = new List>(); bool startedChain = false; int chainStart = 0; MatchCollection matches = MatchByWords(text, punctuation); for (int i = 1; i < matches.Count; i++) { Match prevMatch = matches[i-1]; Match match = matches[i]; bool matchesCriteria = prevMatch.Value.ToLowerInvariant().Last() == match.Value.ToLowerInvariant().First(); if (matchesCriteria && !startedChain) { startedChain = true; chainStart = prevMatch.Index; } else if (!matchesCriteria && startedChain) { startedChain = false; int line = text.Substring(0, chainStart).Count(c => c == '\n')+1; string chain = text.Substring(chainStart, match.Index-chainStart).TrimEnd('\n'); chains.Add(new Tuple(line, chain)); } } // Ensure that last chain gets added to list if (startedChain) { int line = text.Substring(0, chainStart).Count(c => c == '\n')+1; string chain = text.Substring(chainStart).TrimEnd('\n'); chains.Add(new Tuple(line, chain)); } return chains; } /// /// Find all positive integers in given text /// /// Target text /// List of positive integers public static List FindIntegers(string text) { List integers = new List(); MatchCollection matches = MatchByIntegers(text); foreach (Match match in matches) { integers.Add(int.Parse(match.Value)); } return integers; } /// /// Finds the longest chain in the given text, while using given punctuation to determine words. /// /// Target text /// Target punctuation /// public static Tuple FindLongestChain(string text, string punctuation) { List> chains = FindChains(text, punctuation); if (chains.Count == 0) { return null; } Tuple longestChain = chains[0]; foreach (var pair in chains) { if (pair.Item2.Length > longestChain.Item2.Length) { longestChain = pair; } } return longestChain; } /// /// Ouput to file: /// * longest chain and where it was found /// * sum of all positive integers /// /// Input file /// Output file /// Target punctuation public static void ProcessChains(string inputFile, string outputFile, string punctuation) { string text = File.ReadAllText(inputFile, Encoding.UTF8); Tuple longestChain = FindLongestChain(text, punctuation); List integers = FindIntegers(text); using (StreamWriter writer = new StreamWriter(outputFile)) { if (longestChain != null) { writer.WriteLine("Ilgiausia žodžių grandinė {0} eilutėje: {1}", longestChain.Item1, longestChain.Item2); } else { writer.WriteLine("Nėra žodžių grandinių."); } writer.WriteLine("Yra {0} žodžiai sudaryti iš skaitmenų. Jų suma: {1}", integers.Count, integers.Sum()); } } private static string AlignWordsByColumns(List> words, string punctuation) { StringBuilder aligned = new StringBuilder(); Dictionary columns = new Dictionary(); foreach (List row in words) { int column = 0; foreach (string word in row) { if (!columns.ContainsKey(column)) { columns.Add(column, 0); } columns[column] = Math.Max(columns[column], word.Length); column++; } } foreach (List row in words) { int column = 0; for (int i = 0; i < row.Count; i++) { string word = row[i]; aligned.Append(word); if (i < row.Count - 1) { aligned.Append(new string(' ', columns[column] - word.Length)); } column++; } aligned.Append("\n"); } return aligned.ToString(); } /// /// Align every word in a line by columns /// /// Input file /// Output file /// Target punctuation public static void ProcessAligned(string inputFile, string outputFile, string punctuation) { string pattern = string.Format(@"[^{0}]+[{0}]*", Regex.Escape(punctuation)); string text = File.ReadAllText(inputFile, Encoding.UTF8); List> words = new List>(); foreach (string line in InOut.ReadByLines(inputFile)) { List row = new List(); words.Add(row); foreach (Match match in Regex.Matches(line, pattern)) { row.Add(match.Value.TrimEnd('\n')); } } File.WriteAllText(outputFile, AlignWordsByColumns(words, punctuation)); } /// /// Align every line by columns and print words vertically /// /// Input file /// Output file /// Punctuation public static void ProccessVericallyAligned(string inputFile, string outputFile, string punctuation) { string pattern = string.Format(@"[^{0}]+[{0}]*", Regex.Escape(punctuation)); string text = File.ReadAllText(inputFile, Encoding.UTF8); List> words = new List>(); foreach (string line in InOut.ReadByLines(inputFile)) { int column = 0; int row = 0; foreach (Match match in Regex.Matches(line, pattern)) { if (words.Count <= row) { words.Add(new List()); } words[row].Add(match.Value.TrimEnd('\n')); row++; } column++; } File.WriteAllText(outputFile, AlignWordsByColumns(words, punctuation)); } } }