首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >T9翻译器在node.js中的应用

T9翻译器在node.js中的应用
EN

Code Review用户
提问于 2017-05-16 02:41:54
回答 1查看 500关注 0票数 1

我读了一些编程脑筋笑话,看到了一个T9翻译器对代码疯狂的戏弄,并想在node.js中实现它。

从电话号码数字中打印所有可能的单词。这个问题是由微软、谷歌、facebook、亚马逊等公司提出的。让我们看看输入/输出示例来理解这个问题。例如,如果输入编号为234,可以形成的单词为(字母顺序):adg cdh aeg aeh aei afg afi afi bdg bdh bdi求beh be bfg bfh bfi cdg cdh cdi cdi cfg cfg cfh cfi cfi bfi

我担心太多的迭代和可读性。我最初只在递归函数中进行增量,但随后需要对结果数组执行一个.reverse(),我认为这样做更好,只需在转换本身中通过递减来处理。我也想知道我是否在以正确的方式进行我的测试。

t9.js

代码语言:javascript
复制
/*jslint node:true, es5:true*/

/*
 * Based on problem presented by:
 * http://www.crazyforcode.com/print-words-phone-digits/
 */

"use strict";

/**
 * T9 module
 * @module t9
 */

var t9 = [
    [" "], // 0
    [""], // 1
    ["a", "b", "c"], // 2
    ["d", "e", "f"], // 3
    ["g", "h", "i"], // 4
    ["j", "k", "l"], // 5
    ["m", "n", "o"], // 6
    ["p", "q", "r", "s"], // 7
    ["t", "u", "v"], // 8
    ["w", "x", "y", "z"] // 9
];

function rec(bundles, bundleIdx, letterIdx, str, arr) {
    // Add the new letter
    var concatedStr = str + bundles[bundleIdx][letterIdx];

    // Decrement letter
    if (letterIdx > 0) {
        rec(bundles, bundleIdx, letterIdx - 1, str, arr);
    }

    // Increment bundle
    if (bundleIdx < bundles.length - 1) {
        rec(bundles, bundleIdx + 1, bundles[bundleIdx + 1].length - 1, concatedStr, arr);
    }

    // Not a complete word
    if (concatedStr.length < bundles.length) {
        return;
    }

    // Push word
    arr.push(concatedStr);
}

/**
 * Find all the words that could be made with given number using T9 translation
 * @function translate
 * @param {String} numbers The number to translate with t9
 * @returns {String[]} Possible words that could be made
 * @throws Will throw if a non-number string is provided
 */
function translate(numbers) {
    var possibleWords,
        charArrs;

    if (!/^[0-9]+$/.test(numbers)) {
        throw new Error("Must provide a number string");
    }

    possibleWords = [];
    charArrs = numbers
        .split("")
        .map(function (digit) {
            return t9[parseInt(digit, 10)];
        });

    // Start recursive func
    rec(charArrs, 0, charArrs[0].length - 1, "", possibleWords);

    return possibleWords;
}

module.exports = {
    translate: translate
};

t9.test.js

代码语言:javascript
复制
/*jslint node:true, es5:true*/

"use strict";

var assert = require("assert"),
    t9 = require("../src/t9");

// Throw errors properly
assert.throws(function () {
    t9.translate("hello");
}, Error, "Expected an error");

// Translate 3 letter numbers correctly
var expected234 = ["adg", "adh", "adi", "aeg", "aeh", "aei", "afg", "afh", "afi", "bdg", "bdh", "bdi", "beg", "beh", "bei", "bfg", "bfh", "bfi", "cdg", "cdh", "cdi", "ceg", "ceh", "cei", "cfg", "cfh", "cfi"],
    actual234 = t9.translate("234");
assert.deepEqual(expected234, actual234, "Expected 3 numbers to translate");

// Translates 3 and 4 letter numbers correctly
var expected78 = ["pt", "pu", "pv", "qt", "qu", "qv", "rt", "ru", "rv", "st", "su", "sv"],
    actual78 = t9.translate("78");
assert.deepEqual(expected78, actual78, "Expected 3 and 4 numbers to translate");

// Translates with a space
var expected506 = ["j m", "j n", "j o", "k m", "k n", "k o", "l m", "l n", "l o"],
    actual506 = t9.translate("506");
assert.deepEqual(expected506, actual506, "Expected spaces to work");

// Translate complex message
var expected2067 = ["a mp", "a mq", "a mr", "a ms", "a np", "a nq", "a nr", "a ns", "a op", "a oq", "a or", "a os", "b mp", "b mq", "b mr", "b ms", "b np", "b nq", "b nr", "b ns", "b op", "b oq", "b or", "b os", "c mp", "c mq", "c mr", "c ms", "c np", "c nq", "c nr", "c ns", "c op", "c oq", "c or", "c os", ],
    actual2067 = t9.translate("2067");
assert.deepEqual(expected2067, actual2067, "Complex translate to work");

index.js

代码语言:javascript
复制
/*jslint node:true, es5:true*/

"use strict";

var t9 = require("./src/t9");

function handleInput(toTranslate) {
    console.log("Possible words:");
    t9.translate(toTranslate).forEach(function (possibleWord) {
        console.log(possibleWord);
    });
}

if (process.argv.length > 2) {
    handleInput(process.argv[2]);
} else {
    var rl = require("readline").createInterface({
        input: process.stdin,
        output: process.stdout
    });

    rl.question("What numbers? ", function (answer) {
        rl.close();
        handleInput(answer);
    });
}
EN

回答 1

Code Review用户

发布于 2017-05-16 04:55:18

这看起来不错,但我认为您不必要地引入了第二个函数,并且使用了比您需要的更多的参数,从而使基本递归变得有点复杂。

下面完成了同样的事情(注意,其中将近一半是与您的输入验证类似的输入验证,因此算法的实质是六行行):

代码语言:javascript
复制
function t9Words(digits, ret = []) {

  if (typeof digits === 'string') {
    digits = digits.split('').map(x => {
      if (!/\d/.test(x)) throw new Error('Input must be digits')
      return parseInt(x)
    })
  }

  if (!digits.length) return ret.sort()                           // recursion bottom case
  if (!ret.length) return t9Words(digits.slice(1), t9[digits[0]]) // top case

  const nextRet = t9[digits[0]].reduce((m, x) =>
    m.concat(ret.map(word => word.concat(x)))
  , [])

  return t9Words(digits.slice(1), nextRet)
}
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/163429

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档