2
\$\begingroup\$

I wanted to practice functional programming (fp) without using any library but using vanilla JS only. So I took the 4th problem from project euler:

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.

Find the largest palindrome made from the product of two 3-digit numbers.

My solution in fp looks like this:

/*jshint esversion: 6 */
(function () {
  'use strict';

  function* multiply(factor1, factor2) {
    let palindromeNumbers = 0;

    while (true) {
      const product = factor1 * factor2;
      if (isSymmetric(product) && palindromeNumbers < product) {
        palindromeNumbers = product;
      }
      if (factor1 <= 100) {
        factor1 = 999;
        factor2--;
      } else if (factor2 <= 100) {
        yield true;
        return palindromeNumbers;
      } else {
        factor1--;
      }
    }
  }
  const isEqual = (value, compare) => {
    if (value.length != compare.length) {
      return false;
    }
    if (value.length === 1 && value[0] === compare[0]) {
      return true;
    }
    return value[0] === compare[0] &&
      isEqual(value.slice(1), compare.slice(1));
  };
  const isSymmetric = n => {
    const asArray = n.toString()
      .split('');
    const mid = Math.floor(asArray.length / 2);

    const half1 = asArray.slice(0, mid);
    const half2 = asArray.slice(asArray.length - mid)
      .reverse();
    return isEqual(half1, half2);
  };

  const getAllPalindromeNumbers = multiply(999, 999);

  while (getAllPalindromeNumbers.next()
    .value !== true) {}
  const solution = getAllPalindromeNumbers.next()
    .value;
})();

First I wanted to solve this using recursion. But I reached the stack size pretty quickly. Therefore I opted for generators. But I'm not satisfied with my solution especially because of the multiply generator:

  1. I'm am mutating palindromeNumbers, factor1, and factor2
  2. I'm using a while loop twice

Is it possible to solve this problem yet still be consistent with fp, i.e. no mutations and no loops? And of course: Any other improvement suggestions are welcomed.

\$\endgroup\$
  • \$\begingroup\$ Could you please finalize & lock down the code to review? There have been 4 edits already which makes the code under review a moving target. \$\endgroup\$ – Igor Soloydenko Dec 27 '17 at 22:07
  • \$\begingroup\$ @IgorSoloydenko Sorry, I thought the post is free for edit as long as no one answers it. Will make a code freeze now. \$\endgroup\$ – thadeuszlay Dec 27 '17 at 22:12
  • 1
    \$\begingroup\$ I think, you have not break any rule but it's not easy to figure out whether it's okay to start the review or not yet. :) \$\endgroup\$ – Igor Soloydenko Dec 27 '17 at 22:23
  • \$\begingroup\$ Hi @K. A. Buhr, I have a question maybe you can help me: How would you have solved this issue (with no libraries but vanilla JS only)? Would be interested in your approach. Thanks \$\endgroup\$ – thadeuszlay Jan 2 '18 at 9:00
0
\$\begingroup\$

For the cross product I used this code snippet: https://stackoverflow.com/a/36234242

Slow as hell but seems to be fp with vanilla JS only:

/*jshint esversion: 6 */
(function () {
  'use strict';
  const isSymmetric = n => {
    const asString = n.toString();
    return asString === asString.split("")
      .reverse()
      .join("");
  };
  const range = num => Array.from(new Array(num), (_, i) => num - i);
  const from999To100 = range(999)
    .filter(x => x >= 100);

  //https://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in-javascript/36234242#36234242
  const cartesianProduct = arr => arr.reduce(
    (a, b) => a.map(
      x => b.map(
        y => x.concat(y)))
    .reduce((a, b) => a.concat(b), []), [
      []
    ]);

  const combinations = cartesianProduct([
    from999To100, from999To100
  ]);
  const solution = combinations.map(x => x[0] * x[1])
    .filter(isSymmetric)
    .reduce((acc, x) => acc < x ? x : acc, 0);
  console.log("solution ", solution);
})();
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.