Two Word Games

October 9, 2012

We begin by creating a framework that reads a dictionary file and displays those words that meet the parameterized requirement; we’ll be able to use that for both games:

(define (game filter)
  (for-each-input (filter-input read-line filter)
    (lambda (word) (display word) (newline))
    "Desktop/moby.words"))

This is simple because the Standard Prelude provides functions for handling file input: for-each-input processes each line in Desktop/moby.words and prints it with the lambda if it passes the filter. Filter-input is a higher-order function; it takes a reader function (here we use read-line from the Standard Prelude) and a filter function and returns a new filter function for use by for-each-input.

With that out of the way, we look at the problem of finding words with five vowels in order:

(define vowels '(#\a #\e #\i #\o #\u))

(define (vowel? c) (member c vowels))

(define (five-vowels-in-order? str)
  (equal? vowels (filter vowel? (string->list str))))

We wrote it in three pieces, because it seems more natural that way, but you could easily write it all in one function. Here’s the output:

> (game five-vowels-in-order?)
abstemious
abstemiously
abstentious
acheilous
acheirous
acleistous
affectious
aleikoum
anemious
annelidous
arsenious
arterious
bacterious
caesious
facetious
facetiously
fracedinous
majestious
parecious
pareciously
tragedious

The second game is equally simple:

(define (sorted-and-six? str)
  (and (<= 6 (string-length str))
    (sorted? char<? (string-%gt;list str))))

The sorted? function is useful in a variety of situations, and probably ought to be in our Standard Prelude. In fact, I thought it was, and wrote the sorted-and-six? function assuming that sorted? was already defined, only to be surprised when it didn’t work; maybe I’ll add sorted? later. You can see sorted?, along with the rest of the program, at http://programmingpraxis.codepad.org/MDR7xq81. Here’s the output:

> (game sorted-and-six?)
abdest
abhors
acknow
adempt
adhort
adipsy
aegilops
agnosy
almost
anopsy
befist
begins
begirt
behint
beknot
beknow
bijoux
biopsy
cestuy
chimps
chinos
chintz
deflow
deflux
deglory
dehors
dehort
deinos
dhikrs
diluvy
dimpsy
egilops
ghosty

I’ll need to fetch my dictionary to find out what some of those words mean. Everybody use aegilops in a sentence sometime this week!

Pages: 1 2

9 Responses to “Two Word Games”

  1. […] today’s Programming Praxis exercise, our goal is to find all the words in a dictionary that satisfy two […]

  2. My Haskell solution (see http://bonsaicode.wordpress.com/2012/10/09/programming-praxis-two-word-games/ for a version with comments):

    ascVowels :: String -> Bool
    ascVowels = (== "aeiou") . filter (`elem` "aeiou")
    
    sixAsc :: Ord b => [b] -> Bool
    sixAsc s = length s == 6 && and (zipWith (<) s $ tail s)
    
    main :: IO ()
    main = do ws <- fmap lines $ readFile "354984si.ngl"
              mapM_ putStrLn $ filter ascVowels ws
              putStrLn "---"
              mapM_ putStrLn $ filter sixAsc ws
    
  3. Paul said
    import itertools as IT
    vowels = list("aeiou")
    ord_vowels = lambda s: [si for si in s if si in vowels] == vowels
    ord_chars_gt6 = lambda s: 6 <= len(s) == len(set(s)) and sorted(s) == list(s)
    
    def gen_words(fname):
        for line in open(FNAME):
            yield line.split()[0]
    
    #example for ord_chars_gt6    
    for w in IT.ifilter(ord_chars_gt6, gen_words(FNAME)):
        print w
    
  4. kawas said
    (ns two-word-games  (:require [clojure.java.io :as jio]))
    
    (defn five-vowels-in-order? [word]
      (when (= [\a \e \i \o \u] (filter #{\a \e \i \o \u} word)) word))
    
    (defn six-and-sorted? [word]
      (and (= 6 (count word)) (apply <= (map int word))))
    
    (defn game [dict-fp predicate-fn]
      (with-open [rdr (jio/reader dict-fp)]
        (doseq [w (filter predicate-fn (line-seq rdr))] (println w))))
    
    (game "words.txt" five-vowels-in-order?)
    (game "words.txt" six-and-sorted?)
    
  5. PG said

    public class WordGame1
    {
    public List Execute()
    {
    string line;
    var results = new List();
    var file = LoadFile();
    while ((line = file.ReadLine()) != null)
    {
    if (ContainsAllFiveVowels(line))
    results.Add(line);
    }

    return results;
    }

    private static StreamReader LoadFile()
    {
    var assembly = Assembly.GetExecutingAssembly();
    return new StreamReader(assembly.GetManifestResourceStream(“ProgrammingPraxis.Content.354984si.ngl”));
    }

    private static bool ContainsAllFiveVowels(string textString)
    {
    return Vowels.All(vow => textString.IndexOf(vow, StringComparison.CurrentCultureIgnoreCase) >= 0);
    }

    private static IEnumerable Vowels
    {
    get { return new List {“a”, “e”, “i”, “o”, “u”}; }
    }
    }

  6. […] day, another post from Programming Praxis. Today they posted a word game that seems simple enough: first find all […]

  7. JP said

    That was fun. Most of the work went into loading the file and iterating through them line by line (I miss Python’s for line in open(filename, 'r'):), but the rest was pretty straight forward.

    My solution in Racket / Scheme

  8. A Python solution:

    def is_sorted(seq):
        last = None
        for x in seq:
            if last is None:
                last = x
            else:
                if x < last:
                    return False
                last = x
        return True
    
    def vowels(s):
        return reduce(lambda s, c: s + c if c in 'aeiou' else s, s, '')
    
    def map_file(fn, filename):
        result = []
        with open(filename) as infile:
            for line in infile:
                line = line.strip()
                if fn(line):
                    result.append(line)
        return result
    
    def exercise1(filename):
        def fn(line):
            return len(line) > 5 and vowels(line) == 'aeiou'
        return map_file(fn, filename)
    
    def exercise2(filename):
        def fn(line):
            return len(line) > 5 and is_sorted(line)
        return map_file(fn, filename)
    
    from pprint import pprint
    pprint(exercise1('words.lst'))
    pprint(exercise2('words.lst'))
    
  9. OK, those are great. But of course you can take a low-tech approach to word games, like here: http://daisybrain.wordpress.com/2012/03/09/wordarchy/

Leave a comment