freeCodeCamp/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/sum-to-100.english.md

4.9 KiB

id title challengeType
5a23c84252665b21eecc8043 Sum to 100 5

Description

Find solutions to the sum to one hundred puzzle. Add (insert) the mathematical operators + or (plus or minus) before any of the digits in the decimal numeric string 123456789 such that the resulting mathematical expression adds up to a particular sum (in this iconic case, 100). Example:
123 + 4 - 5 + 67 - 89   =   100

Instructions

Write a function that takes a number as parameter. The function should return an array containing all solutions for the given number. The solutions should be strings representing the expressions. For example: "1+23-456+78-9". Sort the array before returning it.

Tests

tests:
  - text: <code>sumTo100</code> should be a function.
    testString: assert(typeof sumTo100 == 'function', '<code>sumTo100</code> should be a function.');
  - text: <code>sumTo100(199)</code> should return an array.
    testString: assert(Array.isArray(sumTo100(199)), '<code>sumTo100(199)</code> should return an array.');
  - text: <code>sumTo100(199)</code> should return <code>["-1+2-3+45+67+89", "123-4+5+6+78-9", "123-4+56+7+8+9"]</code>.
    testString: assert.deepEqual(sumTo100(199), ["-1+2-3+45+67+89", "123-4+5+6+78-9", "123-4+56+7+8+9"], '<code>sumTo100(199)</code> should return <code>["-1+2-3+45+67+89", "123-4+5+6+78-9", "123-4+56+7+8+9"]</code>.');
  - text: <code>sumTo100(209)</code> should return <code>["1+234+56+7-89"]</code>.
    testString: assert.deepEqual(sumTo100(209), ["1+234+56+7-89"], '<code>sumTo100(209)</code> should return <code>["1+234+56+7-89"]</code>.');
  - text: <code>sumTo100(243)</code> should return <code>["-1-234+567-89", "-12+345+6-7-89", "123+45+6+78-9"]</code>.
    testString: assert.deepEqual(sumTo100(243), ["-1-234+567-89", "-12+345+6-7-89", "123+45+6+78-9"], '<code>sumTo100(243)</code> should return <code>["-1-234+567-89", "-12+345+6-7-89", "123+45+6+78-9"]</code>.');
  - text: <code>sumTo100(199)</code> should return <code>["-1+2-3+45+67+89", "123-4+5+6+78-9", "123-4+56+7+8+9"]</code>.
    testString: assert.deepEqual(sumTo100(199), ["-1+2-3+45+67+89", "123-4+5+6+78-9", "123-4+56+7+8+9"], '<code>sumTo100(199)</code> should return <code>["-1+2-3+45+67+89", "123-4+5+6+78-9", "123-4+56+7+8+9"]</code>.');
  - text: <code>sumTo100(197)</code> should return <code>["1-2-3+45+67+89", "12+34-5+67+89", "123+4-5+6+78-9"]</code>.
    testString: assert.deepEqual(sumTo100(197), ["1-2-3+45+67+89", "12+34-5+67+89", "123+4-5+6+78-9"], '<code>sumTo100(197)</code> should return <code>["1-2-3+45+67+89", "12+34-5+67+89", "123+4-5+6+78-9"]</code>.');

Challenge Seed

function sumTo100(n) {
  // Good luck!
}

Solution

function sumTo100(n) {
  var permutationsWithRepetition = function(n, as) {
    return as.length > 0 ?
      foldl1(curry(cartesianProduct)(as), replicate(n, as)) : [];
  };

  var cartesianProduct = function(xs, ys) {
    return [].concat.apply([], xs.map(function(x) {
      return [].concat.apply([], ys.map(function(y) {
        return [
          [x].concat(y)
        ];
      }));
    }));
  };

  var curry = function(f) {
    return function(a) {
      return function(b) {
        return f(a, b);
      };
    };
  };

  var flip = function(f) {
    return function(a, b) {
      return f.apply(null, [b, a]);
    };
  };

  var foldl1 = function(f, xs) {
    return xs.length > 0 ? xs.slice(1)
      .reduce(f, xs[0]) : [];
  };

  var replicate = function(n, a) {
    var v = [a],
      o = [];
    if (n < 1) return o;
    while (n > 1) {
      if (n & 1) o = o.concat(v);
      n >>= 1;
      v = v.concat(v);
    }
    return o.concat(v);
  };

  var asSum = function(xs) {
    var dct = xs.reduceRight(function(a, sign, i) {
      var d = i + 1; //  zero-based index to [1-9] positions
      if (sign !== 0) {
        // Sum increased, digits cleared
        return {
          digits: [],
          n: a.n + sign * parseInt([d].concat(a.digits)
            .join(''), 10)
        };
      } else return { // Digits extended, sum unchanged
        digits: [d].concat(a.digits),
        n: a.n
      };
    }, {
      digits: [],
      n: 0
    });
    return dct.n + (
      dct.digits.length > 0 ? parseInt(dct.digits.join(''), 10) : 0
    );
  };

  var asString = function(xs) {
    var ns = xs.reduce(function(a, sign, i) {
      var d = (i + 1)
        .toString();
      return sign === 0 ? a + d : a + (sign > 0 ? '+' : '-') + d;
    }, '');

    return ns[0] === '+' ? tail(ns) : ns;
  };

  var universe = permutationsWithRepetition(9, [0, 1, -1])
    .filter(function(x) {
      return x[0] !== 1 && asSum(x) === n;
    }).map(asString);
  return universe.sort()
}