1 #!/usr/bin/perl
  2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-200/#TASK2
  3 #
  4 # A seven segment display is an electronic component, usually used to display
  5 # digits. The segments are labeled 'a' through 'g' as shown:
  6 #
  7 #      a
  8 #   -------
  9 # f |     | b
 10 #   |  g  |
 11 #   -------
 12 # e |     | c
 13 #   |  d  |
 14 #   -------
 15 #
 16 # The encoding of each digit can thus be represented compactly as a truth table:
 17 ## my @truth = qw<abcdef bc abdeg abcdg bcfg acdfg acdefg abc abcdefg abcfg>;
 18 # For example, $truth[1] = ‘bc’. The digit 1 would have segments ‘b’ and ‘c’ enabled.
 19 #
 20 # Write a program that accepts any decimal number and draws that number as a
 21 # horizontal sequence of ASCII seven segment displays, similar to the
 22 # following:
 23 #
 24 # -------  -------  -------
 25 #       |  |     |  |     |
 26 #       |  |     |  |     |
 27 # -------                  
 28 # |        |     |  |     |
 29 # |        |     |  |     |
 30 # -------  -------  -------
 31 #
 32 # To qualify as a seven segment display, each segment must be drawn (or not drawn) according to your @truth table.
 33 #
 34 # The number "200" was of course chosen to celebrate our 200th week!
 35 
 36 
 37 ##############################################
 38 ##
 39 ## discussion
 40 ##
 41 ##############################################
 42 ##
 43 ## basically we need to find a way to print one digit after another
 44 ## since terminal output is a bit special, we basically need to
 45 ## build that number as a series of strings one after another
 46 ## then we can append the next digit as a series of strings to the
 47 ## existing ones
 48 ## at the end we can print everything
 49 ##
 50 ## in order to print longer numbers more nicely, we can als wrap long
 51 ## lines just before we reach the end of the terminal width
 52 
 53 use strict;
 54 use warnings;
 55 use feature 'say';
 56 
 57 my $dimensions = `stty size`;
 58 chomp($dimensions);
 59 my ($rows, $columns) = split /\s+/, $dimensions;
 60 
 61 my $MAX_LEN = $columns // 80;
 62 $MAX_LEN -= 9; # make sure the last digit fits completely on the line
 63 die "Terminal too small, try a bigger terminal" if $MAX_LEN < 10;
 64 my @examples = (200, 1, 17, 12425, "123423509876823456567124");
 65 my @truth = qw<abcdef bc abdeg abcdg bcfg acdfg acdefg abc abcdefg abcfg>;
 66 
 67 foreach my $number (@examples) {
 68    print_number($number);
 69 }
 70 
 71 # print a number
 72 sub print_number {
 73    my $number = shift;
 74    # split the number into individual digits
 75    my @digits = split //, $number;
 76    my @print;
 77    foreach my $digit (@digits) {
 78       # get the truth for the given digit
 79       my $truth = $truth[$digit];
 80       # split the truth into a list of segments that are to be set
 81       my @set_segments = split //, $truth;
 82       # but this list of segments into a hash table for easier access
 83       my %set = map { $_ => 1, } @set_segments;
 84       # now for each possible segment, check whether it is set or not
 85       # and append the required output to the corresponding element of
 86       # the output array
 87       if($set{"a"}) {
 88          $print[0] .= " ------- ";
 89       } else {
 90          $print[0] .= "         ";
 91       }
 92       if($set{"f"}) {
 93          $print[1] .= " |";
 94          $print[2] .= " |";
 95       } else {
 96          $print[1] .= "  ";
 97          $print[2] .= "  ";
 98       }
 99       if($set{"b"}) {
100          $print[1] .= "     | ";
101          $print[2] .= "     | ";
102       } else {
103          $print[1] .= "       ";
104          $print[2] .= "       ";
105       }
106       if($set{"g"}) {
107          $print[3] .= " ------- ";
108       } else {
109          $print[3] .= "         ";
110       }
111       if($set{"e"}) {
112          $print[4] .= " |";
113          $print[5] .= " |";
114       } else {
115          $print[4] .= "  ";
116          $print[5] .= "  ";
117       }
118       if($set{"c"}) {
119          $print[4] .= "     | ";
120          $print[5] .= "     | ";
121       } else {
122          $print[4] .= "       ";
123          $print[5] .= "       ";
124       }
125       if($set{"d"}) {
126          $print[6] .= " ------- ";
127       } else {
128          $print[6] .= "         ";
129       }
130       # if we hit the terminal width, output
131       # the digits so far and empty the array
132       # again for the remaining digits
133       if(length($print[0]) > $MAX_LEN) {
134          foreach my $line (@print) {
135             say $line;
136          }
137          @print = ();
138       }
139    }
140    # print the digits
141    foreach my $line (@print) {
142       say $line;
143    }
144 }