How to create a numeric ruler and evenly spaced numeric width markers

Viewed 90

I am new to Perl. An exercise, where I am to create a numeric ruler from which, I size columns for data at 20 characters-width, is proving a little difficult to complete. So far, I have,

printf “%10d” x 5, (1..6);

@ruler = (1..10) x 7;
Print @ruler, “\n”;

It should look something like,

1         2         3         4
1234567890123456789012345678901234567890

What I get for the top row of numbers is an error, ‘Redundant argument in printf at <script.pl> line #; the bottom row produces numbers from 1 to 10, as it ought with the range operator, but I would like it to produce 1 to 9 with a zero on the end. I did think to start the range from 0, but I haven’t figured out how to remove the first index and only the first index.

I would be grateful for your guidance with both issues.

2 Answers

The warning is due to the fact that you pass 6 numbers to printf, but the format only requires 5.


To me,

1         2         3         4
1234567890123456789012345678901234567890

reads as

11, 12, 13, ..., 19, 10, 21, 22, 23, ...

Why does it start with 11? Why is 10 between 19 and 21?

The following makes more sense:

          1         2         3         4
01234567890123456789012345678901234567890      0-based

and

         1         2         3         4
1234567890123456789012345678901234567890       1-based

I'm not going to give the solution outright.

  • If you want the numbers 1 to 9 and 0, that would be 1..9, 0.
  • %10d will add padding on the left. %-10d will add padding on the right.
  • Nothing says you can't prefix the output with something that doesn't repeat, like a zero or a space.

Provided desired output starts count from 11 instead 1 -- it doesn't look right.

Perhaps OP intended to start count from 1 until some $max value with placing a digit representing tens above main counter.

Please study following code sample for compliance with your requirements.

use strict;
use warnings;
use feature 'say';

my $max = shift || 45;

rule($max);

sub rule {
    my $max = shift;
    
    my($a,$b);
    $a .= ' ' x 9 . $_ for 1..$max/10;
    $b .= $_ % 10      for 1..$max;
    
    say $a . "\n" . $b;
}

Output

         1         2         3         4
123456789012345678901234567890123456789012345

Original OP's code requires slight modification to achieve desired output

use strict;
use warnings;
use feature 'say';

my $max = shift || 45;

printf "%10d" x int($max/10) . "\n", (1..$max/10);
print  $_ % 10 for 1..$max;
print "\n";
Related