When will I have a binary car?

19

I noticed that my car's odometer was at 101101 when I got to work today. Which is a cool number because it's binary (and a palindrome, but that's not important). Now, I want to know when the next time I'll have a binary odometer reading. I can't read the odometer while I'm driving, because that would be dangerous, so it'll have to be binary either when I get to work or get home.

There's really bad traffic on the way to and from my office, so I have to take a different route each day.

For the purposes of this challenge, a day is a round trip and starts with my commute to work.

You'll need to take the initial reading of the odometer and a 10 element sequence representing the amount of miles each way. This sequence should be repeated until you get to a binary odometer reading. You should then output the number of days it takes until we get to a binary reading.

Both the milage for the route and the odometer reading will be positive integers. The count of days will either be x or x.5, so your output of the day count needs to support floating point for half days. If the day count is an integer, you don't need to output the .0. The odometer will always eventually reach a binary state.

Any form of input/output is acceptable and standard loopholes are disallowed.

Test cases:

101101, [27, 27, 27, 27, 27, 27, 27, 27, 27, 27] == 165.0
1, [13, 25, 3, 4, 10, 8, 92, 3, 3, 100] == 22.5
2, [2, 3, 1, 2, 7, 6, 10, 92, 3, 7] == 2.0

Morgan Thrapp

Posted 2016-02-22T14:42:57.057

Reputation: 3 574

Will a day result only ever be an integer or an integer plus a half? – FryAmTheEggman – 2016-02-22T14:49:40.410

2@FryAmTheEggman Yes. Each step is half a day. – Morgan Thrapp – 2016-02-22T14:49:57.603

What should happen if the odometer never becomes binary? – CalculatorFeline – 2016-02-22T16:10:21.233

@CatsAreFluffy It always will. You don't have to worry about that case. – Morgan Thrapp – 2016-02-22T16:10:38.870

The days will be floating point. Could you elaborate a bit on that? – Dennis – 2016-02-22T16:37:37.997

@Dennis The day count will either be x or x.5. That's all I meant. If you want to display that by formatting a string, or some other method, that's fine. It just needs to be in the format x or x.5. – Morgan Thrapp – 2016-02-22T16:38:09.843

@MorganThrapp isn't that fixed-point? – cat – 2016-02-22T20:19:49.140

@cat You might be right, my math terminology is shaky at best. – Morgan Thrapp – 2016-02-22T20:21:01.063

5Where do you work/live that 3, 25 and 92 miles (km?) are regular acceptable commute distances? – kingofzeal – 2016-02-22T21:27:43.017

1@kingofzeal A wormhole. – Morgan Thrapp – 2016-02-22T21:30:19.303

Heh, I hit that mark just a few days earlier – 101101 km

– florian h – 2016-02-23T12:37:04.857

How many digits in the odometer? Actually, that doesn't matter, because it's a 1 that's lost in the roll-over. So we can code as if it always has enough room for one more digit. :-) – Toby Speight – 2016-02-23T15:38:41.727

1@TobySpeight It's a magical odometer with an infinite number of digits. – Morgan Thrapp – 2016-02-23T15:39:36.410

Answers

3

Jelly, 22 17 16 bytes

RịS+³DṀ=1
Ṡç1#SH

Try it online!

How it works

Ṡç1#SH     Main link. Left input: n (initial reading). Right input: A (distances)

Ṡ          Compute the sign of n. Since n is positive, this returns 1.
 ç         Apply the helper link to 1, 2, 3, ... until...
  1#         one match is found. Return the match in an array.
    S      Compute the sum of the array. This yields the match.
     H     Halve the result.


RịS+³DṀ=1  Helper link. Left argument: k (integer). Right argument: A (distances)

R          Range; yield [1, ..., k].
 ị         Retrieve the elements of A at those indices.
           Indexing in modular in Jelly.
  S        Compute the sum of the retrieved distances.
   +³      Add n (left input) to the sum.
     D     Convert the sum to base 10.
      Ṁ    Get the maximum digit.
       =1  Compare it with 1.

Dennis

Posted 2016-02-22T14:42:57.057

Reputation: 196 637

6

Javascript, 68 63 61 60 52 bytes

5 bytes off thanks @ETHproductions. 2 3 11!! bytes off thanks @NotthatCharles.

f=(i,a,m=0)=>/[^01]/.test(i+=a[m++%10])?f(i,a,m):m/2

Test here.

removed

Posted 2016-02-22T14:42:57.057

Reputation: 2 785

Darn, you beat me to it. – SuperJedi224 – 2016-02-22T16:00:48.877

Would (i+=a[++m%10]) work? – ETHproductions – 2016-02-22T16:54:35.930

@ETHproductions. Good one!! I forgot it will always be 10 – removed – 2016-02-22T17:05:58.417

why not initialize r as 0.5? Or not initialize r or m whatsoever (they should default to null, ie., 0) – Not that Charles – 2016-02-22T17:41:00.493

@NotthatCharles. Starting with .5 was smart, thanks... Unfortunately, javascript throws undefined instead setting null or 0 for uninitialized variables – removed – 2016-02-22T18:09:27.090

1You can also save a byte by making m=0 in the initializer and increment after modulo (m++%10)... at which point you can just drop r entirely. The whole method is then in the low 50s – Not that Charles – 2016-02-22T18:22:13.707

@NotthatCharles. I was sure I tried that before, thanks again ;) – removed – 2016-02-22T18:27:47.820

5

MATL, 29 26 25 bytes

`tvyyYs+V50<!A~]xx1Mf1)2/

Input format is

[27; 27; 27; 27; 27; 27; 27; 27; 27; 27]
101101

EDIT (June 10, 2016): The following link replaces v by &v (26 bytes) to adapt to changes in the language

Try it online!

`              ]           % do---while loop. Exit loop when top of stack is falsy
 t                         % duplicate. Takes first input (array) first time
  v                        % concat vertically (doubles length of array)
   yy                      % copy top two. Takes second input (todasy's value) first time
     Ys                    % cumulative sum of (repeated) miles each way
       +                   % add to today's value
        V                  % convert each number to a string
         50<!A             % true for strings than only contain '01 ' (ASCII less than 50)
              ~            % negate. This is the loop condition
                xx         % delete stack contents
                  1M       % push again array that tells which strings only contain '01 '
                    f1)    % pick index of first true entry
                       2/  % divide by 2

Luis Mendo

Posted 2016-02-22T14:42:57.057

Reputation: 87 464

3

Lua, 108 Bytes

First time using the repeat..until loop in a codegolf!

function f(o,t)i=0repeat i,o=i+1,(o+t[i%#t+1]).."."o=o:sub(1,o:find("%.")-1)until tonumber(o,2)print(i/2)end

Ungolfed

function f(o,t)               -- o can either be a number or a string, t is a table
                              -- call it like f(2,{27,14,5...})
  i=0                         -- initialise the travel count
  repeat                      -- proceed like a do..while in C
    i,o=i+1,(o+t[i%#t+1]).."."-- increment i, and add t[i] to the odometer
    o=o:sub(1,o:find("%.")-1) -- remove the decimal part of the odometer
  until tonumber(o,2)         -- tries to convert o from binary to decimal
                              -- return nil (and repeat the loop) if it can't
  print(i/2)                  -- print i/2 which is the number of days for i travels
end

After the first loop, o will have a decimal part because of tonumber, I had to remove it... And to add it for the first case, that's why I concatenate it with a ".".

Katenkyo

Posted 2016-02-22T14:42:57.057

Reputation: 2 857

3

PowerShell, 84 73 67 59 57 bytes

param($a,$b)do{$a+=$b[$i++%10]}until(!+($a-replace1))$i/2

Takes input $a and $b, expecting $b to be an explicit array of mileages (e.g., .\binary-car.ps1 1 @(13,25,3,4,10,8,92,3,3,100)). We then enter a do/until loop. Each iteration, we increment $a with the mileage in $b at position $i++ % 10 so that we continually loop through the array. This will start at zero since for the first loop the $i is not initialized, and so evaluates to $null, which equates to 0 in this context, and it's only after that evaluation that the ++ occurs.

Then, the until statement checks if our number is only 0 and 1 by first -replaceing all 1 with nothing, casting that back as an integer with +, and then taking the Boolean-not with !. If it evaluates true, we'll finish the loop, output $i / 2, and terminate the program.

Explanation for the loop conditional -- In PowerShell, any non-zero integer is $true, and any non-empty string is also $true. For example, 231145 (an integer) will change to "2345" (a string) after the -replace, which will integer-cast as 2345 (an integer), the ! of which is $false. However, 101101 (an integer) will change to "00" (a string) which will cast as 0 (an integer), the ! of which is $true. If we didn't have the +, the "00" will ! to $false since it's a non-empty string.

Edit - Saved 11 bytes by swapping equality-on-length for strictly-zero
Edit 2 -- Saved another 6 bytes by realizing that $b.count will always be 10 ...
Edit 3 -- Saved another 8 bytes by using do/until instead of for
Edit 4 -- If the object being -replaced is an integer value, don't need quotes, saving another 2 bytes

AdmBorkBork

Posted 2016-02-22T14:42:57.057

Reputation: 41 581

3

Java, 112 miles bytes

float c(int r,int[]d){float y=0;for(int i=0;;i%=d.length){y+=.5;r+=d[i++];if((""+r).matches("[01]+"))return y;}}

SuperJedi224

Posted 2016-02-22T14:42:57.057

Reputation: 11 342

3

05AB1E, 31 bytes

Code:

0IE\[²vs>sy+D§'aT«-""Qi\2/?}Ž}Ž

Somehow, the code doesn't stop running (and I can't figure out why). Apparently I forgot that there are three loops going on instead of 2. So it would still get into an infinite loop...

Try it online!

Adnan

Posted 2016-02-22T14:42:57.057

Reputation: 41 965

2

Ruby, 58

Nothing special. Just a cycle...

->s,a,i=0{a.cycle{|e|i+=0.5;break i if/[2-9]/!~'%d'%s+=e}}

Not that Charles

Posted 2016-02-22T14:42:57.057

Reputation: 1 905

How do you run it? – bogl – 2016-02-23T13:59:03.743

1@bogl It's a lambda - the easiest way is to append the params in square brackets. Or you can assign the lambda to a variable and, again, append params in square brackets. E.g., ->s,a,i=0{a.cycle{|e|i+=0.5;break i if/[2-9]/!~'%d'%s+=e}}[1, [13, 25, 3, 4, 10, 8, 92, 3, 3, 100]] or... f=->s,a,i=0{a.cycle{|e|i+=0.5;break i if/[2-9]/!~'%d'%s+=e}}; f[1, [13, 25, 3, 4, 10, 8, 92, 3, 3, 100]] – Not that Charles – 2016-02-23T18:03:32.277

1

Pyth, 36 32 30 bytes

Jvz.V0=J+J@QbI<ssM{`J2KbB;chK2

Try it here!

Explanation

Jvz.V0=J+J@QbI<ssM{`J2KbB;chK2  # Q = input sequence

Jvz                             # assign starting value to J
   .V0                          # Start an infinite loop iterating over b starting at 0
      =J                        # Set J to
        +J                      # the sum of J
          @Qb                   # and the value at Q[b % len(q)]
             I                  # if
              <      2          # lower than 2
                  {`J           # Remove duplicate digits from J 
               ssM              # Map the remaning digits back to integers and sum them
                      KbB       # if the above evals to true, save b to K and leave the loop
                         ;      # End loop body
                           hK   # Increment K because we missed one loop increment
                          c  2  # and divide it by 2 to get the days

Denker

Posted 2016-02-22T14:42:57.057

Reputation: 6 639

1

Mathematica, 92 bytes

(y=1;x=#+#2[[1]];While[!StringMatchQ[ToString@x,{"0","1"}..],x+=#2[[y++~Mod~10+1]]];N@y/2)&

Yep. Input is the odometer and a list of times. Output is the day count.

CalculatorFeline

Posted 2016-02-22T14:42:57.057

Reputation: 2 608

1

PHP, 102 98

function f($i,$s){while(1)foreach($s as$v){$d+=.5;$i+=$v;if(preg_match('/^[01]+$/',$i))return$d;}}

Ungolfed Version

function f($i,$s) {
    $d = 0;
    while(true) {
        foreach($s as $v) {
            $d += 0.5;
            $i+=$v;
            if(preg_match('/^[0|1]+$/', $i)) {
                return $d;
            }
        }
    }
}

PHP Notices can be removed of extra cost of 4 characters $d = 0; in golfed version.

Example

$i = 101101;
$s = [27, 27, 27, 27, 27, 27, 27, 27, 27, 27];
f($i,$s);

kuldeep.kamboj

Posted 2016-02-22T14:42:57.057

Reputation: 625

Removing the curly braces around the if, removing the 0 from 0.5, and removing the | between the 1 and 0 in your regex saves you 4 bytes. function f($i,$s){while(1)foreach($s as$v){$d+=.5;$i+=$v;if(preg_match('/^[01]+$/',$i))return$d;}} – Samsquanch – 2016-02-23T14:37:23.037

@Samsquanch, good suggestion, brackets and 0 before .5 clearly I missed. Changed now. – kuldeep.kamboj – 2016-02-24T04:47:14.743

0

C Sharp, 180.

Dear lord C# is long.

using System.Text.RegularExpressions;class a{double c(int a,int[]b){var d=0.5;a+=b[0];var i=1;while(!Regex.IsMatch(a.ToString(),"^[01]+$")){a+=b[i];i+=1;i=i%10;d+=0.5;}return d;}}

Morgan Thrapp

Posted 2016-02-22T14:42:57.057

Reputation: 3 574