RogerBW's Blog

The Weekly Challenge 287: Strong and Valid 22 September 2024

I’ve been doing the Weekly Challenges. The latest involved password analysis and number parsing. (Note that this ends today.)

Task 1: Strong Password

You are given a string, $str.

Write a program to return the minimum number of steps required to make the given string very strong password. If it is already strong then return 0.

Criteria:

  • It must have at least 6 characters.
  • It must contains at least one lowercase letter, at least one upper case letter and at least one digit.
  • It shouldn't contain 3 repeating characters in a row.

The following can be considered as one step:

  • Insert one character
  • Delete one character
  • Replace one character with another

There are flaws with this algorithm: what of "aaaaa", which is arguably two separate three-character repetitions, but can be fixed by changing one character? But it seems to get the job done. In Raku:

sub strongpassword($a) {
    my %ctypes;
    my $reps = 0;
    my $rep = 0;
    my $old = '@';

Initialise the list of change counts.

    my @changes;
    my @chars = $a.comb;

Iterate over the characters in the password.

    for @chars.kv -> $i, $c {

Look for repeats (rule 3)

        if ($i > 0 && $c eq $old) {
            $rep += 1;
            if ($rep >= 2) {
                $reps += 1;
            }
        } else {
            $rep = 0;
            $old = $c;
        }

Look for existence of each specified class (rule 2)

        my $t = 'n';
        if ($c ~~ /<upper>/) {
            $t = 'u';
        } elsif ($c ~~ /<lower>/) {
            $t = 'l';
        } elsif ($c ~~ /<digit>/) {
            $t = 'd';
        }
        %ctypes{$t}++;
    }

Each 3-repeat is a required change.

    @changes.push($reps);

Look at the number of character classes, and see how many characters need to be added.

    %ctypes{'n'}:delete;
    my $k = %ctypes.keys.elems;
    if ($k < 3) {
        my $spare = %ctypes.values.sum - $k;
        if ($spare < 0) {
            @changes.push(-$spare);
        }
    }

Check for length.

    if ($a.chars < 6) {
        @changes.push(6 - $a.chars);
    }

We assume that any change which fixes whatever problem there are most of will also fix another problem, so return the maximum.

    return @changes.max;
}

Task 2: Valid Number

You are given a string, $str.

Write a script to find if it is a valid number.

Conditions for a valid number:

  • An integer number followed by an optional exponent.
  • A decimal number followed by an optional exponent.
  • An integer number is defined with an optional sign '-' or '+' followed by digits.

Decimal Number:

A decimal number is defined with an optional sign '-' or '+' followed by one of the following definitions:

  • Digits followed by a dot '.'.
  • Digits followed by a dot '.' followed by digits.
  • A dot '.' followed by digits.

Exponent:

An exponent is defined with an exponent notation 'e' or 'E' followed by an integer number.

Clearly this is a job for regular expressions, so I didn't do it in PostScript, and since Lua's equivalent lacks alternations that also got quite fiddly. Then it's just a matter of appropriate string escaping.

Should have done this in Rust with winnow but it's fallen out of my head since last year's Advent of Code.

Kotlin:

fun validnumber(a: String): Boolean {
    val integer = "[-+]?[0-9]+"
    val float = """[-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)"""
    val exponential =
        "(" + integer + "|" + float + ")[Ee]" + integer
    val number =
        "^(" + integer + "|" + float + "|" + exponential + ")$" 
    val rx = number.toRegex()
    return rx.containsMatchIn(a)
}

Full code on github.

Add A Comment

Your Name
Your Email
Your Comment

Your submission will be ignored if any field is left blank, but your email address will not be displayed. Comments will be processed through markdown.

Search
Archive
Tags 1920s 1930s 1940s 1950s 1960s 1970s 1980s 1990s 2000s 2010s 3d printing action advent of code aeronautics aikakirja anecdote animation anime army astronomy audio audio tech base commerce battletech beer boardgaming book of the week bookmonth chain of command children chris chronicle church of no redeeming virtues cold war comedy computing contemporary cornish smuggler cosmic encounter coup covid-19 crime crystal cthulhu eternal cycling dead of winter doctor who documentary drama driving drone ecchi economics en garde espionage essen 2015 essen 2016 essen 2017 essen 2018 essen 2019 essen 2022 essen 2023 existential risk falklands war fandom fanfic fantasy feminism film firefly first world war flash point flight simulation food garmin drive gazebo genesys geocaching geodata gin gkp gurps gurps 101 gus harpoon historical history horror hugo 2014 hugo 2015 hugo 2016 hugo 2017 hugo 2018 hugo 2019 hugo 2020 hugo 2021 hugo 2022 hugo 2023 hugo 2024 hugo-nebula reread in brief avoid instrumented life javascript julian simpson julie enfield kickstarter kotlin learn to play leaving earth linux liquor lovecraftiana lua mecha men with beards mpd museum music mystery naval noir non-fiction one for the brow opera parody paul temple perl perl weekly challenge photography podcast politics postscript powers prediction privacy project woolsack pyracantha python quantum rail raku ranting raspberry pi reading reading boardgames social real life restaurant reviews romance rpg a day rpgs ruby rust scala science fiction scythe second world war security shipwreck simutrans smartphone south atlantic war squaddies stationery steampunk stuarts suburbia superheroes suspense television the resistance the weekly challenge thirsty meeples thriller tin soldier torg toys trailers travel type 26 type 31 type 45 vietnam war war wargaming weather wives and sweethearts writing about writing x-wing young adult
Special All book reviews, All film reviews
Produced by aikakirja v0.1