要求受访者手动将字符串解析为 int 的起源是什么?

发布于 2024-09-16 15:46:24 字数 1456 浏览 6 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

安静 2024-09-23 15:46:24

我也没有被问过这个问题。

乍一看,这似乎是一种“尽早淘汰明显无能的白痴,以免浪费宝贵的面试时间”类型的问题。

但如果你仔细观察一下,里面其实有一些非常有趣的东西。因此,如果是那个这个问题的人,这就是我要寻找的内容:

  • 这个问题显然很愚蠢,因为已经有 ECMAScript 标准库中的一个函数正是执行此操作。我希望受访者告诉我这个问题很愚蠢,因为否则他们要么是a)无意识的僵尸,愚蠢地遵循脑死亡命令而不是用他们的大脑,要么b)他们实际上不这样做知道该函数存在。
  • 这显然也是一个解析问题,有趣的是,看看受访者是否将其视为更多的字符串黑客问题或正式的解析问题以及这两种方法会产生多少开销。在这种特殊情况下,我相信字符串黑客是正确的方法,但它仍然会导致一个很好的后续问题:“现在使用递归下降解析器做同样的事情”。任何程序员都应该能够在几分钟内画出解决这个问题的递归下降解析器。
  • 最后但并非最不重要的一点是,这显然是字符串字符的折叠。现在,我不一定期望新手程序员能够立即自己发现这个折叠,但是如果我暗示那里有一个折叠,他们应该能够自己发现它,并以折叠的形式重写他们的解决方案。
  • 当然,您可以判断此类问题的所有一般品质:受访者是否停下来思考问题,或者他是否开始胡思乱想。他是从需求、文档、规范、示例、测试还是代码开始的。他是否要求澄清极端情况(例如空字符串会发生什么,仅包含减号而没有其他内容的字符串会发生什么,空白怎么样,字符串是否保证是格式良好的整数,是负零)一个格式良好的整数)。他是否习惯使用 ES5 的严格子集。他写出可读的代码吗?他是否编写了 jslint 友好的代码

这是一个使用折叠解决问题的示例(在 ECMAScript 中称为 reduce):

"use strict";

function toInteger(s) {
    return s.split('').reverse().reduce(function (n, c, i) {
        if (c === '-') return -n;
        return n + (c.charCodeAt(0) - 48) * Math.pow(10, i);
    }, 0);
}

这是一个简单的递归下降解析器即时构建价值:

"use strict";

function toInteger(s) {
    var input,
        output = 0,
        sign = 1,

        lookahead = function () {
            return input.charAt(0);
        },

        consume = function () {
            var res = input.slice(0, 1);
            input = input.slice(1, input.length);
            return res;
        },

        isDigit = function (c) {
            return /[0-9]/.test(c);
        },

        signParser = function () {
            if (lookahead() === '-') {
                sign *= -1;
                consume();
            }
        },

        digitParser = function () {
            if (!isDigit(lookahead())) return false;
            output *= 10;
            output += (consume().charCodeAt(0) - 48);
            return true;
        },

        numberParser = function () {
            signParser();
            while (digitParser());
        };

    input = s;
    numberParser();
    if (!input.length === 0) return false;
    output *= sign;

    return output;
}

与此类面试问题的情况一样,没有人会认真期望受访者将这些功能写在白板上。特别是递归下降解析器。但恕我直言,任何人都应该能够勾勒出这个函数的样子。特别是,递归下降解析器的优点之一是,它将上下文无关语法非常直接地转换为一组解析函数,并且受访者应该能够粗略地解释这种转换是如何工作的,以及什么什么样的解析函数对应什么样的语法结构。


,从这样一个简单的问题中你可以得到很多很多的东西!

I haven't been asked this question, either.

At first glance, it seems like one of those "weed the obviously incompetent idiots out as early as possible to avaid wasting valuable interview time" type of questions.

But if you look at it more closely, there's actually some quite interesting stuff in there. So, if I were the one asking that question, here's what I would be looking for:

  • That question is obviously stupid, because there already is a function in the ECMAScript standard library that does exactly that. And I would want the interviewee to tell me that the question is stupid, because otherwise they are either a) mindless zombies that stupidly follow braindead orders instead of engaging their brain, or b) they don't actually know that that function exists.
  • It's also obviously a parsing problem, and it is interesting to see whether the interviewee approaches it as more of a string hacking problem or a formal parsing problem and how much overhead either approach generates. In this particular case, I believe that string hacking is the right approach, but it still leads into a great followup question: "Now do the same thing with a recursive-descent parser". Any programmer should be able to sketch out the recursive-descent parser for this problem within a couple of minutes.
  • Last but not least, this is obviously a fold over the characters of the string. Now, I would not necessarily expect a novice programmer to spot this fold on their own right away, but if I hint that there is a fold in there, they should be able to spot it themselves, and rewrite their solution in form of a fold.
  • And of course, you can judge all the general qualities that this type of question allows you to: does the interviewee stop and think about the problem or does he start hacking away. Does he start with requirements, documentation, specification, examples, tests, or code. Does he ask for clarification of the corner cases (like what happens with the empty string, what happens with a string that only contains a minus sign and nothing else, what about whitespace, are strings guaranteed to be well-formed integers, is negative zero a well-formed integer). Does he habitually use the strict subset of ES5. Does he write readable code. Does he write jslint-friendly code

Here's an example of solving the problem with a fold (which in ECMAScript is called reduce):

"use strict";

function toInteger(s) {
    return s.split('').reverse().reduce(function (n, c, i) {
        if (c === '-') return -n;
        return n + (c.charCodeAt(0) - 48) * Math.pow(10, i);
    }, 0);
}

And this is a simple recursive-descent parser which builds up the value on the fly:

"use strict";

function toInteger(s) {
    var input,
        output = 0,
        sign = 1,

        lookahead = function () {
            return input.charAt(0);
        },

        consume = function () {
            var res = input.slice(0, 1);
            input = input.slice(1, input.length);
            return res;
        },

        isDigit = function (c) {
            return /[0-9]/.test(c);
        },

        signParser = function () {
            if (lookahead() === '-') {
                sign *= -1;
                consume();
            }
        },

        digitParser = function () {
            if (!isDigit(lookahead())) return false;
            output *= 10;
            output += (consume().charCodeAt(0) - 48);
            return true;
        },

        numberParser = function () {
            signParser();
            while (digitParser());
        };

    input = s;
    numberParser();
    if (!input.length === 0) return false;
    output *= sign;

    return output;
}

As is always the case with this kind of interview questions, nobody would seriously expect the interviewee to just write those functions down on the whiteboard. Especially the recursive-descent parser. But IMHO, anybody should be able to sketch out what the function would look like. In particular, one of the beauties of a recursive-descent parser is that it is a very direct transformation of a context-free grammar into a set of parsing functions, and an interviewee should be able to explain roughly how that transformation works, and what kind of parsing functions correspond to what kind of grammar constructs.


phew, that is a lot of stuff that you can get out of such a simple question!

云仙小弟 2024-09-23 15:46:24

他们想测试你的数学知识,因为许多“码猴”没有接受过适当的数学教育。

以数字 $d_1 d_2...d_n$ 表示的数字可以写成以下形式:$d_1 r^(n - 1) + ... + d_(n - 1) r^1 + d_n$,其中r 是基数。

这意味着,十进制 123 = $1 * 10^2 + 2 * 10^1 + 3$
而八进制的 123 是 $1 * 8^2 + 2 * 8^1 + 3$ = 83

function to_i(str, rad) {
  // the function to transform an ascii code into a number value
  function dig(c) {
    if (c >= 48 && c <= 57) {
      // 0 - 9: as-is
      return c - 48;
    } else if (c >= 97 && c <= 122) {
      // a - z: a means 10, b means 11 and so on until z
      return 10 + c - 97;
    } else {
      return Number.NaN;
    }
  }

  // validate arguments
  if (str == '' || rad < 2 || rad > 35) return Number.NaN;
  // strip extra characters and lowercase ("$10" -> "10")
  var result = str.toLowerCase().match(/^.*?(-?)([a-z0-9]+).*?$/);
  // break on empty numbers
  if (result == null || !result[2]) return Number.NaN;
  // get sign multiplier
  var sign = (result[1] == '-' ? -1 : 1), val = result[2], num = 0;
  // num = dv_0 * rad ** n + dv1 * rad ** (n - 1) + ... dv_n * rad ** 0
  //  where dv_n = dig(val.charCodeAt(i))
  //  and a ** b = a * ... * a, b times
  // for each digits
  for (var i = val.length - 1, m = 1; i >= 0; i --, m *= rad) {
    // get digit value
    var dv = dig(val.charCodeAt(i));
    // validate digit value (you can't put 5 in binary)
    if (dv >= rad || num == Number.NaN) return Number.NaN;
    // multiply
    num += m * dv;
  }
  // return 
  return num * sign;
}

to_i("ff", 16);

这个支持基数,a 表示 10,b 表示 11 等等直到z
希望这有效。

They wanted to test your math knowledge, because many "code monkeys" did not receive proper math education.

A number that is expressed in digits $d_1 d_2...d_n$ can be written in this form: $d_1 r^(n - 1) + ... + d_(n - 1) r^1 + d_n$, where r is the radix.

That means, 123 in decimal = $1 * 10^2 + 2 * 10^1 + 3$
while 123 in octal is $1 * 8^2 + 2 * 8^1 + 3$ = 83

function to_i(str, rad) {
  // the function to transform an ascii code into a number value
  function dig(c) {
    if (c >= 48 && c <= 57) {
      // 0 - 9: as-is
      return c - 48;
    } else if (c >= 97 && c <= 122) {
      // a - z: a means 10, b means 11 and so on until z
      return 10 + c - 97;
    } else {
      return Number.NaN;
    }
  }

  // validate arguments
  if (str == '' || rad < 2 || rad > 35) return Number.NaN;
  // strip extra characters and lowercase ("$10" -> "10")
  var result = str.toLowerCase().match(/^.*?(-?)([a-z0-9]+).*?$/);
  // break on empty numbers
  if (result == null || !result[2]) return Number.NaN;
  // get sign multiplier
  var sign = (result[1] == '-' ? -1 : 1), val = result[2], num = 0;
  // num = dv_0 * rad ** n + dv1 * rad ** (n - 1) + ... dv_n * rad ** 0
  //  where dv_n = dig(val.charCodeAt(i))
  //  and a ** b = a * ... * a, b times
  // for each digits
  for (var i = val.length - 1, m = 1; i >= 0; i --, m *= rad) {
    // get digit value
    var dv = dig(val.charCodeAt(i));
    // validate digit value (you can't put 5 in binary)
    if (dv >= rad || num == Number.NaN) return Number.NaN;
    // multiply
    num += m * dv;
  }
  // return 
  return num * sign;
}

to_i("ff", 16);

This one supports radixes, a means 10, b means 11 and so on until z.
Hope this works.

流年里的时光 2024-09-23 15:46:24

也没听说过这个问题,在美国面试的时候他们总是问我更难的问题。我希望他们问我这样一个简单的问题。

Never heard of this question either, during interviews in US they always asked me much harder questions. I wish they asked me such a simple question.

紅太極 2024-09-23 15:46:24

根据其他答案的轶事证据,我会自己回答这个问题,并接受相同的观点:这似乎不是一个“罐装”面试问题。

Based on the anecdotal evidence from other answers, I will answer this myself, and accept same: this does not seem to be a "canned" interview question.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文