Search code examples
language-agnosticcode-golfrosetta-stone

Code Golf: Seven Segments


The challenge

The shortest code by character count to generate seven segment display representation of a given hex number.

Input

Input is made out of digits [0-9] and hex characters in both lower and upper case [a-fA-F] only. There is no need to handle special cases.

Output

Output will be the seven segment representation of the input, using those ASCII faces:

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

Restrictions

The use of the following is forbidden: eval, exec, system, figlet, toilet and external libraries.

Test cases:

Input:
    deadbeef

Output:
        _  _        _  _  _ 
     _||_ |_| _||_ |_ |_ |_ 
    |_||_ | ||_||_||_ |_ |  


Input:
    4F790D59

Output:
        _  _  _  _     _  _ 
    |_||_   ||_|| | _||_ |_|
      ||    | _||_||_| _| _|

Code count includes input/output (i.e full program).


Solution

  • Perl, 134 characters

    All linebreaks may be removed.

    @s=unpack"C*",~"P\xdbLI\xc3a`[\@AB\xe0t\xc8df";
    $_=<>;for$s(6,3,0){print map$s[hex$&]&1<<$_+$s?$_%2?"_":"|":" ",
    0..2while/./g;print$/}
    

    Explanation

    @s stores the bits for each segment. The entries are in order from 0 to F (thanks to hex()) and the bits map to segments in this order:

    6 7 x
    3 4 5
    0 1 2
    

    with 0 being the LSB. (Bit 6 is unused). The values are stored packed in the string bit-inverted so there are a lot more printable characters; the ~ operator flips the bits and unpack gives me numbers (perl's bitwise operators are much clumsier when it comes to strings).

    With the data in hand I read the input and proceed to loop over it three times; the only difference between the three loops is the bitmask required. For each character of input three characters of output are printed. The character to be printed is

    $s[ hex $& ] & (1 << ($_ + $s) )
    ? ($_ % 2 ? "_" : "|" )
    : " "
    

    where @s is the lookup table, $s is the shift in effect depending on the row, and $_ is whether we're printing the 1st, 2nd, or 3rd character in the row. If the right bit in the lookup table entry is false it prints a space; otherwise it prints a "|" on the sides or a "_" in the middle.