Abecedarian words
and pangrams
Weekly challenge 161 — 18 April 2022
Week 161: 18 Apr 2022
A pangram is a sentence or phrase that uses every letter in the English alphabet at least once.
Using the provided dictionary generate at least one pangram.
Your pangram does not have to be a syntactically valid English sentence (doing so would require far more work, and a dictionary of nouns, verbs, adjectives, adverbs, and conjunctions). Also note that repeated letters, and even repeated words, are permitted.
Perhaps the most well known pangram is:
The quick brown fox jumps over the lazy dog
The approach I used to creating pangrams was to choose a random word from the dictionary as my pangram's first word. I then chose more random words from the dictionary, and added each of them to my pangram if they contained a letter I didn't already have. And once I had all 26 letters I stopped.
This works well, and my submission delivers a sample of 10 results.
I then wondered how close I could get to the shortest (fewest words or letters). I ran through my algorithm 10 000 times and it's clear that it can get down to 8 words and 60ish letters. The best I did after just a few tries is:
tributary shipwrecked mollifying gavels gazes frequents jerky exhaling 8 words, 63 letters
The 'quick brown fox' pangram has 9 words but only 35 letters, so I thought a better algorithm might be one that prefers shorter words. Limiting the word length to 5 gave:
rowdy clix bang newt quick huffs zest ohm video opera jell 11 words, 48 letters
I think that's not bad for a fairly simplistic algorithm (though I'm a little dubious about 'clix'.)
#!/usr/bin/perl # Peter Campbell Smith - 2022-04-18 # PWC 161 task 2 use v5.28; use strict; use warnings; use utf8; my ($dictionary, $done, $k, $last_word, $num_letter, $num_letters, $num_words, $ord_a, $pangram, $word, $num_chars, @best_words, @best_chars, $tries, @words); # fetch dictionary $dictionary = `curl -s -L https://github.com/manwar/perlweeklychallenge-club/raw/master/data/dictionary.txt`; while ($dictionary =~ m|(.*?)\n|g) { $word = lc($1); chomp($word); push @words, lc($word); } $last_word = scalar @words; $done = 2 ** 26 - 1; # bitmap if all 26 letters have been found $ord_a = ord('a'); # make 10 'random' pangrams say qq[--- 10 random pangrams ---]; for $k (1 .. 10) { ($pangram, $num_words, $num_letters) = pangram(); say qq[\nPangram $k:\n$pangram\n$num_words words, $num_letters letters]; } # find the fewest words and letters from lots of tries $tries = 10000; say qq[\n--- Fewest words and letters from $tries tries ---]; @best_words = ('', 1000, 1000); @best_chars = ('', 1000, 1000); for $k (1 .. $tries) { ($pangram, $num_words, $num_letters) = pangram(); if ($num_words < $best_words[1]) { @best_words = ($pangram, $num_words, $num_letters); } if ($num_letters < $best_chars[2]) { @best_chars = ($pangram, $num_words, $num_letters); } } say qq[\nLeast words:\n$best_words[0]\n$best_words[1] words, $best_words[2] letters]; say qq[\nLeast letters:\n$best_chars[0]\n$best_chars[1] words, $best_chars[2] letters]; sub pangram { my ($bit, $letter, $num_chars, $num_words, $pangram, $pattern, $target, $word, @letters); # generates a 'random' pangram # initialise $target = 0; # bitmap so far $pangram = ''; # loop over random words while ($word = $words[int(rand($last_word))]) { # split word into letters @letters = split(//, $word); # next if $#letters > 4; # see blog about this line # create bitmap of this word $pattern = 0; for $letter (@letters) { $bit = ord($letter) - $ord_a; $pattern |= 2 ** $bit; } # if this word has letter(s) we don't have, add it to the pangram if ($pattern & ~ $target) { $pangram .= $word . ' '; $target |= $pattern; $num_words ++; $num_chars += $#letters + 1; } # have we got them all yet? last if $target == $done; } return($pangram, $num_words, $num_chars); }
--- 10 random pangrams --- Pangram 1: lithium uninformative corkscrewed proudly swigging juveniles biology expose lizards tranquilizing 10 words, 88 letters Pangram 2: authoring ramifications philanthropic bani plunges nosebleed betray wired executed yank junipers eloquently overworks snooze 14 words, 111 letters Pangram 3: plod irks warms cessations game harebrained reimbursed evolve grossly cupful justify liquefying inexplicably hazes 14 words, 101 letters Pangram 4: televises pores actresses seconds wages baboons beaching bestiality because frequented randomly storekeepers zippering extraordinarily judiciously 15 words, 132 letters Pangram 5: plural summarizes prominence scabs trios merchandised interviewed flaky sharking rejoice inquest lexicons 12 words, 94 letters Pangram 6: trailers permanence counterclockwise asphyxiation brocaded compelling jangles waterfront cavities plaque lizards 11 words, 102 letters Pangram 7: axes fillet greases fairness faraway impair presidents pinked extinction robust hobnobbing violate eloquence friezes jabbered 15 words, 111 letters Pangram 8: humored blur recycles ripeness laxative fleeter validating slakes touchdown equanimity interjected brazier 12 words, 95 letters Pangram 9: psych indoctrinates outdistances dummy survey profited griefs weest slanders marquees xxi matchbook jackknifing agonize 14 words, 106 letters Pangram 10: protections convenient lubricate hims hay characterized gushing drinker extrapolating fluent winning judiciously squeezing 13 words, 110 letters --- Fewest words and letters from 10000 tries --- Least words: objectively chloroformed scripting equivalents waterfront paddock exile pasteurizing 8 words, 77 letters Least letters: precise botany levee extinguishes sizable swamp bedrock after judo squats 10 words, 64 letters
Any content of this website which has been created by Peter Campbell Smith is in the public domain