Weekly Challenge: Short and friendly

Weekly Challenge 317 Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding. Challenge, My solutions Task 1: Acronyms Task You are given an array of words and a word. Write a script to return true if concatenating the first letter of each word in the given array matches the given word, return false otherwise. My solution For input from the command line, I take the last string as an acronym, and the rest as an array of words. My solution is two lines. It could be a one liner, but that would make it less readable. The first line takes the first letter of each word and combines them to create a variable called acronym. The then compare this case-insensitively with the given word. def is_acronyms(array: list, word: str) -> bool: acronym = ''.join(s[0] for s in array) return acronym.lower() == word.lower() The Perl code follows the same logic. sub main (@array) { my $word = pop(@array); my $acronym = join( '', map { substr( $_, 0, 1 ) } @array ); say lc($acronym) eq lc($word) ? 'true' : 'false'; } Examples $ ./ch-1.py Perl Weekly Challenge PWC True $ ./ch-1.py Bob Charlie Joe BCJ True $ ./ch-1.py Morning Good MM False Task 2: Friendly Strings Task You are given two strings. Write a script to return true if swapping any two letters in one string match the other string, return false otherwise. My solution The first thing I check is if the strings are of the same length. They they are of different lengths, I know that this is False. def friendly_strings(str1: str, str2: str) -> bool: if len(str1) != len(str2): return False The next thing I check is if the strings are the same, there is at least one letter that appears more than once. If I take the string bitter for example, swapping the third and fourth letter is possible to ensure both strings remain the same. OTOH, if the strings one container each letter once - like abc - it isn't possible to swap two letters. if str1 == str2: freq = Counter(str1) return any(i for i in freq.values() if i > 1) The next step I do is get the position of the letters where the character is different between the two strings. differences = [ i for i in range(len(str1)) if str1[i] != str2[i]] If there are only two differences, I check that the letters at those positions are in the opposite position in the other string, and return True if that is the case. if len(differences) == 2: pos1, pos2 = differences if str1[pos1] == str2[pos2] and str2[pos1] == str1[pos2]: return True Finally, I return False if we haven't return True previously. return False Examples $ ./ch-2.py desc dsec True $ ./ch-2.py fcyn fcny True $ ./ch-2.py poo eop False $ ./ch-2.py stripe sprite True $ ./ch-2.py bitter bitter True $ ./ch-2.py biter biter False

Apr 20, 2025 - 06:40
 0
Weekly Challenge: Short and friendly

Weekly Challenge 317

Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.

Challenge, My solutions

Task 1: Acronyms

Task

You are given an array of words and a word.

Write a script to return true if concatenating the first letter of each word in the given array matches the given word, return false otherwise.

My solution

For input from the command line, I take the last string as an acronym, and the rest as an array of words. My solution is two lines. It could be a one liner, but that would make it less readable.

The first line takes the first letter of each word and combines them to create a variable called acronym. The then compare this case-insensitively with the given word.

def is_acronyms(array: list, word: str) -> bool:
    acronym = ''.join(s[0] for s in array)
    return acronym.lower() == word.lower()

The Perl code follows the same logic.

sub main (@array) {
    my $word = pop(@array);
    my $acronym = join( '', map { substr( $_, 0, 1 ) } @array );
    say lc($acronym) eq lc($word) ? 'true' : 'false';
}

Examples

$ ./ch-1.py Perl Weekly Challenge PWC
True

$ ./ch-1.py Bob Charlie Joe BCJ
True

$ ./ch-1.py Morning Good MM
False

Task 2: Friendly Strings

Task

You are given two strings.

Write a script to return true if swapping any two letters in one string match the other string, return false otherwise.

My solution

The first thing I check is if the strings are of the same length. They they are of different lengths, I know that this is False.

def friendly_strings(str1: str, str2: str) -> bool:
    if len(str1) != len(str2):
        return False

The next thing I check is if the strings are the same, there is at least one letter that appears more than once. If I take the string bitter for example, swapping the third and fourth letter is possible to ensure both strings remain the same. OTOH, if the strings one container each letter once - like abc - it isn't possible to swap two letters.

    if str1 == str2:
        freq = Counter(str1)
        return any(i for i in freq.values() if i > 1)

The next step I do is get the position of the letters where the character is different between the two strings.

    differences = [ i for i in range(len(str1)) if str1[i] != str2[i]]

If there are only two differences, I check that the letters at those positions are in the opposite position in the other string, and return True if that is the case.

    if len(differences) == 2:
        pos1, pos2 = differences
        if str1[pos1] == str2[pos2] and str2[pos1] == str1[pos2]:
            return True

Finally, I return False if we haven't return True previously.

    return False

Examples

$ ./ch-2.py desc dsec
True

$ ./ch-2.py fcyn fcny
True

$ ./ch-2.py poo eop
False

$ ./ch-2.py stripe sprite
True

$ ./ch-2.py bitter bitter
True

$ ./ch-2.py biter biter
False