18
\$\begingroup\$

Imagine a path made up of < and > and ending in a @, e.g.

><>@

A walker starts on the left-most cell. He will traverse the path as follows:

  • If the walker is on a @ cell, he's reached the goal and is done.
  • If the walker is on a > cell, the entire path shifts one step to the right, cyclically, taking the walker with it.
  • If the walker is on a < cell, the entire path shifts one step to the left, cyclically, taking the walker with it.
  • Afterwards, the walker takes a single step. If he's at either end of the path, he moves away from the end. Otherwise he keeps moving in the direction he moved on the last step (ignoring the rotation), walking right initially.

Let's work through the above example. The walker's position is marked with ^:

><>@   --rotate-->  @><>
^                    ^
step right (first step):
@><>   --rotate-->  ><>@
  ^                  ^
step right:
><>@   --rotate-->  @><>
  ^                    ^
step left (dead end):
@><>   --rotate-->  ><>@
  ^                  ^
step left:
><>@   --rotate-->  @><>
^                    ^
step left:
@><>   Goal reached!
^

The walker visited 6 cells in the process (including the starting cell as well as the @, and counting each cell as often as it's visited).

Here is a small example, where the walker is transported across the edges by a rotation:

>>@   --rotate-->  @>>
^                   ^
step right (first step):
@>>   --rotate-->  >@>
  ^                ^
step right (dead end):
>@>   Goal reached!
 ^

This time the walker visited 3 cells.

We can easily turn this into an integer sequence:

  • You're given a positive integer N, e.g. 9.
  • You compute the the binary representation of this integer, e.g. 1001.
  • Then turn 1 into > and 0 into < and append a @: ><<>@.
  • We associate with N the number of cells visited by the walker in the number constructed this way.

The first few elements of the resulting sequence are:

2, 3, 3, 4, 6, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
6, 10, 6, 10, 8, 8, 6, 10, 8, 8, 6, 6, 6, 6, 7, 7

This may seem quite arbitrary, but the resulting sequence actually turns out to have a lot of structure:

enter image description here

For reference, you can find the first 2048 numbers of the sequence in this pastebin.

The Challenge

You guessed it: you're to compute the above sequence. You can do that one of three ways:

  • You can produce an infinite sequence (while memory permits), either by continuously outputting (separated by non-numeric characters) values or by using some form of infinite generator in languages that support them. If you print an infinite stream to STDOUT, you don't have to print the numbers one by one, but make sure that every number would be printed after a finite amount of time (and in order). If you use this option, you should not take any input.
  • You can take an integer N as input and produce the Nth term of the sequence.
  • You can take an integer N as input and produce everything up to the Nth term of the sequence, either as a list or string using an unambiguous separator.

Since I don't want to penalise languages which can't easily convert between bases, instead of the integer N you may instead take the binary representation of N, using 0s and 1s as usual (as a list or string), with the most-significant bit first.

You may write a program or function, taking input via STDIN (or closest alternative), command-line argument or function argument and outputting the result via STDOUT (or closest alternative), function return value or function (out) parameter.

Standard rules apply.

Background

This actually computes the number of "ticks" a straight-forward interpreter of my esoteric programming language Labyrinth would need to interpret the "path" as source code. In that case, the "walker" is simply the instruction pointer (which has a position and a direction), the @ command terminates the program and < and > are source-code modification commands.

\$\endgroup\$
  • \$\begingroup\$ which of is required ? 1 , 2, or 3 and how are our submissions scored \$\endgroup\$ – Abr001am Apr 27 '16 at 19:46
  • \$\begingroup\$ @Agawa001 "You can do that one of three ways:" Choose either one of them, whichever you think is easiest for the approach and language you want to use. \$\endgroup\$ – Martin Ender Apr 27 '16 at 19:47
  • \$\begingroup\$ Why all the repeating numbers today!?! codegolf.stackexchange.com/questions/78787/… :D \$\endgroup\$ – cat Apr 28 '16 at 17:46
6
\$\begingroup\$

Jelly, 10 bytes

ð+\ḤiḤoµL‘

This function accepts a single integer in form of the list of its binary digits as input.

The algorithm is equivalent to the one from @Agawa001's answer.

Try it online! or generate the first 2048 numbers.

Background

Enumerate the positions underneath the path from 0 to L, giving a total of L + 1 positions. L coincides the number of binary digits of the number N that encodes the path. With this notation, the walker starts at position 0, the goal at position L.

With each step the walker takes, he gets one step closer to the goal (in the direction he's currently walking). Also, with each shift-step, depending on whether he walks with or against the shifting direction, he either increments or decrements his position by 2 modulo L + 1, or he stays in the current position.

To change direction, he has to land on position L - 1 (facing L) or position 1 (facing 0), then get shifted in his direction. The next step he takes will bring him back to his previous position, facing the opposite direction.

  • If L is even, L - 1 is odd, so he cannot advance from his initial position to L - 1 directly. The only way to reach it is to pass through L, getting carried to 0 and taking the next step to land on 1, then advancing to the right. This requires advancing 2L positions, which can be done in no less than L steps.

    However, after taking L steps without changing direction, he will have reached the goal. Adding one for the starting cell, we get a total of L + 1 visited cells in this case.

  • If L is odd, L - 1 is even, so he can reach that position by getting shifted (L - 1) / 2 times to the right. If position L - 1 is underneath a 1 at that time, he will get shifted to position L, turn around, and step on position L - 1 (facing leftwards).

    This may or may not happen before he reaches his goal, so there are two cases to analyze:

    • If there are less than (L + 1) / 2 occurrences of 1 in the binary expansion of N, taking L steps will not suffice to turn direction. Since these L steps bring the walker to his goal, adding one for the starting cell, we get a total of L + 1 visited cells in this case.

    • If there are at least (L + 1) / 2 occurrences of 1 in the binary expansion of N, advancing to the ((L + 1) / 2)th occurrence will require I steps, where I is the initial position of that occurrence of 1.

      Thus, after taking I steps, the walker is in position L - 1, facing leftwards. To turn directions again, he would have to walk advance leftwards to position 1. However, as in the even case, since (L - 1) - 1 is odd, this will require going through 0 and taking no less tha L steps.

      Since the initial distance to the goal in the left direction is 1, after taking I steps, the walker finds himself at distance of I + 1 from the goal after changing directions. Since I < L, we have that I + 1 ≤ L, so the next I + 1 steps will bring him to the goal.

      This gives a total of I + I + 1 = 2I + 1 taken steps. Adding one for the starting cell, we get a total of 2I + 1 + 1 = 2(I + 1) visited cells in this case.

How it works

ð+\ḤiḤoµL‘  Main link. Argument: x (list of binary digits of N)

       µ    Monadic chain. Argument: x
        L   Compute L, the length of x.
         ‘  Increment to yield L + 1.

ð           Dyadic chain. Left argument: x. Right argument: L + 1
 +\         Compute the cumulative sum of x.
            This replaces the k-th one (and all zeroes to its right) with k.
   Ḥ        Unhalve; multiply all partial sums by 2.
    i       Find the first index of L + 1.
            This either gives I + 1, the 1-based index of the ((L + 1) / 2)-th one
            or 0 if the list doesn't contain L + 1.
            The result will be 0 if x contains less than (L + 1) / 2 ones
            or if L + 1 is an odd integer.
     Ḥ      Unhalve; yield either 2(I + 1) or 0.
      o     Logical OR with L + 1; if the previous operation returned a falsy
            value (i.e., if it yielded 0), replace that value with L + 1.
\$\endgroup\$
9
\$\begingroup\$

Matlab (score=230,n=inf)

function w(s,f),b=[];e=0;for i=s:f,a=dec2bin(i);c=find(a=='1');g=numel(a)+1;if numel(c)>=g/2;if mod(g,2)==1,fprintf('%d ',g);else,d=c(g/2);fprintf('%d ',2*d);end,else,fprintf('%d ',g);end,e=e+1;if(e==100),e=0;fprintf('\n');end;end
  • The function takes s as starting index and f as ending (type inf if you want to keep on to infinite).
  • The function can go forever without any remarkable time-lag between any two outputs type h=1000000000000000000000000000000000000000000000000000;w(h,h+1) to make sure.
  • The algorithm follows a mathematical approach that i will explain later, and it does confirm Martin's referenced list, basing on this program:

    stored=[2, 3, 3, 4, 6, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 10, 6, 10, 8, 8, 6, 10, 8, 8, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 14, 8, 8, 8, 14, 8, 14, 12, 12, 8, 8, 8, 14, 8, 14, 12, 12, 8, 14, 12, 12, 10, 10, 10, 10, 8, 8, 8, 14, 8, 14, 12, 12, 8, 14, 12, 12, 10, 10, 10, 10, 8, 14, 12, 12, 10, 10, 10, 10, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 18, 10, 10, 10, 10, 10, 10, 10, 18, 10, 10, 10, 18, 10, 18, 16, 16, 10, 10, 10, 10, 10, 10, 10, 18, 10, 10, 10, 18, 10, 18, 16, 16, 10, 10, 10, 18, 10, 18, 16, 16, 10, 18, 16, 16, 14, 14, 14, 14, 10, 10, 10, 10, 10, 10, 10, 18, 10, 10, 10, 18, 10, 18, 16, 16, 10, 10, 10, 18, 10, 18, 16, 16, 10, 18, 16, 16, 14, 14, 14, 14, 10, 10, 10, 18, 10, 18, 16, 16, 10, 18, 16, 16, 14, 14, 14, 14, 10, 18, 16, 16, 14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 10, 10, 10, 18, 10, 10, 10, 18, 10, 18, 16, 16, 10, 10, 10, 18, 10, 18, 16, 16, 10, 18, 16, 16, 14, 14, 14, 14, 10, 10, 10, 18, 10, 18, 16, 16, 10, 18, 16, 16, 14, 14, 14, 14, 10, 18, 16, 16, 14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 18, 10, 18, 16, 16, 10, 18, 16, 16, 14, 14, 14, 14, 10, 18, 16, 16, 14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, 10, 18, 16, 16, 14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 22, 12, 12, 12, 22, 12, 22, 20, 20, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 22, 12, 22, 20, 20, 12, 22, 20, 20, 18, 18, 18, 18, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 22, 20, 20, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13];
    b=[];for i=1:numel(stored)
    a=dec2bin(i);
    c=find(a=='1');
    if numel(c)>=(numel(a)+1)/2
    if mod(numel(a)+1,2)==1
    b=[b numel(a)+1];
    else
    d=c((numel(a)+1)/2);
    b=[b 2*d];
    end
    else
    b=[b numel(a)+1];
    end
    end
    for i=1:numel(stored)
    if (b(i))
    if b(i)~=stored(i)
    'error',
    end
    end
    end
    
  • Since the algorithm verifies 2048 first testcases, I will blindly assume it would for any test case, so my algorithm works regarding few properties i discovered in this process without the pain of shifting and moving pointer:

    1- if the twice the number of 1's in binary translation doesnt exceed the length of the sequnce L so the output isL+1

    2- if the sequence length is even and the previous condition isnt set so the output is same L+1

    3- otherwise, the output is twice the L/2th index of 1.

\$\endgroup\$
  • \$\begingroup\$ Can you clarify what you mean with "the output is twice the L/2th index of 1."? It's incredibly unclear. \$\endgroup\$ – orlp Apr 27 '16 at 22:18
  • \$\begingroup\$ @orlp in this sequence 10010001 the second occurence of 1 is 4, by 2 is 8. \$\endgroup\$ – Abr001am Apr 27 '16 at 22:44
  • 1
    \$\begingroup\$ This can be golfed down to at least 89 bytes, a=dec2bin(input(''));c=find(a=='1');g=nnz(a)+1;if nnz(c)<g/2|mod(g,2);g,else,2*c(g/2),end, which only gives a single element of the sequence. \$\endgroup\$ – David Apr 28 '16 at 1:29
8
\$\begingroup\$

Python, 122 119 113 110 108 107 103 bytes

def l(b):
 p=e=w=len(b);d=i=1
 while e:p+=1-2*b[w-e];d*=2*(1!=d-p>~w)-1;p-=d;e=(e-d)%-~w;i+=1
 return i

Takes input as a list of binary digits. Helper function to test:

b = lambda n: [int(d) for d in bin(n)[2:]]

Credit to Lynn for saving 7 bytes.

\$\endgroup\$
  • 4
    \$\begingroup\$ Pew pew pew. :D \$\endgroup\$ – AdmBorkBork Apr 27 '16 at 20:28
  • \$\begingroup\$ It’s not much, but… I suppose p-d-1in[-2,w] saves one byte. \$\endgroup\$ – Lynn Apr 27 '16 at 20:34
  • \$\begingroup\$ Changing the statement to d*=2*(1!=d-p>~w)-1 saves four more! °v° \$\endgroup\$ – Lynn Apr 27 '16 at 20:49
  • \$\begingroup\$ @Lynn Nice use of de Morgan's laws! \$\endgroup\$ – orlp Apr 27 '16 at 21:00
  • \$\begingroup\$ can u please provide a wide output range to compare with mine ? thanx \$\endgroup\$ – Abr001am Apr 27 '16 at 21:37
3
\$\begingroup\$

Python 2, 99 bytes

def l(b):l=len(b);return(l>=sum(b)*2or l%2<1)and-~l or[i+1for i,c in enumerate(b)if b[i]][l/2]*2

Python port of Agawa001's brilliant answer.

Readable version:

def l(b):
    if len(b) >= 2*sum(b) or len(b)%2 == 0:
        return len(b) + 1

    return 2*[i+1 for i, c in enumerate(b) if b[i]][len(b)//2]
\$\endgroup\$
  • \$\begingroup\$ @Agawa001 I haven't understood your algorithm yet, but I have experimentally verified it up to 10 million. \$\endgroup\$ – orlp Apr 27 '16 at 23:15
3
\$\begingroup\$

MATL, 31, 25 bytes

BXHnQtHsy2/<w2\+~?2/Hfw)E

This is just a MATL version of Agawa001's algorithm, except it takes an integer input N and returns the N-th term in the sequence. It was tricky keeping up with all the elements in the stack! I had to resort to using a clipboard to avoid going insane. You can Try it online!

Can be made into a loop printing the first N terms by adding :"@ before the code, and ]D after.

Thanks to Luis Mendo for saving 6 whole bytes!

\$\endgroup\$
2
\$\begingroup\$

Julia 0.4, 4̷4̷ 42 bytes

x->(k=endof(x)+1;try k=2find(x)[k/2]end;k)

This function accepts a single integer in form of the list of its binary digits as input.

The algorithm is equivalent to the one from @Agawa001's answer and my Jelly answer.

Try it online!

How it works

find(x) returns the 1-based indices of all non-zero elements of x. We attempt to access the resulting array at index k / 2 and, if successful, overwrite k with twice the selected index.

This will fail if and only if one of the following is true:

  • k / 2 is a non-integral float, so and InexactError is raised.

  • The index array has less than k / 2 elements, so a BoundsError is raised.

In either case, overwriting k will fail, so its original value will be returned.

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 65 bytes

s=>(l=s.length+1)%2|!(m=s.match(`(0*1){$l/2}}`))?l:m[0].length*2

Accepts a binary string. Uses the bounce check from the various other answers.

\$\endgroup\$
1
\$\begingroup\$

Python 2, 74 bytes

def f(x):k=len(x)+1;print next((i*2for i in range(k)if k==2*sum(x[:i])),k)

This function accepts a single integer in form of the list of its binary digits as input.

The algorithm is equivalent to the one from @Agawa001's answer and my Jelly answer.

Test it on Ideone.

How it works

next attempts to find the first integer 2i for which k==2*sum(x[:i]) returns true. Since x[:i] contains i elements, this gives the 1-based index of the (k / 2)th 1.

next will fail if k/2 is non-integral or if x contains less than k / 2 ones. In this case, the default value k is returned.

\$\endgroup\$
0
\$\begingroup\$

><>, 63 bytes

2r11&>}:?v{1->:l2-%?vr{{$>1+$}$:2=$@&101.
 +&?!^&n;>{1+^ .0+bf<

From the moment I saw the example pattern in this challenge, I knew which language to use :)

Using N to get the Nth term.

Input assumed to be in binary at the stack. Rather than moving the walker around, this solution relies mostly on moving the tape under the walker.

Try it online!

\$\endgroup\$

Your Answer

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

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