CodeWars-Binomial Expansion [全网第一篇<自封>]

431 阅读5分钟

ISSUE

The purpose of this kata is to write a program that can do some algebra. Write a function expand that takes in an expression with a single, one character variable, and expands it. The expression is in the form (ax+b)^n where a and b are integers which may be positive or negative, x is any single character variable, and n is a natural number. If a = 1, no coefficient will be placed in front of the variable. If a = -1, a "-" will be placed in front of the variable.

The expanded form should be returned as a string in the form ax^b+cx^d+ex^f... where a, c, and e are the coefficients of the term, x is the original one character variable that was passed in the original expression and b, d, and f, are the powers that x is being raised to in each term and are in decreasing order. If the coefficient of a term is zero, the term should not be included. If the coefficient of a term is one, the coefficient should not be included. If the coefficient of a term is -1, only the "-" should be included. If the power of the term is 0, only the coefficient should be included. If the power of the term is 1, the caret and power should be excluded.

Examples:

expand("(x+1)^2");      // returns "x^2+2x+1"
expand("(p-1)^3");      // returns "p^3-3p^2+3p-1"
expand("(2f+4)^6");     // returns "64f^6+768f^5+3840f^4+10240f^3+15360f^2+12288f+4096"
expand("(-2a-4)^0");    // returns "1"
expand("(-12t+43)^2");  // returns "144t^2-1032t+1849"
expand("(r+0)^203");    // returns "r^203"
expand("(-x-1)^2");     // returns "x^2+2x+1"

Sample Tests

describe("expand()", function () {
  it("Should correctly expand binomials where a=1 and b is positive", function () {
    Test.assertEquals(expand("(x+1)^0"), "1");
    Test.assertEquals(expand("(x+1)^1"), "x+1");
    Test.assertEquals(expand("(x+1)^2"), "x^2+2x+1");
  });
  it("Should correctly expand binomials where a=1 and b is negative", function () {
    Test.assertEquals(expand("(x-1)^0"), "1");
    Test.assertEquals(expand("(x-1)^1"), "x-1");
    Test.assertEquals(expand("(x-1)^2"), "x^2-2x+1");
  });
  it("Should correctly expand binomials where a is positive.", function () {
    Test.assertEquals(expand("(5m+3)^4"), "625m^4+1500m^3+1350m^2+540m+81");
    Test.assertEquals(expand("(2x-3)^3"), "8x^3-36x^2+54x-27");
    Test.assertEquals(expand("(7x-7)^0"), "1");
  });
  it("Should correctly expand binomials where a is negative.", function () {
    Test.assertEquals(expand("(-5m+3)^4"), "625m^4-1500m^3+1350m^2-540m+81");
    Test.assertEquals(expand("(-2k-3)^3"), "-8k^3-36k^2-54k-27");
    Test.assertEquals(expand("(-7x-7)^0"), "1");
  });
});

翻译

这个kata的目的是编写一个可以做一些代数的程序。编写一个函数expand,它接受一个带有单个字符变量的表达式,并对其进行扩展。表达式的形式为(ax+b)^n,其中a和b是正整数或负整数,x是任何单字符变量,n是自然数。如果a=1,则变量前面不会放置任何系数。如果a=-1,则在变量前面加“-”。
扩展后的表单应以ax^b+cx^d+ex^f格式的字符串形式返回。。。其中a、c和e是该项的系数,x是在原始表达式中传递的原始单字符变量,b、d和f是x在每个项中被提升到的幂,并按降序排列。如果一项的系数为零,则不应包括该项。如果一项的系数为1,则不应包括该系数。如果一项的系数为-1,则只应包括“-”。如果项的幂为0,则只应包括系数。如果术语的幂为1,则应排除插入符号和幂。

前奏

  • 目前高数大部分的问题是把次方约束在3以内的二元内的表达式拓展 其他的内容则与该题思想不一致
  • 目前的一个思路是把表达式和次方分开再迭代,那么他的过程则被简化为只要算一元一次方程的2次方之内的表达式啦
  • 思路有了 则开整,好像看看最佳答案是怎么个思想
  • 首先第一个问题是提取表达式中的a,b,n,x 最推荐的方法当然是正则表达式 ,把ab分解出来后发现之前的思路有问题 使用的二次项定理,那么问题就清晰明了了(并没有)

解题思路

既然确定了使用二项式定理,则要将其中的系数指数和常熟提取出

  1. 首先对于传入的字符串需要把其中的参数提取出来,这里可以考虑使用正则表达式完成该项工作:
  let n = Number(expr.split('^')[1]), //n是最好取得的
    left = expr.split('^')[0],  //把指数部分左边取出
    method = left.replace(/[^-+]/g, '')[1] ? left.replace(/[^-+]/g, '')[1] : left.replace(/[^-+]/g, '')[0], //把两个因子的操作取出
    sym = left.replace(/[^a-z]/g, '');
  if (n == 0) return '1'
  if (left[1] == sym) {
    var a = 1, b = Number(method + left.split(method)[1].replace(')', ''))
  } else {
    if (left[1] == '-') {
      var a = left.replace('(', '==').replace(sym, '==').split('==')[1], b = Number(method + left.replace('(', '').replace(')', '').split(method).pop())
    }
    else {
      let ab = left.replace('(', '').replace(')', '').replace(sym, '').split(method)
      var a = Number(ab[0]), b = Number(method + ab[1])
    }
  1. 得到a b n 之后需要获的结果的每一项:
  for (let i = 0; i <= n; i++) {
    let u = ULL(n, i), j = Math.pow(a, n - i), k = Math.pow(b, i), temp = u * j * k
    // console.log(temp);
    if (temp == 0) continue
    if (i < n - 1) { //x指数大于1
      if (temp != 1 && temp != -1) {
        temp = temp + sym + '^' + (n - i)
      } else if (temp == 1) { //x指数大于1,但是系数为1
        temp = sym + '^' + (n - i)
      } else {
        temp = '-' + sym + '^' + (n - i)
      }
    } else if (i == (n - 1)) { //x指数为1
      if (temp != 1 && temp != -1) {
        temp = temp + sym
      } else if (temp == 1) { //x指数为1,系数为1
        temp = sym
      } else {//x指数为1,系数为-1
        temp = '-' + sym
      }
    } else { //x的指数为0
      temp = temp
    }
    result.push(temp);
  }

这里还有个问题就是计算排列组合

function ULL(n, m) {
  if (n < m) c = 0;
  else if (n == m || m == 0) c = 1;
  else {
    c = 1;
    n = n - m + 1;
    for (i = 1; i <= m; i++) {
      c *= n++;
      c /= i;
    }
  }
  return c;
}

最后把结果拼接再把‘-+’替换为‘-’就可以得到结果了