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 }