7-segment differences

26

1

I think most people around here know what a 7-segment display for digits is:

 _         _   _         _    _    _    _    _ 
| |    |   _|  _|  |_|  |_   |_     |  |_|  |_|
|_|    |  |_   _|    |   _|  |_|    |  |_|   _|

We can define the 7-segment difference (7SD) between two digits to be the number of segments that need to be toggled to switch from one to the other. E.g. the 7SD between 1 and 2 is 5 (the three horizontal segments and the lower two vertical segments need to be toggled), and the 7SD between 6 and 8 is 1.

Furthermore, we can define the 7SD between two numbers to be the sum of 7SDs between their corresponding digits. If one number is longer than the other, we assume they are right-aligned and add the number of segments needed to display the additional most-significant digits of the larger number. As an example, consider the 7SD between 12345 and 549:

  x:  1 2 3 4 5
  y:      5 4 9
7SD:  2+5+2+0+1 = 10

Your task is to compute 7SD between n and n+1, given n.

For convenience, here is the full table of 7SDs between individual digits. The row _ represents an empty position.

   _ 0 1 2 3 4 5 6 7 8 9

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

Input

  • Input is a single positive integer n.
  • You may write a program or function, taking input via STDIN (or closest alternative), command-line argument or function argument.
  • You may assume that the input is at most one less than the largest number which can be represented by your language's standard integer type, as long as that type supports at least values up to and including 127.

Output

  • You should print a single integer, the 7SD between n and n+1.
  • You may output via STDOUT (or closest alternative), function return value or function (out) argument.

Scoring

Standard rules apply, shortest code (in bytes) wins.

Test Cases

For some obscure reason, this sequence isn't in OEIS yet, although there is the closely related sequence A123587. Here are the first 100 numbers (starting with n = 1, 2, 3, ...):

5, 2, 3, 3, 1, 5, 4, 1, 4, 4, 5, 2, 3, 3, 1, 5, 4, 1, 7, 4, 5, 2, 3, 3, 1, 
5, 4, 1, 4, 4, 5, 2, 3, 3, 1, 5, 4, 1, 5, 4, 5, 2, 3, 3, 1, 5, 4, 1, 5, 4, 
5, 2, 3, 3, 1, 5, 4, 1, 3, 4, 5, 2, 3, 3, 1, 5, 4, 1, 7, 4, 5, 2, 3, 3, 1, 
5, 4, 1, 6, 4, 5, 2, 3, 3, 1, 5, 4, 1, 3, 4, 5, 2, 3, 3, 1, 5, 4, 1, 6, 4

The first input for which the 7SD is greater than 9 is 1999 which should yield 11. Here are some other larger examples:

n          7SD
1999        11
12345        1
999999      14
5699999     15
8765210248   1

Martin Ender

Posted 2016-06-12T21:10:50.327

Reputation: 184 808

Answers

8

Jelly, 25 22 21 20 bytes

‘DṁDḟ"DFị9979482ḃ5¤S

Try it online! or verify all test cases.

Background

We first increment the input n and discard all digits of n + 1 that haven't changed.

For example, if n is 5699999, we get the following.

n     : 5700000
n + 1 : 5699999
Result:  700000

All digits in this result have a fixed number of segments that have to get toggled. We can convert the list of toggles to bijective base 5 to save some bytes.

digit:   1 2 3 4 5 6 7 8 9 0
toggles: 4 5 2 3 3 1 5 4 1 2

The output is simply the sum of the individual toggles.

This works for most values of n, but special care must be taken if n + 1 has more digits than n. In this case, all digits must be 9's, and we solve this problem by chopping off a trailing 0 from n + 1.

For example, if n is 999999, we get the following.

n     :  999999
n + 1 : 1000000
Result: 100000

This works because the leading 1 evaluates to 4 toggles (distance between 0 and 1), while the actual amount of toggles is 2 (distance between 0 and 1), and suppressing one trailing 0 removes its 2 toggles from the sum.

How it works

‘DṁDḟ"DFị9979482ḃ5¤S  Main link. Argument: n

‘                     Compute n+1.
 D                    Convert n+1 from integer to base 10.
   D                  Convert n from integer to base 10.
  ṁ                   Mold the left result as the right result.
                      This chops of a 0 if n+1 has more digits than n.
    ḟ"D               Vectorized filter-false with the base 10 digits of n.
                      This removes the digits from n+1 that are identical to
                      the corresponding digits of n.
       F              Flatten the resulting list of lists.
         9979482ḃ5¤   Convert 9979482 to bijective base 5.
                      This yields [4, 5, 2, 3, 3, 1, 5, 4, 1, 2].
        ị             Retrieve the digits at the right that correspond to the
                      indices at the left.
                   S  Compute the sum of the results.

Dennis

Posted 2016-06-12T21:10:50.327

Reputation: 196 637

10

JavaScript (ES6), 46 40 bytes

f=n=>n?+"452331541"[n%10]||f(n/10|0)+2:2

Alternative formulation, also 46 40 bytes:

f=n=>n?26523308>>n%10*3&7||f(n/10|0)+2:2

Edit: Saved 6 bytes thanks to @xsot.

Neil

Posted 2016-06-12T21:10:50.327

Reputation: 95 035

If the logical or operator in ES6 behaves like the one in python you can further shorten your second code. Refer to my submission for an example. – xsot – 2016-06-13T05:11:16.667

@xsot Actually I can shorten both! I don't think it helps me to change the zero special-case because that's only 4 bytes as it is. – Neil – 2016-06-13T07:47:28.180

Wow, I'm surprised that the first one works. I expected an error. – xsot – 2016-06-13T08:42:02.487

@xsot javascript does not simply error out. It just does whatever seemed like the most correct approach during those ten days Javascript was born. . Later versions let you opt into an a bit stricter behavior, but why would anyone here do that? Shortcircuiting behavior of logical operators is pretty common, though, only PHP doing the wrong thing by always returning a boolean. – John Dvorak – 2016-06-14T07:27:41.817

@JanDvorak Actually, I was surprised by the fact that you can access an index of a string bigger than the length of the string. – xsot – 2016-06-14T08:43:29.423

@xsot That's because it's not an index, it's a property reference, so all I end up doing is referencing an undefined, hence falsey, property. – Neil – 2016-06-14T08:46:18.780

Can someone explain the magic numbers and where they came from? – Patrick Roberts – 2016-06-14T13:13:42.313

@PatrickRoberts It's the string reversed and converted from base 8 to decimal. – Neil – 2016-06-14T14:48:20.333

Oh, I just found the explanation of the string here

– Patrick Roberts – 2016-06-14T14:52:24.543

10

Python, 50 48 bytes

f=lambda n:26523308-0**n*2>>n%10*3&7or f(n/10)+2

Explanation

This function operates on the least significant digit of the number n, summing the 7SD of the digits when incremented by one until after the first non-9 digit.

26523308 is a bitmask that encodes the mapping for the digits 0-8. When n=0, which only occurs when n comprises only 9s, the answer will be off by two. This is compensated by the expression 0**n*2. As for the digit 9, the bitmask evaluates to zero which will trigger the recursive call while adding 2 to the 7SD.

xsot

Posted 2016-06-12T21:10:50.327

Reputation: 5 069

Can we have some explanation of how this does the transformation? I mean, +1 for cleverness but I got lost in the clever. – CAD97 – 2016-06-13T19:47:03.907

8

05AB1E, 31 30 28 27 26 bytes

Code:

9Ü©T%•2X›ùì•sè¹g®g-·¹Ú9Q·O

Explanation (outdated):

9Ü                              # Trim off trailing 9's
  ©                             # Copy this into the register
   T%                           # Get the last non-9 digit
     žh                         # Short for 0123456789
       •2X›ù앧                 # Compressed version of 4523315412
               ‡                # Transliterate

We are changing the following to the last non-9 digit:

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

For the special cases:

                ¹g              # Get the length of the input
                  ®g            # Get the length of the input with all trailing 9 gone
                    -           # Substract, giving the number of 9's at the end of 
                                  the input
                     2*         # Multiply by two
                       O        # Sum everything up
                        ¹Ú      # Uniquify the input
                          9Qi   # If this is equal to 9 (only 9's in the input)
                             Ì  #   Increment by 2 (_ -> 1)

Uses the CP-1252 encoding. Try it online!.

28 byte alternative: D[¤©•2X›ùì•sès®9Ê#¨]\rÚ9Q4*O.

Adnan

Posted 2016-06-12T21:10:50.327

Reputation: 41 965

5

Java, 63 bytes

The world is righted as Python passes Java once more.

Cause, ya know, Java.

int f(int n){return n>0?n%10<9?26523308>>n%10*3&7:2+f(n/10):2;}

See it on ideone

Maxes out at 2147483647, as that is Java's Integer.MAX_VALUE.

This is a port of my Python answer which is a port of the ES6 answer.

CAD97

Posted 2016-06-12T21:10:50.327

Reputation: 1 367

3

MATL, 61 39 36 bytes

tQvV15\'3dAsMh818RG5'6Y27WZaw)Z}Z~Bz

Try it online!

Explanation

tQv            % Implicit input. Duplicate, add 1, concatenate vertically
V              % Convert to 2D char array: each number in a row, possibly left-padded 
               % with a space
15\            % Modulo 15. With modular indexing this corresponds to the order
               % '9', ' ', '0', '1', ..., '8'
'3dAsMh818RG5' % This string encodes active segments for each of the 11 chars
6Y2            % Source alphabet printable ASCII chars (predefined literal)
7W             % Target alphabet: [0 1 ... 127]
Za             % Base conversion: decode string into vector of 11 numbers, where each
               % number from 0 to 127 encodes the 7-segment representation of a digit,
               % in the order '9', ' ', '0', '1', ..., '8'
w              % Swap top two elements in stack
)              % Use as index. Gives 2-row array, where each column is a digit 
Z}             % Split into the two rows
Z~             % Bitwise XOR, elementwise
B              % Convert to binary. Each number gives a row
z              % Number of nonzero elements. Implicitly display

Luis Mendo

Posted 2016-06-12T21:10:50.327

Reputation: 87 464

3

Julia, 44 bytes

!x=x<1?2:(t=x%10÷1)<9?3045058÷6^t%6:2+!.1x

Try it here.

Dennis saved a byte!

Lynn

Posted 2016-06-12T21:10:50.327

Reputation: 55 648

1Out of curiosity, why not just use the numbers? – Conor O'Brien – 2016-06-12T22:33:26.210

I can't believe there's a Julia TIO. Welp, time to learn Julia then... – Mama Fun Roll – 2016-06-14T04:58:35.677

3

Python, 71 66 bytes

48 bytes by xsot. Even more magic maths!

f=lambda n:(2+f(n/10)if n%10==9else 26523308>>n%10*3&7)if n else 2

See it on ideone

Because the prior Python answer doesn't work and is far from optimal. A simple port of a previous ES6 version. Now using bit twiddling (from the ES6 alternate formulation) to cut out a cast!

Can be made to work with Python 3 by explicitly using floordiv for +1 byte.

CAD97

Posted 2016-06-12T21:10:50.327

Reputation: 1 367

you can take out the space after 9 – Maltysen – 2016-06-13T01:26:24.387

@Maltysen apparently you are correct. I thought it would error because e is a valid letter after a num in, for example, 9e9. – CAD97 – 2016-06-13T01:30:04.390

This is longer than my Java answer! How can we remedy this? Note that reversing the comparison from n%10==9 to n%10<9 doesn't save as the if doesn't need a space in this order.

– CAD97 – 2016-06-13T02:23:12.573

And I come back to see xsot has made a much shorter Python version. Well done! – CAD97 – 2016-06-13T19:50:19.903

2

Pyth - 78 30 27 bytes

That first one was embarrassing.

s@LjC"
(J"ThC{I#.tjRThBQT

Test Suite.

Maltysen

Posted 2016-06-12T21:10:50.327

Reputation: 25 023

26 bytes – Leaky Nun – 2016-06-12T23:15:07.647

26 bytes – Leaky Nun – 2016-06-12T23:24:27.870

2

Jolf, 32 bytes

Ώ?H?<γ%Ht9P."452331541"γ+2Ώc/Ht2

Try it here!

Explanation

This is a transpilation of Neil's answer.

Ώ?H?<γ%Ht9P."452331541"γ+2Ώc/Ht2
Ώ                                 define a function Ώ of H
 ?H                            2  (when H is zero, return is 2)
      %Ht                         H mod 10
     γ                            γ = ^
   ?<    9                        is it less than 9?
                                  if so:
           ."452331541"γ           get the γth element of that string
          P                        as a number
                                  else
                        +2         add two to
                          Ώ        Ώ over
                           c/Ht    int(H / 10)

Conor O'Brien

Posted 2016-06-12T21:10:50.327

Reputation: 36 228

0

J, 53 bytes

2:`((2+10$:@<.@%~[)`(6|3045058<.@%6^])@.(9>])10&|)@.*

Originally based on @Neil's solution. Then improved by saving a byte using the same formula in @Lynn's solution.

The 54 byte version based on the string is

2:`((2+10$:@<.@%~[)`('452331541'".@{~])@.(9>])10&|)@.*

Usage

   f =: 2:`((2+10$:@<.@%~[)`(6|3045058<.@%6^])@.(9>])10&|)@.*
   f 1999
11
   f 1999 12345 999999 5699999 8765210248
11 1 14 15 1

miles

Posted 2016-06-12T21:10:50.327

Reputation: 15 654

0

Retina, 34 bytes

M!`.9*$
^9
0
T`d`4523315412
.
$*
.

Try it online! (The first line just allows the processing of multiple test cases at once.)

Explanation

Like most answers have discovered by now, we don't need to use the full table, since only the least-significant non-9 digit changes when incrementing. That's also how this answer works.

M!`.9*$

This matches (M) the regex .9*$ i.e. the first digit that is only separated by 9s from the end. The ! tells Retina to replace the input with this match, discarding everything that doesn't affect the 7SD.

^9
0

If the input now starts with a 9 that means, the input itself consisted only of 9s, so the 7-segment display needs to prepend a 1 which costs 2. The simplest way to handle this is to replace the leading 9 in this case with a 0, since the cost of incrementing a 9 (to 0) is 2 and the cost of incrementing 0 (to 1) is 4, so this raises the overall cost by 2 as required.

T`d`4523315412

Now we have a transliteration stage which replaces each digit with its cost for incrementing it (since the d expands to 0123456789). Note that this is the first subdiagonal of the 7SD table.

.
$*

This replaces each digit n with n copies of 1, i.e. it converts each digit to unary, and since there are no separators immediately adds them together.

.

Finally, we count the number of characters (i.e. number of matches of .) in the result, which converts the unary sum back to decimal.

Martin Ender

Posted 2016-06-12T21:10:50.327

Reputation: 184 808