Camel
Peter
Peter Campbell Smith

Fun with strings

Weekly challenge 329 — 7 July 2025

Week 329: 7 Jul 2025

Task 2

Task — Nice string

You are given a string made up of lower and upper case English letters only. Write a script to return the longest substring of the given string which is nice.

A string is nice if, for every letter of the alphabet that the string contains, it appears both in uppercase and lowercase.

Examples


Example 1
Input: $str = 'YaaAho'
Output: 'aaA'

Example 2
Input: $str = 'cC'
Output: 'cC'

Example 3
Input: $str = 'A'
Output: ''
No nice string found.

Analysis

I chose to approach this challenge in what could be called the systematic - or boring - way.

I loop over the possible starting characters, and then over the possible lengths of substrings which are larger than the nicest substring found so far. I then check each of these for niceness, and if one is nice, I save it as the new nicest.

I chose to pull out the test for a substring being nice into a separate subroutine is_nice() mainly to make the code clearer to read.

Try it 

Try running the script with any input:



example: chopCHOPwood

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2025-07-07
use utf8;     # Week 329 - task 2 - Nice string
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

nice_string('YaaAho');
nice_string('cC');
nice_string('A');
nice_string('ABCDEedcbaZABCDEedcbaa');

# longer example
my (@chars, $string);
@chars = (('A' .. 'I'),('a' .. 'i'));
$string .= $chars[int(rand(18))] for 0 .. 50;
nice_string($string);

sub nice_string {
    
    my ($string, $c, $best, $longest, $s, $t, $try);
    
    # initialise
    $string = shift;
    $c = length($string);
    $best = '';
    $longest = 0;
    
    # loop over starting points
    for $s (0 .. $c - 2) {
        
        # loop up to remaining length
        for $t (0 .. $c - $s) {
            next unless $t >= $longest;
            $try = substr($string, $s, $t);
            
            # nicest so far?
            if (is_nice($try)) { 
                $best = $try;
                $longest = $t;
            }
        }
    }
    
    say qq[\nInput:  '$string'];
    say qq[Output: '$best'];
}

sub is_nice {
    
    my ($string, @chars, $c, $C);
    
    # initialise
    $string = shift;
    @chars = split('', $string);
    
    # check for nicety
    for $c (@chars) {
        $C = $c gt 'Z' ? uc($c) : lc($c);
        return 0 unless $string =~ m|$C|;
    }
    return 1;
}

Output


Input:  'YaaAho'
Output: 'aaA'

Input:  'cC'
Output: 'cC'

Input:  'A'
Output: ''

Input:  'ABCDEedcbaZABCDEedcbaa'
Output: 'ABCDEedcbaa'

Input:  'IDbaDfiIDCDFHeEdHeFbGEGgbeBHdCAfBHbFfHIgCfiifAAI'
Output: 'bGEGgbeB'

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain