Unlock your Lock

34

4

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.

user2190035

Posted 2019-08-26T06:55:49.867

Reputation: 441

May I change the order of two parameters? – tsh – 2019-08-26T07:40:00.157

May we update the digits in any order as long as it's optimal? – Arnauld – 2019-08-26T08:10:59.967

@Arnauld No because I unlock my lock one by one :) – user2190035 – 2019-08-26T08:34:08.700

Can we print same step more than once? For example: "999 099 099 089 ..." – Night2 – 2019-08-26T09:34:32.953

2@Night2 No, since the program should simulate the "unlocking process" of a combination look. – user2190035 – 2019-08-26T09:36:44.247

6Related – Luis Mendo – 2019-08-26T11:30:19.133

Do we have to print the first iteration of the lock? – Embodiment of Ignorance – 2019-08-27T02:36:20.970

@EmbodimentofIgnorance yes – user2190035 – 2019-08-27T06:11:20.207

You should provide an example where at least one of the digits needs to be rotated down to go the correct direction. – Greg Martin – 2019-08-27T20:02:22.963

@GregMartin Done – user2190035 – 2019-08-29T06:46:20.103

Answers

12

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

TFeld

Posted 2019-08-26T06:55:49.867

Reputation: 19 246

299 bytes using a different way to calculate. – Joel – 2019-08-27T01:08:44.557

@Joel Thanks! :) – TFeld – 2019-08-27T06:56:10.607

296 bytes - bonus: works for any array size – Jitse – 2019-08-27T11:31:24.823

195 bytes - since you are using Python 2, might as wel lose the // – Jitse – 2019-08-27T11:47:55.210

@Jitse Thanks :) – TFeld – 2019-08-27T14:46:02.203

6

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)

Jonathan Allan

Posted 2019-08-26T06:55:49.867

Reputation: 67 804

4

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[]

Arnauld

Posted 2019-08-26T06:55:49.867

Reputation: 111 334

d/6&1^d>0||9 -> d/5>5/d?9:1 – tsh – 2019-08-26T08:32:46.493

2

Jelly, 25 bytes

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

Try it online!

Full program.

Erik the Outgolfer

Posted 2019-08-26T06:55:49.867

Reputation: 38 134

2

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.

Chas Brown

Posted 2019-08-26T06:55:49.867

Reputation: 8 959

98 bytes – Joel – 2019-08-27T01:09:47.920

1@Joel: Thanks! Actually, since it's Python 2, // is the same as /, so there's an additonal byte gained. – Chas Brown – 2019-08-27T02:29:40.487

This looks like the exact same approach as @TFeld's answer, but with slight modifications

– Jitse – 2019-08-27T13:03:56.230

@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... – Chas Brown – 2019-08-27T20:16:28.597

1

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!

Night2

Posted 2019-08-26T06:55:49.867

Reputation: 5 484

1

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!

Nick Kennedy

Posted 2019-08-26T06:55:49.867

Reputation: 11 829

1

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.

Neil

Posted 2019-08-26T06:55:49.867

Reputation: 95 035

1

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

t-clausen.dk

Posted 2019-08-26T06:55:49.867

Reputation: 2 874

This solution doesn't keep leading 0's in the output. Example: 000-999 – Matthew – 2019-08-26T19:03:08.530

1@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 – t-clausen.dk – 2019-08-26T19:05:43.250

1@Matthew - it is fixed now btw. Removed the input boxes which isn't part of sql anyway – t-clausen.dk – 2019-08-26T19:15:01.960

0

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!

Embodiment of Ignorance

Posted 2019-08-26T06:55:49.867

Reputation: 7 014

0

J, 36 bytes

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

Try it online!

Will add explanation tomorrow.

Jonah

Posted 2019-08-26T06:55:49.867

Reputation: 8 729

0

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])

Wolfie

Posted 2019-08-26T06:55:49.867

Reputation: 221

0

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!

Olivier Grégoire

Posted 2019-08-26T06:55:49.867

Reputation: 10 647

0

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!

AZTECCO

Posted 2019-08-26T06:55:49.867

Reputation: 2 441

0

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!

JohnWells

Posted 2019-08-26T06:55:49.867

Reputation: 611