Advent of Code 2017 Day 3 (part 1) in Functional Programming (FP)

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite












I wanted to practice functional programming (FP) without using any library but using vanilla JS only. So I took a problem from Advent of Code.



https://adventofcode.com/2017/day/3




You come across an experimental new kind of memory stored on an
infinite two-dimensional grid.



Each square on the grid is allocated in a spiral pattern starting at a
location marked 1 and then counting up while spiraling outward. For
example, the first few squares are allocated like this:




 17 16 15 14 13
18 5 4 3 12
19 6 1 2 11
20 7 8 9 10
21 22 23---> ...



While this is very space-efficient (no squares are skipped), requested
data must be carried back to square 1 (the location of the only access
port for this memory system) by programs that can only move up, down,
left, or right. They always take the shortest path: the Manhattan
Distance between the location of the data and square 1.



For example:



Data from square 1 is carried 0 steps, since it's at the access port.
Data from square 12 is carried 3 steps, such as: down, left, left.
Data from square 23 is carried only 2 steps: up twice. Data from
square 1024 must be carried 31 steps. How many steps are required to
carry the data from the square identified in your puzzle input all the
way to the access port?



Your puzzle input is still 289326.




My solution in FP is:



const getSquare = (b, n) => 
const result = Math.pow(b, 2);
if (n === 1)
return 1;

if (result >= n)
return b;

return getSquare(b + 2, n);
;
const seq = (m, n) => m > n ? : [m].concat(seq(m + 1, n));
const getDirection = (square, n) =>
const steps = (square - 1) / 2;
if (n === 1) return 0;
const east = seq(Math.pow(square - 2, 2) + 1, Math.pow(square - 2, 2) +
square - 1);
const north = seq(east[east.length - 1] + 1, east[east.length - 1] +
square - 1);
const west = seq(north[north.length - 1] + 1, north[north.length - 1] +
square - 1);
const south = seq(west[west.length - 1] + 1, west[west.length - 1] +
square - 1);
const x_directions = [east, west];
const y_directions = [north, south];
const getSteps = getStepsOf(n);
const xy_direction = getSteps(x_directions);
const yx_direction = getSteps(y_directions);
const addSteps = addXAndYSteps(steps);

return xy_direction !== -1 ? addSteps(xy_direction) : addSteps(yx_direction);
;
const addXAndYSteps = steps => directions =>
if ((directions + 1) > steps)
return steps + ((directions + 1) - steps);
else if ((directions + 1) === steps)
return steps;
else
return steps + (steps - (directions + 1));

;
const getStepsOf = n => directions => directions.reduce((res, direction) =>
const position = direction.findIndex(dir => dir === n);
return (position > -1) ? position : res;
, -1);
const num = 289326;
const solution = n => getDirection(getSquare(1, n), n);
console.log("Total Steps: ", solution(num));


Is there a better way to write it in FP with pure JavaScript, i.e. no additional FP library? Any improvement suggestions are welcomed.







share|improve this question



























    up vote
    3
    down vote

    favorite












    I wanted to practice functional programming (FP) without using any library but using vanilla JS only. So I took a problem from Advent of Code.



    https://adventofcode.com/2017/day/3




    You come across an experimental new kind of memory stored on an
    infinite two-dimensional grid.



    Each square on the grid is allocated in a spiral pattern starting at a
    location marked 1 and then counting up while spiraling outward. For
    example, the first few squares are allocated like this:




     17 16 15 14 13
    18 5 4 3 12
    19 6 1 2 11
    20 7 8 9 10
    21 22 23---> ...



    While this is very space-efficient (no squares are skipped), requested
    data must be carried back to square 1 (the location of the only access
    port for this memory system) by programs that can only move up, down,
    left, or right. They always take the shortest path: the Manhattan
    Distance between the location of the data and square 1.



    For example:



    Data from square 1 is carried 0 steps, since it's at the access port.
    Data from square 12 is carried 3 steps, such as: down, left, left.
    Data from square 23 is carried only 2 steps: up twice. Data from
    square 1024 must be carried 31 steps. How many steps are required to
    carry the data from the square identified in your puzzle input all the
    way to the access port?



    Your puzzle input is still 289326.




    My solution in FP is:



    const getSquare = (b, n) => 
    const result = Math.pow(b, 2);
    if (n === 1)
    return 1;

    if (result >= n)
    return b;

    return getSquare(b + 2, n);
    ;
    const seq = (m, n) => m > n ? : [m].concat(seq(m + 1, n));
    const getDirection = (square, n) =>
    const steps = (square - 1) / 2;
    if (n === 1) return 0;
    const east = seq(Math.pow(square - 2, 2) + 1, Math.pow(square - 2, 2) +
    square - 1);
    const north = seq(east[east.length - 1] + 1, east[east.length - 1] +
    square - 1);
    const west = seq(north[north.length - 1] + 1, north[north.length - 1] +
    square - 1);
    const south = seq(west[west.length - 1] + 1, west[west.length - 1] +
    square - 1);
    const x_directions = [east, west];
    const y_directions = [north, south];
    const getSteps = getStepsOf(n);
    const xy_direction = getSteps(x_directions);
    const yx_direction = getSteps(y_directions);
    const addSteps = addXAndYSteps(steps);

    return xy_direction !== -1 ? addSteps(xy_direction) : addSteps(yx_direction);
    ;
    const addXAndYSteps = steps => directions =>
    if ((directions + 1) > steps)
    return steps + ((directions + 1) - steps);
    else if ((directions + 1) === steps)
    return steps;
    else
    return steps + (steps - (directions + 1));

    ;
    const getStepsOf = n => directions => directions.reduce((res, direction) =>
    const position = direction.findIndex(dir => dir === n);
    return (position > -1) ? position : res;
    , -1);
    const num = 289326;
    const solution = n => getDirection(getSquare(1, n), n);
    console.log("Total Steps: ", solution(num));


    Is there a better way to write it in FP with pure JavaScript, i.e. no additional FP library? Any improvement suggestions are welcomed.







    share|improve this question























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      I wanted to practice functional programming (FP) without using any library but using vanilla JS only. So I took a problem from Advent of Code.



      https://adventofcode.com/2017/day/3




      You come across an experimental new kind of memory stored on an
      infinite two-dimensional grid.



      Each square on the grid is allocated in a spiral pattern starting at a
      location marked 1 and then counting up while spiraling outward. For
      example, the first few squares are allocated like this:




       17 16 15 14 13
      18 5 4 3 12
      19 6 1 2 11
      20 7 8 9 10
      21 22 23---> ...



      While this is very space-efficient (no squares are skipped), requested
      data must be carried back to square 1 (the location of the only access
      port for this memory system) by programs that can only move up, down,
      left, or right. They always take the shortest path: the Manhattan
      Distance between the location of the data and square 1.



      For example:



      Data from square 1 is carried 0 steps, since it's at the access port.
      Data from square 12 is carried 3 steps, such as: down, left, left.
      Data from square 23 is carried only 2 steps: up twice. Data from
      square 1024 must be carried 31 steps. How many steps are required to
      carry the data from the square identified in your puzzle input all the
      way to the access port?



      Your puzzle input is still 289326.




      My solution in FP is:



      const getSquare = (b, n) => 
      const result = Math.pow(b, 2);
      if (n === 1)
      return 1;

      if (result >= n)
      return b;

      return getSquare(b + 2, n);
      ;
      const seq = (m, n) => m > n ? : [m].concat(seq(m + 1, n));
      const getDirection = (square, n) =>
      const steps = (square - 1) / 2;
      if (n === 1) return 0;
      const east = seq(Math.pow(square - 2, 2) + 1, Math.pow(square - 2, 2) +
      square - 1);
      const north = seq(east[east.length - 1] + 1, east[east.length - 1] +
      square - 1);
      const west = seq(north[north.length - 1] + 1, north[north.length - 1] +
      square - 1);
      const south = seq(west[west.length - 1] + 1, west[west.length - 1] +
      square - 1);
      const x_directions = [east, west];
      const y_directions = [north, south];
      const getSteps = getStepsOf(n);
      const xy_direction = getSteps(x_directions);
      const yx_direction = getSteps(y_directions);
      const addSteps = addXAndYSteps(steps);

      return xy_direction !== -1 ? addSteps(xy_direction) : addSteps(yx_direction);
      ;
      const addXAndYSteps = steps => directions =>
      if ((directions + 1) > steps)
      return steps + ((directions + 1) - steps);
      else if ((directions + 1) === steps)
      return steps;
      else
      return steps + (steps - (directions + 1));

      ;
      const getStepsOf = n => directions => directions.reduce((res, direction) =>
      const position = direction.findIndex(dir => dir === n);
      return (position > -1) ? position : res;
      , -1);
      const num = 289326;
      const solution = n => getDirection(getSquare(1, n), n);
      console.log("Total Steps: ", solution(num));


      Is there a better way to write it in FP with pure JavaScript, i.e. no additional FP library? Any improvement suggestions are welcomed.







      share|improve this question













      I wanted to practice functional programming (FP) without using any library but using vanilla JS only. So I took a problem from Advent of Code.



      https://adventofcode.com/2017/day/3




      You come across an experimental new kind of memory stored on an
      infinite two-dimensional grid.



      Each square on the grid is allocated in a spiral pattern starting at a
      location marked 1 and then counting up while spiraling outward. For
      example, the first few squares are allocated like this:




       17 16 15 14 13
      18 5 4 3 12
      19 6 1 2 11
      20 7 8 9 10
      21 22 23---> ...



      While this is very space-efficient (no squares are skipped), requested
      data must be carried back to square 1 (the location of the only access
      port for this memory system) by programs that can only move up, down,
      left, or right. They always take the shortest path: the Manhattan
      Distance between the location of the data and square 1.



      For example:



      Data from square 1 is carried 0 steps, since it's at the access port.
      Data from square 12 is carried 3 steps, such as: down, left, left.
      Data from square 23 is carried only 2 steps: up twice. Data from
      square 1024 must be carried 31 steps. How many steps are required to
      carry the data from the square identified in your puzzle input all the
      way to the access port?



      Your puzzle input is still 289326.




      My solution in FP is:



      const getSquare = (b, n) => 
      const result = Math.pow(b, 2);
      if (n === 1)
      return 1;

      if (result >= n)
      return b;

      return getSquare(b + 2, n);
      ;
      const seq = (m, n) => m > n ? : [m].concat(seq(m + 1, n));
      const getDirection = (square, n) =>
      const steps = (square - 1) / 2;
      if (n === 1) return 0;
      const east = seq(Math.pow(square - 2, 2) + 1, Math.pow(square - 2, 2) +
      square - 1);
      const north = seq(east[east.length - 1] + 1, east[east.length - 1] +
      square - 1);
      const west = seq(north[north.length - 1] + 1, north[north.length - 1] +
      square - 1);
      const south = seq(west[west.length - 1] + 1, west[west.length - 1] +
      square - 1);
      const x_directions = [east, west];
      const y_directions = [north, south];
      const getSteps = getStepsOf(n);
      const xy_direction = getSteps(x_directions);
      const yx_direction = getSteps(y_directions);
      const addSteps = addXAndYSteps(steps);

      return xy_direction !== -1 ? addSteps(xy_direction) : addSteps(yx_direction);
      ;
      const addXAndYSteps = steps => directions =>
      if ((directions + 1) > steps)
      return steps + ((directions + 1) - steps);
      else if ((directions + 1) === steps)
      return steps;
      else
      return steps + (steps - (directions + 1));

      ;
      const getStepsOf = n => directions => directions.reduce((res, direction) =>
      const position = direction.findIndex(dir => dir === n);
      return (position > -1) ? position : res;
      , -1);
      const num = 289326;
      const solution = n => getDirection(getSquare(1, n), n);
      console.log("Total Steps: ", solution(num));


      Is there a better way to write it in FP with pure JavaScript, i.e. no additional FP library? Any improvement suggestions are welcomed.









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jan 9 at 19:20
























      asked Jan 9 at 18:53









      thadeuszlay

      435212




      435212

























          active

          oldest

          votes











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184678%2fadvent-of-code-2017-day-3-part-1-in-functional-programming-fp%23new-answer', 'question_page');

          );

          Post as a guest



































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes










           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184678%2fadvent-of-code-2017-day-3-part-1-in-functional-programming-fp%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Python Lists

          Aion

          JavaScript Array Iteration Methods