Sunday Puzzle May 22, 2022

Posted on Updated on

Manipulate an Island Name to get Another Island

It’s an easyish one and comes from Blaine Deal, who conducts a weekly blog about Will’s NPR puzzles. Take the name of an island. Move its first letter two spaces later in the alphabet (so A would become C, B would become D, etc.). Reverse the result and you’ll have the name of another island. What islands are these?

Link to the challenge
Change the first letter and reverse the name to get another island

Techniques Used

  • String manipulation
  • Simple file handling
  • Linq methods ‘Aggregate’ and ‘Reverse’
Screen shot showing the solution

Synopsis

Will was right, that was a pretty easy puzzle 😊. The hardest part about this one was building my island list. Eventually, I was able to use the list on Britannica.com, after manually editing their text for about half an hour.

After saving the result as a file, it was a simple matter of 1) reading that file into a list, 2) manipulating each list entry, and 3) checking whether the result was also an entry in that list.

Here’s the Code!

private void btnSolve_Click(object sender, RoutedEventArgs e) {
  Mouse.OverrideCursor = Cursors.Wait;
  var islandLst = new List<string>();
  //Read the file and put each line into the list declared above:
  var fName = @"C:\Users\Randy\Documents\Puzzles\Data\Islands.txt";
  using (var sr = File.OpenText(fName))
    while (sr.Peek() != -1)
      islandLst.Add(sr.ReadLine() ?? "");

  foreach(var island in islandLst) {
    //Manipulate the first letter and store the result in variable 'switched'
    var switched = (char)(char.ToLower(island[0]) + 2) + island[1..];
    //Reverse the letters and convert to a string:
    var reversed = switched.Reverse().Aggregate("", (p,c) => p + c);
    //Convert the first letter to upper case
    var candidate = char.ToUpper(reversed[0]) + reversed[1..];
    //Search the list for the result:
    var ndx = islandLst.BinarySearch(candidate);
    if (ndx >= 0)
      //Display the results:
      txtResult.Text += $"{island} - {islandLst[ndx]}\n";
  }

  Mouse.OverrideCursor = null;
}

Discussion

Here’s how I manipulate each entry in the islandLst to form a candidate to check. The lines highlighted above are discussed below:

  • var switched = (char)(char.ToLower(island[0]) + 2) + island[1..];
    • Note that .NET allows you to treat a string variable as an array of char, so you can use indexing on that array. To wit,
      • island[0] retrieves the first character from that array, at index 0
    • .NET also allows you to perform arithmetic on char variables, so, if c is a char variable, then c + 2 is a character moved up in the alphabet by two. So 'g' + 2 = 'i', because i is two higher than g. However, the result is not a char, so I need to cast it back to char before concatenating it with the remainder of the string. Casting is accomplished with the syntax (char), used as a prefix above.
  • var reversed = switched.Reverse().Aggregate("", (p,c) => p + c);
    • Reverse()’ is a Linq method that builds an IEnumerable ‘list’ of char in the reverse order of the original. I can use it on a string because, as mentioned above, a string is an array of char, and Linq can operate on an array (because an array is an IEnumerable)
    • Aggregate‘ is another Linq method that has two parameters:
      • The initial/seed value to aggregate with, namely, an empty string “”
      • A Lambda expression (p,c) => p + c that tells .NET how to perform the aggregation. My variable ‘p‘ represents the previous value (the results so far), and my variable ‘c‘ represents the current list entry being processed. Effectively, my code says “for each list entry, add it to the running output”
    • Why use Aggregate? Because, as mentioned above, Reverse gives me a list (technically an IEnumerable), and I need to convert it to a string.
  • var candidate = char.ToUpper(reversed[0]) + reversed[1..];
    1. Take the first char (reversed[0]) and convert it to upper case (char.ToUpper)
    2. Concatenate that with the remainder of the string (reversed[1..]). Note that the plus sign + serves as a concatenation operator, and .NET allows you to concatenate a char to a string.

Finally, having built a candidate, I search the list again to see if that list actually contains the candidate.

var ndx = islandLst.BinarySearch(candidate);

If the binary search operation returns a non-negative number, it means we have a solution!

Get the Code

Here’s the link to get my code. Note that you will need a (free) DropBox account to access that link. The compressed file contains my island list, which you can use to solve the puzzle yourself.

Leave a comment