RogerBW's Blog

The Weekly Challenge 182: Max is Common 14 September 2022

I’ve been doing the Weekly Challenges. The latest involved list searching and finding a common subpath. (Note that this is open until 18 September 2022.)

Task 1: Max Index

You are given a list of integers.

Write a script to find the index of the first biggest number in the list.

I interpret "first biggest" to mean the first occurrence of the largest number. Quite straightforward in most languages: go through the list, and if the value is higher than any stored value store this value as maximum and its index for output, then return the last stored index. For example in Rust:

fn maxindex(n: Vec<isize>) -> usize {
    let mut mxv = 0;
    let mut mxi = 0;
    for (i, v) in n.iter().enumerate() {
        if i == 0 || *v > mxv {
            mxv = *v;
            mxi = i;
        }
    }
    mxi
}

(We'll never actually use the initial values of mxi and mxv unless the list is empty, and behaviour in that case is undefined. -1 would probably be a helpful thing to return in that case.)

But what a few languages lack is that enumerate (in Rust and Python; each_with_index in Ruby, .forEach in JavaScript, and .withIndex in Kotlin), which lets me go through a list getting both index and value in a single operation. Lua and PostScript don't have it – though I've written one for PostScript. Perl is also lacking this, and that seems like a shame; sure, I can just iterate through indices and pull the value out of the list, but it's more faff for the programmer and an extra chance to get things wrong.

(I thought Raku also lacked it, but I was wrong; you can do it with the .pairs method.)

Task 2: Common Path

Given a list of absolute Linux file paths, determine the deepest path to the directory that contains all of them.

A common substring is a more usual sort of task, but this seems fairly straightforward. I break up the input strings into path components, then iterate one component at a time until I get a mismatch. In Perl:

sub commonpath($p) {
  my @pa;
  my @pl;
  foreach my $sp (@{$p}) {

Break up the input path, and store it and the number of components in it.

    my @q = split '/',$sp;
    push @pl,scalar @q;
    push @pa,\@q;
  }
  my @out;

Iterating to the number of components of the shortest path…

  foreach my $cl (0..min(@pl)-1) {
    my $ex = 0;

Get the value of the first input's component.

    my $tx = $pa[0][$cl];

Compare it with the rest of the components at that position. (This compares it with itself too, but that shouldn't be a major imposition.) If any of the comparisons fails, drop out of the loop. (I could do a deep exit here with a label, which I'd use if I were just writing Perl and/or Raku, but that isn't an option in some of the languages.)

    foreach my $pe (@pa) {
      if ($pe->[$cl] ne $tx) {
        $ex = 1;
        last;
      }
    }
    if ($ex) {
      last;
    }
    push @out,$tx;
  }

Assemble and return the matching components.

  return join('/',@out);
}

Full code on github.


  1. Posted by Stephen G Lynn at 03:07pm on 14 September 2022

    Maybe 'each' in Perl 5.12+ would be the equivalent of Rust enumerate. https://perldoc.perl.org/functions/each

  2. Posted by RogerBW at 03:12pm on 14 September 2022

    Excellent, thanks! I know that as a function on hashes, and didn't realise it could apply to arrays too.

Comments on this post are now closed. If you have particular grounds for adding a late comment, comment on a more recent post quoting the URL of this one.

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 aviation 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 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 2022 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