From d56a4cbb64f7d5f0378c21b80ebcf2c31fe3bdde Mon Sep 17 00:00:00 2001
From: cc0322 <36272241+cc0322@users.noreply.github.com>
Date: Thu, 8 Feb 2018 23:54:23 -0500
Subject: [PATCH] Add files
---
App.config | 6 ++
AssemblyInfo.cs | 36 ++++++++
NewProjectCC.csproj | 52 +++++++++++
Program.cs | 208 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 302 insertions(+)
create mode 100644 App.config
create mode 100644 AssemblyInfo.cs
create mode 100644 NewProjectCC.csproj
create mode 100644 Program.cs
diff --git a/App.config b/App.config
new file mode 100644
index 0000000..d740e88
--- /dev/null
+++ b/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs
new file mode 100644
index 0000000..dc13a39
--- /dev/null
+++ b/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("NewProjectCC")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("NewProjectCC")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("11e7112d-322a-43d8-ba9e-1616f0cd7fcf")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/NewProjectCC.csproj b/NewProjectCC.csproj
new file mode 100644
index 0000000..21c0939
--- /dev/null
+++ b/NewProjectCC.csproj
@@ -0,0 +1,52 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {11E7112D-322A-43D8-BA9E-1616F0CD7FCF}
+ Exe
+ NewProjectCC
+ NewProjectCC
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
new file mode 100644
index 0000000..2e07dd1
--- /dev/null
+++ b/Program.cs
@@ -0,0 +1,208 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace NewProjectCC
+{
+ /// Thinking of a large system, I'd like to save all the output from one key to the other to a hashtable. This will save the time complexity since we don't need to
+ /// process any logic from key to key but only get value from hashtable.
+ /// If the size of the input file is big, and we have enough resource, I believe we can do a divide and conquer to read different lines from the input file and process it at the same time.
+ /// I didn't implement devide and conquer today. But do please let me know if you'd like me to implement it that way. Thank you so much!
+ class Program
+ {
+ //Keyboard characters except space
+ const string KeyBoard = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+ //Hashtable which stores the preprocessed output from key to another key on the keyboard
+ public static Hashtable keyToKeyMatrix;
+
+ static void Main(string[] args)
+ {
+ //Generate the hashtable from pre-process to get the output key from one key to another on the keyboard
+ PreProcess();
+ //Get input search term by line
+ var input = ParseArgument();
+ //For each line of the search term, process the result, and write it down to the console.
+ if (input != null)
+ {
+ Console.WriteLine("The output is: ");
+ Console.WriteLine("---");
+ foreach (var r in GetResult(input))
+ {
+ //If it's the message for invalid input, don't add comma between each character.
+ if (r.Contains("Invalid input detected in this term"))
+ Console.WriteLine(r);
+ else
+ Console.WriteLine(string.Join(",", r.ToCharArray()));
+ }
+ }
+ //To keep console open until press a key
+ Console.WriteLine("---");
+ Console.WriteLine("Press any key to close this window...");
+ Console.Read();
+ }
+
+ ///
+ /// Get result by matching the characters read from the input file and write the path to the console
+ ///
+ /// A string list, each line contains a sarch term (one line from input file)
+ /// string array for the path output
+ private static string[] GetResult(List input)
+ {
+ var result = new string[input.Count];
+ int resultIndex = 0;
+ //Read by term
+ foreach (var line in input)
+ {
+ var output = string.Empty;
+ //If the line is empty, there's no output.
+ if (!string.IsNullOrEmpty(line))
+ {
+ //Define start point A
+ var preChar = 'A';
+ for (int i = 0; i < line.Length; i++)
+ {
+ //If the input character is not valid (not in the keyboard)
+ if (!(line[i].Equals(' ') || KeyBoard.Contains(line[i])))
+ {
+ output = (string.Format("Invalid input detected in this term: {0}", line[i]));
+ break;
+ }
+
+ //Get the correct output path from current character and previous character
+ if (line[i].Equals(' '))
+ output += "S";
+ else if (line[i].Equals(preChar))
+ output += "#";
+ else
+ {
+ var index = string.Format("{0}{1}", preChar, line[i]);
+ output += keyToKeyMatrix[index].ToString();
+ preChar = line[i];
+ }
+ }
+ }
+ //Add the output per line to the result string array.
+ result[resultIndex++] = output;
+ }
+
+ return result;
+ }
+
+ ///
+ /// Parse argument, read file name from console, and read the file
+ ///
+ /// String list by reading file by line.
+ private static List ParseArgument()
+ {
+ var inputPerLine = new List();
+ var line = string.Empty;
+
+ //Read file name
+ Console.WriteLine("Please specify your input file below: ");
+ try
+ {
+ var inputFileName = Console.ReadLine();
+ if (inputFileName != null)
+ {
+ //Read file using streamreader
+ StreamReader file = new StreamReader(inputFileName);
+ //Read line
+ while ((line = file.ReadLine()) != null)
+ {
+ inputPerLine.Add(line);
+ }
+ }
+ }
+ catch (Exception)
+ {
+ //Catch exception while reading file, write it to console
+ Console.WriteLine("Error occurred during reading the file, please try again.");
+ return null;
+ }
+
+ //If the input file is empty, return a console message.
+ if (inputPerLine.Count == 0)
+ {
+ Console.WriteLine("Empty input file detected.");
+ return null;
+ }
+
+ return inputPerLine;
+ }
+
+ ///
+ /// This preprocess will generate a hashtable and write this hashtable to a file, so this doesn't need to be run unless the file is missing.
+ /// For each element in this hashtable, the key is currentKey to NextKey when these two keys are different. For example, "AB" means from A to B on the given keyboard;
+ /// the value is the path through the onscreen keyboard (output). For example, the value for "AB" is "R#"
+ ///
+ /// Hashtable with path from one key to the other
+ private static Hashtable PreProcess()
+ {
+ keyToKeyMatrix = new Hashtable();
+
+ //Convert the keyboard string to ASCII chars
+ var charsASCII = Encoding.ASCII.GetBytes(KeyBoard.ToCharArray());
+
+ //Process the ASCII char array, so that A is 0, and every other cahracter is the distance to A, including 1-0 which shows on the onscreen keyboard too.
+ for (int n = 0; n < charsASCII.Length; n++)
+ {
+ //This handles number 0
+ if (n == charsASCII.Length - 1)
+ charsASCII[n] -= 13; //ASCII for 0 = 48, in the keyboard string, 0's index is 35. So 48-35=13
+ //This handles number 1-9
+ else if (n >= charsASCII.Length - 10)
+ charsASCII[n] -= 23; //ASCII for 1 = 49, in the keyboard string, 1's index is 26. So 49-26=23
+ else
+ charsASCII[n] -= 65; //ASCII for A = 65
+ }
+
+ //These loops calcultes the real path from one key to another from the oncreen keyboard, and add the key and the value to the hashtable
+ for (int i = 0; i < charsASCII.Length; i++)
+ {
+ //Since the paths are always opposite between one key to another, only loop the the ones after charsASCII[i] is enough
+ for (int j = i + 1; j < charsASCII.Length; j++)
+ {
+ var outputPattern = string.Empty;
+ var outputPatternReverse = string.Empty;
+
+ //Think the onscreen keyboard as a matrix with x and y coordinate, the position for the two keys are presents as in positioni and positionj
+ var positioni = new KeyValuePair(charsASCII[i] % 6, charsASCII[i] / 6);
+ var positionj = new KeyValuePair(charsASCII[j] % 6, charsASCII[j] / 6);
+
+ //Get the horizonal distance
+ var horizonalDistance = positionj.Key - positioni.Key;
+ //If the distance is greater than 0, then from key i to key j, we need to move right, and from key j to key i , we need to move left. Vise Versa.
+ for (int a = 0; a < Math.Abs(horizonalDistance); a++)
+ {
+ outputPattern += "L";
+ outputPatternReverse += "R";
+ }
+ if (horizonalDistance > 0)
+ {
+ var temp = outputPattern;
+ outputPattern = outputPatternReverse;
+ outputPatternReverse = temp;
+ }
+
+ //Since key j is always after key i , the vertical distance is always greater or equal than 0
+ for (int b = 0; b < (positionj.Value - positioni.Value); b++)
+ {
+ outputPattern += "D";
+ outputPatternReverse += "U";
+ }
+
+ //Get char from the keyboard string
+ var chars = KeyBoard.ToCharArray();
+
+ //Add "" as key, the path with selected key # as value
+ keyToKeyMatrix.Add(string.Format("{0}{1}", chars[i], chars[j]), string.Format("{0}#", outputPattern));
+ keyToKeyMatrix.Add(string.Format("{0}{1}", chars[j], chars[i]), string.Format("{0}#", outputPatternReverse));
+ }
+ }
+ return keyToKeyMatrix;
+ }
+ }
+}