Seven Segment Scrolling

15

2

Sandbox Post

Intro

The information panels are everywhere. When the technology became cheaper, the paper posters were transformed into luminous signs that show words that appear on one side and come out on the other, like the one on the figure:

enter image description here

When one of these signs starts up, it usually starts empty and the text leaves from the right side to the left, moving until it disappears.

Its functionality is to go on and off the small light bulbs (LEDs) to give the sensation of movement.

If instead of text we only need to show numbers, the poster can be much less sophisticated using the so-called seven-segment markers like the following:

enter image description here

In this case each number is represented by the combination on / off of only 7 light segments that allow to represent all the numbers:

enter image description here

The question we ask ourselves is how many changes of lights (how many on and off) should be made to pass through one of these posters a certain number?

For example, to show the 123 in a 3-digit sign that starts with all the LEDs off we will have:

enter image description here

This makes a total of 42 changes of lights.


Challenge

Given a non-negative number and a positive sign length calculate the number of lights changes.

Rules

  • Assume input consist in a non-negative number (N >= 0) and a positive sign length (M > 0)
  • Assume Sign length >= Number length (M >= digits(N))

Test cases

123, 3        => 42
45, 5         => 60
111, 3        => 12
98765, 10     => 220
0, 3          => 36

Luis felipe De jesus Munoz

Posted 2018-08-22T18:12:13.927

Reputation: 9 639

https://en.wikipedia.org/wiki/Seven-segment_display#Displaying_letters useful link – qwr – 2018-08-22T18:20:13.590

1

What's the goal of the question? In reality, a part like MAX7219 will control the 8 digits, to have them displayed you would just send the 8 digits to the MAX7219 via SPI commands. The decimal point 8th bit from 1 or 2 digits would be used to for the -/+ light. For instance, 4 could be daisychained to make an 8 x 32 dot display to scroll text across, like this one I made: https://www.youtube.com/watch?v=hwYqgyMc5S4

– CrossRoads – 2018-08-22T18:18:14.377

3@CrossRoads Actually this is not intended for a real hardware answer or anything like this. It is a challenge to create an algorithm which can output the number of lights changes of a given number in multiples 7-segment displays – Luis felipe De jesus Munoz – 2018-08-22T19:18:03.837

1Suggested test case: 0,3 => 36 – Chas Brown – 2018-08-22T22:21:52.480

1May we take the first integer as a string, or list of digits? – Οurous – 2018-08-22T23:38:39.800

1@Οurous no, you must take both inputs as integer – Luis felipe De jesus Munoz – 2018-08-23T00:40:52.993

I'm with @CrossRoads - it's a pointless challenge as no hardware would ever work this way. – Alnitak – 2018-08-23T07:13:01.823

1@Alnitak This is not intented to work in real world. It is just a programming challenge. Nothing to do with how real hardware works..... – Luis felipe De jesus Munoz – 2018-08-23T11:50:14.927

Answers

7

Python 2, 129 126 119 104 bytes

def f(n,k,p=0):z=p<1or n>0;q=-~ord('}/lx2Z^o~z'[n%10])*z;return(z and f(n/10,k,q))+k*bin(p^q).count('1')

Try it online!

Thx for a big 15 bytes from ovs.

As specified, takes a non-negative number and a positive sign length, and returns total changes.

Chas Brown

Posted 2018-08-22T18:12:13.927

Reputation: 8 959

4What the actual fuck is this sorcery. You are a Python Lord. I get so happy getting my code under 200 bytes then you show up with '7367355777e0d93bf0fb' – Don Thousand – 2018-08-23T00:40:06.680

@Rushabh Mehta: Heh heh. Well, I'm only standing on the shoulders of giants. Check out these tips posted by the true Jedi Knights. The string strategy I learned from here.

– Chas Brown – 2018-08-23T03:35:59.913

2104 bytes or 102 bytes with an unprintable (\x7f) between p and {. – ovs – 2018-08-23T12:09:35.217

@ovs: Nice adjustment! – Chas Brown – 2018-08-23T19:41:22.520

3

JavaScript (Node.js), 104 94 93 93 bytes

Saved 1 byte thanks to @Shaggy

B=n=>n&&n%2+B(n>>1)
F=(d,w,q)=>w*B(q^(q=d&&"w`>|i]_p}".charCodeAt(d%10)))+(d&&F(d/10|0,w,q))

Try it online!

ETHproductions

Posted 2018-08-22T18:12:13.927

Reputation: 47 880

I think this works for -1 byte.

– Shaggy – 2018-08-22T20:21:43.613

@Shaggy Nice trick, thanks! – ETHproductions – 2018-08-22T22:33:45.840

OP has clarified that both inputs must specifically be integers (and not lists of digits or strings) – Οurous – 2018-08-23T00:47:55.410

@Οurous Thanks, fixed at +0 bytes. – ETHproductions – 2018-08-23T01:08:38.500

1Also, I think 0,3 should give 36; you give 0. (I had the same problem - fixing this cost me about 10 bytes grrrr... :) ). – Chas Brown – 2018-08-23T06:03:37.913

You can save 3 bytes by using Buffer().

– Arnauld – 2018-08-23T22:37:21.323

3

Jelly, 23 bytes

Dị“¤]þ+>~Œ¶?w‘Ø0j^ƝBFS×

A dyadic link accepting the integer to display on the left and the sign length on the right which yields the number of changes (also works if the number of digits in the integer to display is greater than the sign length).

Try it online!

How?

During the entire show each 7-segment display (at some point) transitions from empty to the first digit, then to the second and so on, and finally from the last to empty again. The transitions each cost the bitwise XOR of the on-segments of the from-digit and to-digit (where empty is a "digit" with 0 on-segments). I stole the on-segments as integers from a previous revision of ETHproductions' answer, but any permutation of the 7 segments would do just as well.

Dị“¤]þ+>~Œ¶?w‘Ø0j^ƝBFS× - Link: integer to display, V; integer sign length, L  e.g. 123, 3
D                       - cast V to decimal digits                                  [1,2,3]
  “¤]þ+>~Œ¶?w‘          - code-page indices list = [3,93,31,43,62,126,19,127,63,119]
 ị                      - index into (1-based & modular) (vectorises)             [3,93,31]
              Ø0        - literal = [0,0]                                             [0,0]
                j       - join                                                [0,3,93,31,0]
                  Ɲ     - pairwise application of:
                 ^      -   bitwise XOR                                        [3,94,66,31]
                   B    - convert to binary digits (vectorises)               [[1,1],[1,0,1,1,1,1,0],[1,0,0,0,0,1,0],[1,1,1,1,1]]
                    F   - flatten                                             [1,1,1,0,1,1,1,1,0,1,0,0,0,0,1,0,1,1,1,1,1]
                     S  - sum                                                            14
                      × - multiply by L                                                  42

Jonathan Allan

Posted 2018-08-22T18:12:13.927

Reputation: 67 804

Could you save a byte by taking the number as a digit array? https://tio.run/##ATsAxP9qZWxsef//4buL4oCcwqRdw74rPn7FksK2P3figJjDmDBqXsadQkZTw5f///9bOSw4LDcsNiw1Xf8xMA

– Shaggy – 2018-08-22T20:26:35.477

Yes, but "Given a non-negative number" and "input consist in a non-negative number" seemed strict to me. – Jonathan Allan – 2018-08-22T21:17:15.940

2

Japt, 31 30 bytes

Adapted from Jonathan's Jelly solution. Takes input in reverse order with the number to be displayed as a digit array.

*Vm!c"w]+>~?" pT ä^T x_¤¬x

Try it

Shaggy

Posted 2018-08-22T18:12:13.927

Reputation: 24 623

OP has clarified that both inputs must specifically be integers (and not lists of digits or strings) – Οurous – 2018-08-23T00:48:17.320

2

Clean, 280 bytes

import StdEnv,Data.List
~ =toInt
?s=sum[(~s>>p)rem 2\\p<-[0..6]]
$n l#j=repeatn l 0
#n=j++[~c-47\\c<-:toString n]++j
#k=[getItems(map((!!)[0,119,3,62,31,75,93,125,19,127,95])n)[i-l..i-1]\\i<-[0..length n]]
=sum(zipWith@(tl k)k)
@[u][]= ?u
@[u:x][v:y]= ?((bitxor)u v)+ @x y
@[][]=0

Try it online!

There has to be a shorter way..

Οurous

Posted 2018-08-22T18:12:13.927

Reputation: 7 916

1

Charcoal, 40 bytes

≔⁺×⁷0⭆S§⪪”)∧??%←⁶%*An”⁷IιθI×NΣEθ¬⁼ι§θ⁺⁷κ

Try it online! Link is to verbose version of code. Works by converting the input into the binary segment values, then counting the number of changes between each character. Explanation:

      S                     Convert first input to string
     ⭆                      Map over digits and join
         ”)∧??%←⁶%*An”      Compressed segment value string
        ⪪             ⁷     Split into groups of seven characters
                        ι   Current digit
                       I    Convert to integer
       §                    Index into groups
    0                       Literal `0`
  ×⁷                        Repeat seven times
 ⁺                          Concatentate
≔                        θ  Assign to variable `q`

     θ          Variable `q`
    E           Map over characters
             κ  Current index
           ⁺⁷   Add seven
          θ     Variable `q`
         §      Cyclically index
        ι       Current character
       ⁼        Compare
      ¬         Logical not
   Σ            Sum results
  N             Second input
 ×              Multiply
I               Cast to string
                Implicitly print

Neil

Posted 2018-08-22T18:12:13.927

Reputation: 95 035

1

JavaScript (Node.js), 88 bytes

Takes input as (integer)(width).

n=>w=>[...n+'',g=n=>n&&1+g(n&n-1)].map(c=>s+=g(x^(x=Buffer('w$]m.k{%o')[c])),x=s=0)|s*w

Try it online!

How?

Given a list \$\{d_1,d_2,\dots,d_n\}\$ of \$n\$ digits and a display width \$w\$, the total number \$N\$ of light changes is given by:

$$N=({T'}_{d_1}+\sum_{i=2}^n{T_{d_{i-1},d_i}}+{T'}_n)\times w$$

Where \$T_{x,y}\$ is the number of light changes for a transition from digit \$x\$ to digit \$y\$ and \${T'}_{x}\$ is the number of light changes for a transition from the blank digit to digit \$x\$ (or the other way around).

Commented

n => w =>                       // n = integer; w = width of display
  [ ...n + '',                  // coerce n to a string and split it
    g = n =>                    // g = helper function counting the number of 1's
      n && 1 + g(n & n - 1)     // by defining it here, we also force an extra iteration
  ]                             // with an undefined digit (interpreted as the blank digit)
  .map(c =>                     // for each entry c in this array:
    s += g(                     //   add to s the result of a call to g():
      x ^ (x =                  //     XOR the previous value of x
        Buffer('w$]m.k{%?o')[c] //     with the new one, picked from a 10-entry lookup
      )                         //     gives undefined (coerced to 0) for the last entry
    ),                          //   end of call to g()
    x = s = 0                   //   start with x = 0 and s = 0
  ) | s * w                     // end of map(); return s * w

Arnauld

Posted 2018-08-22T18:12:13.927

Reputation: 111 334