The Bear's Den

Enter at your own risk

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 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.