1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
#!/usr/bin/env perl
# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
#=============================================================================
# ch-2.pl
#=============================================================================
# Copyright (c) 2021, Bob Lied
#=============================================================================
# Perl Weekly Challenge 02 Task #3 Hash-counting string
# You are given a positive integer $N.
# Write a script to produce Hash-counting string of that length.
#
# The definition of a hash-counting string is as follows:
# - the string consists only of digits 0-9 and hashes, ‘#’
# - there are no two consecutive hashes: ‘##’ does not appear in your string
# - the last character is a hash
# - the number immediately preceding each hash (if it exists) is the position
# of that hash in the string, with the position being counted up from 1
#
# It can be shown that for every positive integer N there is exactly one such
# length-N string.
# Examples:
# (a) "#" is the counting string of length 1
# (b) "2#" is the counting string of length 2
# (c) "#3#" is the string of length 3
# (d) "#3#5#7#10#" is the string of length 10
# (e) "2#4#6#8#11#14#" is the string of length 14
#=============================================================================
use strict;
use warnings;
use 5.032;
use experimental qw/signatures/;
use Getopt::Long;
my $doTest = 0;
my $verbose = 0;
GetOptions("test" => \$doTest, "verbose" => \$verbose);
exit(!runTest()) if $doTest;
sub Usage { "Usage: $0 N" }
my $N = shift;
die "Need a positive integer", Usage() unless defined $N && $N >= 0;
say hashCountingString($N);
sub hashCountingString($N)
{
my $place = $N;
# Flip back and forth between printing positions and hashes.
use constant HASH => 1;
use constant PLACE => 2;
# Build backwards, last character will be #
my $str = "#";
my $prev = HASH;
while ( $place > 1 )
{
if ( $prev == HASH ) { $str = "$place$str"; $place -= length($place); $prev = PLACE; }
else { $str = "#$str" ; $place-- ; $prev = HASH; }
say "N=[$N] place=[$place] str=[$str]" if $verbose;
}
return $str;
}
sub runTest
{
use Test::More;
is( hashCountingString( 1), "#", "H 1" );
is( hashCountingString( 2), "2#", "H 2" );
is( hashCountingString( 3), "#3#", "H 3" );
is( hashCountingString( 8), "2#4#6#8#", "H 8" );
is( hashCountingString( 9), "#3#5#7#9#", "H 9" );
is( hashCountingString( 10), "#3#5#7#10#", "H 10" );
is( hashCountingString( 14), "2#4#6#8#11#14#", "H 14" );
is( hashCountingString(102), "2#4#6#8#11#14#17#20#23#26#29#32#35#38#41#44#47#50#53#56#59#62#65#68#71#74#77#80#83#86#89#92#95#98#102#", "H 102" );
done_testing;
}
|