Friend or Foe

The name of the function in the Codewars challenge is ill-chosen. The function returns a list of friends (even if an empty one). The name of the function should imply some pluralism. It could be onlyFriends or something similar (not friends because functions should be like verbs, indicating some sort of action, not nouns, indicating some sort of things.

Approach 1

  1. Let friends be an empty list.

  2. If input list of names is empty, return friends.

  3. Let name be the left-most, not yet checked name of the list.

  4. If name length is 4 (four), then name is your friend. Append it to the friends list.

  5. Go back to step 2.

JavaScript

Unit Tests

import { friend } from './friend-foe-v1.js';

describe('friend()', () => {
  it('should return the friends', () => {
    [
      [[], []],
      [['K', 'Mu', 'Mia'], []],
      [['Goku', 'Lara'], ['Goku', 'Lara']],
      [['Ryan', 'Kieran', 'Mark'], ['Ryan', 'Mark']],
      [['Ryan', 'Jimmy', '123', '4', 'Cool Man'], ['Ryan']],
      [
        ['Jimm', 'Cari', 'aret', 'truehdnviegkwgvke', 'sixtyiscooooool'],
        ['Jimm', 'Cari', 'aret'],
      ],
      [['Love', 'Your', 'Face', '😄'], ['Love', 'Your', 'Face']],
    ].forEach(([input, output]) => {
      expect(friend(input)).toEqual(output);
    });
  });
});

Solution 1

/**
 * @type {number}
 */
const REQUIRED_LENGHT = 4;

/**
 * Checks whether the input string has the length `len`.
 *
 * @sig Number -> String -> Boolean
 *
 * @param {Number}
 * @return {(function(String): Boolean}
 *
 * @example
 * hasLengthOf(4)('ECMA');
 * // → true
 *
 * const hasLengthOf1 = hasLengthOf(1);
 * hasLengthOf1('hey');
 * // → false
 */
const hasLengthOf = len => ({ length }) => length === len;

/** Checks if a given name is a friend.
 *
 * NOTE: Frieds are people who have four-letter names, like “Yoda”,
 * “Leia” or “Luke” 🤣.
 *
 * @sig [String] -> [String]
 *
 * @param {Array<string>} names
 * @return {Array<string>}
 *
 * @example
 * friend(['Ahsoka', 'Luke', 'Aayla', 'Yoda']);
 * // → ['Luke', 'Yoda']
 */
export function friend(names) {
  return names.filter(hasLengthOf(REQUIRED_LENGHT));
};

TypeScript

Unit Tests

import { assertEquals } from '/deps.ts'
import { filterFriends } from './friend-foe-v1.ts';

Deno.test('filterFriends()', () => {
  [
    [[], []],
    [['K', 'Mu', 'Mia'], []],
    [['Goku', 'Lara'], ['Goku', 'Lara']],
    [['Ryan', 'Kieran', 'Mark'], ['Ryan', 'Mark']],
    [['Ryan', 'Jimmy', '123', '4', 'Cool Man'], ['Ryan']],
    [
      ['Jimm', 'Cari', 'aret', 'truehdnviegkwgvke', 'sixtyiscooooool'],
      ['Jimm', 'Cari', 'aret'],
    ],
    [['Love', 'Your', 'Face', '😄'], ['Love', 'Your', 'Face']],
  ].forEach(([input, output]) => {
    assertEquals(filterFriends(input), output);
  });
});

Solution 1

/**
 * Friends have names of 4 (four) letters, like “Yoda”,
 * “Leia” or “Luke" 🤣.
 */
const FRIEND_NAME_LENGHT = 4;

/**
 * Checks whether the given string has length `len`.
 */
const hasLengthOf = function hasLengthOf(len: number) {
  return function ({ length }: string): boolean {
    return length === len;
  }
}

/**
 * Filter names that have length `FRIEND_NAME_LENGHT`.
 */
function filterFriends(names: string[]){
  return names.filter(hasLengthOf(FRIEND_NAME_LENGHT));
}

export { filterFriends };

Scheme

Unit Tests