freeCodeCamp/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/split-a-character-string-ba...

3.5 KiB

id title challengeType
5a23c84252665b21eecc801d Split a character string based on change of character 5

Description

Split a (character) string into comma (plus a blank) delimited strings based on a change of character (left to right). Blanks should be treated as any other character (except they are problematic to display clearly). The same applies to commas. For instance, the string: "gHHH5YY++///\" should be split as: ["g", "HHH", "5", "YY", "++", "///", "\" ]

Instructions

Tests

tests:
  - text: <code>split</code> should be a function.
    testString: assert(typeof split == 'function', '<code>split</code> should be a function.');
  - text: <code>split("hello")</code> should return a array.
    testString: assert(Array.isArray(split("hello")), '<code>split("hello")</code> should return a array.');
  - text: <code>split("hello")</code> should return <code>["h", "e", "ll", "o"]</code>.
    testString: assert.deepEqual(split("hello"), ["h", "e", "ll", "o"], '<code>split("hello")</code> should return <code>["h", "e", "ll", "o"]</code>.');
  - text: <code>split("commission")</code> should return <code>["c", "o", "mm", "i", "ss", "i", "o", "n"]</code>.
    testString: assert.deepEqual(split("commission"), ["c", "o", "mm", "i", "ss", "i", "o", "n"], '<code>split("commission")</code> should return <code>["c", "o", "mm", "i", "ss", "i", "o", "n"]</code>.');
  - text: <code>split("ssss----====llloooo")</code> should return <code>["ssss", "----", "====", "lll", "oooo"]</code>.
    testString: assert.deepEqual(split("ssss----====llloooo"), ["ssss", "----", "====", "lll", "oooo"], '<code>split("ssss----====llloooo")</code> should return <code>["ssss", "----", "====", "lll", "oooo"]</code>.');
  - text: <code>split("sssmmmaaammmaaat")</code> should return <code>["sss", "mmm", "aaa", "mmm", "aaa", "t"]</code>.
    testString: assert.deepEqual(split("sssmmmaaammmaaat"), ["sss", "mmm", "aaa", "mmm", "aaa", "t"], '<code>split("sssmmmaaammmaaat")</code> should return <code>["sss", "mmm", "aaa", "mmm", "aaa", "t"]</code>.');
  - text: <code>split("gHHH5YY++///\")</code> should return <code>["g", "HHH", "5", "YY", "++", "///", "\\"]</code>.
    testString: assert.deepEqual(split("gHHH5YY++///\\"), ["g", "HHH", "5", "YY", "++", "///", "\\"], '<code>split("gHHH5YY++///\")</code> should return <code>["g", "HHH", "5", "YY", "++", "///", "\\"]</code>.');

Challenge Seed

function split (str) {
  // Good luck!
}

Solution

function split (str) {
  const concat = xs =>
    xs.length > 0 ? (() => {
      const unit = typeof xs[0] === 'string' ? '' : [];
      return unit.concat.apply(unit, xs);
    })() : [];

  const group = xs => groupBy((a, b) => a === b, xs);

  const groupBy = (f, xs) => {
    const dct = xs.slice(1)
      .reduce((a, x) => {
        const
          h = a.active.length > 0 ? a.active[0] : undefined,
          blnGroup = h !== undefined && f(h, x);
        return {
          active: blnGroup ? a.active.concat([x]) : [x],
          sofar: blnGroup ? a.sofar : a.sofar.concat([a.active])
        };
      }, {
        active: xs.length > 0 ? [xs[0]] : [],
        sofar: []
      });
    return dct.sofar.concat(dct.active.length > 0 ? [dct.active] : []);
  };

  const map = (f, xs) => xs.map(f);

  const stringChars = s => s.split('');

  return map(concat, group(stringChars(str)))
}