37
\$\begingroup\$

You have locked your bike with a combination lock of 3 digits. Now you want to go for a ride and need to unlock it with the help of following program.

Input

1st parameter

The digit combination of your lock in locked state. It must be different from the 2nd parameter (=the combination of unlocked state). (Or else your bike could be stolen!)

Range 000..999. Leading zeros must not be omitted.

2nd parameter

The digit combination of your lock in unlocked state. This value is your goal.

Range 000..999. Leading zeros must not be omitted.

Output

A list of each state of the combination lock after each "rotation" including the initial state (which is always the 1st parameter) and the last step (which is always the 2nd paramater).

Algorithm

You start "rotating" the first digit one by one until you reach the correct digit in unlocked state. But, because you are in knowledge of the whole unlock-code, you rotate the digit in the direction in which you need the smallest amount of rotations to reach the digit in unlocked state. In case of a tie you can choose whatever direction you prefer.

When you have reached the correct first digit, you start the same procedure with the 2nd and then with the 3rd.

The order of digits is to understand as a circle:

... 9 0 1 2 3 4 5 6 7 8 9 0 1 2 ...

This means, that the smallest amount of rotations from 1 to 9 is not

1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 = 8

but

1 -> 0 -> 9 = 2.

Notes

Examples

Example 1, correct

Input: 999 001

Output:
999
099
009
000
001

Example 2, correct

Input: 000 292

Output:
000
100
200
290
291
292

Example 3, wrong output

Input: 999 121

Wrong output:
999
899 // Wrong because wrong rotation direction.
799
699
...

Correct output:
999
099
199
109
119
129
120
121

Example 4, wrong input

Input: 1 212 // Wrong because no leading zeros.

This is the shortest answer wins.

\$\endgroup\$
10
  • \$\begingroup\$ May I change the order of two parameters? \$\endgroup\$
    – tsh
    Commented Aug 26, 2019 at 7:40
  • \$\begingroup\$ May we update the digits in any order as long as it's optimal? \$\endgroup\$
    – Arnauld
    Commented Aug 26, 2019 at 8:10
  • \$\begingroup\$ @Arnauld No because I unlock my lock one by one :) \$\endgroup\$
    – user11909
    Commented Aug 26, 2019 at 8:34
  • 2
    \$\begingroup\$ @Night2 No, since the program should simulate the "unlocking process" of a combination look. \$\endgroup\$
    – user11909
    Commented Aug 26, 2019 at 9:36
  • 6
    \$\begingroup\$ Related \$\endgroup\$
    – Luis Mendo
    Commented Aug 26, 2019 at 11:30

15 Answers 15

12
\$\begingroup\$

Python 2, 113 107 105 99 95 bytes

a,b=input()
i=0
print a
for x in a:
 while x-b[i]:a[i]=x=(x+(x-b[i])%10/5*2-1)%10;print a
 i+=1

Try it online!

Takes input as lists of integers


Saved:

  • -6 bytes, thanks to Joel
  • -4 bytes, thanks to Jitse
\$\endgroup\$
3
  • 2
    \$\begingroup\$ 99 bytes using a different way to calculate. \$\endgroup\$
    – Joel
    Commented Aug 27, 2019 at 1:08
  • 2
    \$\begingroup\$ 96 bytes - bonus: works for any array size \$\endgroup\$
    – Jitse
    Commented Aug 27, 2019 at 11:31
  • 1
    \$\begingroup\$ 95 bytes - since you are using Python 2, might as wel lose the // \$\endgroup\$
    – Jitse
    Commented Aug 27, 2019 at 11:47
6
\$\begingroup\$

Jelly, 15 bytes

_æ%5ḣT$ṂṠ⁸_%⁵ðƬ

A dyadic Link accepting the start-code on the left and the target-code on the right as lists of integers (in \$[0,9]\$, lengths equal but otherwise arbitrary) which yields a list of lists of the codes from start-code to target-code.

Try it online!

How?

_æ%5ḣT$ṂṠ⁸_%⁵ðƬ - Link: list of integers, s; list of integers, t
              Ƭ - collect up values until a fixed point is reached applying:
             ð  -   the dyadic chain:  (i.e. f(x, t) where x starts off as s)
_               -     subtract (t from x) (vectorises) - i.e. [ta-xa, tb-xb, tc-xc]
   5            -     literal five
 æ%             -     symmetric modulo (vectorises) - i.e. [[-4..5][ta-xa], [-4..5][tb-xb], [-4..5][tc-xc]]
      $         -     last two links as a monad:
     T          -       truthy indices  - e.g. [0,-4,1]->[2,3]
    ḣ           -       head to index (vectorises)       [[0,-4],[0,-4,1]]
       Ṃ        -     minimum                            [0,-4]
        Ṡ       -     sign (vectorises)                  [0,-1]
         ⁸      -     chain's left argument (x)
          _     -     subtract (vectorises) - i.e. move the single spindle one in the chosen direction
            ⁵   -     literal ten
           %    -     modulo (since 9+1=10 not 0)
\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6),  73 72  70 bytes

Saved 2 bytes thanks to @tsh

Takes input as 2 arrays of digits in curried syntax (a)(b). Returns a string.

a=>g=b=>b.some(x=>d=x-(a[++i]%=10),i=-1)?a+`
`+g(b,a[i]+=d/5<5/d||9):b

Try it online!

Commented

a =>                  // a[] = initial combination
g = b =>              // b[] = target combination
  b.some(x =>         // for each digit x in b[]:
    d =               //   compute the difference d:
      x -             //     between x
      (a[++i] %= 10), //     and the corresponding digit in a[]
                      //     we apply a mod 10, because it may have exceed 9
                      //     during the previous iteration
    i = -1            //   start with i = -1
  ) ?                 // end of some(); if it's truthy:
    a + `\n` +        //   append a[] followed by a line feed
    g(                //   followed by the result of a recursive call:
      b,              //     pass b[] unchanged
      a[i] +=         //     add either 1 or 9 to a[i]:
        d / 5 < 5 / d //       add 1 if d / 5 < 5 / d
        || 9          //       otherwise, add 9
    )                 //   end of recursive call
  :                   // else:
    b                 //   stop recursion and return b[]
\$\endgroup\$
1
  • \$\begingroup\$ d/6&1^d>0||9 -> d/5>5/d?9:1 \$\endgroup\$
    – tsh
    Commented Aug 26, 2019 at 8:32
2
\$\begingroup\$

Jelly, 25 bytes

_æ%5+⁹⁹rḊ€%⁵J;Ɱ"$ẎṄḢ}⁺¦¥ƒ

Try it online!

Full program.

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

Python 2, 101 97 bytes

a,c=input()
print a
for i in 0,1,2:
 while a[i]!=c[i]:a[i]=(a[i]+(a[i]-c[i])%10/5*2-1)%10;print a

Try it online!

3 bytes thx to Joel.

Takes input as lists of ints.

\$\endgroup\$
4
  • \$\begingroup\$ 98 bytes \$\endgroup\$
    – Joel
    Commented Aug 27, 2019 at 1:09
  • 1
    \$\begingroup\$ @Joel: Thanks! Actually, since it's Python 2, // is the same as /, so there's an additonal byte gained. \$\endgroup\$
    – Chas Brown
    Commented Aug 27, 2019 at 2:29
  • \$\begingroup\$ This looks like the exact same approach as @TFeld's answer, but with slight modifications \$\endgroup\$
    – Jitse
    Commented Aug 27, 2019 at 13:03
  • \$\begingroup\$ @Jitse: Well, we've both been modifying our answers; for example, he started with for x,y,i in zip(a,c,[0,1,2]) if I recall... \$\endgroup\$
    – Chas Brown
    Commented Aug 27, 2019 at 20:16
1
\$\begingroup\$

Jelly, 30 bytes

_ż+¥⁵AÞḢṠxAƊ×€ʋ"JṬ€$$Ẏ;@W}+\%⁵

Try it online!

A dyadic link taking as its left argument the unlock code and its right the current locked state, both as lists of integers.

This feels far too long!

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

PHP, 114 bytes

for([,$a,$b]=$argv;$i<3;($x=$a[$i]-$b[$i])?(print$a._).$a[$i]=($y=$a[$i]+(5/$x>$x/5?-1:1))<0?9:$y%10:++$i);echo$b;

Try it online!

My solution probably sucks, but that is the best I can think of for now!

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

Charcoal, 48 bytes

θ≔EθIιθF³«≔⁻﹪⁺⁻I§ηι§θι⁵χ⁵ζF↔櫧≔θι﹪⁺§θι÷ζ↔ζχ⸿⪫θω

Try it online! Link is to verbose version of code. Explanation:

θ

Print the initial position.

≔EθIιθ

Change the initial position string into an array of numeric digits for calculation purposes.

F³«

Loop over each digit in turn.

≔⁻﹪⁺⁻I§ηι§θι⁵χ⁵ζ

Calculate the number of rotations needed to unlock that digit. This is a number from -5 to 4 where -5 means 5 downward rotations and 4 means 4 upward rotations.

F↔ζ«

Loop over each rotation.

§≔θι﹪⁺§θι÷ζ↔ζχ

Update the digit according to the sign of the rotation.

⸿⪫θω

Output the digits as a string on a new line.

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

T-SQL 2008, 170 bytes

I added some linebreaks to make it readable

DECLARE @1 char(3)='123',@2 char(3)='956'

DECLARE @r int,@s int,@ int=0
g:SET @+=1
h:SELECT @r=substring(@1,@,1)+9,@s=@r-substring(@2+'1',@,1)
IF @s=9GOTO g
PRINT @1
SET @1=stuff(@1,@,1,(@r+@s/5%2*2)%10)
IF @<4GOTO h

Try it online

\$\endgroup\$
3
  • \$\begingroup\$ This solution doesn't keep leading 0's in the output. Example: 000-999 \$\endgroup\$
    – Matthew
    Commented Aug 26, 2019 at 19:03
  • 1
    \$\begingroup\$ @Matthew you are almost right, I was hoping to use this build in input option, however, if you start with 0 in input it will be removed from the input. It is not the solution that fails though \$\endgroup\$ Commented Aug 26, 2019 at 19:05
  • 1
    \$\begingroup\$ @Matthew - it is fixed now btw. Removed the input boxes which isn't part of sql anyway \$\endgroup\$ Commented Aug 26, 2019 at 19:15
0
\$\begingroup\$

C# (Visual C# Interactive Compiler), 101 bytes

a=>b=>{for(int i=0;i<3;i++)for(;a[i]!=b[i];a[i]+=(a[i]-b[i]+10)%10<5?9:1,a[i]%=10)Print(a);Print(a);}

Try it online!

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

J, 36 bytes

10|[+/\@,#:@4 2 1#~[:>&|/`]}10|-,:-~

Try it online!

Will add explanation tomorrow.

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

MATLAB, 100 89 bytes

A different approach (using implicit expansion to create a subtraction matrix) reduces 11 bytes:

function f(a,b);c = mod(a-b+5,10)-5;a,mod(a-cumsum(repelem(eye(3).*sign(c),abs(c),1)),10)

[Original 100 byte solution]

function f(a,b);c=mod(a-b+5,10)-5;a,for n=1:3;for r=1:abs(c(n));a(n)=mod(a(n)-sign(c(n)),10),end;end

Both called by passing the inputs as 3-element arrays, e.g. f([9 1 1], [2 3 2])

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

Java (JDK), 139 bytes

a->b->{for(int i;;a[i]+=(a[i]-b[i]+10)%10<5?9:1,a[i]%=10){System.out.println(""+a[i=0]+a[1]+a[2]);for(;i<3&&a[i]==b[i];i++);if(i>2)break;}}

Try it online!

Same algorithm as everyone, rolled differently because Java's System.out.println is pretty expensive!

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

C (clang), 125 bytes

t,*d;f(*a,*b){for(t=d=a;t?printf("%d%d%d\n",*a,a[1],a[2]):d++,t=*d-b[d-a],d-a<3;*d=(*d+=!~*d*10)%10)t?*d+=(t+10)/5&1?1:-1:0;}

Try it online!

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

Kotlin, 162 bytes

{s:Array<Int>,e:Array<Int>->var i=0
o@while(i<3){println(""+s[0]+s[1]+s[2])
while(s[i]==e[i]){if(i>1)break@o
i++}
s[i]=(s[i]+if((e[i]-s[i]+10)%10>5)9 else 1)%10}}

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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