Skip to content

Instantly share code, notes, and snippets.

@bvanderlaan
Last active October 12, 2018 13:50
Show Gist options
  • Save bvanderlaan/e52d4570bbbbc430a59899a6f445f3cb to your computer and use it in GitHub Desktop.
Save bvanderlaan/e52d4570bbbbc430a59899a6f445f3cb to your computer and use it in GitHub Desktop.
Matching Socks

Matching Socks

This Kata is as follows: If I give you a collection where each entry in the collection is a sock and a sock has a side (right or left) write a function which will produce a new collection of pairs.

That is given this:

{
  "socks": [
    { "side": "left" }, 
    { "side": "right" }, 
    { "side": "left" }, 
    { "side": "left" }, 
    { "side": "right" }, 
    { "side": "right" }
  ]
}

Produce something like this:

{
  "pairs": [
    [{ "side": "left" }, { "side": "right" }],
    [{ "side": "left" }, { "side": "right" }],
    [{ "side": "left" }, { "side": "right" }]
  ]
}

In later stages of this kata the socks will have additional categories such as match pairs of left and right black socks vs. left and right white socks with red stripes

Here is one of my takes on this Kata

'use strict';

const { expect } = require('chai');
const crypto = require('crypto');

// CODE ////////////////
class Sock {
  constructor(side, color = 'black') {
    this.side = side;
    this.color = color;

    this.id = crypto.createHash('md5')
      .update(`${this.color}`)
      .digest('hex');
  }


  static toSock(data) {
    return new Sock(data.side, data.color);
  }

  toJSON() {
    return {
      side: this.side,
      color: this.color,
    };
  }
}

const matchSocks = (data) => {
  let lefts = [];
  let rights = [];
  const matches = [];

  const socks = data.map(sock => Sock.toSock(sock))
    .sort((a, b) => ((a.id === b.id) ? 0 : 1));

  let currentType = '';
  socks.forEach((sock) => {
    if (!currentType || (currentType !== sock.id)) {
      currentType = sock.id;
      lefts = [];
      rights = [];
    }

    if (sock.side === 'left') {
      if (rights.length === 0) {
        lefts.push(sock);
      } else {
        matches.push([sock.toJSON(), rights.pop().toJSON()]);
      }
    } else if (sock.side === 'right') {
      if (lefts.length === 0) {
        rights.push(sock);
      } else {
        matches.push([lefts.pop().toJSON(), sock.toJSON()]);
      }
    }
  });

  return matches;
};


// TEST ////////////
describe('Match Socks', () => {
  it('should match left to right socks', () => {
    expect(matchSocks([
      { side: 'left' },
      { side: 'right' },
    ])).to.deep.equals([[{ side: 'left', color: 'black' }, { side: 'right', color: 'black' }]]);
  });

  it('should not include leftover socks', () => {
    expect(matchSocks([
      { side: 'left' },
      { side: 'right' },
      { side: 'left' },
    ])).to.deep.equals([[{ side: 'left', color: 'black' }, { side: 'right', color: 'black' }]]);

    expect(matchSocks([
      { side: 'left' },
    ])).to.deep.equals([]);

    expect(matchSocks([
      { side: 'right' },
    ])).to.deep.equals([]);

    expect(matchSocks([])).to.deep.equals([]);
  });

  it('should match multiple pairs socks', () => {
    expect(matchSocks([
      { side: 'left' },
      { side: 'right' },
      { side: 'right' },
      { side: 'left' },
      { side: 'right' },
      { side: 'left' },
      { side: 'right' },
      { side: 'left' },
    ])).to.deep.equals([
      [{ side: 'left', color: 'black' }, { side: 'right', color: 'black' }],
      [{ side: 'left', color: 'black' }, { side: 'right', color: 'black' }],
      [{ side: 'left', color: 'black' }, { side: 'right', color: 'black' }],
      [{ side: 'left', color: 'black' }, { side: 'right', color: 'black' }],
    ]);
  });

  it('should match colour too', () => {
    expect(matchSocks([
      { side: 'left', color: 'red' },
      { side: 'left', color: 'blue' },
      { side: 'right', color: 'blue' },
      { side: 'right', color: 'red' },
    ])).to.deep.equals([
      [{ side: 'left', color: 'blue' }, { side: 'right', color: 'blue' }],
      [{ side: 'left', color: 'red' }, { side: 'right', color: 'red' }],
    ]);
  });
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment