| 06 March 2026 | Challenge 363 |
Lying Sheriffs
Task 1: String Lie Detector
Submitted by: Mohammad Sajid Anwar
You are given a string.
Write a script that parses a self-referential string and determines whether its claims about itself are true. The string will make statements about its own composition, specifically the number of vowels and consonants it contains.
Example 1
Input: $str = "aa — two vowels and zero consonants"
Output: true
Example 2
Input: $str = "iv — one vowel and one consonant"
Output: true
Example 3
Input: $str = "hello - three vowels and two consonants"
Output: false
Example 4
Input: $str = "aeiou — five vowels and zero consonants"
Output: true
Example 5
Input: $str = "aei — three vowels and zero consonants"
Output: true
Solution
Need to make some assumption about the given string:
- The string has two parts: a subject and a statement
- subject and statement are separated by
<space><dash><space>, where<dash>is any character having the Unicode propertyDash_Punctuation. - A statement has the form
<X> vowel[s] and <Y> consonant[s] - Grammar doesn’t need to be correct:
one vowelsis acceptable as well astwo vowel. - case is not significant
- characters in the subject outside the range
a-zare ignored
The second assumption results from the examples, where <dash> turns out to be one of "\N{EM DASH}" and
"\N{HYPHEN-MINUS}".
Generalizing to their common category, so e.g. "\N{HYPHEN}" may be used, too.
Using Lingua::EN::Words2Nums to convert English words to numbers and tr/// to count vowels and consonants.
use strict;
use warnings;
use Lingua::EN::Words2Nums;
sub string_lie_detector {
my ($subject, $vowels, $consonants) =
lc(shift) =~ /^(.*?)\s\p{Pd}\s(.*?) vowels? and (.*?) consonants?$/
or return;
words2nums($vowels) == $subject =~ tr/aeiou// or return;
words2nums($consonants) == $subject =~ tr/bcdfghjklmnpqrstvwxyz// or return;
1;
}
See the full solution to task 1.
Task 2: Subnet Sheriff
Submitted by: Peter Campbell Smith
You are given an IPv4 address and an IPv4 network (in CIDR format).
Write a script to determine whether both are valid and the address falls within the network. For more information see the Wikipedia article.
Example 1
Input: $ip_addr = "192.168.1.45"
$domain = "192.168.1.0/24"
Output: true
Example 2
Input: $ip_addr = "10.0.0.256"
$domain = "10.0.0.0/24"
Output: false
Example 3
Input: $ip_addr = "172.16.8.9"
$domain = "172.16.8.9/32"
Output: true
Example 4
Input: $ip_addr = "172.16.4.5"
$domain = "172.16.0.0/14"
Output: true
Example 5
Input: $ip_addr = "192.0.2.0"
$domain = "192.0.2.0/25"
Output: true
Solution
Do not reinvent the wheel!
Use Net::IPv4Addr instead.
The module’s POD suggests trapping ipv4_parse and ipv4_network for errors.
They seem to produce spurious warnings in case of parsing errors, therefore suppressing warnings completely for them.
use strict;
use warnings;
use Net::IPv4Addr qw(ipv4_parse ipv4_network ipv4_in_network);
use experimental 'signatures';
sub subnet_sheriff ($ip_addr, $domain) {
my ($addr, $net);
eval {
local $SIG{__WARN__} = sub {};
$addr = ipv4_parse($ip_addr);
1
} or return;
eval {
local $SIG{__WARN__} = sub {};
$net = ipv4_network($domain);
1
} or return;
ipv4_in_network($net, $addr);
}
See the full solution to task 2.