title: How could we refactor two related logics which are part of the same algorithm, into two separate methods?
body: <p>I am doing the following programming exercise: <a href="https://www.codewars.com/kata/5d0ae91acac0a50232e8a547" rel="nofollow noreferrer">Traffic Lights - one car</a>. Its statement is:</p>
  
  <blockquote>
    <p>Overview</p>
    
    <p>A character string represents a city road.</p>
    
    <p>Cars travel on the road obeying the traffic lights..</p>
    
    <p>Legend:</p>
  
  <pre><code>. = Road
  C = Car
  G = GREEN traffic light
  O = ORANGE traffic light
  R = RED traffic light
  </code></pre>
    
    <p>Something like this: C...R............G......</p>
    
    <p>Rules Simulation</p>
    
    <p>At each iteration:</p>
  
  <pre><code>the lights change, according to the traffic light rules... then
  the car moves, obeying the car rules
  </code></pre>
    
    <p>Traffic Light Rules</p>
    
    <p>Traffic lights change colour as follows:</p>
  
  <pre><code>GREEN for 5 time units... then
  ORANGE for 1 time unit... then
  RED for 5 time units....
  ... and repeat the cycle
  </code></pre>
    
    <p>Car Rules</p>
  
  <pre><code>Cars travel left to right on the road, moving 1 character position per time unit
  
  Cars can move freely until they come to a traffic light. Then:
      if the light is GREEN they can move forward (temporarily occupying the same cell as the light)
      if the light is ORANGE then they must stop (if they have already entered the intersection they can continue through)
      if the light is RED the car must stop until the light turns GREEN again
  </code></pre>
    
    <p>Kata Task</p>
    
    <p>Given the initial state of the road, return the states for all
    iterations of the simiulation. Input</p>
  
  <pre><code>road = the road array
  n = how many time units to simulate (n &gt;= 0)
  </code></pre>
    
    <p>Output</p>
  
  <pre><code>An array containing the road states at every iteration (including the initial state)
      Note: If a car occupies the same position as a traffic light then show only the car
  </code></pre>
    
    <p>Notes</p>
  
  <pre><code>There is only one car
  For the initial road state
      the car is always at the first character position
      traffic lights are either GREEN or RED, and are at the beginning of their countdown cycles
  There are no reaction delays - when the lights change the car drivers will react immediately!
  If the car goes off the end of the road it just disappears from view
  There will always be some road between adjacent traffic lights
  </code></pre>
    
    <p>Example</p>
    
    <p>Run simulation for 10 time units</p>
    
    <p>Input</p>
  
  <pre><code>road = "C...R............G......"
  n = 10
  </code></pre>
    
    <p>Result</p>
  
  <pre><code>    [   "C...R............G......", // 0 initial state as passed  
      ".C..R............G......", // 1
     "..C.R............G......", // 2  
      "...CR............G......", // 3
     "...CR............G......", // 4  
      "....C............O......", // 5 show the car, not the light  
      "....GC...........R......", // 6
     "....G.C..........R......", // 7  
      "....G..C.........R......", // 8
     "....G...C........R......", // 9  
      "....O....C.......R......"  // 10 ]
  </code></pre>
  </blockquote>
  
  <p>First I have written the following code:</p>
  
  <pre><code>public class Dinglemouse {
    public static String[] trafficLights/**/(String road, int n) {
      System.out.println("\n\nroad: "+road);
      System.out.println("\nn: "+n);
      String[] items = road.split("");
      int semaphoreTimeUnits = 0;
      boolean carHasMovedThisIteration = false;
      String hiddenSemaphore = "";
      String[] iterations = new String[n+1]; iterations[0] = road;
  
      for(int i = 0; i &lt; n; i++, semaphoreTimeUnits++){
        //System.out.println("i: "+i);
        for(int j = 0; j &lt; items.length - 2; j++){
          //System.out.println("j: "+j);
          //System.out.println("semaphoreTimeUnits: "+semaphoreTimeUnits);
          if(items[j].equals("C") &amp;&amp; !carHasMovedThisIteration &amp;&amp; !items[j+1].equals("R")){
            if(hiddenSemaphore.equals("")){
              items[j] = ".";
            }else{
              if(hiddenSemaphore.equals("O")){
                if(road.charAt(j) == 'R'){
                  items[j] = "G";
                }else if(road.charAt(j) == 'G'){
                  items[j] = "R";
                }else{
                  items[j] = hiddenSemaphore;
                }
              }
              hiddenSemaphore = "";
            }
            if(!items[j+1].equals(".")){
              hiddenSemaphore = items[j+1];
            }
          items[j+1] = "C";
          carHasMovedThisIteration = true;
          }
          if(items[j+2].equals("R") &amp;&amp; road.charAt(j+2) == 'R' &amp;&amp; semaphoreTimeUnits &gt;= 4
          || items[j+2].equals("G") &amp;&amp; road.charAt(j+2) == 'G' &amp;&amp; semaphoreTimeUnits &gt;= 4){
            items[j+2] = "O";    
          }
          if(items[j+2].equals("O") &amp;&amp; semaphoreTimeUnits &gt;= 5){
            if(road.charAt(j+2) == 'R'){
              items[j+2] = "G";    
            }else if(road.charAt(j+2) == 'G'){
              items[j+2] = "R";  
            }
          }
          if((items[j+2].equals("G") || items[j+2].equals("R")) &amp;&amp; semaphoreTimeUnits &gt;= 10){
            items[j+2] = String.valueOf(road.charAt(j+2));    
            semaphoreTimeUnits = 0;
          }
          //System.out.println("items: "+String.join("", items));
        }
        iterations[i+1] = String.join("", items);
        System.out.println("items: "+String.join("", items));
        carHasMovedThisIteration = false;
      }
      return iterations;
    }
  }
  </code></pre>
  
  <p>And the test (extracted from the exercise)</p>
  
  <pre><code>import org.junit.Test;
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.fail;
  
  
  public class ExampleTests {
  
    private static void doTest(String initial, String[] expected, int n) {
      String got[] = Dinglemouse.trafficLights(initial, n);
      assertEquals("Result array length", expected.length, got.length);
  
      int errIdx = -1;
      for (int i = 0; i &lt; got.length; i++) {
        if (!expected[i].equals(got[i])) { errIdx = i; break; }
      }
  
      System.out.println("Expected:");
      for (int i = 0; i &lt; expected.length; i++) {
        System.out.println(String.format("%03d %s", i, Common.display(expected[i])));
      }
  
      if (errIdx &gt;= 0) {
        System.out.println("\nYour result:");
        for (int i = 0; i &lt; got.length; i++) {
          System.out.println(String.format("%03d %s", i, Common.display(got[i])));
        }
        fail(String.format("A difference was detected at index %d", errIdx));
      }
    }
  
    @Test
    public void example() {
      int n = 10;
      String sim[] = {
        "C...R............G......",  // 0
        ".C..R............G......",  // 1
        "..C.R............G......",  // 2
        "...CR............G......",  // 3
        "...CR............G......",  // 4
        "....C............O......",  // 5
        "....GC...........R......",  // 6
        "....G.C..........R......",  // 7
        "....G..C.........R......",  // 8
        "....G...C........R......",  // 9
        "....O....C.......R......"   // 10
      };
      doTest(sim[0], sim, n);
    }
  
  }
  </code></pre>
  
  <p>Expected is:</p>
  
  <pre><code>Expected:
  000 C...R............G......
  001 .C..R............G......
  002 ..C.R............G......
  003 ...CR............G......
  004 ...CR............G......
  005 ....C............O......
  006 ....GC...........R......
  007 ....G.C..........R......
  008 ....G..C.........R......
  009 ....G...C........R......
  010 ....O....C.......R......
  </code></pre>
  
  <p>The code output is:</p>
  
  <p>Your result:</p>
  
  <pre><code>000 C...R............G......
  001 .C..R............G......
  002 ..C.R............G......
  003 ...CR............G......
  004 ...CR............G......
  005 ....C............O......
  006 ....GC...........R......
  007 ....G.C..........R......
  008 ....G..C.........R......
  009 ....G...C........R......
  010 ....G....C.......R......
  </code></pre>
  
  <p>So then as you will notice:</p>
  
  <pre><code>A difference was detected at index 10
  </code></pre>
  
  <p>Because of it expects an O instead of the G, at index 10.</p>
  
  <p>1) How do we achieve that the car when is at an orange traffic light, the next 4 iterations it shows a green light, instead of the next 5 ones, as is being printed now.</p>
  
  <p>2) How could we <strong>refactor</strong>, simplify the code, to separate car movement logic, and traffic ligths logic.</p>
  
  <p>I have tried to extract car movement logic as:</p>
  
  <pre><code>public class Dinglemouse {
    public static String[] trafficLights/**/(String road, int n) {
      System.out.println("\n\nroad: "+road);
      System.out.println("\nn: "+n);
      String[] items = road.split("");
      int semaphoreTimeUnits = 0;
      boolean carHasMovedThisIteration = false;
      String hiddenSemaphore = "";
      String[] iterations = new String[n+1]; iterations[0] = road;
  
      for(int i = 0; i &lt; n; i++, semaphoreTimeUnits++){
        //System.out.println("i: "+i);
        for(int j = 0; j &lt; items.length - 2; j++){
          //System.out.println("j: "+j);
          //System.out.println("semaphoreTimeUnits: "+semaphoreTimeUnits);
  
          simulateCarMovement(j, items, carHasMovedThisIteration, hiddenSemaphore, road);
  
          if(items[j+2].equals("R") &amp;&amp; road.charAt(j+2) == 'R' &amp;&amp; semaphoreTimeUnits &gt;= 4
          || items[j+2].equals("G") &amp;&amp; road.charAt(j+2) == 'G' &amp;&amp; semaphoreTimeUnits &gt;= 4){
            items[j+2] = "O";    
          }
          if(items[j+2].equals("O") &amp;&amp; semaphoreTimeUnits &gt;= 5){
            if(road.charAt(j+2) == 'R'){
              items[j+2] = "G";    
            }else if(road.charAt(j+2) == 'G'){
              items[j+2] = "R";  
            }
          }
          if((items[j+2].equals("G") || items[j+2].equals("R")) &amp;&amp; semaphoreTimeUnits &gt;= 10){
            items[j+2] = String.valueOf(road.charAt(j+2));    
            semaphoreTimeUnits = 0;
          }
          //System.out.println("items: "+String.join("", items));
        }
        iterations[i+1] = String.join("", items);
        System.out.println("items: "+String.join("", items));
        carHasMovedThisIteration = false;
      }
      return iterations;
    }
  
  
    static void simulateCarMovement(int j, String[] items, boolean carHasMovedThisIteration, String hiddenSemaphore, String road){
      if(items[j].equals("C") &amp;&amp; !carHasMovedThisIteration &amp;&amp; !items[j+1].equals("R")){
        if(hiddenSemaphore.equals("")){
          items[j] = ".";
        }else{
          if(hiddenSemaphore.equals("O")){
            if(road.charAt(j) == 'R'){
              items[j] = "G";
            }else if(road.charAt(j) == 'G'){
              items[j] = "R";
            }else{
              items[j] = hiddenSemaphore;
            }
          }
          hiddenSemaphore = "";
        }
        if(!items[j+1].equals(".")){
          hiddenSemaphore = items[j+1];
        }
      items[j+1] = "C";
      carHasMovedThisIteration = true;
      }
    }
  }
  </code></pre>
  
  <p>However I think we have some difficulties with the variables being passed into the simulateCarMovement method, because of they are not being returned. So then the output for this refactored code would be:</p>
  
  <pre><code>Expected:
  000 C...R............G......
  001 .C..R............G......
  002 ..C.R............G......
  003 ...CR............G......
  004 ...CR............G......
  005 ....C............O......
  006 ....GC...........R......
  007 ....G.C..........R......
  008 ....G..C.........R......
  009 ....G...C........R......
  010 ....O....C.......R......
  
  Your result:
  000 C...R............G......
  001 ...CR............G......
  002 ...CR............G......
  003 ...CR............G......
  004 ...CR............G......
  005 ......................C.
  006 ......................C.
  007 ......................C.
  008 ......................C.
  009 ......................C.
  010 ......................C.
  
  A difference was detected at index 1
  </code></pre>
  
  <p>I have also read:</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/43086489/how-refactor-two-methods-which-are-very-similar">How refactor two methods which are very similar</a></li>
  <li><a href="https://stackoverflow.com/questions/37124323/i-have-two-methods-which-are-nearly-the-same-how-to-refactor-them">I have two methods which are nearly the same, how to refactor them?</a></li>
  </ul>
  
  <p>How could we refactor two related logics which are part of the same algorithm, into two separate methods?</p>