Predict mars robot positionGeneral review of Robot classMartian Robots - a small JS programRobot arm...

Am I using the wrong word all along?

Avoiding morning and evening handshakes

Find the number of ways to express 1050 as sum of consecutive integers

Where is this triangular-shaped space station from?

How can I mix up weapons for large groups of similar monsters/characters?

Does Windows 10's telemetry include sending *.doc files if Word crashed?

Wanted: 5.25 floppy to usb adapter

What happens if a wizard reaches level 20 but has no 3rd-level spells that they can use with the Signature Spells feature?

If I delete my router's history can my ISP still provide it to my parents?

Crystal compensation for temp and voltage

Finding ratio of the area of triangles

How to approximate rolls for potions of healing using only d6's?

Criticizing long fiction. How is it different from short?

What is the wife of a henpecked husband called?

How to acknowledge an embarrassing job interview, now that I work directly with the interviewer?

If all harmonics are generated by plucking, how does a guitar string produce a pure frequency sound?

Dilemma of explaining to interviewer that he is the reason for declining second interview

Why is working on the same position for more than 15 years not a red flag?

Does this pattern of summing polygonal numbers to get a square repeat indefinitely?

Why does the DC-9-80 have this cusp in its fuselage?

What's the purpose of these copper coils with resitors inside them in A Yamaha RX-V396RDS amplifier?

Word to be used for "standing with your toes pointing out"

I am on the US no-fly list. What can I do in order to be allowed on flights which go through US airspace?

Why do neural networks need so many training examples to perform?



Predict mars robot position


General review of Robot classMartian Robots - a small JS programRobot arm manipulation libraryGenerating Robot NameMars Rover SimulatorMars rover movement and positionMars Rover problem in J2D console robot warsMars Rover Kata using TDD and SOLIDSearch insert position













1












$begingroup$


Description




A robot lands on Mars, which happens to be a cartesian grid; assuming that we hand the robot these instructions, such as LFFFRFFFRRFFF, where "L" is a "turn 90 degrees left", "R" is a "turn 90 degrees right", and "F" is "go forward one space, please write control code for the robot such that it ends up at the appropriate-and-correct destination, and include unit tests.




Here is an example output with command "FF":



[0, 2]



Code



class Robot {
private int x;
private int y;
private int currentDirection;

Robot() {
this(0, 0);
}

Robot(int x, int y) {
this.x = x;
this.y = y;
currentDirection = 0;
}

public void move(String moves) {
for (char ch : moves.toCharArray()) {
if (ch == 'R') currentDirection += 1;
if (ch == 'L') currentDirection -= 1;

currentDirection = currentDirection % 4;

if (ch != 'F') continue;

System.out.println(currentDirection);
if (currentDirection == 0) {
y += 1;
} if (currentDirection == 1) {
x += 1;
} if (currentDirection == 2) {
y -= 1;
} if (currentDirection == 3) {
x -= 1;
}
}
}

public void reset() {
x = 0;
y = 0;
currentDirection = 0;
}

public String position() {
return x + ":" + y;
}
}

class Main {
public static void main(String[] args) {
Robot robot = new Robot();
robot.move("FF");
System.out.println(robot.position()); // 0,2
robot.reset();
System.out.println(robot.position()); // 0,0
robot.move("FFRF");
System.out.println(robot.position()); // 1,2
robot.reset();
robot.move("FFRRRFF");
System.out.println(robot.position()); // -2,2
}
}


How can I make this code more object oriented?










share|improve this question









$endgroup$

















    1












    $begingroup$


    Description




    A robot lands on Mars, which happens to be a cartesian grid; assuming that we hand the robot these instructions, such as LFFFRFFFRRFFF, where "L" is a "turn 90 degrees left", "R" is a "turn 90 degrees right", and "F" is "go forward one space, please write control code for the robot such that it ends up at the appropriate-and-correct destination, and include unit tests.




    Here is an example output with command "FF":



    [0, 2]



    Code



    class Robot {
    private int x;
    private int y;
    private int currentDirection;

    Robot() {
    this(0, 0);
    }

    Robot(int x, int y) {
    this.x = x;
    this.y = y;
    currentDirection = 0;
    }

    public void move(String moves) {
    for (char ch : moves.toCharArray()) {
    if (ch == 'R') currentDirection += 1;
    if (ch == 'L') currentDirection -= 1;

    currentDirection = currentDirection % 4;

    if (ch != 'F') continue;

    System.out.println(currentDirection);
    if (currentDirection == 0) {
    y += 1;
    } if (currentDirection == 1) {
    x += 1;
    } if (currentDirection == 2) {
    y -= 1;
    } if (currentDirection == 3) {
    x -= 1;
    }
    }
    }

    public void reset() {
    x = 0;
    y = 0;
    currentDirection = 0;
    }

    public String position() {
    return x + ":" + y;
    }
    }

    class Main {
    public static void main(String[] args) {
    Robot robot = new Robot();
    robot.move("FF");
    System.out.println(robot.position()); // 0,2
    robot.reset();
    System.out.println(robot.position()); // 0,0
    robot.move("FFRF");
    System.out.println(robot.position()); // 1,2
    robot.reset();
    robot.move("FFRRRFF");
    System.out.println(robot.position()); // -2,2
    }
    }


    How can I make this code more object oriented?










    share|improve this question









    $endgroup$















      1












      1








      1





      $begingroup$


      Description




      A robot lands on Mars, which happens to be a cartesian grid; assuming that we hand the robot these instructions, such as LFFFRFFFRRFFF, where "L" is a "turn 90 degrees left", "R" is a "turn 90 degrees right", and "F" is "go forward one space, please write control code for the robot such that it ends up at the appropriate-and-correct destination, and include unit tests.




      Here is an example output with command "FF":



      [0, 2]



      Code



      class Robot {
      private int x;
      private int y;
      private int currentDirection;

      Robot() {
      this(0, 0);
      }

      Robot(int x, int y) {
      this.x = x;
      this.y = y;
      currentDirection = 0;
      }

      public void move(String moves) {
      for (char ch : moves.toCharArray()) {
      if (ch == 'R') currentDirection += 1;
      if (ch == 'L') currentDirection -= 1;

      currentDirection = currentDirection % 4;

      if (ch != 'F') continue;

      System.out.println(currentDirection);
      if (currentDirection == 0) {
      y += 1;
      } if (currentDirection == 1) {
      x += 1;
      } if (currentDirection == 2) {
      y -= 1;
      } if (currentDirection == 3) {
      x -= 1;
      }
      }
      }

      public void reset() {
      x = 0;
      y = 0;
      currentDirection = 0;
      }

      public String position() {
      return x + ":" + y;
      }
      }

      class Main {
      public static void main(String[] args) {
      Robot robot = new Robot();
      robot.move("FF");
      System.out.println(robot.position()); // 0,2
      robot.reset();
      System.out.println(robot.position()); // 0,0
      robot.move("FFRF");
      System.out.println(robot.position()); // 1,2
      robot.reset();
      robot.move("FFRRRFF");
      System.out.println(robot.position()); // -2,2
      }
      }


      How can I make this code more object oriented?










      share|improve this question









      $endgroup$




      Description




      A robot lands on Mars, which happens to be a cartesian grid; assuming that we hand the robot these instructions, such as LFFFRFFFRRFFF, where "L" is a "turn 90 degrees left", "R" is a "turn 90 degrees right", and "F" is "go forward one space, please write control code for the robot such that it ends up at the appropriate-and-correct destination, and include unit tests.




      Here is an example output with command "FF":



      [0, 2]



      Code



      class Robot {
      private int x;
      private int y;
      private int currentDirection;

      Robot() {
      this(0, 0);
      }

      Robot(int x, int y) {
      this.x = x;
      this.y = y;
      currentDirection = 0;
      }

      public void move(String moves) {
      for (char ch : moves.toCharArray()) {
      if (ch == 'R') currentDirection += 1;
      if (ch == 'L') currentDirection -= 1;

      currentDirection = currentDirection % 4;

      if (ch != 'F') continue;

      System.out.println(currentDirection);
      if (currentDirection == 0) {
      y += 1;
      } if (currentDirection == 1) {
      x += 1;
      } if (currentDirection == 2) {
      y -= 1;
      } if (currentDirection == 3) {
      x -= 1;
      }
      }
      }

      public void reset() {
      x = 0;
      y = 0;
      currentDirection = 0;
      }

      public String position() {
      return x + ":" + y;
      }
      }

      class Main {
      public static void main(String[] args) {
      Robot robot = new Robot();
      robot.move("FF");
      System.out.println(robot.position()); // 0,2
      robot.reset();
      System.out.println(robot.position()); // 0,0
      robot.move("FFRF");
      System.out.println(robot.position()); // 1,2
      robot.reset();
      robot.move("FFRRRFF");
      System.out.println(robot.position()); // -2,2
      }
      }


      How can I make this code more object oriented?







      java object-oriented programming-challenge






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 3 hours ago









      CodeYogiCodeYogi

      2,01742875




      2,01742875






















          2 Answers
          2






          active

          oldest

          votes


















          2












          $begingroup$

          Initialization



          As written, your robot lander can land at any X,Y coordinate on your grid, but will always be facing in the positive Y-axis direction. This seems unreasonable. If wind, turbulence can cause a position uncertainty, which requires initializing the robot at a particular X,Y coordinate, it seems reasonable to assume it might also land in any facing.



          Robot() {
          this(0, 0, 0);
          }

          Robot(int x, int y) {
          this(x, y, 0);
          }

          Robot(int x, int y, int initial_facing) {
          // ...
          }




          Commands & Instructions



          Your instructions are a series of single letter commands, but you can't actually send a single command to the robot. You should separate the individual commands from the series of instructions. Something like:



          void turn_left() { ... }
          void turn_right() { ... }
          void move_forward() { ... }

          public void command(char command_letter) {
          switch (command_letter) {
          case 'L': turn_left(); break;
          case 'R': turn_right(); break;
          case 'F': move_forward(); break;
          default: throw new IllegalArgumentException("Invalid command: "+command_letter);
          }
          }

          public void instructions(String moves) {
          for (char command_letter : moves.toCharArray()) {
          command(command_letter);
          }
          }




          Where am I?



          position() returns a String containing the coordinates of the robot. If a control program wants to query the position of the robot, in order to determine what commands should be sent to send it to the desired location, it would need to parse that string back into integer values.



          Consider instead returning the actual integer positions, possibly like:



          public int[] position() {
          return new int[]{ x, y };
          }


          Alternately, you might want to create a class Position which can store the x,y location of the robot. Or you could use java.awt.Point



          public Point position() {
          return new Point(x, y);
          }


          Perhaps override the toString() method to return a human friendly description of the robot, including its position. Or maybe a position_as_string() method.



          Which way is the robot facing? Can't directly tell! You currently have to query the position(), then move("F"), followed by position(), and then compare the positions to determine which way the robot is facing! How about adding a facing() method?





          Learn how to write proper unit tests. For example, with JUnit5, you could write:



          import static org.junit.jupiter.api.Assertions.assertEquals;
          import org.junit.jupiter.api.Test;

          class RobotTests {

          private final Robot robot = new Robot();

          @Test
          void starts_at_origin() {
          assertEquals("0:0", robot.position());
          }

          @Test
          void move_forward_twice() {
          robot.move("FF");
          assertEquals("0:2", robot.position());
          }

          @Test
          void move_and_turn_right() {
          robot.move("FFRF");
          assertEquals("1:2", robot.position());
          }

          @Test
          void three_rights_make_a_left() {
          robot.move("FFRRRFF");
          assertEquals("-2:2", robot.position());
          }

          @Test
          void but_one_left_does_not() {
          robot.move("FFLFF");
          assertEquals("-2:2", robot.position());
          }
          }


          Notice that each test is run in a brand-new RobotTests instance, so you don't need to call robot.reset() between each.



          If you run this unit test, you'll find 4 of 5 tests pass, one test fails. I'll leave you to figure out why.





          Additional Concerns



          currentDirection taking on the values 0, 1, 2 and 3 to represent the 4 cardinal directions is limiting. If later, you want to add in diagonal moves (NW, SW, SE, or NE), would you use the values 4 and above to represent them? Or would you renumber the original 4 directions to be 0, 2, 4 and 6, and use 1, 3, 5, and 7 for the diagonal directions?



          You might be tempted to use an enum for the direction values, but I think that would be a bad idea. I would use 0, 90, 180, and 270 as direction values. These have physical meaning. If later your robot is allowed a more realistic double x, y; coordinate system, you could also change to use double currentDirection; and allow turns of a fraction of a degree. With enum, you'd lose this possible future flexibility.



          As an alternative, you might also consider using a directional vector:



          int dx=0, dy=1;   // currentDirection = 0°


          And move_forward simply becomes:



          x += dx;
          y += dy;


          And a turn right could become:



          int old_dx = dx;

          dx = dy;
          dy = -old_dx;





          share|improve this answer









          $endgroup$









          • 1




            $begingroup$
            This is solid advice. Personally I don't think an enum is a bad solution if we can assume the requirements aren't going to change.
            $endgroup$
            – Konrad Morawski
            1 hour ago



















          2












          $begingroup$

          I would consider refactoring direction into an enum, instead of a magic number. This would allow to encapsulate the related logic in this type.



          It might look like that:



              enum Direction {
          UP(0, 1),
          RIGHT(1, 0),
          DOWN(0, -1),
          LEFT(-1, 0);

          final int xVector;
          final int yVector;

          private final Direction FIRST = Direction.values()[0];
          private final Direction LAST = Direction.values()[Direction.values().length];

          Direction(int xVector, int yVector) {
          this.xVector = xVector;
          this.yVector = yVector;
          }

          Direction rotatedLeft() {
          return this == FIRST
          ? LAST // cycle complete
          : Direction.values()[ordinal() - 1]; // previous value
          }

          Direction rotatedRight() {
          return this == LAST
          ? FIRST // cycle complete
          : Direction.values()[ordinal() + 1]; // next value
          }
          }


          And then the Robot code becomes (including some subjective clean up, unrelated to the object-oriented aspect itself):



          class Robot {
          private int x;
          private int y;
          private Direction currentDirection;

          Robot() {
          this(0, 0);
          }

          Robot(int x, int y) {
          this.x = x;
          this.y = y;
          currentDirection = Direction.UP;
          }

          public void move(String moves) {
          for (char code : moves.toCharArray()) {
          // a matter of taste, I like to extract logic
          // out of looping constructs for clarity
          move(code);
          }
          }

          private void move(char code) {
          switch (code) {
          case 'R': {
          currentDirection = currentDirection.rotatedRight();
          break;
          }
          case 'L': {
          currentDirection = currentDirection.rotatedLeft();
          break;
          }
          case 'F': {
          // you'd call the println thing here.
          // as it's not part of the requirements I assumed it to be a debugging artifact
          this.x += currentDirection.xVector;
          this.y += currentDirection.yVector;
          break;
          }
          }
          }

          public void reset() {
          x = 0;
          y = 0;
          currentDirection = Direction.UP;
          }

          public String position() {
          return x + ":" + y;
          }
          }


          I think this is more object-oriented, and also an improvement.



          You could take it one step further and encapsulate the x and y coordinates in a little standalone class (Position). Like so:



              class Position {
          static final Position DEFAULT = new Position(0, 0);

          final int x;
          final int y;

          public Position(int x, int y) {
          this.x = x;
          this.y = y;
          }

          public Position movedInto(Direction direction) {
          return new Position(x + direction.xVector, y + direction.yVector);
          }

          @Override
          public String toString() {
          return x + ":" + y;
          }
          }


          Then in the Robot class you replace x and y fields with Position position, and you no longer recalculate the position in the Robot class, as you can simply go:



          case 'F': {
          position = position.movedInto(currentDirection);
          break;
          }


          in the move method.



          Plus:



              public void reset() {
          position = Position.DEFAULT;
          currentDirection = Direction.UP;
          }

          public String position() {
          return position.toString();
          }


          Yet another idea would be to encapsulate the move codes themselves into a class or classes. It's sometimes hard to say where to draw the line, as making code more and more OO comes at the cost of more boilerplate, and can be a form of overengineering.



          I admit I haven't tested my refactored version, I only approached the question in terms of code design.






          share|improve this answer











          $endgroup$













          • $begingroup$
            Since this is a programming-challenge, I like the Direction enum refactoring (+1), but for a future-friendly robot, I think enum Direction is a bad idea. (See my answer.)
            $endgroup$
            – AJNeufeld
            1 hour ago










          • $begingroup$
            Fixed the bug, thanks. The azimuth / alpha (I guess we could call it that?) is a neat alternative to an enum. An alpha value is more flexible as you pointed out, the cost is that recalculating x and y when the direction is, say, 270, won't look as straightforward. So I feel it's a tradeoff between explicity and flexibility.
            $endgroup$
            – Konrad Morawski
            1 hour ago













          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',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          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%2f214669%2fpredict-mars-robot-position%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2












          $begingroup$

          Initialization



          As written, your robot lander can land at any X,Y coordinate on your grid, but will always be facing in the positive Y-axis direction. This seems unreasonable. If wind, turbulence can cause a position uncertainty, which requires initializing the robot at a particular X,Y coordinate, it seems reasonable to assume it might also land in any facing.



          Robot() {
          this(0, 0, 0);
          }

          Robot(int x, int y) {
          this(x, y, 0);
          }

          Robot(int x, int y, int initial_facing) {
          // ...
          }




          Commands & Instructions



          Your instructions are a series of single letter commands, but you can't actually send a single command to the robot. You should separate the individual commands from the series of instructions. Something like:



          void turn_left() { ... }
          void turn_right() { ... }
          void move_forward() { ... }

          public void command(char command_letter) {
          switch (command_letter) {
          case 'L': turn_left(); break;
          case 'R': turn_right(); break;
          case 'F': move_forward(); break;
          default: throw new IllegalArgumentException("Invalid command: "+command_letter);
          }
          }

          public void instructions(String moves) {
          for (char command_letter : moves.toCharArray()) {
          command(command_letter);
          }
          }




          Where am I?



          position() returns a String containing the coordinates of the robot. If a control program wants to query the position of the robot, in order to determine what commands should be sent to send it to the desired location, it would need to parse that string back into integer values.



          Consider instead returning the actual integer positions, possibly like:



          public int[] position() {
          return new int[]{ x, y };
          }


          Alternately, you might want to create a class Position which can store the x,y location of the robot. Or you could use java.awt.Point



          public Point position() {
          return new Point(x, y);
          }


          Perhaps override the toString() method to return a human friendly description of the robot, including its position. Or maybe a position_as_string() method.



          Which way is the robot facing? Can't directly tell! You currently have to query the position(), then move("F"), followed by position(), and then compare the positions to determine which way the robot is facing! How about adding a facing() method?





          Learn how to write proper unit tests. For example, with JUnit5, you could write:



          import static org.junit.jupiter.api.Assertions.assertEquals;
          import org.junit.jupiter.api.Test;

          class RobotTests {

          private final Robot robot = new Robot();

          @Test
          void starts_at_origin() {
          assertEquals("0:0", robot.position());
          }

          @Test
          void move_forward_twice() {
          robot.move("FF");
          assertEquals("0:2", robot.position());
          }

          @Test
          void move_and_turn_right() {
          robot.move("FFRF");
          assertEquals("1:2", robot.position());
          }

          @Test
          void three_rights_make_a_left() {
          robot.move("FFRRRFF");
          assertEquals("-2:2", robot.position());
          }

          @Test
          void but_one_left_does_not() {
          robot.move("FFLFF");
          assertEquals("-2:2", robot.position());
          }
          }


          Notice that each test is run in a brand-new RobotTests instance, so you don't need to call robot.reset() between each.



          If you run this unit test, you'll find 4 of 5 tests pass, one test fails. I'll leave you to figure out why.





          Additional Concerns



          currentDirection taking on the values 0, 1, 2 and 3 to represent the 4 cardinal directions is limiting. If later, you want to add in diagonal moves (NW, SW, SE, or NE), would you use the values 4 and above to represent them? Or would you renumber the original 4 directions to be 0, 2, 4 and 6, and use 1, 3, 5, and 7 for the diagonal directions?



          You might be tempted to use an enum for the direction values, but I think that would be a bad idea. I would use 0, 90, 180, and 270 as direction values. These have physical meaning. If later your robot is allowed a more realistic double x, y; coordinate system, you could also change to use double currentDirection; and allow turns of a fraction of a degree. With enum, you'd lose this possible future flexibility.



          As an alternative, you might also consider using a directional vector:



          int dx=0, dy=1;   // currentDirection = 0°


          And move_forward simply becomes:



          x += dx;
          y += dy;


          And a turn right could become:



          int old_dx = dx;

          dx = dy;
          dy = -old_dx;





          share|improve this answer









          $endgroup$









          • 1




            $begingroup$
            This is solid advice. Personally I don't think an enum is a bad solution if we can assume the requirements aren't going to change.
            $endgroup$
            – Konrad Morawski
            1 hour ago
















          2












          $begingroup$

          Initialization



          As written, your robot lander can land at any X,Y coordinate on your grid, but will always be facing in the positive Y-axis direction. This seems unreasonable. If wind, turbulence can cause a position uncertainty, which requires initializing the robot at a particular X,Y coordinate, it seems reasonable to assume it might also land in any facing.



          Robot() {
          this(0, 0, 0);
          }

          Robot(int x, int y) {
          this(x, y, 0);
          }

          Robot(int x, int y, int initial_facing) {
          // ...
          }




          Commands & Instructions



          Your instructions are a series of single letter commands, but you can't actually send a single command to the robot. You should separate the individual commands from the series of instructions. Something like:



          void turn_left() { ... }
          void turn_right() { ... }
          void move_forward() { ... }

          public void command(char command_letter) {
          switch (command_letter) {
          case 'L': turn_left(); break;
          case 'R': turn_right(); break;
          case 'F': move_forward(); break;
          default: throw new IllegalArgumentException("Invalid command: "+command_letter);
          }
          }

          public void instructions(String moves) {
          for (char command_letter : moves.toCharArray()) {
          command(command_letter);
          }
          }




          Where am I?



          position() returns a String containing the coordinates of the robot. If a control program wants to query the position of the robot, in order to determine what commands should be sent to send it to the desired location, it would need to parse that string back into integer values.



          Consider instead returning the actual integer positions, possibly like:



          public int[] position() {
          return new int[]{ x, y };
          }


          Alternately, you might want to create a class Position which can store the x,y location of the robot. Or you could use java.awt.Point



          public Point position() {
          return new Point(x, y);
          }


          Perhaps override the toString() method to return a human friendly description of the robot, including its position. Or maybe a position_as_string() method.



          Which way is the robot facing? Can't directly tell! You currently have to query the position(), then move("F"), followed by position(), and then compare the positions to determine which way the robot is facing! How about adding a facing() method?





          Learn how to write proper unit tests. For example, with JUnit5, you could write:



          import static org.junit.jupiter.api.Assertions.assertEquals;
          import org.junit.jupiter.api.Test;

          class RobotTests {

          private final Robot robot = new Robot();

          @Test
          void starts_at_origin() {
          assertEquals("0:0", robot.position());
          }

          @Test
          void move_forward_twice() {
          robot.move("FF");
          assertEquals("0:2", robot.position());
          }

          @Test
          void move_and_turn_right() {
          robot.move("FFRF");
          assertEquals("1:2", robot.position());
          }

          @Test
          void three_rights_make_a_left() {
          robot.move("FFRRRFF");
          assertEquals("-2:2", robot.position());
          }

          @Test
          void but_one_left_does_not() {
          robot.move("FFLFF");
          assertEquals("-2:2", robot.position());
          }
          }


          Notice that each test is run in a brand-new RobotTests instance, so you don't need to call robot.reset() between each.



          If you run this unit test, you'll find 4 of 5 tests pass, one test fails. I'll leave you to figure out why.





          Additional Concerns



          currentDirection taking on the values 0, 1, 2 and 3 to represent the 4 cardinal directions is limiting. If later, you want to add in diagonal moves (NW, SW, SE, or NE), would you use the values 4 and above to represent them? Or would you renumber the original 4 directions to be 0, 2, 4 and 6, and use 1, 3, 5, and 7 for the diagonal directions?



          You might be tempted to use an enum for the direction values, but I think that would be a bad idea. I would use 0, 90, 180, and 270 as direction values. These have physical meaning. If later your robot is allowed a more realistic double x, y; coordinate system, you could also change to use double currentDirection; and allow turns of a fraction of a degree. With enum, you'd lose this possible future flexibility.



          As an alternative, you might also consider using a directional vector:



          int dx=0, dy=1;   // currentDirection = 0°


          And move_forward simply becomes:



          x += dx;
          y += dy;


          And a turn right could become:



          int old_dx = dx;

          dx = dy;
          dy = -old_dx;





          share|improve this answer









          $endgroup$









          • 1




            $begingroup$
            This is solid advice. Personally I don't think an enum is a bad solution if we can assume the requirements aren't going to change.
            $endgroup$
            – Konrad Morawski
            1 hour ago














          2












          2








          2





          $begingroup$

          Initialization



          As written, your robot lander can land at any X,Y coordinate on your grid, but will always be facing in the positive Y-axis direction. This seems unreasonable. If wind, turbulence can cause a position uncertainty, which requires initializing the robot at a particular X,Y coordinate, it seems reasonable to assume it might also land in any facing.



          Robot() {
          this(0, 0, 0);
          }

          Robot(int x, int y) {
          this(x, y, 0);
          }

          Robot(int x, int y, int initial_facing) {
          // ...
          }




          Commands & Instructions



          Your instructions are a series of single letter commands, but you can't actually send a single command to the robot. You should separate the individual commands from the series of instructions. Something like:



          void turn_left() { ... }
          void turn_right() { ... }
          void move_forward() { ... }

          public void command(char command_letter) {
          switch (command_letter) {
          case 'L': turn_left(); break;
          case 'R': turn_right(); break;
          case 'F': move_forward(); break;
          default: throw new IllegalArgumentException("Invalid command: "+command_letter);
          }
          }

          public void instructions(String moves) {
          for (char command_letter : moves.toCharArray()) {
          command(command_letter);
          }
          }




          Where am I?



          position() returns a String containing the coordinates of the robot. If a control program wants to query the position of the robot, in order to determine what commands should be sent to send it to the desired location, it would need to parse that string back into integer values.



          Consider instead returning the actual integer positions, possibly like:



          public int[] position() {
          return new int[]{ x, y };
          }


          Alternately, you might want to create a class Position which can store the x,y location of the robot. Or you could use java.awt.Point



          public Point position() {
          return new Point(x, y);
          }


          Perhaps override the toString() method to return a human friendly description of the robot, including its position. Or maybe a position_as_string() method.



          Which way is the robot facing? Can't directly tell! You currently have to query the position(), then move("F"), followed by position(), and then compare the positions to determine which way the robot is facing! How about adding a facing() method?





          Learn how to write proper unit tests. For example, with JUnit5, you could write:



          import static org.junit.jupiter.api.Assertions.assertEquals;
          import org.junit.jupiter.api.Test;

          class RobotTests {

          private final Robot robot = new Robot();

          @Test
          void starts_at_origin() {
          assertEquals("0:0", robot.position());
          }

          @Test
          void move_forward_twice() {
          robot.move("FF");
          assertEquals("0:2", robot.position());
          }

          @Test
          void move_and_turn_right() {
          robot.move("FFRF");
          assertEquals("1:2", robot.position());
          }

          @Test
          void three_rights_make_a_left() {
          robot.move("FFRRRFF");
          assertEquals("-2:2", robot.position());
          }

          @Test
          void but_one_left_does_not() {
          robot.move("FFLFF");
          assertEquals("-2:2", robot.position());
          }
          }


          Notice that each test is run in a brand-new RobotTests instance, so you don't need to call robot.reset() between each.



          If you run this unit test, you'll find 4 of 5 tests pass, one test fails. I'll leave you to figure out why.





          Additional Concerns



          currentDirection taking on the values 0, 1, 2 and 3 to represent the 4 cardinal directions is limiting. If later, you want to add in diagonal moves (NW, SW, SE, or NE), would you use the values 4 and above to represent them? Or would you renumber the original 4 directions to be 0, 2, 4 and 6, and use 1, 3, 5, and 7 for the diagonal directions?



          You might be tempted to use an enum for the direction values, but I think that would be a bad idea. I would use 0, 90, 180, and 270 as direction values. These have physical meaning. If later your robot is allowed a more realistic double x, y; coordinate system, you could also change to use double currentDirection; and allow turns of a fraction of a degree. With enum, you'd lose this possible future flexibility.



          As an alternative, you might also consider using a directional vector:



          int dx=0, dy=1;   // currentDirection = 0°


          And move_forward simply becomes:



          x += dx;
          y += dy;


          And a turn right could become:



          int old_dx = dx;

          dx = dy;
          dy = -old_dx;





          share|improve this answer









          $endgroup$



          Initialization



          As written, your robot lander can land at any X,Y coordinate on your grid, but will always be facing in the positive Y-axis direction. This seems unreasonable. If wind, turbulence can cause a position uncertainty, which requires initializing the robot at a particular X,Y coordinate, it seems reasonable to assume it might also land in any facing.



          Robot() {
          this(0, 0, 0);
          }

          Robot(int x, int y) {
          this(x, y, 0);
          }

          Robot(int x, int y, int initial_facing) {
          // ...
          }




          Commands & Instructions



          Your instructions are a series of single letter commands, but you can't actually send a single command to the robot. You should separate the individual commands from the series of instructions. Something like:



          void turn_left() { ... }
          void turn_right() { ... }
          void move_forward() { ... }

          public void command(char command_letter) {
          switch (command_letter) {
          case 'L': turn_left(); break;
          case 'R': turn_right(); break;
          case 'F': move_forward(); break;
          default: throw new IllegalArgumentException("Invalid command: "+command_letter);
          }
          }

          public void instructions(String moves) {
          for (char command_letter : moves.toCharArray()) {
          command(command_letter);
          }
          }




          Where am I?



          position() returns a String containing the coordinates of the robot. If a control program wants to query the position of the robot, in order to determine what commands should be sent to send it to the desired location, it would need to parse that string back into integer values.



          Consider instead returning the actual integer positions, possibly like:



          public int[] position() {
          return new int[]{ x, y };
          }


          Alternately, you might want to create a class Position which can store the x,y location of the robot. Or you could use java.awt.Point



          public Point position() {
          return new Point(x, y);
          }


          Perhaps override the toString() method to return a human friendly description of the robot, including its position. Or maybe a position_as_string() method.



          Which way is the robot facing? Can't directly tell! You currently have to query the position(), then move("F"), followed by position(), and then compare the positions to determine which way the robot is facing! How about adding a facing() method?





          Learn how to write proper unit tests. For example, with JUnit5, you could write:



          import static org.junit.jupiter.api.Assertions.assertEquals;
          import org.junit.jupiter.api.Test;

          class RobotTests {

          private final Robot robot = new Robot();

          @Test
          void starts_at_origin() {
          assertEquals("0:0", robot.position());
          }

          @Test
          void move_forward_twice() {
          robot.move("FF");
          assertEquals("0:2", robot.position());
          }

          @Test
          void move_and_turn_right() {
          robot.move("FFRF");
          assertEquals("1:2", robot.position());
          }

          @Test
          void three_rights_make_a_left() {
          robot.move("FFRRRFF");
          assertEquals("-2:2", robot.position());
          }

          @Test
          void but_one_left_does_not() {
          robot.move("FFLFF");
          assertEquals("-2:2", robot.position());
          }
          }


          Notice that each test is run in a brand-new RobotTests instance, so you don't need to call robot.reset() between each.



          If you run this unit test, you'll find 4 of 5 tests pass, one test fails. I'll leave you to figure out why.





          Additional Concerns



          currentDirection taking on the values 0, 1, 2 and 3 to represent the 4 cardinal directions is limiting. If later, you want to add in diagonal moves (NW, SW, SE, or NE), would you use the values 4 and above to represent them? Or would you renumber the original 4 directions to be 0, 2, 4 and 6, and use 1, 3, 5, and 7 for the diagonal directions?



          You might be tempted to use an enum for the direction values, but I think that would be a bad idea. I would use 0, 90, 180, and 270 as direction values. These have physical meaning. If later your robot is allowed a more realistic double x, y; coordinate system, you could also change to use double currentDirection; and allow turns of a fraction of a degree. With enum, you'd lose this possible future flexibility.



          As an alternative, you might also consider using a directional vector:



          int dx=0, dy=1;   // currentDirection = 0°


          And move_forward simply becomes:



          x += dx;
          y += dy;


          And a turn right could become:



          int old_dx = dx;

          dx = dy;
          dy = -old_dx;






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 1 hour ago









          AJNeufeldAJNeufeld

          5,6141420




          5,6141420








          • 1




            $begingroup$
            This is solid advice. Personally I don't think an enum is a bad solution if we can assume the requirements aren't going to change.
            $endgroup$
            – Konrad Morawski
            1 hour ago














          • 1




            $begingroup$
            This is solid advice. Personally I don't think an enum is a bad solution if we can assume the requirements aren't going to change.
            $endgroup$
            – Konrad Morawski
            1 hour ago








          1




          1




          $begingroup$
          This is solid advice. Personally I don't think an enum is a bad solution if we can assume the requirements aren't going to change.
          $endgroup$
          – Konrad Morawski
          1 hour ago




          $begingroup$
          This is solid advice. Personally I don't think an enum is a bad solution if we can assume the requirements aren't going to change.
          $endgroup$
          – Konrad Morawski
          1 hour ago













          2












          $begingroup$

          I would consider refactoring direction into an enum, instead of a magic number. This would allow to encapsulate the related logic in this type.



          It might look like that:



              enum Direction {
          UP(0, 1),
          RIGHT(1, 0),
          DOWN(0, -1),
          LEFT(-1, 0);

          final int xVector;
          final int yVector;

          private final Direction FIRST = Direction.values()[0];
          private final Direction LAST = Direction.values()[Direction.values().length];

          Direction(int xVector, int yVector) {
          this.xVector = xVector;
          this.yVector = yVector;
          }

          Direction rotatedLeft() {
          return this == FIRST
          ? LAST // cycle complete
          : Direction.values()[ordinal() - 1]; // previous value
          }

          Direction rotatedRight() {
          return this == LAST
          ? FIRST // cycle complete
          : Direction.values()[ordinal() + 1]; // next value
          }
          }


          And then the Robot code becomes (including some subjective clean up, unrelated to the object-oriented aspect itself):



          class Robot {
          private int x;
          private int y;
          private Direction currentDirection;

          Robot() {
          this(0, 0);
          }

          Robot(int x, int y) {
          this.x = x;
          this.y = y;
          currentDirection = Direction.UP;
          }

          public void move(String moves) {
          for (char code : moves.toCharArray()) {
          // a matter of taste, I like to extract logic
          // out of looping constructs for clarity
          move(code);
          }
          }

          private void move(char code) {
          switch (code) {
          case 'R': {
          currentDirection = currentDirection.rotatedRight();
          break;
          }
          case 'L': {
          currentDirection = currentDirection.rotatedLeft();
          break;
          }
          case 'F': {
          // you'd call the println thing here.
          // as it's not part of the requirements I assumed it to be a debugging artifact
          this.x += currentDirection.xVector;
          this.y += currentDirection.yVector;
          break;
          }
          }
          }

          public void reset() {
          x = 0;
          y = 0;
          currentDirection = Direction.UP;
          }

          public String position() {
          return x + ":" + y;
          }
          }


          I think this is more object-oriented, and also an improvement.



          You could take it one step further and encapsulate the x and y coordinates in a little standalone class (Position). Like so:



              class Position {
          static final Position DEFAULT = new Position(0, 0);

          final int x;
          final int y;

          public Position(int x, int y) {
          this.x = x;
          this.y = y;
          }

          public Position movedInto(Direction direction) {
          return new Position(x + direction.xVector, y + direction.yVector);
          }

          @Override
          public String toString() {
          return x + ":" + y;
          }
          }


          Then in the Robot class you replace x and y fields with Position position, and you no longer recalculate the position in the Robot class, as you can simply go:



          case 'F': {
          position = position.movedInto(currentDirection);
          break;
          }


          in the move method.



          Plus:



              public void reset() {
          position = Position.DEFAULT;
          currentDirection = Direction.UP;
          }

          public String position() {
          return position.toString();
          }


          Yet another idea would be to encapsulate the move codes themselves into a class or classes. It's sometimes hard to say where to draw the line, as making code more and more OO comes at the cost of more boilerplate, and can be a form of overengineering.



          I admit I haven't tested my refactored version, I only approached the question in terms of code design.






          share|improve this answer











          $endgroup$













          • $begingroup$
            Since this is a programming-challenge, I like the Direction enum refactoring (+1), but for a future-friendly robot, I think enum Direction is a bad idea. (See my answer.)
            $endgroup$
            – AJNeufeld
            1 hour ago










          • $begingroup$
            Fixed the bug, thanks. The azimuth / alpha (I guess we could call it that?) is a neat alternative to an enum. An alpha value is more flexible as you pointed out, the cost is that recalculating x and y when the direction is, say, 270, won't look as straightforward. So I feel it's a tradeoff between explicity and flexibility.
            $endgroup$
            – Konrad Morawski
            1 hour ago


















          2












          $begingroup$

          I would consider refactoring direction into an enum, instead of a magic number. This would allow to encapsulate the related logic in this type.



          It might look like that:



              enum Direction {
          UP(0, 1),
          RIGHT(1, 0),
          DOWN(0, -1),
          LEFT(-1, 0);

          final int xVector;
          final int yVector;

          private final Direction FIRST = Direction.values()[0];
          private final Direction LAST = Direction.values()[Direction.values().length];

          Direction(int xVector, int yVector) {
          this.xVector = xVector;
          this.yVector = yVector;
          }

          Direction rotatedLeft() {
          return this == FIRST
          ? LAST // cycle complete
          : Direction.values()[ordinal() - 1]; // previous value
          }

          Direction rotatedRight() {
          return this == LAST
          ? FIRST // cycle complete
          : Direction.values()[ordinal() + 1]; // next value
          }
          }


          And then the Robot code becomes (including some subjective clean up, unrelated to the object-oriented aspect itself):



          class Robot {
          private int x;
          private int y;
          private Direction currentDirection;

          Robot() {
          this(0, 0);
          }

          Robot(int x, int y) {
          this.x = x;
          this.y = y;
          currentDirection = Direction.UP;
          }

          public void move(String moves) {
          for (char code : moves.toCharArray()) {
          // a matter of taste, I like to extract logic
          // out of looping constructs for clarity
          move(code);
          }
          }

          private void move(char code) {
          switch (code) {
          case 'R': {
          currentDirection = currentDirection.rotatedRight();
          break;
          }
          case 'L': {
          currentDirection = currentDirection.rotatedLeft();
          break;
          }
          case 'F': {
          // you'd call the println thing here.
          // as it's not part of the requirements I assumed it to be a debugging artifact
          this.x += currentDirection.xVector;
          this.y += currentDirection.yVector;
          break;
          }
          }
          }

          public void reset() {
          x = 0;
          y = 0;
          currentDirection = Direction.UP;
          }

          public String position() {
          return x + ":" + y;
          }
          }


          I think this is more object-oriented, and also an improvement.



          You could take it one step further and encapsulate the x and y coordinates in a little standalone class (Position). Like so:



              class Position {
          static final Position DEFAULT = new Position(0, 0);

          final int x;
          final int y;

          public Position(int x, int y) {
          this.x = x;
          this.y = y;
          }

          public Position movedInto(Direction direction) {
          return new Position(x + direction.xVector, y + direction.yVector);
          }

          @Override
          public String toString() {
          return x + ":" + y;
          }
          }


          Then in the Robot class you replace x and y fields with Position position, and you no longer recalculate the position in the Robot class, as you can simply go:



          case 'F': {
          position = position.movedInto(currentDirection);
          break;
          }


          in the move method.



          Plus:



              public void reset() {
          position = Position.DEFAULT;
          currentDirection = Direction.UP;
          }

          public String position() {
          return position.toString();
          }


          Yet another idea would be to encapsulate the move codes themselves into a class or classes. It's sometimes hard to say where to draw the line, as making code more and more OO comes at the cost of more boilerplate, and can be a form of overengineering.



          I admit I haven't tested my refactored version, I only approached the question in terms of code design.






          share|improve this answer











          $endgroup$













          • $begingroup$
            Since this is a programming-challenge, I like the Direction enum refactoring (+1), but for a future-friendly robot, I think enum Direction is a bad idea. (See my answer.)
            $endgroup$
            – AJNeufeld
            1 hour ago










          • $begingroup$
            Fixed the bug, thanks. The azimuth / alpha (I guess we could call it that?) is a neat alternative to an enum. An alpha value is more flexible as you pointed out, the cost is that recalculating x and y when the direction is, say, 270, won't look as straightforward. So I feel it's a tradeoff between explicity and flexibility.
            $endgroup$
            – Konrad Morawski
            1 hour ago
















          2












          2








          2





          $begingroup$

          I would consider refactoring direction into an enum, instead of a magic number. This would allow to encapsulate the related logic in this type.



          It might look like that:



              enum Direction {
          UP(0, 1),
          RIGHT(1, 0),
          DOWN(0, -1),
          LEFT(-1, 0);

          final int xVector;
          final int yVector;

          private final Direction FIRST = Direction.values()[0];
          private final Direction LAST = Direction.values()[Direction.values().length];

          Direction(int xVector, int yVector) {
          this.xVector = xVector;
          this.yVector = yVector;
          }

          Direction rotatedLeft() {
          return this == FIRST
          ? LAST // cycle complete
          : Direction.values()[ordinal() - 1]; // previous value
          }

          Direction rotatedRight() {
          return this == LAST
          ? FIRST // cycle complete
          : Direction.values()[ordinal() + 1]; // next value
          }
          }


          And then the Robot code becomes (including some subjective clean up, unrelated to the object-oriented aspect itself):



          class Robot {
          private int x;
          private int y;
          private Direction currentDirection;

          Robot() {
          this(0, 0);
          }

          Robot(int x, int y) {
          this.x = x;
          this.y = y;
          currentDirection = Direction.UP;
          }

          public void move(String moves) {
          for (char code : moves.toCharArray()) {
          // a matter of taste, I like to extract logic
          // out of looping constructs for clarity
          move(code);
          }
          }

          private void move(char code) {
          switch (code) {
          case 'R': {
          currentDirection = currentDirection.rotatedRight();
          break;
          }
          case 'L': {
          currentDirection = currentDirection.rotatedLeft();
          break;
          }
          case 'F': {
          // you'd call the println thing here.
          // as it's not part of the requirements I assumed it to be a debugging artifact
          this.x += currentDirection.xVector;
          this.y += currentDirection.yVector;
          break;
          }
          }
          }

          public void reset() {
          x = 0;
          y = 0;
          currentDirection = Direction.UP;
          }

          public String position() {
          return x + ":" + y;
          }
          }


          I think this is more object-oriented, and also an improvement.



          You could take it one step further and encapsulate the x and y coordinates in a little standalone class (Position). Like so:



              class Position {
          static final Position DEFAULT = new Position(0, 0);

          final int x;
          final int y;

          public Position(int x, int y) {
          this.x = x;
          this.y = y;
          }

          public Position movedInto(Direction direction) {
          return new Position(x + direction.xVector, y + direction.yVector);
          }

          @Override
          public String toString() {
          return x + ":" + y;
          }
          }


          Then in the Robot class you replace x and y fields with Position position, and you no longer recalculate the position in the Robot class, as you can simply go:



          case 'F': {
          position = position.movedInto(currentDirection);
          break;
          }


          in the move method.



          Plus:



              public void reset() {
          position = Position.DEFAULT;
          currentDirection = Direction.UP;
          }

          public String position() {
          return position.toString();
          }


          Yet another idea would be to encapsulate the move codes themselves into a class or classes. It's sometimes hard to say where to draw the line, as making code more and more OO comes at the cost of more boilerplate, and can be a form of overengineering.



          I admit I haven't tested my refactored version, I only approached the question in terms of code design.






          share|improve this answer











          $endgroup$



          I would consider refactoring direction into an enum, instead of a magic number. This would allow to encapsulate the related logic in this type.



          It might look like that:



              enum Direction {
          UP(0, 1),
          RIGHT(1, 0),
          DOWN(0, -1),
          LEFT(-1, 0);

          final int xVector;
          final int yVector;

          private final Direction FIRST = Direction.values()[0];
          private final Direction LAST = Direction.values()[Direction.values().length];

          Direction(int xVector, int yVector) {
          this.xVector = xVector;
          this.yVector = yVector;
          }

          Direction rotatedLeft() {
          return this == FIRST
          ? LAST // cycle complete
          : Direction.values()[ordinal() - 1]; // previous value
          }

          Direction rotatedRight() {
          return this == LAST
          ? FIRST // cycle complete
          : Direction.values()[ordinal() + 1]; // next value
          }
          }


          And then the Robot code becomes (including some subjective clean up, unrelated to the object-oriented aspect itself):



          class Robot {
          private int x;
          private int y;
          private Direction currentDirection;

          Robot() {
          this(0, 0);
          }

          Robot(int x, int y) {
          this.x = x;
          this.y = y;
          currentDirection = Direction.UP;
          }

          public void move(String moves) {
          for (char code : moves.toCharArray()) {
          // a matter of taste, I like to extract logic
          // out of looping constructs for clarity
          move(code);
          }
          }

          private void move(char code) {
          switch (code) {
          case 'R': {
          currentDirection = currentDirection.rotatedRight();
          break;
          }
          case 'L': {
          currentDirection = currentDirection.rotatedLeft();
          break;
          }
          case 'F': {
          // you'd call the println thing here.
          // as it's not part of the requirements I assumed it to be a debugging artifact
          this.x += currentDirection.xVector;
          this.y += currentDirection.yVector;
          break;
          }
          }
          }

          public void reset() {
          x = 0;
          y = 0;
          currentDirection = Direction.UP;
          }

          public String position() {
          return x + ":" + y;
          }
          }


          I think this is more object-oriented, and also an improvement.



          You could take it one step further and encapsulate the x and y coordinates in a little standalone class (Position). Like so:



              class Position {
          static final Position DEFAULT = new Position(0, 0);

          final int x;
          final int y;

          public Position(int x, int y) {
          this.x = x;
          this.y = y;
          }

          public Position movedInto(Direction direction) {
          return new Position(x + direction.xVector, y + direction.yVector);
          }

          @Override
          public String toString() {
          return x + ":" + y;
          }
          }


          Then in the Robot class you replace x and y fields with Position position, and you no longer recalculate the position in the Robot class, as you can simply go:



          case 'F': {
          position = position.movedInto(currentDirection);
          break;
          }


          in the move method.



          Plus:



              public void reset() {
          position = Position.DEFAULT;
          currentDirection = Direction.UP;
          }

          public String position() {
          return position.toString();
          }


          Yet another idea would be to encapsulate the move codes themselves into a class or classes. It's sometimes hard to say where to draw the line, as making code more and more OO comes at the cost of more boilerplate, and can be a form of overengineering.



          I admit I haven't tested my refactored version, I only approached the question in terms of code design.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 1 hour ago

























          answered 1 hour ago









          Konrad MorawskiKonrad Morawski

          1,708710




          1,708710












          • $begingroup$
            Since this is a programming-challenge, I like the Direction enum refactoring (+1), but for a future-friendly robot, I think enum Direction is a bad idea. (See my answer.)
            $endgroup$
            – AJNeufeld
            1 hour ago










          • $begingroup$
            Fixed the bug, thanks. The azimuth / alpha (I guess we could call it that?) is a neat alternative to an enum. An alpha value is more flexible as you pointed out, the cost is that recalculating x and y when the direction is, say, 270, won't look as straightforward. So I feel it's a tradeoff between explicity and flexibility.
            $endgroup$
            – Konrad Morawski
            1 hour ago




















          • $begingroup$
            Since this is a programming-challenge, I like the Direction enum refactoring (+1), but for a future-friendly robot, I think enum Direction is a bad idea. (See my answer.)
            $endgroup$
            – AJNeufeld
            1 hour ago










          • $begingroup$
            Fixed the bug, thanks. The azimuth / alpha (I guess we could call it that?) is a neat alternative to an enum. An alpha value is more flexible as you pointed out, the cost is that recalculating x and y when the direction is, say, 270, won't look as straightforward. So I feel it's a tradeoff between explicity and flexibility.
            $endgroup$
            – Konrad Morawski
            1 hour ago


















          $begingroup$
          Since this is a programming-challenge, I like the Direction enum refactoring (+1), but for a future-friendly robot, I think enum Direction is a bad idea. (See my answer.)
          $endgroup$
          – AJNeufeld
          1 hour ago




          $begingroup$
          Since this is a programming-challenge, I like the Direction enum refactoring (+1), but for a future-friendly robot, I think enum Direction is a bad idea. (See my answer.)
          $endgroup$
          – AJNeufeld
          1 hour ago












          $begingroup$
          Fixed the bug, thanks. The azimuth / alpha (I guess we could call it that?) is a neat alternative to an enum. An alpha value is more flexible as you pointed out, the cost is that recalculating x and y when the direction is, say, 270, won't look as straightforward. So I feel it's a tradeoff between explicity and flexibility.
          $endgroup$
          – Konrad Morawski
          1 hour ago






          $begingroup$
          Fixed the bug, thanks. The azimuth / alpha (I guess we could call it that?) is a neat alternative to an enum. An alpha value is more flexible as you pointed out, the cost is that recalculating x and y when the direction is, say, 270, won't look as straightforward. So I feel it's a tradeoff between explicity and flexibility.
          $endgroup$
          – Konrad Morawski
          1 hour ago




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214669%2fpredict-mars-robot-position%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Cannot install PyQt5 The Next CEO of Stack OverflowCannot install tcpreplay 3.4.4cannot...

          Kapp-Putsch Acontecimentos | Outros artigos | Menu de navegação

          Why did early computer designers eschew integers? The Next CEO of Stack OverflowWhat register...