Skip to content

Commit 1ed2964

Browse files
committed
322 blogged
1 parent 6e53728 commit 1ed2964

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
---
2+
layout: post
3+
title: "Dashing This Off: Weekly Challenge #332"
4+
author: "Dave Jacoby"
5+
date: "2025-05-22 19:14:54 -0400"
6+
categories: ""
7+
---
8+
9+
Welcome to [_**Weekly Challenge #322!**_](https://theweeklychallenge.org/blog/perl-weekly-challenge-322/) **322** is an [untouchable number](https://en.wikipedia.org/wiki/Untouchable_number). I hadn't heard about them until researching this number.
10+
11+
### Task 1: String Format
12+
13+
> Submitted by: Mohammad Sajid Anwar
14+
> You are given a string and a positive integer.
15+
>
16+
> Write a script to format the string, removing any dashes, in groups of size given by the integer. The first group can be smaller than the integer but should have at least one character. Groups should be separated by dashes.
17+
18+
#### Let's Talk About It
19+
20+
We go backwards from the end of the string, and if the current group is shorter than `i`, we pull the dash. This involves `substr`, both as an _lvalue_ and an _rvalue_. I think this is solvable going front-to-back, not back-to-front like I did it, but going through the problem mentally, I didn't think I could get the example's answers that way.
21+
22+
#### Show Me The Code!
23+
24+
```perl
25+
#!/usr/bin/env perl
26+
27+
use strict;
28+
use warnings;
29+
use experimental qw{ say state postderef signatures };
30+
31+
use List::Util qw{ sum0 };
32+
33+
my @examples = (
34+
35+
{
36+
str => 'ABC-D-E-F',
37+
i => 3,
38+
},
39+
{
40+
str => 'A-BC-D-E',
41+
i => 2,
42+
},
43+
{
44+
str => '-A-BC-DE',
45+
i => 4,
46+
},
47+
);
48+
49+
for my $example (@examples) {
50+
my $output = string_format($example);
51+
say <<"END";
52+
Input: \$str = "$example->{str}"
53+
\$i = $example->{i}
54+
Output: $output
55+
END
56+
}
57+
58+
sub string_format ($obj) {
59+
my $i = $obj->{i};
60+
my $str = $obj->{str};
61+
$str = substr( $str, 1 ) while $str =~ /^-/mx;
62+
my $l = length $str;
63+
for my $x ( reverse 0 .. $l ) {
64+
my $c = substr( $str, $x, 1 );
65+
next if $c =~ /\w/mx;
66+
next if $x + 1 >= $l;
67+
my $group = substr( $str, $x + 1 );
68+
($group) = split /-/, $group;
69+
if ( length $group < $i ) {
70+
substr( $str, $x, 1 ) = '';
71+
}
72+
}
73+
return $str;
74+
}
75+
```
76+
77+
```text
78+
$ ./ch-1.pl
79+
Input: $str = "ABC-D-E-F"
80+
$i = 3
81+
Output: ABC-DEF
82+
83+
Input: $str = "A-BC-D-E"
84+
$i = 2
85+
Output: A-BC-DE
86+
87+
Input: $str = "-A-BC-DE"
88+
$i = 4
89+
Output: A-BCDE
90+
```
91+
92+
### Task 2: Rank Array
93+
94+
> Submitted by: Mohammad Sajid Anwar
95+
> You are given an array of integers.
96+
>
97+
> Write a script to return an array of the ranks of each element: the lowest value has rank 1, next lowest rank 2, etc. If two elements are the same then they share the same rank.
98+
99+
#### Let's Talk About It
100+
101+
Ranking goes according to numeric order, so we sort the integers and remove duplicates (`uniq sort @ints`, with `uniq` coming from List::Util), and then rank the first number `1`, the second `2` and so on. I then throw that into a hash, and `map` the ranks onto the original unsorted array.
102+
103+
#### Show Me The Code!
104+
105+
```perl
106+
#!/usr/bin/env perl
107+
108+
use strict;
109+
use warnings;
110+
use experimental qw{ say state postderef signatures };
111+
use List::Util qw{ uniq };
112+
113+
my @examples = (
114+
115+
[ 55, 22, 44, 33 ],
116+
[ 10, 10, 10 ],
117+
[ 5, 1, 1, 4, 3 ],
118+
);
119+
120+
for my $example (@examples) {
121+
my @ints = $example->@*;
122+
my $ints = join ', ', @ints;
123+
my @output = rank_array( $example->@* );
124+
my $output = join ', ', @output;
125+
say <<"END";
126+
Input: \@ints = ($ints)
127+
Output: ($output)
128+
END
129+
}
130+
131+
sub rank_array (@ints) {
132+
my @sorted = uniq sort { $a <=> $b } @ints;
133+
my %ranks;
134+
my $r = 1;
135+
for my $s (@sorted) { $ranks{$s} = $r++; }
136+
return map { $ranks{$_} } @ints;
137+
}
138+
```
139+
140+
```text
141+
$ ./ch-2.pl
142+
Input: @ints = (55, 22, 44, 33)
143+
Output: (4, 1, 3, 2)
144+
145+
Input: @ints = (10, 10, 10)
146+
Output: (1, 1, 1)
147+
148+
Input: @ints = (5, 1, 1, 4, 3)
149+
Output: (4, 1, 1, 3, 2)
150+
```
151+
152+
#### If you have any questions or comments, I would be glad to hear it. Ask me on [Mastodon](https://mastodon.xyz/@jacobydave) or [make an issue on my blog repo.](https://github.com/jacoby/jacoby.github.io)

0 commit comments

Comments
 (0)