Month: October 2017

Sunday Puzzle for Oct 1st, 2017

Posted on

Flan.pngI sure hope I found the solution Will was looking for! I’ve never heard of ‘flan’ until now. I know Will creates crossword puzzles for a living, so maybe flan is a common word to him. Or, maybe, as a New Yorker, he eats fancy desserts all the time.

According to Google, the dish pictured here is a ‘flan’. Sorry, it looks like cheese cake to me! I guess I’m not a gourmand.

Screen Shot_Oct1_2017.png
Screen shot showing the challenge and it’s solution

Struggle Notes

If you look at the buttons on my screen shot, you might guess I tried pretty hard to get alternative word lists. (I wasn’t too happy with ‘flan’.)

  • The button ‘Try All Words” uses a huge dictionary of English words (forget mere food words, try anything!), so if the solution used common words, like ‘corn’, that would have solved it
  • The button “Get Name Brand Foods” downloads foods that might not be in my dictionary of English words.
    • Since neither of those two methods found a different solution, I’m sticking with flan/gumbo.

Downloading Food Names

Gumbo.png
Mmm, gumbo!

Note my other button, ”Get Food Names”.

 

  • This button goes to Wikipedia’s page https://en.wikipedia.org/wiki/Lists_of_foods, which is a list of links…
  • Follows each link, and grabs the food names from that page
  • The result is 347 files of various food names, such as ‘List_of_pies,_tarts_and_flans’.
  • If you’re a web guru, you might guess that takes a while to run. And you’d be correct; it took about 15 minutes to download them all.

Techniques Used

How To Shift Letters Using Linq

string shifted = aWord.Select(c => c == 'z' ? 'a' : (char)(c + 1))
                      .Aggregate("", (p, c) => p + c);

This code shifts each letter by one, as Will describes it in the challenge. For example, ‘flan’ becomes ‘gmbo’.
Notes:

  1. My variable ‘aWord’ might contain, for example, the word ‘flan’
  2. Linq Select treats aWord as a list of letters (i.e. list of char data type)
    1. The code examines each letter, c
    2. I use the ternary operator on each letter. ‘Ternary Operator” is a short-hand if-statement
    3. It takes the form condition ? first_expression : second_expression;
    4. If the letter c is ‘z’ (my condition)
      1. Return an ‘a’ (my first expression)
      2. Otherwise, add one to it and convert it back to char (2nd expression)
  3. The aggregate operator converts the list of char back into a string
  4. If  ‘aWord’ contained “flan”, shifted would be assigned “gmbo”

How to Solve the Puzzle

The method below uses the code from above to shift a 4-letter word. My method needs a list of 4-letter foods and of 5-letter foods, passed as parameters

private void SearchListsForSolution(List<string> fiveLetterFoodList, 
                  List<string> fourLetterFoodList) {
  List<string> solutionList = new List<string>();
  foreach (string aWord in fourLetterFoodList) {
    if (!solutionList.Contains(aWord)) {
      string shifted = aWord.Select(c => c == 'z' ? 'a' : (char)(c + 1))
                  .Aggregate("", (p, c) => p + c);

      //Loop injects 'u' at 3 different positions to build candidate
      //So we try 'gumbo', 'gmubo' and 'gmbuo'
      for (int i = 1; i <= 3; i++) {
        string candidate = shifted.Substring(0, i) 
                           + "u" + shifted.Substring(i);

        //fiveLetterFoodList is a sorted list of foods
        int p = fiveLetterFoodList.BinarySearch(candidate);
        //if p is greater than zero, we found candidate in the list
        if (p >= 0) {
          //Add the 4-letter word, shifted version 
          //and 5-letter word to textbox
          tbSolution.Text += 
             $"{aWord } → {shifted} + u → {fiveLetterFoodList[p]}\n";
          solutionList.Add(aWord);
        }
      }
    }
  }
}

Notes

  • There are only 3 places to inject a u into a 4-letter word
  • My code tries all 3 places and checks to see if the result is a word
  • By using Binary Search against the 5-letter word list
  • The BinarySearch method returns an index > 0 if it finds the candidate
  • So when that happens, I update my TextBox ‘tbSolution’ to include what I just found
  • The list ‘SolutionList’ helps me avoid entering the same solution twice; I need it because ‘flan’ was present in multiple files

Removing Diacritics

Just in case, I tried fixing words like ‘Ragú‘, converting it to ‘Ragu‘ by removing the accent over the letter u. (It didn’t help.) It was pretty easy; I just copied the code from here: “Stripping is an Interesting Job…

That code looked like this:

static string RemoveDiacritics(string text) 
{
    var normalizedString = text.Normalize(NormalizationForm.FormD);
    var stringBuilder = new StringBuilder();

    foreach (var c in normalizedString)
    {
        var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
        if (unicodeCategory != UnicodeCategory.NonSpacingMark)
        {
            stringBuilder.Append(c);
        }
    }

    return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}

Get the Code!

As usual, you can download my code from my DropBox account here. As usual, they will only let you download if you create a free account with them. Note: my zip file contains all the food lists, located in my bin folder.