RogerBW's Blog

The Weekly Challenge 340: Ascending Duplicates 28 September 2025

I’ve been doing the Weekly Challenges. The latest involved list duplicates and integer parsing. (Note that this ends today.)

Task 1: Duplicate Removals

You are given a string, $str, consisting of lowercase English letters.

Write a script to return the final string after all duplicate removals have been made. Repeat duplicate removals on the given string until we no longer can.

A duplicate removal consists of choosing two adjacent and equal letters and removing them.

One could search for duplicates repeatedly, but a once-through algorithm can get the job done more efficiently. Fairly simple if you have variable-size arrays, and everything I'm using does. For example in Python:

def duplicateremovals(a):

Initialise the output list.

  b = []

Iterate over the input list.

  for c in a:

If there is no output list, or its last element doesn't match the current one, push the current one.

    if len(b) == 0 or c != b[-1]:
      b.append(c)

Otherwise remove the last element and discard both it and the current one.

    else:
      b.pop()
  return ''.join(b)

In PostScript I can assemble this on the stack.

/duplicateremovals {

Split the string to an array of characters. (It's nearly that already, but this makes some operations easier.)

    s2a

Bury an array start marker.

    [ exch

Iterate over the input list.

      {

If there's something in the array

          counttomark 0 gt

And it equals the present value

          3 copy pop eq and {

Dump both of them. (Otherwise the current value automatically stays on the stack.)

              pop pop
          } if
      } forall
    ]

Assemble the output array back into a string.

    a2s
} bind def

Task 2: Ascending Numbers

You are given a string, $str, is a list of tokens separated by a single space. Every token is either a positive number consisting of digits 0-9 with no leading zeros, or a word consisting of lowercase English letters.

Write a script to check if all the numbers in the given string are strictly increasing from left to right.

The trick here is parsing a string to an integer while having to deal with strings that aren't. Foe me this usually means some sort of composite return type (Rust, Scala, Kotlin), or the possibility of a null or undef value. In some languages (e.g. Typst, which doesn't have error handling, and Ruby, which returns a zero if it can't parse the string) I check the string against a regexp to match possible numbers before feeding it to the converter.

(I do not at any point check for positive numbers; by the specification, a zero should not be parsed. But there aren't any of those in the test cases.)

Perl:

sub ascendingnumbers($a) {

Initialise the variable for the previously found value.

  my $prev = undef;

Iterate words.

  foreach my $c (split ' ', $a) {

If it's a number,

    if ($c =~ /^[0-9]+$/) {

If we have a previous number and that's no smaller than this one, fail.

      if (defined $prev && $prev >= $c) {
        return 0;
      }

Store the previous number.

      $prev = $c;
    }
  }

If we get all the way through, succeed.

  1;
}

Rust with the Option class makes this cleaner. (Since that's what parse() returns, I'm using it for the previous value too.)

fn ascendingnumbers(a: &str) -> bool {
    let mut prev: Option<u32> = None;
    for c in a.split(" ") {
        if let Ok(n) = c.parse::<u32>() {
            if !prev.is_none() && prev.unwrap() >= n {
                return false;
            }
            prev = Some(n);
        }
    }
    true
}

And PostScript has error handling, quite extensive and configurable if you want to get into the weeds, but I took an easier approach: the stopped keyword returns boolean-true if the previous block caused an error, something like eval in other languages. So I end up processing the word via:

        {
            cvi
        } stopped {

If it failed, throw away the uconverted string value

            pop
        } {

Otherwise, process the integer here.

        } ifelse

Full code on github.

Add A Comment

Your Name
Your Email
Your Comment

Note that I will only approve comments that relate to the blog post itself, not ones that relate only to previous comments. This is to ensure that the blog remains outside the scope of the UK's Online Safety Act (2023).

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 2300ad 3d printing action advent of code aeronautics aikakirja anecdote animation anime army astronomy audio audio tech base commerce battletech bayern 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 disaster 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 essen 2024 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 horrorm science fiction hugo 2014 hugo 2015 hugo 2016 hugo 2017 hugo 2018 hugo 2019 hugo 2020 hugo 2021 hugo 2022 hugo 2023 hugo 2024 hugo 2025 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 openscad opera parody paul temple perl perl weekly challenge photography podcast poetry politics postscript powers prediction privacy project woolsack pyracantha python quantum rail raku ranting raspberry pi reading reading boardgames social real life restaurant review 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 typst 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