Je suis en train de résoudre une question récente interview à l'aide Scala ..trouver les frappes clavier à l'écran pour scala
Vous avez un clavier à l'écran qui est une grille de 6 lignes, 5 colonnes chacune. Avec les alphabets de A à Z et l'espace vide sont d'abord disposés dans la rangée de la grille.
Vous pouvez utiliser ce clavier à l'écran pour taper des mots .. en utilisant votre télécommande TV en appuyant sur les touches Gauche, Droite, Haut, Bas ou OK pour taper chaque caractère. Question: à l'aide d'une chaîne d'entrée, trouvez la séquence de touches à appuyer sur la télécommande pour saisir l'entrée.
La mise en œuvre du code peut être trouvé à
https://github.com/mradityagoyal/scala/blob/master/OnScrKb/src/main/scala/OnScrKB.scala
J'ai essayé de résoudre cela en utilisant trois approches différentes ..
simple forldLeft.
def keystrokesByFL(input: String, startChar: Char = 'A'): String = { val zero = ("", startChar) //(acc, last) + next => (acc+ aToB , next) def op(zero: (String, Char), next: Char): (String, Char) = zero match { case (acc, last) => (acc + path(last, next), next) } val result = input.foldLeft(zero)(op) result._1
}
diviser pour mieux régner - Utilise diviser pour régner mécanisme. L'algorithme est similaire au tri par fusion. * Nous divisons le mot d'entrée en deux si la longueur est> 3 * nous appelons récursivement le sous-programme pour obtenir le chemin des moitiés gauche et droite de la scission. * A la fin .. nous ajoutons les frappes pour les premières touches + de la fin de la première chaîne au début de la deuxième chaîne + les séquences de touches pour la seconde. * Essentiellement, nous divisons la chaîne d'entrée en deux moitiés plus petites jusqu'à ce que nous arrivions à la taille 4. Pour plus petit que 4, nous utilisons le pli droit.
def keystrokesByDnQ(input: String, startChar: Char = 'A'): String = { def splitAndMerge(in: String, startChar: Char): String = { if (in.length() < 4) { //if length is <4 then dont split.. as you might end up with one side having only 1 char. keystrokesByFL(in, startChar) } else { //split val (x, y) = in.splitAt(in.length()/2) splitAndMerge(x, startChar) + splitAndMerge(y, x.last) } } splitAndMerge(input, startChar)
}
Fold - utilise la propriété que l'opération sous-jacente est associative (mais non commutative). * Par exemple, les séquences de touches ("ABCDEFGHI", startChar = 'A') == combinaisons de touches ("ABC", startChar = 'A') + combinaisons de touches ("DEF", "C") + combinaisons de touches ("GHI", 'F')
def keystrokesByF(input: String, startChar: Char = 'A'): String = { val mapped = input.map { x => PathAcc(text = "" + x, path = "") } // map each character in input to case class PathAcc("CharAsString", "") val z = PathAcc(text = ""+startChar, path = "") //the starting char. def op(left: PathAcc, right: PathAcc): PathAcc = { PathAcc(text = left.text + right.text, path = left.path + path(left.text.last, right.text.head) + right.path) } val foldresult = mapped.fold(z)(op) foldresult.path }
Mes questions: 1. la diviser pour mieux régner approche mieux que Fold?
sont Fold et diviser pour mieux régner mieux que foldLeft (pour ce problème spécifique)
Est-il possible que je peux représenter la diviser pour mieux régner l'approche ou l'approche Fold en tant que Monade? Je peux voir que la loi associative est satisfaite ... mais je ne suis pas capable de comprendre si un monoï est présent ici .. et si oui .. qu'est-ce que cela fait pour moi?
Divide et conquer approche-t-il le meilleur disponible pour ce problème particulier?
Quelle approche est la mieux adaptée pour les étincelles?
Toutes les suggestions sont les bienvenues ..