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
'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' }],
]);
});
});