15
\$\begingroup\$

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
\$\endgroup\$
  • 1
    \$\begingroup\$ 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: youtube.com/watch?v=hwYqgyMc5S4 \$\endgroup\$ – CrossRoads Aug 22 '18 at 18:18
  • 3
    \$\begingroup\$ @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 \$\endgroup\$ – Luis felipe De jesus Munoz Aug 22 '18 at 19:18
  • 1
    \$\begingroup\$ Suggested test case: 0,3 => 36 \$\endgroup\$ – Chas Brown Aug 22 '18 at 22:21
  • 1
    \$\begingroup\$ May we take the first integer as a string, or list of digits? \$\endgroup\$ – Οurous Aug 22 '18 at 23:38
  • 1
    \$\begingroup\$ @Οurous no, you must take both inputs as integer \$\endgroup\$ – Luis felipe De jesus Munoz Aug 23 '18 at 0:40
7
\$\begingroup\$

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.

\$\endgroup\$
  • 4
    \$\begingroup\$ What 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' \$\endgroup\$ – Don Thousand Aug 23 '18 at 0:40
  • \$\begingroup\$ @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. \$\endgroup\$ – Chas Brown Aug 23 '18 at 3:35
  • 2
    \$\begingroup\$ 104 bytes or 102 bytes with an unprintable (\x7f) between p and {. \$\endgroup\$ – ovs Aug 23 '18 at 12:09
  • \$\begingroup\$ @ovs: Nice adjustment! \$\endgroup\$ – Chas Brown Aug 23 '18 at 19:41
3
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ Could you save a byte by taking the number as a digit array? tio.run/##ATsAxP9qZWxsef//… \$\endgroup\$ – Shaggy Aug 22 '18 at 20:26
  • \$\begingroup\$ Yes, but "Given a non-negative number" and "input consist in a non-negative number" seemed strict to me. \$\endgroup\$ – Jonathan Allan Aug 22 '18 at 21:17
3
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ I think this works for -1 byte. \$\endgroup\$ – Shaggy Aug 22 '18 at 20:21
  • \$\begingroup\$ @Shaggy Nice trick, thanks! \$\endgroup\$ – ETHproductions Aug 22 '18 at 22:33
  • \$\begingroup\$ OP has clarified that both inputs must specifically be integers (and not lists of digits or strings) \$\endgroup\$ – Οurous Aug 23 '18 at 0:47
  • \$\begingroup\$ @Οurous Thanks, fixed at +0 bytes. \$\endgroup\$ – ETHproductions Aug 23 '18 at 1:08
  • 1
    \$\begingroup\$ Also, I think 0,3 should give 36; you give 0. (I had the same problem - fixing this cost me about 10 bytes grrrr... :) ). \$\endgroup\$ – Chas Brown Aug 23 '18 at 6:03
2
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ OP has clarified that both inputs must specifically be integers (and not lists of digits or strings) \$\endgroup\$ – Οurous Aug 23 '18 at 0:48
2
\$\begingroup\$

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..

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

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
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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