Find shortest sequence of mathematical operations










2















I'm mathematically trying to determine the shortest sequence of moves to reach a desired numerical result. I have two functions, both of which multiply a number by 2, and minus the value of the other number.



I've included my code so far, which has me manually calling the two functions to obtain the desired result; however, I would like help figuring out the logic to do this automatically with a loop.






function findShortestSequence(number) 
let left = 0;
let right = 1;
let moves = ;

const moveLeft = () =>
moves.push('L');
left = 2 * left - right;


const moveRight = () =>
moves.push('R');
right = 2 * right - left;


moveLeft();
moveLeft();
moveRight();
moveLeft();

console.log(left, right, moves);


findShortestSequence(-11)












share|improve this question




























    2















    I'm mathematically trying to determine the shortest sequence of moves to reach a desired numerical result. I have two functions, both of which multiply a number by 2, and minus the value of the other number.



    I've included my code so far, which has me manually calling the two functions to obtain the desired result; however, I would like help figuring out the logic to do this automatically with a loop.






    function findShortestSequence(number) 
    let left = 0;
    let right = 1;
    let moves = ;

    const moveLeft = () =>
    moves.push('L');
    left = 2 * left - right;


    const moveRight = () =>
    moves.push('R');
    right = 2 * right - left;


    moveLeft();
    moveLeft();
    moveRight();
    moveLeft();

    console.log(left, right, moves);


    findShortestSequence(-11)












    share|improve this question


























      2












      2








      2


      4






      I'm mathematically trying to determine the shortest sequence of moves to reach a desired numerical result. I have two functions, both of which multiply a number by 2, and minus the value of the other number.



      I've included my code so far, which has me manually calling the two functions to obtain the desired result; however, I would like help figuring out the logic to do this automatically with a loop.






      function findShortestSequence(number) 
      let left = 0;
      let right = 1;
      let moves = ;

      const moveLeft = () =>
      moves.push('L');
      left = 2 * left - right;


      const moveRight = () =>
      moves.push('R');
      right = 2 * right - left;


      moveLeft();
      moveLeft();
      moveRight();
      moveLeft();

      console.log(left, right, moves);


      findShortestSequence(-11)












      share|improve this question
















      I'm mathematically trying to determine the shortest sequence of moves to reach a desired numerical result. I have two functions, both of which multiply a number by 2, and minus the value of the other number.



      I've included my code so far, which has me manually calling the two functions to obtain the desired result; however, I would like help figuring out the logic to do this automatically with a loop.






      function findShortestSequence(number) 
      let left = 0;
      let right = 1;
      let moves = ;

      const moveLeft = () =>
      moves.push('L');
      left = 2 * left - right;


      const moveRight = () =>
      moves.push('R');
      right = 2 * right - left;


      moveLeft();
      moveLeft();
      moveRight();
      moveLeft();

      console.log(left, right, moves);


      findShortestSequence(-11)








      function findShortestSequence(number) 
      let left = 0;
      let right = 1;
      let moves = ;

      const moveLeft = () =>
      moves.push('L');
      left = 2 * left - right;


      const moveRight = () =>
      moves.push('R');
      right = 2 * right - left;


      moveLeft();
      moveLeft();
      moveRight();
      moveLeft();

      console.log(left, right, moves);


      findShortestSequence(-11)





      function findShortestSequence(number) 
      let left = 0;
      let right = 1;
      let moves = ;

      const moveLeft = () =>
      moves.push('L');
      left = 2 * left - right;


      const moveRight = () =>
      moves.push('R');
      right = 2 * right - left;


      moveLeft();
      moveLeft();
      moveRight();
      moveLeft();

      console.log(left, right, moves);


      findShortestSequence(-11)






      javascript algorithm






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 13 '18 at 10:58







      AnonymousSB

















      asked Nov 13 '18 at 10:27









      AnonymousSBAnonymousSB

      2,229221




      2,229221






















          5 Answers
          5






          active

          oldest

          votes


















          3














          I was just looking at -11, and considering 11 being 1011 in binary, which resembles your manual solution of LLRL, just backwards. Tests suggest that this may be the key for negative numbers: get their absolute value, and start shifting towards the right until it becomes zero. When you shift out an 1, move to the left, when you shift out a 0, move to the right. The last step will be a left-move, and the result goes into left.

          Then I just checked what about positive numbers, simply swapping the moves (because leaving them in place would provide the negative result) and it appeared to generate one number above the goal. So I just subtracted one from the original and it started to work. Of course this time the last step is going to be a right-move, and result goes into right:






          function findShortestSequence(number) (org==right));


          for(var i=-20;i<=20;i++)
          findShortestSequence(i);





          While I do not chase to provide a full explanation, I can provide some pieces which one may find useful:



          • the "subtract 1 if positive" part feels like creating anti-two's complement number (in two's complement, in case of positive number you do not do anything, and in case of negative number you get its positive pair, invert its bits, and add 1 to the result)

          • from a distance the "multiply by 2 and do a fix" is not that extreme:

            if one somehow ends up with 10001001 (137) and 1001 is the fixer, then multiply by 2 shifts everything to the left (100010010, 274), and if you want to keep that 0001001 part in its original place, subtracting the fixer "locally divides" that part back to its original place (100010010-1001=100001001), this is more or less what moveRight does to positive numbers

          • updating the fixer is more convoluted, though some parts of it do resemble the previous idea: 2*1001 becomes 10010, and subtracting 10001001 fixes back 1001 on the lower places, and also introduces that 1 from the beginning at high places. The nasty part is that 10001001 is clearly larger than 10010, so the result is a negative number, and in fact the fixer (left in case of a positive target number) has never been 1001, because at its very first update ever, it becomes "2*0-something" (where "something" is a positive number, as right starts from 1). Indeed, looking at the example loop, left always seems to end up being non-positive, and right seems to be non-negative

          • the anti-two's complement thing also uglifies the picture, it may be cleaner to think about negative target numbers first, as there the fixer (right) is non-negative, and positive*2-negative also stays positive:
            ...11110001001 (left) and 1001 (right), ...11110001001*2 is ...111100010010, and ...111100010010-1001=...111100001001, first part of the mission is accomplished (keeping the 1001 pattern in place)

            and if the goal is to have ...1110010001001 later (after 2 moveLeft-s), then moveRight really does 1001*2=10010, 10010-...11110001001(-119)=10001001, which is exactly what is needed to extend the 1001 pattern into 10001001 for the 8 lowest places)

          • about being "shortest": the fastest growing part is moveRight, if left remains 0 all the time, right jumps to the next power of two each step, so ceil(log2(number)) steps are needed to reach or surpass the given number, which equals to the number of significant binary digits required represent the number, which equals the steps taken by the loop.





          share|improve this answer

























          • That is a great observation about using bitwise operators. One slight modification I've made is to get rid of the if(org <= 0) statement, and replace the moveLeft() and moveRight() with ternaries.

            – AnonymousSB
            Nov 13 '18 at 21:27











          • @AnonymousSB as I had some doubts about the "look, it is easy" explanation in the other answer, so added some thoughts about what is happening inside

            – tevemadar
            Nov 14 '18 at 12:35











          • Caleb Lucas' answer seems to me to fail with positive numbers. Am I misreading it? For example, any power of 2 would include an 'L', when clearly we only need R's. And testing just for 3 and -3 returns LL for both. How could that be?

            – גלעד ברקן
            Nov 14 '18 at 15:25











          • @גלעדברקן That answer is simply wrong for positive numbers: returns the sequence producing the corresponding negative number, just mirrored. It fails to work starting from 1, which should result in an empty sequence, as right=1 already (same as for 0, since left=0 already)

            – tevemadar
            Nov 14 '18 at 15:56











          • @AnonymousSB this solution is far longer than the short one exactly because it does the calculation too. Unfortunately I did not think that adding (org==left)||(org==right) into the log-line was an absolute necessity.

            – tevemadar
            Nov 15 '18 at 22:03


















          1














          I think I came to the same conclusion as tevemadar. Here it is in code:






          function confirm(str, n)
          let l = 0;
          let r = 1;
          let i = 0;

          while(str[i])
          if (str[i++] == 'L')
          l = 2*l - r;
          else
          r = 2*r - l;


          if ([l, r].includes(n))
          return true;

          return false;


          function f(n)
          if ([0, 1].includes(n))
          return '';
          else if (n > 1)
          return (n - 1)
          .toString(2)
          .split('')
          .map(x => x & 1 ? 'R' : 'L')
          .reverse()
          .join('');
          else
          return (-n)
          .toString(2)
          .split('')
          .map(x => x & 1 ? 'L' : 'R')
          .reverse()
          .join('');


          for (let i=-11; i<=11; i++)
          fi = f(i);
          console.log(i + ': ' + fi + ', ' + confirm(fi, i));








          share|improve this answer























          • While at least the faulty accepted answer is completely gone, I remain being puzzled why it is so important for OP to accept an answer which is a different one from mine...

            – tevemadar
            Nov 15 '18 at 16:19












          • I accepted this answer because the confirm function provided shows that it generates the correct moves, unless there is something I’m missing?

            – AnonymousSB
            Nov 15 '18 at 19:20


















          0














          You could take an iterative approach with a stack for the next state for checking the result.



          This approach tests the smallest amount of changes first and then takes a growing count of possibilities.






          function findShortestSequence(number) 
          const
          moveLeft = (left, right, moves) => [left * 2 - right, right, [...moves, 'L']],
          moveRight = (left, right, moves) => [left, right * 2 - left, [...moves, 'R']],
          functions = [moveLeft, moveRight];

          var stack = [[0, 1, ]],
          left, right, moves;

          while ([left, right, moves] = stack.shift())
          if (left === number) return moves;
          functions.forEach(fn => stack.push(fn(left, right, moves)));



          console.log(findShortestSequence(-11));

          .as-console-wrapper max-height: 100% !important; top: 0; 








          share|improve this answer
































            0














            Yes, I also completely agree with myself, and find my hint useful (ok, that answer is gone).

            If verification is not needed, generating the steps is this simple:






            function getSequence(n)

            for(var i=-20;i<=20;i++)
            console.log(i,getSequence(i));

            .as-console-wrapper max-height: 100% !important; top: 0; 








            share|improve this answer























            • I really do appreciate your effort, and original observation about it being binary. This solution is much more succinct to @גלעדברקן's answer, and provides the same results. Quite smart to swap the steps ahead of time. Given that the max binary has a length of 31, I don't see any major issues with the time complexity; however, you could use cut down on one pass with this replace instead .replace(/0|1/g, match => match === '0' ? steps[0] : steps[1])

              – AnonymousSB
              Nov 15 '18 at 21:03


















            0














            EDIT: Since we have a correct and proper solution to this question, the pattern of mirroring as applied in CommandBuilder for positive integers is a misconception and should have never been used: it generates duplicate command strings for some integers. Please see CommandBuilderTwo for a more appropriate solution.




            Given the fact that L = 0 and R = 1, we can convert the desired decimal number, P, into binary and store each digit inversely as 1 for L and 0 for R when negative



            Let us also take these factors into consideration. For any given number P:



            1. P could be a positive number that is the result of (2 ^ N); where 0 < N <= 32

            2. P could be a positive number that is the result of (2 ^ N) - 1; where 0 < N <= 32

            3. P could be any other positive number

            4. P could be any negative number

            We can efficiently determine the commands required to build the inputted desired number using the following solution:



            public class CommandBuilder 

            private static String getCommand(long N)


            private static boolean isPowerOfTwo(long val)
            return (int) Math.ceil( Math.log(val) / Math.log(2))
            == (int) Math.floor(Math.log(val) / Math.log(2));


            private static boolean isPowerOfTwoMinusOne(long val)
            int root = (int) Math.ceil(Math.log(val) / Math.log(2));
            return Math.pow(2, root) - 1 == val;


            //Driver method
            public static void main(String args)

            for(int i = 0; i <= 25; i++)
            System.out.println("The command required to produce " + i + ": " + getCommand(i) );
            System.out.println("The command required to produce -" + i + ": " + getCommand(-i) );


            int edge = Integer.MAX_VALUE;
            System.out.println("The command required to produce " + edge + ": " + getCommand(edge) );
            System.out.println("The command required to produce -" + edge + ": " + getCommand(-edge) );






            This is a solution equivalent to @tevemadar's description of his solution, albeit in java.



            public class CommandBuilderTwo 

            private static String buildCommand(int N) N == 1)
            return "no command can be built";

            boolean negated = false;

            if(N < 0)
            N = -N;
            negated = true;
            else
            --N;


            String bin = Integer.toBinaryString(N).split("");

            StringBuilder res = new StringBuilder();

            if(negated)
            for (String c: bin)
            if((Integer.valueOf(c) & 1) == 1)
            res.append('L');
            else
            res.append('R');

            else
            for (String c: bin)
            if((Integer.valueOf(c) & 1) == 1)
            res.append('R');
            else
            res.append('L');



            //Reverse string built
            String command = res.toString();
            res = new StringBuilder();
            for(int i = command.length() - 1; i >= 0; i--)
            res.append(command.charAt(i));


            return res.toString();


            //Driver method
            public static void main (String args)
            for(int i = 0; i <= 25; i++)
            System.out.println("The command required to produce " + i + ": " + buildCommand(i) );
            System.out.println("The command required to produce -" + i + ": " + buildCommand(-i) );


            int edge = Integer.MAX_VALUE;
            System.out.println("The command required to produce " + edge + ": " + buildCommand(edge) );
            System.out.println("The command required to produce -" + edge + ": " + buildCommand(-edge) );







            share|improve this answer

























            • If 11 = 1011 = LRLL, and -11 is just LRLL reversed as LLRL, couldn't I just negate the number to positive, convert to binary with toString(2), swap the 1 for L and 0 for R, and reverse the string if it was negated?

              – AnonymousSB
              Nov 13 '18 at 22:18











            • @AnonymousSB Sounds like that should work just fine too.

              – Caleb Lucas
              Nov 13 '18 at 22:31











            • I think in the case of the following numbers, we discard. 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647

              – AnonymousSB
              Nov 14 '18 at 1:51











            • Caleb and @AnonymousSB, I'm confused. How can 3 and -3 have the same set of instructions, LL? It seems to me the code here fails for positive numbers. Did I misunderstand something? For example, any power of 2 would include an 'L', when clearly we only need R's.

              – גלעד ברקן
              Nov 14 '18 at 15:28










            Your Answer






            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: "1"
            ;
            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: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            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%2fstackoverflow.com%2fquestions%2f53278908%2ffind-shortest-sequence-of-mathematical-operations%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            5 Answers
            5






            active

            oldest

            votes








            5 Answers
            5






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            3














            I was just looking at -11, and considering 11 being 1011 in binary, which resembles your manual solution of LLRL, just backwards. Tests suggest that this may be the key for negative numbers: get their absolute value, and start shifting towards the right until it becomes zero. When you shift out an 1, move to the left, when you shift out a 0, move to the right. The last step will be a left-move, and the result goes into left.

            Then I just checked what about positive numbers, simply swapping the moves (because leaving them in place would provide the negative result) and it appeared to generate one number above the goal. So I just subtracted one from the original and it started to work. Of course this time the last step is going to be a right-move, and result goes into right:






            function findShortestSequence(number) (org==right));


            for(var i=-20;i<=20;i++)
            findShortestSequence(i);





            While I do not chase to provide a full explanation, I can provide some pieces which one may find useful:



            • the "subtract 1 if positive" part feels like creating anti-two's complement number (in two's complement, in case of positive number you do not do anything, and in case of negative number you get its positive pair, invert its bits, and add 1 to the result)

            • from a distance the "multiply by 2 and do a fix" is not that extreme:

              if one somehow ends up with 10001001 (137) and 1001 is the fixer, then multiply by 2 shifts everything to the left (100010010, 274), and if you want to keep that 0001001 part in its original place, subtracting the fixer "locally divides" that part back to its original place (100010010-1001=100001001), this is more or less what moveRight does to positive numbers

            • updating the fixer is more convoluted, though some parts of it do resemble the previous idea: 2*1001 becomes 10010, and subtracting 10001001 fixes back 1001 on the lower places, and also introduces that 1 from the beginning at high places. The nasty part is that 10001001 is clearly larger than 10010, so the result is a negative number, and in fact the fixer (left in case of a positive target number) has never been 1001, because at its very first update ever, it becomes "2*0-something" (where "something" is a positive number, as right starts from 1). Indeed, looking at the example loop, left always seems to end up being non-positive, and right seems to be non-negative

            • the anti-two's complement thing also uglifies the picture, it may be cleaner to think about negative target numbers first, as there the fixer (right) is non-negative, and positive*2-negative also stays positive:
              ...11110001001 (left) and 1001 (right), ...11110001001*2 is ...111100010010, and ...111100010010-1001=...111100001001, first part of the mission is accomplished (keeping the 1001 pattern in place)

              and if the goal is to have ...1110010001001 later (after 2 moveLeft-s), then moveRight really does 1001*2=10010, 10010-...11110001001(-119)=10001001, which is exactly what is needed to extend the 1001 pattern into 10001001 for the 8 lowest places)

            • about being "shortest": the fastest growing part is moveRight, if left remains 0 all the time, right jumps to the next power of two each step, so ceil(log2(number)) steps are needed to reach or surpass the given number, which equals to the number of significant binary digits required represent the number, which equals the steps taken by the loop.





            share|improve this answer

























            • That is a great observation about using bitwise operators. One slight modification I've made is to get rid of the if(org <= 0) statement, and replace the moveLeft() and moveRight() with ternaries.

              – AnonymousSB
              Nov 13 '18 at 21:27











            • @AnonymousSB as I had some doubts about the "look, it is easy" explanation in the other answer, so added some thoughts about what is happening inside

              – tevemadar
              Nov 14 '18 at 12:35











            • Caleb Lucas' answer seems to me to fail with positive numbers. Am I misreading it? For example, any power of 2 would include an 'L', when clearly we only need R's. And testing just for 3 and -3 returns LL for both. How could that be?

              – גלעד ברקן
              Nov 14 '18 at 15:25











            • @גלעדברקן That answer is simply wrong for positive numbers: returns the sequence producing the corresponding negative number, just mirrored. It fails to work starting from 1, which should result in an empty sequence, as right=1 already (same as for 0, since left=0 already)

              – tevemadar
              Nov 14 '18 at 15:56











            • @AnonymousSB this solution is far longer than the short one exactly because it does the calculation too. Unfortunately I did not think that adding (org==left)||(org==right) into the log-line was an absolute necessity.

              – tevemadar
              Nov 15 '18 at 22:03















            3














            I was just looking at -11, and considering 11 being 1011 in binary, which resembles your manual solution of LLRL, just backwards. Tests suggest that this may be the key for negative numbers: get their absolute value, and start shifting towards the right until it becomes zero. When you shift out an 1, move to the left, when you shift out a 0, move to the right. The last step will be a left-move, and the result goes into left.

            Then I just checked what about positive numbers, simply swapping the moves (because leaving them in place would provide the negative result) and it appeared to generate one number above the goal. So I just subtracted one from the original and it started to work. Of course this time the last step is going to be a right-move, and result goes into right:






            function findShortestSequence(number) (org==right));


            for(var i=-20;i<=20;i++)
            findShortestSequence(i);





            While I do not chase to provide a full explanation, I can provide some pieces which one may find useful:



            • the "subtract 1 if positive" part feels like creating anti-two's complement number (in two's complement, in case of positive number you do not do anything, and in case of negative number you get its positive pair, invert its bits, and add 1 to the result)

            • from a distance the "multiply by 2 and do a fix" is not that extreme:

              if one somehow ends up with 10001001 (137) and 1001 is the fixer, then multiply by 2 shifts everything to the left (100010010, 274), and if you want to keep that 0001001 part in its original place, subtracting the fixer "locally divides" that part back to its original place (100010010-1001=100001001), this is more or less what moveRight does to positive numbers

            • updating the fixer is more convoluted, though some parts of it do resemble the previous idea: 2*1001 becomes 10010, and subtracting 10001001 fixes back 1001 on the lower places, and also introduces that 1 from the beginning at high places. The nasty part is that 10001001 is clearly larger than 10010, so the result is a negative number, and in fact the fixer (left in case of a positive target number) has never been 1001, because at its very first update ever, it becomes "2*0-something" (where "something" is a positive number, as right starts from 1). Indeed, looking at the example loop, left always seems to end up being non-positive, and right seems to be non-negative

            • the anti-two's complement thing also uglifies the picture, it may be cleaner to think about negative target numbers first, as there the fixer (right) is non-negative, and positive*2-negative also stays positive:
              ...11110001001 (left) and 1001 (right), ...11110001001*2 is ...111100010010, and ...111100010010-1001=...111100001001, first part of the mission is accomplished (keeping the 1001 pattern in place)

              and if the goal is to have ...1110010001001 later (after 2 moveLeft-s), then moveRight really does 1001*2=10010, 10010-...11110001001(-119)=10001001, which is exactly what is needed to extend the 1001 pattern into 10001001 for the 8 lowest places)

            • about being "shortest": the fastest growing part is moveRight, if left remains 0 all the time, right jumps to the next power of two each step, so ceil(log2(number)) steps are needed to reach or surpass the given number, which equals to the number of significant binary digits required represent the number, which equals the steps taken by the loop.





            share|improve this answer

























            • That is a great observation about using bitwise operators. One slight modification I've made is to get rid of the if(org <= 0) statement, and replace the moveLeft() and moveRight() with ternaries.

              – AnonymousSB
              Nov 13 '18 at 21:27











            • @AnonymousSB as I had some doubts about the "look, it is easy" explanation in the other answer, so added some thoughts about what is happening inside

              – tevemadar
              Nov 14 '18 at 12:35











            • Caleb Lucas' answer seems to me to fail with positive numbers. Am I misreading it? For example, any power of 2 would include an 'L', when clearly we only need R's. And testing just for 3 and -3 returns LL for both. How could that be?

              – גלעד ברקן
              Nov 14 '18 at 15:25











            • @גלעדברקן That answer is simply wrong for positive numbers: returns the sequence producing the corresponding negative number, just mirrored. It fails to work starting from 1, which should result in an empty sequence, as right=1 already (same as for 0, since left=0 already)

              – tevemadar
              Nov 14 '18 at 15:56











            • @AnonymousSB this solution is far longer than the short one exactly because it does the calculation too. Unfortunately I did not think that adding (org==left)||(org==right) into the log-line was an absolute necessity.

              – tevemadar
              Nov 15 '18 at 22:03













            3












            3








            3







            I was just looking at -11, and considering 11 being 1011 in binary, which resembles your manual solution of LLRL, just backwards. Tests suggest that this may be the key for negative numbers: get their absolute value, and start shifting towards the right until it becomes zero. When you shift out an 1, move to the left, when you shift out a 0, move to the right. The last step will be a left-move, and the result goes into left.

            Then I just checked what about positive numbers, simply swapping the moves (because leaving them in place would provide the negative result) and it appeared to generate one number above the goal. So I just subtracted one from the original and it started to work. Of course this time the last step is going to be a right-move, and result goes into right:






            function findShortestSequence(number) (org==right));


            for(var i=-20;i<=20;i++)
            findShortestSequence(i);





            While I do not chase to provide a full explanation, I can provide some pieces which one may find useful:



            • the "subtract 1 if positive" part feels like creating anti-two's complement number (in two's complement, in case of positive number you do not do anything, and in case of negative number you get its positive pair, invert its bits, and add 1 to the result)

            • from a distance the "multiply by 2 and do a fix" is not that extreme:

              if one somehow ends up with 10001001 (137) and 1001 is the fixer, then multiply by 2 shifts everything to the left (100010010, 274), and if you want to keep that 0001001 part in its original place, subtracting the fixer "locally divides" that part back to its original place (100010010-1001=100001001), this is more or less what moveRight does to positive numbers

            • updating the fixer is more convoluted, though some parts of it do resemble the previous idea: 2*1001 becomes 10010, and subtracting 10001001 fixes back 1001 on the lower places, and also introduces that 1 from the beginning at high places. The nasty part is that 10001001 is clearly larger than 10010, so the result is a negative number, and in fact the fixer (left in case of a positive target number) has never been 1001, because at its very first update ever, it becomes "2*0-something" (where "something" is a positive number, as right starts from 1). Indeed, looking at the example loop, left always seems to end up being non-positive, and right seems to be non-negative

            • the anti-two's complement thing also uglifies the picture, it may be cleaner to think about negative target numbers first, as there the fixer (right) is non-negative, and positive*2-negative also stays positive:
              ...11110001001 (left) and 1001 (right), ...11110001001*2 is ...111100010010, and ...111100010010-1001=...111100001001, first part of the mission is accomplished (keeping the 1001 pattern in place)

              and if the goal is to have ...1110010001001 later (after 2 moveLeft-s), then moveRight really does 1001*2=10010, 10010-...11110001001(-119)=10001001, which is exactly what is needed to extend the 1001 pattern into 10001001 for the 8 lowest places)

            • about being "shortest": the fastest growing part is moveRight, if left remains 0 all the time, right jumps to the next power of two each step, so ceil(log2(number)) steps are needed to reach or surpass the given number, which equals to the number of significant binary digits required represent the number, which equals the steps taken by the loop.





            share|improve this answer















            I was just looking at -11, and considering 11 being 1011 in binary, which resembles your manual solution of LLRL, just backwards. Tests suggest that this may be the key for negative numbers: get their absolute value, and start shifting towards the right until it becomes zero. When you shift out an 1, move to the left, when you shift out a 0, move to the right. The last step will be a left-move, and the result goes into left.

            Then I just checked what about positive numbers, simply swapping the moves (because leaving them in place would provide the negative result) and it appeared to generate one number above the goal. So I just subtracted one from the original and it started to work. Of course this time the last step is going to be a right-move, and result goes into right:






            function findShortestSequence(number) (org==right));


            for(var i=-20;i<=20;i++)
            findShortestSequence(i);





            While I do not chase to provide a full explanation, I can provide some pieces which one may find useful:



            • the "subtract 1 if positive" part feels like creating anti-two's complement number (in two's complement, in case of positive number you do not do anything, and in case of negative number you get its positive pair, invert its bits, and add 1 to the result)

            • from a distance the "multiply by 2 and do a fix" is not that extreme:

              if one somehow ends up with 10001001 (137) and 1001 is the fixer, then multiply by 2 shifts everything to the left (100010010, 274), and if you want to keep that 0001001 part in its original place, subtracting the fixer "locally divides" that part back to its original place (100010010-1001=100001001), this is more or less what moveRight does to positive numbers

            • updating the fixer is more convoluted, though some parts of it do resemble the previous idea: 2*1001 becomes 10010, and subtracting 10001001 fixes back 1001 on the lower places, and also introduces that 1 from the beginning at high places. The nasty part is that 10001001 is clearly larger than 10010, so the result is a negative number, and in fact the fixer (left in case of a positive target number) has never been 1001, because at its very first update ever, it becomes "2*0-something" (where "something" is a positive number, as right starts from 1). Indeed, looking at the example loop, left always seems to end up being non-positive, and right seems to be non-negative

            • the anti-two's complement thing also uglifies the picture, it may be cleaner to think about negative target numbers first, as there the fixer (right) is non-negative, and positive*2-negative also stays positive:
              ...11110001001 (left) and 1001 (right), ...11110001001*2 is ...111100010010, and ...111100010010-1001=...111100001001, first part of the mission is accomplished (keeping the 1001 pattern in place)

              and if the goal is to have ...1110010001001 later (after 2 moveLeft-s), then moveRight really does 1001*2=10010, 10010-...11110001001(-119)=10001001, which is exactly what is needed to extend the 1001 pattern into 10001001 for the 8 lowest places)

            • about being "shortest": the fastest growing part is moveRight, if left remains 0 all the time, right jumps to the next power of two each step, so ceil(log2(number)) steps are needed to reach or surpass the given number, which equals to the number of significant binary digits required represent the number, which equals the steps taken by the loop.





            function findShortestSequence(number) (org==right));


            for(var i=-20;i<=20;i++)
            findShortestSequence(i);





            function findShortestSequence(number) (org==right));


            for(var i=-20;i<=20;i++)
            findShortestSequence(i);






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 15 '18 at 22:06

























            answered Nov 13 '18 at 11:21









            tevemadartevemadar

            4,3932725




            4,3932725












            • That is a great observation about using bitwise operators. One slight modification I've made is to get rid of the if(org <= 0) statement, and replace the moveLeft() and moveRight() with ternaries.

              – AnonymousSB
              Nov 13 '18 at 21:27











            • @AnonymousSB as I had some doubts about the "look, it is easy" explanation in the other answer, so added some thoughts about what is happening inside

              – tevemadar
              Nov 14 '18 at 12:35











            • Caleb Lucas' answer seems to me to fail with positive numbers. Am I misreading it? For example, any power of 2 would include an 'L', when clearly we only need R's. And testing just for 3 and -3 returns LL for both. How could that be?

              – גלעד ברקן
              Nov 14 '18 at 15:25











            • @גלעדברקן That answer is simply wrong for positive numbers: returns the sequence producing the corresponding negative number, just mirrored. It fails to work starting from 1, which should result in an empty sequence, as right=1 already (same as for 0, since left=0 already)

              – tevemadar
              Nov 14 '18 at 15:56











            • @AnonymousSB this solution is far longer than the short one exactly because it does the calculation too. Unfortunately I did not think that adding (org==left)||(org==right) into the log-line was an absolute necessity.

              – tevemadar
              Nov 15 '18 at 22:03

















            • That is a great observation about using bitwise operators. One slight modification I've made is to get rid of the if(org <= 0) statement, and replace the moveLeft() and moveRight() with ternaries.

              – AnonymousSB
              Nov 13 '18 at 21:27











            • @AnonymousSB as I had some doubts about the "look, it is easy" explanation in the other answer, so added some thoughts about what is happening inside

              – tevemadar
              Nov 14 '18 at 12:35











            • Caleb Lucas' answer seems to me to fail with positive numbers. Am I misreading it? For example, any power of 2 would include an 'L', when clearly we only need R's. And testing just for 3 and -3 returns LL for both. How could that be?

              – גלעד ברקן
              Nov 14 '18 at 15:25











            • @גלעדברקן That answer is simply wrong for positive numbers: returns the sequence producing the corresponding negative number, just mirrored. It fails to work starting from 1, which should result in an empty sequence, as right=1 already (same as for 0, since left=0 already)

              – tevemadar
              Nov 14 '18 at 15:56











            • @AnonymousSB this solution is far longer than the short one exactly because it does the calculation too. Unfortunately I did not think that adding (org==left)||(org==right) into the log-line was an absolute necessity.

              – tevemadar
              Nov 15 '18 at 22:03
















            That is a great observation about using bitwise operators. One slight modification I've made is to get rid of the if(org <= 0) statement, and replace the moveLeft() and moveRight() with ternaries.

            – AnonymousSB
            Nov 13 '18 at 21:27





            That is a great observation about using bitwise operators. One slight modification I've made is to get rid of the if(org <= 0) statement, and replace the moveLeft() and moveRight() with ternaries.

            – AnonymousSB
            Nov 13 '18 at 21:27













            @AnonymousSB as I had some doubts about the "look, it is easy" explanation in the other answer, so added some thoughts about what is happening inside

            – tevemadar
            Nov 14 '18 at 12:35





            @AnonymousSB as I had some doubts about the "look, it is easy" explanation in the other answer, so added some thoughts about what is happening inside

            – tevemadar
            Nov 14 '18 at 12:35













            Caleb Lucas' answer seems to me to fail with positive numbers. Am I misreading it? For example, any power of 2 would include an 'L', when clearly we only need R's. And testing just for 3 and -3 returns LL for both. How could that be?

            – גלעד ברקן
            Nov 14 '18 at 15:25





            Caleb Lucas' answer seems to me to fail with positive numbers. Am I misreading it? For example, any power of 2 would include an 'L', when clearly we only need R's. And testing just for 3 and -3 returns LL for both. How could that be?

            – גלעד ברקן
            Nov 14 '18 at 15:25













            @גלעדברקן That answer is simply wrong for positive numbers: returns the sequence producing the corresponding negative number, just mirrored. It fails to work starting from 1, which should result in an empty sequence, as right=1 already (same as for 0, since left=0 already)

            – tevemadar
            Nov 14 '18 at 15:56





            @גלעדברקן That answer is simply wrong for positive numbers: returns the sequence producing the corresponding negative number, just mirrored. It fails to work starting from 1, which should result in an empty sequence, as right=1 already (same as for 0, since left=0 already)

            – tevemadar
            Nov 14 '18 at 15:56













            @AnonymousSB this solution is far longer than the short one exactly because it does the calculation too. Unfortunately I did not think that adding (org==left)||(org==right) into the log-line was an absolute necessity.

            – tevemadar
            Nov 15 '18 at 22:03





            @AnonymousSB this solution is far longer than the short one exactly because it does the calculation too. Unfortunately I did not think that adding (org==left)||(org==right) into the log-line was an absolute necessity.

            – tevemadar
            Nov 15 '18 at 22:03













            1














            I think I came to the same conclusion as tevemadar. Here it is in code:






            function confirm(str, n)
            let l = 0;
            let r = 1;
            let i = 0;

            while(str[i])
            if (str[i++] == 'L')
            l = 2*l - r;
            else
            r = 2*r - l;


            if ([l, r].includes(n))
            return true;

            return false;


            function f(n)
            if ([0, 1].includes(n))
            return '';
            else if (n > 1)
            return (n - 1)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'R' : 'L')
            .reverse()
            .join('');
            else
            return (-n)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'L' : 'R')
            .reverse()
            .join('');


            for (let i=-11; i<=11; i++)
            fi = f(i);
            console.log(i + ': ' + fi + ', ' + confirm(fi, i));








            share|improve this answer























            • While at least the faulty accepted answer is completely gone, I remain being puzzled why it is so important for OP to accept an answer which is a different one from mine...

              – tevemadar
              Nov 15 '18 at 16:19












            • I accepted this answer because the confirm function provided shows that it generates the correct moves, unless there is something I’m missing?

              – AnonymousSB
              Nov 15 '18 at 19:20















            1














            I think I came to the same conclusion as tevemadar. Here it is in code:






            function confirm(str, n)
            let l = 0;
            let r = 1;
            let i = 0;

            while(str[i])
            if (str[i++] == 'L')
            l = 2*l - r;
            else
            r = 2*r - l;


            if ([l, r].includes(n))
            return true;

            return false;


            function f(n)
            if ([0, 1].includes(n))
            return '';
            else if (n > 1)
            return (n - 1)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'R' : 'L')
            .reverse()
            .join('');
            else
            return (-n)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'L' : 'R')
            .reverse()
            .join('');


            for (let i=-11; i<=11; i++)
            fi = f(i);
            console.log(i + ': ' + fi + ', ' + confirm(fi, i));








            share|improve this answer























            • While at least the faulty accepted answer is completely gone, I remain being puzzled why it is so important for OP to accept an answer which is a different one from mine...

              – tevemadar
              Nov 15 '18 at 16:19












            • I accepted this answer because the confirm function provided shows that it generates the correct moves, unless there is something I’m missing?

              – AnonymousSB
              Nov 15 '18 at 19:20













            1












            1








            1







            I think I came to the same conclusion as tevemadar. Here it is in code:






            function confirm(str, n)
            let l = 0;
            let r = 1;
            let i = 0;

            while(str[i])
            if (str[i++] == 'L')
            l = 2*l - r;
            else
            r = 2*r - l;


            if ([l, r].includes(n))
            return true;

            return false;


            function f(n)
            if ([0, 1].includes(n))
            return '';
            else if (n > 1)
            return (n - 1)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'R' : 'L')
            .reverse()
            .join('');
            else
            return (-n)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'L' : 'R')
            .reverse()
            .join('');


            for (let i=-11; i<=11; i++)
            fi = f(i);
            console.log(i + ': ' + fi + ', ' + confirm(fi, i));








            share|improve this answer













            I think I came to the same conclusion as tevemadar. Here it is in code:






            function confirm(str, n)
            let l = 0;
            let r = 1;
            let i = 0;

            while(str[i])
            if (str[i++] == 'L')
            l = 2*l - r;
            else
            r = 2*r - l;


            if ([l, r].includes(n))
            return true;

            return false;


            function f(n)
            if ([0, 1].includes(n))
            return '';
            else if (n > 1)
            return (n - 1)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'R' : 'L')
            .reverse()
            .join('');
            else
            return (-n)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'L' : 'R')
            .reverse()
            .join('');


            for (let i=-11; i<=11; i++)
            fi = f(i);
            console.log(i + ': ' + fi + ', ' + confirm(fi, i));








            function confirm(str, n)
            let l = 0;
            let r = 1;
            let i = 0;

            while(str[i])
            if (str[i++] == 'L')
            l = 2*l - r;
            else
            r = 2*r - l;


            if ([l, r].includes(n))
            return true;

            return false;


            function f(n)
            if ([0, 1].includes(n))
            return '';
            else if (n > 1)
            return (n - 1)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'R' : 'L')
            .reverse()
            .join('');
            else
            return (-n)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'L' : 'R')
            .reverse()
            .join('');


            for (let i=-11; i<=11; i++)
            fi = f(i);
            console.log(i + ': ' + fi + ', ' + confirm(fi, i));





            function confirm(str, n)
            let l = 0;
            let r = 1;
            let i = 0;

            while(str[i])
            if (str[i++] == 'L')
            l = 2*l - r;
            else
            r = 2*r - l;


            if ([l, r].includes(n))
            return true;

            return false;


            function f(n)
            if ([0, 1].includes(n))
            return '';
            else if (n > 1)
            return (n - 1)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'R' : 'L')
            .reverse()
            .join('');
            else
            return (-n)
            .toString(2)
            .split('')
            .map(x => x & 1 ? 'L' : 'R')
            .reverse()
            .join('');


            for (let i=-11; i<=11; i++)
            fi = f(i);
            console.log(i + ': ' + fi + ', ' + confirm(fi, i));






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 14 '18 at 2:20









            גלעד ברקןגלעד ברקן

            13k21542




            13k21542












            • While at least the faulty accepted answer is completely gone, I remain being puzzled why it is so important for OP to accept an answer which is a different one from mine...

              – tevemadar
              Nov 15 '18 at 16:19












            • I accepted this answer because the confirm function provided shows that it generates the correct moves, unless there is something I’m missing?

              – AnonymousSB
              Nov 15 '18 at 19:20

















            • While at least the faulty accepted answer is completely gone, I remain being puzzled why it is so important for OP to accept an answer which is a different one from mine...

              – tevemadar
              Nov 15 '18 at 16:19












            • I accepted this answer because the confirm function provided shows that it generates the correct moves, unless there is something I’m missing?

              – AnonymousSB
              Nov 15 '18 at 19:20
















            While at least the faulty accepted answer is completely gone, I remain being puzzled why it is so important for OP to accept an answer which is a different one from mine...

            – tevemadar
            Nov 15 '18 at 16:19






            While at least the faulty accepted answer is completely gone, I remain being puzzled why it is so important for OP to accept an answer which is a different one from mine...

            – tevemadar
            Nov 15 '18 at 16:19














            I accepted this answer because the confirm function provided shows that it generates the correct moves, unless there is something I’m missing?

            – AnonymousSB
            Nov 15 '18 at 19:20





            I accepted this answer because the confirm function provided shows that it generates the correct moves, unless there is something I’m missing?

            – AnonymousSB
            Nov 15 '18 at 19:20











            0














            You could take an iterative approach with a stack for the next state for checking the result.



            This approach tests the smallest amount of changes first and then takes a growing count of possibilities.






            function findShortestSequence(number) 
            const
            moveLeft = (left, right, moves) => [left * 2 - right, right, [...moves, 'L']],
            moveRight = (left, right, moves) => [left, right * 2 - left, [...moves, 'R']],
            functions = [moveLeft, moveRight];

            var stack = [[0, 1, ]],
            left, right, moves;

            while ([left, right, moves] = stack.shift())
            if (left === number) return moves;
            functions.forEach(fn => stack.push(fn(left, right, moves)));



            console.log(findShortestSequence(-11));

            .as-console-wrapper max-height: 100% !important; top: 0; 








            share|improve this answer





























              0














              You could take an iterative approach with a stack for the next state for checking the result.



              This approach tests the smallest amount of changes first and then takes a growing count of possibilities.






              function findShortestSequence(number) 
              const
              moveLeft = (left, right, moves) => [left * 2 - right, right, [...moves, 'L']],
              moveRight = (left, right, moves) => [left, right * 2 - left, [...moves, 'R']],
              functions = [moveLeft, moveRight];

              var stack = [[0, 1, ]],
              left, right, moves;

              while ([left, right, moves] = stack.shift())
              if (left === number) return moves;
              functions.forEach(fn => stack.push(fn(left, right, moves)));



              console.log(findShortestSequence(-11));

              .as-console-wrapper max-height: 100% !important; top: 0; 








              share|improve this answer



























                0












                0








                0







                You could take an iterative approach with a stack for the next state for checking the result.



                This approach tests the smallest amount of changes first and then takes a growing count of possibilities.






                function findShortestSequence(number) 
                const
                moveLeft = (left, right, moves) => [left * 2 - right, right, [...moves, 'L']],
                moveRight = (left, right, moves) => [left, right * 2 - left, [...moves, 'R']],
                functions = [moveLeft, moveRight];

                var stack = [[0, 1, ]],
                left, right, moves;

                while ([left, right, moves] = stack.shift())
                if (left === number) return moves;
                functions.forEach(fn => stack.push(fn(left, right, moves)));



                console.log(findShortestSequence(-11));

                .as-console-wrapper max-height: 100% !important; top: 0; 








                share|improve this answer















                You could take an iterative approach with a stack for the next state for checking the result.



                This approach tests the smallest amount of changes first and then takes a growing count of possibilities.






                function findShortestSequence(number) 
                const
                moveLeft = (left, right, moves) => [left * 2 - right, right, [...moves, 'L']],
                moveRight = (left, right, moves) => [left, right * 2 - left, [...moves, 'R']],
                functions = [moveLeft, moveRight];

                var stack = [[0, 1, ]],
                left, right, moves;

                while ([left, right, moves] = stack.shift())
                if (left === number) return moves;
                functions.forEach(fn => stack.push(fn(left, right, moves)));



                console.log(findShortestSequence(-11));

                .as-console-wrapper max-height: 100% !important; top: 0; 








                function findShortestSequence(number) 
                const
                moveLeft = (left, right, moves) => [left * 2 - right, right, [...moves, 'L']],
                moveRight = (left, right, moves) => [left, right * 2 - left, [...moves, 'R']],
                functions = [moveLeft, moveRight];

                var stack = [[0, 1, ]],
                left, right, moves;

                while ([left, right, moves] = stack.shift())
                if (left === number) return moves;
                functions.forEach(fn => stack.push(fn(left, right, moves)));



                console.log(findShortestSequence(-11));

                .as-console-wrapper max-height: 100% !important; top: 0; 





                function findShortestSequence(number) 
                const
                moveLeft = (left, right, moves) => [left * 2 - right, right, [...moves, 'L']],
                moveRight = (left, right, moves) => [left, right * 2 - left, [...moves, 'R']],
                functions = [moveLeft, moveRight];

                var stack = [[0, 1, ]],
                left, right, moves;

                while ([left, right, moves] = stack.shift())
                if (left === number) return moves;
                functions.forEach(fn => stack.push(fn(left, right, moves)));



                console.log(findShortestSequence(-11));

                .as-console-wrapper max-height: 100% !important; top: 0; 






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 13 '18 at 12:49

























                answered Nov 13 '18 at 11:21









                Nina ScholzNina Scholz

                187k1596172




                187k1596172





















                    0














                    Yes, I also completely agree with myself, and find my hint useful (ok, that answer is gone).

                    If verification is not needed, generating the steps is this simple:






                    function getSequence(n)

                    for(var i=-20;i<=20;i++)
                    console.log(i,getSequence(i));

                    .as-console-wrapper max-height: 100% !important; top: 0; 








                    share|improve this answer























                    • I really do appreciate your effort, and original observation about it being binary. This solution is much more succinct to @גלעדברקן's answer, and provides the same results. Quite smart to swap the steps ahead of time. Given that the max binary has a length of 31, I don't see any major issues with the time complexity; however, you could use cut down on one pass with this replace instead .replace(/0|1/g, match => match === '0' ? steps[0] : steps[1])

                      – AnonymousSB
                      Nov 15 '18 at 21:03















                    0














                    Yes, I also completely agree with myself, and find my hint useful (ok, that answer is gone).

                    If verification is not needed, generating the steps is this simple:






                    function getSequence(n)

                    for(var i=-20;i<=20;i++)
                    console.log(i,getSequence(i));

                    .as-console-wrapper max-height: 100% !important; top: 0; 








                    share|improve this answer























                    • I really do appreciate your effort, and original observation about it being binary. This solution is much more succinct to @גלעדברקן's answer, and provides the same results. Quite smart to swap the steps ahead of time. Given that the max binary has a length of 31, I don't see any major issues with the time complexity; however, you could use cut down on one pass with this replace instead .replace(/0|1/g, match => match === '0' ? steps[0] : steps[1])

                      – AnonymousSB
                      Nov 15 '18 at 21:03













                    0












                    0








                    0







                    Yes, I also completely agree with myself, and find my hint useful (ok, that answer is gone).

                    If verification is not needed, generating the steps is this simple:






                    function getSequence(n)

                    for(var i=-20;i<=20;i++)
                    console.log(i,getSequence(i));

                    .as-console-wrapper max-height: 100% !important; top: 0; 








                    share|improve this answer













                    Yes, I also completely agree with myself, and find my hint useful (ok, that answer is gone).

                    If verification is not needed, generating the steps is this simple:






                    function getSequence(n)

                    for(var i=-20;i<=20;i++)
                    console.log(i,getSequence(i));

                    .as-console-wrapper max-height: 100% !important; top: 0; 








                    function getSequence(n)

                    for(var i=-20;i<=20;i++)
                    console.log(i,getSequence(i));

                    .as-console-wrapper max-height: 100% !important; top: 0; 





                    function getSequence(n)

                    for(var i=-20;i<=20;i++)
                    console.log(i,getSequence(i));

                    .as-console-wrapper max-height: 100% !important; top: 0; 






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 15 '18 at 16:55









                    tevemadartevemadar

                    4,3932725




                    4,3932725












                    • I really do appreciate your effort, and original observation about it being binary. This solution is much more succinct to @גלעדברקן's answer, and provides the same results. Quite smart to swap the steps ahead of time. Given that the max binary has a length of 31, I don't see any major issues with the time complexity; however, you could use cut down on one pass with this replace instead .replace(/0|1/g, match => match === '0' ? steps[0] : steps[1])

                      – AnonymousSB
                      Nov 15 '18 at 21:03

















                    • I really do appreciate your effort, and original observation about it being binary. This solution is much more succinct to @גלעדברקן's answer, and provides the same results. Quite smart to swap the steps ahead of time. Given that the max binary has a length of 31, I don't see any major issues with the time complexity; however, you could use cut down on one pass with this replace instead .replace(/0|1/g, match => match === '0' ? steps[0] : steps[1])

                      – AnonymousSB
                      Nov 15 '18 at 21:03
















                    I really do appreciate your effort, and original observation about it being binary. This solution is much more succinct to @גלעדברקן's answer, and provides the same results. Quite smart to swap the steps ahead of time. Given that the max binary has a length of 31, I don't see any major issues with the time complexity; however, you could use cut down on one pass with this replace instead .replace(/0|1/g, match => match === '0' ? steps[0] : steps[1])

                    – AnonymousSB
                    Nov 15 '18 at 21:03





                    I really do appreciate your effort, and original observation about it being binary. This solution is much more succinct to @גלעדברקן's answer, and provides the same results. Quite smart to swap the steps ahead of time. Given that the max binary has a length of 31, I don't see any major issues with the time complexity; however, you could use cut down on one pass with this replace instead .replace(/0|1/g, match => match === '0' ? steps[0] : steps[1])

                    – AnonymousSB
                    Nov 15 '18 at 21:03











                    0














                    EDIT: Since we have a correct and proper solution to this question, the pattern of mirroring as applied in CommandBuilder for positive integers is a misconception and should have never been used: it generates duplicate command strings for some integers. Please see CommandBuilderTwo for a more appropriate solution.




                    Given the fact that L = 0 and R = 1, we can convert the desired decimal number, P, into binary and store each digit inversely as 1 for L and 0 for R when negative



                    Let us also take these factors into consideration. For any given number P:



                    1. P could be a positive number that is the result of (2 ^ N); where 0 < N <= 32

                    2. P could be a positive number that is the result of (2 ^ N) - 1; where 0 < N <= 32

                    3. P could be any other positive number

                    4. P could be any negative number

                    We can efficiently determine the commands required to build the inputted desired number using the following solution:



                    public class CommandBuilder 

                    private static String getCommand(long N)


                    private static boolean isPowerOfTwo(long val)
                    return (int) Math.ceil( Math.log(val) / Math.log(2))
                    == (int) Math.floor(Math.log(val) / Math.log(2));


                    private static boolean isPowerOfTwoMinusOne(long val)
                    int root = (int) Math.ceil(Math.log(val) / Math.log(2));
                    return Math.pow(2, root) - 1 == val;


                    //Driver method
                    public static void main(String args)

                    for(int i = 0; i <= 25; i++)
                    System.out.println("The command required to produce " + i + ": " + getCommand(i) );
                    System.out.println("The command required to produce -" + i + ": " + getCommand(-i) );


                    int edge = Integer.MAX_VALUE;
                    System.out.println("The command required to produce " + edge + ": " + getCommand(edge) );
                    System.out.println("The command required to produce -" + edge + ": " + getCommand(-edge) );






                    This is a solution equivalent to @tevemadar's description of his solution, albeit in java.



                    public class CommandBuilderTwo 

                    private static String buildCommand(int N) N == 1)
                    return "no command can be built";

                    boolean negated = false;

                    if(N < 0)
                    N = -N;
                    negated = true;
                    else
                    --N;


                    String bin = Integer.toBinaryString(N).split("");

                    StringBuilder res = new StringBuilder();

                    if(negated)
                    for (String c: bin)
                    if((Integer.valueOf(c) & 1) == 1)
                    res.append('L');
                    else
                    res.append('R');

                    else
                    for (String c: bin)
                    if((Integer.valueOf(c) & 1) == 1)
                    res.append('R');
                    else
                    res.append('L');



                    //Reverse string built
                    String command = res.toString();
                    res = new StringBuilder();
                    for(int i = command.length() - 1; i >= 0; i--)
                    res.append(command.charAt(i));


                    return res.toString();


                    //Driver method
                    public static void main (String args)
                    for(int i = 0; i <= 25; i++)
                    System.out.println("The command required to produce " + i + ": " + buildCommand(i) );
                    System.out.println("The command required to produce -" + i + ": " + buildCommand(-i) );


                    int edge = Integer.MAX_VALUE;
                    System.out.println("The command required to produce " + edge + ": " + buildCommand(edge) );
                    System.out.println("The command required to produce -" + edge + ": " + buildCommand(-edge) );







                    share|improve this answer

























                    • If 11 = 1011 = LRLL, and -11 is just LRLL reversed as LLRL, couldn't I just negate the number to positive, convert to binary with toString(2), swap the 1 for L and 0 for R, and reverse the string if it was negated?

                      – AnonymousSB
                      Nov 13 '18 at 22:18











                    • @AnonymousSB Sounds like that should work just fine too.

                      – Caleb Lucas
                      Nov 13 '18 at 22:31











                    • I think in the case of the following numbers, we discard. 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647

                      – AnonymousSB
                      Nov 14 '18 at 1:51











                    • Caleb and @AnonymousSB, I'm confused. How can 3 and -3 have the same set of instructions, LL? It seems to me the code here fails for positive numbers. Did I misunderstand something? For example, any power of 2 would include an 'L', when clearly we only need R's.

                      – גלעד ברקן
                      Nov 14 '18 at 15:28















                    0














                    EDIT: Since we have a correct and proper solution to this question, the pattern of mirroring as applied in CommandBuilder for positive integers is a misconception and should have never been used: it generates duplicate command strings for some integers. Please see CommandBuilderTwo for a more appropriate solution.




                    Given the fact that L = 0 and R = 1, we can convert the desired decimal number, P, into binary and store each digit inversely as 1 for L and 0 for R when negative



                    Let us also take these factors into consideration. For any given number P:



                    1. P could be a positive number that is the result of (2 ^ N); where 0 < N <= 32

                    2. P could be a positive number that is the result of (2 ^ N) - 1; where 0 < N <= 32

                    3. P could be any other positive number

                    4. P could be any negative number

                    We can efficiently determine the commands required to build the inputted desired number using the following solution:



                    public class CommandBuilder 

                    private static String getCommand(long N)


                    private static boolean isPowerOfTwo(long val)
                    return (int) Math.ceil( Math.log(val) / Math.log(2))
                    == (int) Math.floor(Math.log(val) / Math.log(2));


                    private static boolean isPowerOfTwoMinusOne(long val)
                    int root = (int) Math.ceil(Math.log(val) / Math.log(2));
                    return Math.pow(2, root) - 1 == val;


                    //Driver method
                    public static void main(String args)

                    for(int i = 0; i <= 25; i++)
                    System.out.println("The command required to produce " + i + ": " + getCommand(i) );
                    System.out.println("The command required to produce -" + i + ": " + getCommand(-i) );


                    int edge = Integer.MAX_VALUE;
                    System.out.println("The command required to produce " + edge + ": " + getCommand(edge) );
                    System.out.println("The command required to produce -" + edge + ": " + getCommand(-edge) );






                    This is a solution equivalent to @tevemadar's description of his solution, albeit in java.



                    public class CommandBuilderTwo 

                    private static String buildCommand(int N) N == 1)
                    return "no command can be built";

                    boolean negated = false;

                    if(N < 0)
                    N = -N;
                    negated = true;
                    else
                    --N;


                    String bin = Integer.toBinaryString(N).split("");

                    StringBuilder res = new StringBuilder();

                    if(negated)
                    for (String c: bin)
                    if((Integer.valueOf(c) & 1) == 1)
                    res.append('L');
                    else
                    res.append('R');

                    else
                    for (String c: bin)
                    if((Integer.valueOf(c) & 1) == 1)
                    res.append('R');
                    else
                    res.append('L');



                    //Reverse string built
                    String command = res.toString();
                    res = new StringBuilder();
                    for(int i = command.length() - 1; i >= 0; i--)
                    res.append(command.charAt(i));


                    return res.toString();


                    //Driver method
                    public static void main (String args)
                    for(int i = 0; i <= 25; i++)
                    System.out.println("The command required to produce " + i + ": " + buildCommand(i) );
                    System.out.println("The command required to produce -" + i + ": " + buildCommand(-i) );


                    int edge = Integer.MAX_VALUE;
                    System.out.println("The command required to produce " + edge + ": " + buildCommand(edge) );
                    System.out.println("The command required to produce -" + edge + ": " + buildCommand(-edge) );







                    share|improve this answer

























                    • If 11 = 1011 = LRLL, and -11 is just LRLL reversed as LLRL, couldn't I just negate the number to positive, convert to binary with toString(2), swap the 1 for L and 0 for R, and reverse the string if it was negated?

                      – AnonymousSB
                      Nov 13 '18 at 22:18











                    • @AnonymousSB Sounds like that should work just fine too.

                      – Caleb Lucas
                      Nov 13 '18 at 22:31











                    • I think in the case of the following numbers, we discard. 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647

                      – AnonymousSB
                      Nov 14 '18 at 1:51











                    • Caleb and @AnonymousSB, I'm confused. How can 3 and -3 have the same set of instructions, LL? It seems to me the code here fails for positive numbers. Did I misunderstand something? For example, any power of 2 would include an 'L', when clearly we only need R's.

                      – גלעד ברקן
                      Nov 14 '18 at 15:28













                    0












                    0








                    0







                    EDIT: Since we have a correct and proper solution to this question, the pattern of mirroring as applied in CommandBuilder for positive integers is a misconception and should have never been used: it generates duplicate command strings for some integers. Please see CommandBuilderTwo for a more appropriate solution.




                    Given the fact that L = 0 and R = 1, we can convert the desired decimal number, P, into binary and store each digit inversely as 1 for L and 0 for R when negative



                    Let us also take these factors into consideration. For any given number P:



                    1. P could be a positive number that is the result of (2 ^ N); where 0 < N <= 32

                    2. P could be a positive number that is the result of (2 ^ N) - 1; where 0 < N <= 32

                    3. P could be any other positive number

                    4. P could be any negative number

                    We can efficiently determine the commands required to build the inputted desired number using the following solution:



                    public class CommandBuilder 

                    private static String getCommand(long N)


                    private static boolean isPowerOfTwo(long val)
                    return (int) Math.ceil( Math.log(val) / Math.log(2))
                    == (int) Math.floor(Math.log(val) / Math.log(2));


                    private static boolean isPowerOfTwoMinusOne(long val)
                    int root = (int) Math.ceil(Math.log(val) / Math.log(2));
                    return Math.pow(2, root) - 1 == val;


                    //Driver method
                    public static void main(String args)

                    for(int i = 0; i <= 25; i++)
                    System.out.println("The command required to produce " + i + ": " + getCommand(i) );
                    System.out.println("The command required to produce -" + i + ": " + getCommand(-i) );


                    int edge = Integer.MAX_VALUE;
                    System.out.println("The command required to produce " + edge + ": " + getCommand(edge) );
                    System.out.println("The command required to produce -" + edge + ": " + getCommand(-edge) );






                    This is a solution equivalent to @tevemadar's description of his solution, albeit in java.



                    public class CommandBuilderTwo 

                    private static String buildCommand(int N) N == 1)
                    return "no command can be built";

                    boolean negated = false;

                    if(N < 0)
                    N = -N;
                    negated = true;
                    else
                    --N;


                    String bin = Integer.toBinaryString(N).split("");

                    StringBuilder res = new StringBuilder();

                    if(negated)
                    for (String c: bin)
                    if((Integer.valueOf(c) & 1) == 1)
                    res.append('L');
                    else
                    res.append('R');

                    else
                    for (String c: bin)
                    if((Integer.valueOf(c) & 1) == 1)
                    res.append('R');
                    else
                    res.append('L');



                    //Reverse string built
                    String command = res.toString();
                    res = new StringBuilder();
                    for(int i = command.length() - 1; i >= 0; i--)
                    res.append(command.charAt(i));


                    return res.toString();


                    //Driver method
                    public static void main (String args)
                    for(int i = 0; i <= 25; i++)
                    System.out.println("The command required to produce " + i + ": " + buildCommand(i) );
                    System.out.println("The command required to produce -" + i + ": " + buildCommand(-i) );


                    int edge = Integer.MAX_VALUE;
                    System.out.println("The command required to produce " + edge + ": " + buildCommand(edge) );
                    System.out.println("The command required to produce -" + edge + ": " + buildCommand(-edge) );







                    share|improve this answer















                    EDIT: Since we have a correct and proper solution to this question, the pattern of mirroring as applied in CommandBuilder for positive integers is a misconception and should have never been used: it generates duplicate command strings for some integers. Please see CommandBuilderTwo for a more appropriate solution.




                    Given the fact that L = 0 and R = 1, we can convert the desired decimal number, P, into binary and store each digit inversely as 1 for L and 0 for R when negative



                    Let us also take these factors into consideration. For any given number P:



                    1. P could be a positive number that is the result of (2 ^ N); where 0 < N <= 32

                    2. P could be a positive number that is the result of (2 ^ N) - 1; where 0 < N <= 32

                    3. P could be any other positive number

                    4. P could be any negative number

                    We can efficiently determine the commands required to build the inputted desired number using the following solution:



                    public class CommandBuilder 

                    private static String getCommand(long N)


                    private static boolean isPowerOfTwo(long val)
                    return (int) Math.ceil( Math.log(val) / Math.log(2))
                    == (int) Math.floor(Math.log(val) / Math.log(2));


                    private static boolean isPowerOfTwoMinusOne(long val)
                    int root = (int) Math.ceil(Math.log(val) / Math.log(2));
                    return Math.pow(2, root) - 1 == val;


                    //Driver method
                    public static void main(String args)

                    for(int i = 0; i <= 25; i++)
                    System.out.println("The command required to produce " + i + ": " + getCommand(i) );
                    System.out.println("The command required to produce -" + i + ": " + getCommand(-i) );


                    int edge = Integer.MAX_VALUE;
                    System.out.println("The command required to produce " + edge + ": " + getCommand(edge) );
                    System.out.println("The command required to produce -" + edge + ": " + getCommand(-edge) );






                    This is a solution equivalent to @tevemadar's description of his solution, albeit in java.



                    public class CommandBuilderTwo 

                    private static String buildCommand(int N) N == 1)
                    return "no command can be built";

                    boolean negated = false;

                    if(N < 0)
                    N = -N;
                    negated = true;
                    else
                    --N;


                    String bin = Integer.toBinaryString(N).split("");

                    StringBuilder res = new StringBuilder();

                    if(negated)
                    for (String c: bin)
                    if((Integer.valueOf(c) & 1) == 1)
                    res.append('L');
                    else
                    res.append('R');

                    else
                    for (String c: bin)
                    if((Integer.valueOf(c) & 1) == 1)
                    res.append('R');
                    else
                    res.append('L');



                    //Reverse string built
                    String command = res.toString();
                    res = new StringBuilder();
                    for(int i = command.length() - 1; i >= 0; i--)
                    res.append(command.charAt(i));


                    return res.toString();


                    //Driver method
                    public static void main (String args)
                    for(int i = 0; i <= 25; i++)
                    System.out.println("The command required to produce " + i + ": " + buildCommand(i) );
                    System.out.println("The command required to produce -" + i + ": " + buildCommand(-i) );


                    int edge = Integer.MAX_VALUE;
                    System.out.println("The command required to produce " + edge + ": " + buildCommand(edge) );
                    System.out.println("The command required to produce -" + edge + ": " + buildCommand(-edge) );








                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 20 '18 at 21:20

























                    answered Nov 13 '18 at 21:25









                    Caleb LucasCaleb Lucas

                    6816




                    6816












                    • If 11 = 1011 = LRLL, and -11 is just LRLL reversed as LLRL, couldn't I just negate the number to positive, convert to binary with toString(2), swap the 1 for L and 0 for R, and reverse the string if it was negated?

                      – AnonymousSB
                      Nov 13 '18 at 22:18











                    • @AnonymousSB Sounds like that should work just fine too.

                      – Caleb Lucas
                      Nov 13 '18 at 22:31











                    • I think in the case of the following numbers, we discard. 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647

                      – AnonymousSB
                      Nov 14 '18 at 1:51











                    • Caleb and @AnonymousSB, I'm confused. How can 3 and -3 have the same set of instructions, LL? It seems to me the code here fails for positive numbers. Did I misunderstand something? For example, any power of 2 would include an 'L', when clearly we only need R's.

                      – גלעד ברקן
                      Nov 14 '18 at 15:28

















                    • If 11 = 1011 = LRLL, and -11 is just LRLL reversed as LLRL, couldn't I just negate the number to positive, convert to binary with toString(2), swap the 1 for L and 0 for R, and reverse the string if it was negated?

                      – AnonymousSB
                      Nov 13 '18 at 22:18











                    • @AnonymousSB Sounds like that should work just fine too.

                      – Caleb Lucas
                      Nov 13 '18 at 22:31











                    • I think in the case of the following numbers, we discard. 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647

                      – AnonymousSB
                      Nov 14 '18 at 1:51











                    • Caleb and @AnonymousSB, I'm confused. How can 3 and -3 have the same set of instructions, LL? It seems to me the code here fails for positive numbers. Did I misunderstand something? For example, any power of 2 would include an 'L', when clearly we only need R's.

                      – גלעד ברקן
                      Nov 14 '18 at 15:28
















                    If 11 = 1011 = LRLL, and -11 is just LRLL reversed as LLRL, couldn't I just negate the number to positive, convert to binary with toString(2), swap the 1 for L and 0 for R, and reverse the string if it was negated?

                    – AnonymousSB
                    Nov 13 '18 at 22:18





                    If 11 = 1011 = LRLL, and -11 is just LRLL reversed as LLRL, couldn't I just negate the number to positive, convert to binary with toString(2), swap the 1 for L and 0 for R, and reverse the string if it was negated?

                    – AnonymousSB
                    Nov 13 '18 at 22:18













                    @AnonymousSB Sounds like that should work just fine too.

                    – Caleb Lucas
                    Nov 13 '18 at 22:31





                    @AnonymousSB Sounds like that should work just fine too.

                    – Caleb Lucas
                    Nov 13 '18 at 22:31













                    I think in the case of the following numbers, we discard. 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647

                    – AnonymousSB
                    Nov 14 '18 at 1:51





                    I think in the case of the following numbers, we discard. 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647

                    – AnonymousSB
                    Nov 14 '18 at 1:51













                    Caleb and @AnonymousSB, I'm confused. How can 3 and -3 have the same set of instructions, LL? It seems to me the code here fails for positive numbers. Did I misunderstand something? For example, any power of 2 would include an 'L', when clearly we only need R's.

                    – גלעד ברקן
                    Nov 14 '18 at 15:28





                    Caleb and @AnonymousSB, I'm confused. How can 3 and -3 have the same set of instructions, LL? It seems to me the code here fails for positive numbers. Did I misunderstand something? For example, any power of 2 would include an 'L', when clearly we only need R's.

                    – גלעד ברקן
                    Nov 14 '18 at 15:28

















                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Stack Overflow!


                    • 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.

                    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%2fstackoverflow.com%2fquestions%2f53278908%2ffind-shortest-sequence-of-mathematical-operations%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







                    這個網誌中的熱門文章

                    How to read a connectionString WITH PROVIDER in .NET Core?

                    Node.js Script on GitHub Pages or Amazon S3

                    Museum of Modern and Contemporary Art of Trento and Rovereto