The weekly challenge 267 - Task 2: Line Counts

 1 #!/usr/bin/perl
 2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-267/#TASK2
 3 #
 4 # Task 2: Line Counts
 5 # ===================
 6 #
 7 # You are given a string, $str, and a 26-items array @widths containing the width of each character from a to z.
 8 #
 9 # Write a script to find out the number of lines and the width of the last line
10 # needed to display the given string, assuming you can only fit 100 width units
11 # on a line.
12 #
13 ## Example 1
14 ##
15 ## Input: $str = "abcdefghijklmnopqrstuvwxyz"
16 ##        @widths = (10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10)
17 ## Output: (3, 60)
18 ##
19 ## Line 1: abcdefghij (100 pixels)
20 ## Line 2: klmnopqrst (100 pixels)
21 ## Line 3: uvwxyz (60 pixels)
22 #
23 ## Example 2
24 ##
25 ## Input: $str = "bbbcccdddaaa"
26 ##        @widths = (4,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10)
27 ## Output: (2, 4)
28 ##
29 ## Line 1: bbbcccdddaa (98 pixels)
30 ## Line 2: a (4 pixels)
31 #
32 ############################################################
33 ##
34 ## discussion
35 ##
36 ############################################################
37 #
38 # Split the string into its characters. For each character, check if it still fits
39 # into the current line. If it doesn't, reset the length of the current line to 0 and
40 # add the width to this new line. In the end, we will have the number of lines and
41 # the current length, so we just print both.
42 
43 use strict;
44 use warnings;
45 
46 line_counts( "abcdefghijklmnopqrstuvwxyz", 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10);
47 line_counts( "bbbcccdddaaa", 4,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10);
48 
49 sub line_counts {
50    my ($str, @widths) = @_;
51    print "Input: \$str    = \"$str\"\n";
52    print "       \@widths = (", join(",", @widths), ")\n";
53    my $line_width = 100;
54    my $current = 0;
55    my $line_count = 0;
56    foreach my $char (split //, $str) {
57       my $idx = ord($char) - 97;
58       if($current + $widths[$idx] > $line_width) {
59          # We would have an overflow, so reset the current length to 0
60          $current = 0;
61       }
62       if($current == 0) {
63          # this is either a new line or the first one
64          # add 1 to line_count in both cases, as we start
65          # with 0 above.
66          $line_count++;
67       }
68       $current += $widths[$idx];
69    }
70    print "Output: ($line_count, $current)\n";
71 }