{"id":5441,"date":"2024-05-26T03:00:00","date_gmt":"2024-05-26T07:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=5441"},"modified":"2024-05-22T10:27:26","modified_gmt":"2024-05-22T14:27:26","slug":"use-grep-to-solve-a-2-dimensional-word-puzzle","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=5441","title":{"rendered":"Use \u2018grep\u2019 to solve a 2-dimensional word puzzle"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"5441\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p>As a systems administrator, you need to keep a lot of \u201ctools\u201d on your \u201ctool belt\u201d of skills. Understanding how to best apply different tools and concepts to new problems can turn a difficult problem into a small one. One skill I used frequently when I worked as a systems administrator &#8211; early in my career &#8211; was <em>regular expressions<\/em>.<\/p>\n\n\n\n<p>You can learn more about regular expressions from the <code>regex<\/code> manual page, in section 7 of the online manual, with <code>man 7 regex<\/code>. The basics of regular expressions are:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Character<\/th><th>Meaning<\/th><\/tr><\/thead><tbody><tr><td><code>^<\/code><\/td><td>The start of a line<\/td><\/tr><tr><td><code>$<\/code><\/td><td>The end of a line<\/td><\/tr><tr><td><code>.<\/code><\/td><td>Any single character<\/td><\/tr><tr><td><code>[<\/code> and <code>]<\/code><\/td><td>Match any of a set of characters, such as <code>[ab]<\/code> to match <em>either<\/em> <code>a<\/code> or <code>b<\/code>, or <code>[a-z]<\/code> to match <em>any<\/em> lowercase letter<\/td><\/tr><tr><td><code>*<\/code><\/td><td>Zero or more of the thing before it, like <code>a*<\/code> to match zero or more of <code>a<\/code><\/td><\/tr><tr><td><code>?<\/code><\/td><td>Zero or one of the thing, like <code>a?<\/code> to match an <code>a<\/code> that may or may not be there<\/td><\/tr><tr><td><code>+<\/code><\/td><td>One or more of the thing, like <code>a+<\/code> to match one or more of <code>a<\/code><\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">Regular expression characters and what they mean<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"playing-a-word-puzzle-game\">Playing a word puzzle game<\/h2>\n\n\n\n<p>I like to play puzzle games to relax, especially word puzzles. I wrote before about <a href=\"https:\/\/www.both.org\/?p=5265\">playing the Wordle game<\/a>, but recently I discovered another game: <a href=\"https:\/\/www.washingtonpost.com\/games\/keyword\/\">Keyword<\/a> is a word puzzle game that presents six words of different lengths, written vertically, each missing a single letter. The missing letters also form a word that runs horizontally. You need to pick the right letters to both <em>fill in the missing letters from the words<\/em> and <em>create a new six-letter word<\/em>.<\/p>\n\n\n\n<p>This is an excellent opportunity to practice using <code>grep<\/code> to leverage regular expressions to find words in the system dictionary that match the six words &#8211; and at the same time, uncover the hidden word.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"400\" height=\"550\" src=\"https:\/\/www.both.org\/wp-content\/uploads\/2024\/05\/keyword1.png\" alt=\"screenshot of Keyword, showing six incomplete words and a hidden secret word\" class=\"wp-image-5442\"\/><\/figure>\n\n\n\n<p>In this puzzle, we have six words, each missing one letter:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>at?lete<\/li>\n\n\n\n<li>d?al<\/li>\n\n\n\n<li>dec?de<\/li>\n\n\n\n<li>p?ot<\/li>\n\n\n\n<li>?ear<\/li>\n\n\n\n<li>parc?ment<\/li>\n<\/ol>\n\n\n\n<p>Some of these may be immediately obvious. I can\u2019t imagine the first word as being anything other than <strong>athlete<\/strong>. The last word seems obvious as <strong>parchment<\/strong>. But the third word could be either <strong>decide<\/strong> or <strong>decade<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"list-the-possible-words\">List the possible words<\/h2>\n\n\n\n<p>Let\u2019s use <code>grep<\/code> to match each of the possible six words from a dictionary of possible words. On Linux, the <code>\/usr\/share\/dict\/words<\/code> file contains a list of over a half-million correctly-spelled words, such as you might use in a spell-checking application. Let\u2019s use regular expressions to match each incomplete word to valid words from the <code>words<\/code> file. To match each word, we only need a few regular expression characters: <code>^<\/code> and <code>$<\/code> and <code>[a-z]<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ grep '^at&#91;a-z]lete$' \/usr\/share\/dict\/words\nathlete\n\n$ grep '^d&#91;a-z]al$' \/usr\/share\/dict\/words\ndeal\ndhal\ndial\ndual\n\n$ grep '^dec&#91;a-z]de$' \/usr\/share\/dict\/words\ndecade\ndecede\ndecide\ndecode\n\n$ grep '^p&#91;a-z]ot$' \/usr\/share\/dict\/words\nphot\nplot\npoot\n\n$ grep '^&#91;a-z]ear$' \/usr\/share\/dict\/words\nbear\ndear\nfear\ngear\nhear\njear\nlear\nmear\nnear\npear\nrear\nsear\ntear\nwear\nyear\n\n$ grep '^parc&#91;a-z]ment$' \/usr\/share\/dict\/words\nparchment<\/code><\/pre>\n\n\n\n<p>Some of the incomplete words have only one match in the <code>words<\/code> file, while others have quite a few. Still, matching these words with <code>grep<\/code> gives us a lot of information to fill in the missing word. The matched words from the dictionary tell us what letters can appear in each position:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The first letter can only be <strong>h<\/strong><\/li>\n\n\n\n<li>The second letter can be <strong>e<\/strong>, <strong>h<\/strong>, <strong>i<\/strong>, or <strong>u<\/strong><\/li>\n\n\n\n<li>The third letter might be <strong>a<\/strong>, <strong>e<\/strong>, <strong>i<\/strong>, or <strong>o<\/strong><\/li>\n\n\n\n<li>The fourth letter is one of <strong>h<\/strong>, <strong>l<\/strong>, or <strong>o<\/strong><\/li>\n\n\n\n<li>The fifth letter has several possibilities!<\/li>\n\n\n\n<li>The last letter can only be <strong>h<\/strong><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"narrowing-the-options\">Narrowing the options<\/h2>\n\n\n\n<p>We can build a regular expression to match a six-letter word from the dictionary, where each letter is what we have uncovered. For each letter, we\u2019ll use a pattern to match a specific letter, like <code>[ehiu]<\/code> to match one of <strong>e<\/strong>, <strong>h<\/strong>, <strong>i<\/strong>, or <strong>u<\/strong>. I\u2019m not sure I want to type in all fifteen possible letters for the fifth letter, so let\u2019s see how far we can get by specifying <code>.<\/code> for that letter, to match any character at that position.<\/p>\n\n\n\n<p>Our <code>grep<\/code> command to find the possible letters looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ grep '^h&#91;ehiu]&#91;aeio]&#91;hlo].h$' \/usr\/share\/dict\/words\nhealth<\/code><\/pre>\n\n\n\n<p>So now we have discovered <em>exactly one<\/em> six-letter word that also fills in the missing letter for each incomplete word: <strong>health<\/strong>. And that\u2019s correct!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"400\" height=\"550\" src=\"https:\/\/www.both.org\/wp-content\/uploads\/2024\/05\/keyword2.png\" alt=\"screenshot of Keyword, showing HEALTH as the missing word\" class=\"wp-image-5444\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"matching-patterns\">Matching patterns<\/h2>\n\n\n\n<p>Regular expressions match patterns in text. Here, we\u2019ve used <code>grep<\/code> and regular expressions in a fun way to play a word puzzle game. With a well-formed regular expression, you can also find specific messages in a log file, or uncover errors in output files. Practice using regular expressions so you can add this great \u201ctool\u201d to your virtual \u201ctool belt\u201d of system administrator skills.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Regular expressions match patterns and help you solve problems.<\/p>\n","protected":false},"author":33,"featured_media":2820,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[100,69,83],"tags":[104,147,383],"class_list":["post-5441","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-command-line","category-fun","category-problem-solving","tag-command-line","tag-fun","tag-regular-expressions"],"modified_by":"Jim Hall","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/5441","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5441"}],"version-history":[{"count":1,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/5441\/revisions"}],"predecessor-version":[{"id":5445,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/5441\/revisions\/5445"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/2820"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5441"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5441"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5441"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}