One Man Went To Mow

Discussion in 'NZ Computing' started by Lawrence D'Oliveiro, Nov 17, 2009.

  1. This is an exercise in using the GNU M4 macro processor to generate a
    nursery rhyme. I wonder if anyone has tried to use M4 as, say, a more
    powerful substitute for the C-language preprocessor? Anyway...

    Starting from the bottom up, first of all I needed a way to turn a number
    into words, so 1 becomes “oneâ€, and so on up to 10 (the maximum number of
    verses I’m going to generate). Here’s what I came up with:

    define(`n', `regexp(` x one two three four five six seven eight nine ten', `^\'repeat(` [^ ]+', $1)` \([^ ]+\)', `\1')')

    so “n(1)†expands to “one†and so on, where “repeat†is defined as

    define(`repeat', `ifelse($2, 0, `', $2, 1, `$1', `$1`'repeat(`$1', eval($2 - 1))')')

    so for example “repeat(abc, 3)†expands to “abcabcabcâ€.

    Next, a macro to capitalize the first letter of a word:

    define(`cap', `regexp(`$1', `^\(.\)\(.*\)$', `translit(`\1', `a-z', `A-Z')\2')')

    so “cap(london)†expands to “Londonâ€. How many verses am I going to output:

    define(`nrverses', 10)

    A macro to generate an appropriate singular or plural noun phrase:

    define(`nmen', `cap(n($1)) ifelse($1, 1, man, men)')

    thus, “nmen(1)†expands to “One manâ€, “nmen(2)†expands to “Two men†and so
    on.

    Factoring the simple, repetitive parts of the verses:

    define(`tomow', ` went to mow')
    define(`mow1', `tomow a meadow')

    This macro generates the first line of each verse:

    define(`firstline', `nmen($1)`'tomow,mow1')

    The remaining lines of each verse:

    define(`restlines', `ifelse($1, 1, `nmen(1) and his dog,mow1', `nmen($1)
    restlines(eval($1 - 1))')')

    Starting to come together now. Each complete verse:

    define(`verse', `firstline($1)
    restlines($1)')

    This one generates all the verses from the specified one up to the last one:

    define(`verses', `verse($1)`'ifelse($1, nrverses, `', `

    verses(eval($1 + 1))')')

    So tell it to output from the first verse:

    verses(1)

    et voilà, the complete output:

    One man went to mow, went to mow a meadow
    One man and his dog, went to mow a meadow

    Two men went to mow, went to mow a meadow
    Two men
    One man and his dog, went to mow a meadow

    Three men went to mow, went to mow a meadow
    Three men
    Two men
    One man and his dog, went to mow a meadow

    Four men went to mow, went to mow a meadow
    Four men
    Three men
    Two men
    One man and his dog, went to mow a meadow

    Five men went to mow, went to mow a meadow
    Five men
    Four men
    Three men
    Two men
    One man and his dog, went to mow a meadow

    Six men went to mow, went to mow a meadow
    Six men
    Five men
    Four men
    Three men
    Two men
    One man and his dog, went to mow a meadow

    Seven men went to mow, went to mow a meadow
    Seven men
    Six men
    Five men
    Four men
    Three men
    Two men
    One man and his dog, went to mow a meadow

    Eight men went to mow, went to mow a meadow
    Eight men
    Seven men
    Six men
    Five men
    Four men
    Three men
    Two men
    One man and his dog, went to mow a meadow

    Nine men went to mow, went to mow a meadow
    Nine men
    Eight men
    Seven men
    Six men
    Five men
    Four men
    Three men
    Two men
    One man and his dog, went to mow a meadow

    Ten men went to mow, went to mow a meadow
    Ten men
    Nine men
    Eight men
    Seven men
    Six men
    Five men
    Four men
    Three men
    Two men
    One man and his dog, went to mow a meadow

    Of course, if you copied my code literally, you’ll end up with lots of
    spurious blank lines interspersed. Inserting appropriate instances of the
    necessary “dnl†calls in all the right places is left as an exercise for the
    reader. :)
     
    Lawrence D'Oliveiro, Nov 17, 2009
    #1
    1. Advertising

  2. Lawrence D'Oliveiro

    Ron McNulty Guest

    On Nov 17, 10:01 pm, Lawrence D'Oliveiro <l...@geek-
    central.gen.new_zealand> wrote:
    > This is an exercise in using the GNU M4 macro processor to generate a
    > nursery rhyme. I wonder if anyone has tried to use M4 as, say, a more
    > powerful substitute for the C-language preprocessor? Anyway...
    >
    > Starting from the bottom up, first of all I needed a way to turn a number
    > into words, so 1 becomes “one”, and so on up to 10 (the maximum number of
    > verses I’m going to generate). Here’s what I came up with:
    >
    >     define(`n', `regexp(` x one two three four five six seven eight nine ten', `^\'repeat(` [^ ]+', $1)` \([^ ]+\)', `\1')')
    >
    > so “n(1)” expands to “one” and so on, where “repeat” is defined as
    >
    >     define(`repeat', `ifelse($2, 0, `', $2, 1, `$1', `$1`'repeat(`$1', eval($2 - 1))')')
    >
    > so for example “repeat(abc, 3)” expands to “abcabcabc”.
    >
    > Next, a macro to capitalize the first letter of a word:
    >
    >     define(`cap', `regexp(`$1', `^\(.\)\(.*\)$', `translit(`\1', `a-z', `A-Z')\2')')
    >
    > so “cap(london)” expands to “London”. How many verses am I going to output:
    >
    >     define(`nrverses', 10)
    >
    > A macro to generate an appropriate singular or plural noun phrase:
    >
    >     define(`nmen', `cap(n($1)) ifelse($1, 1, man, men)')
    >
    > thus, “nmen(1)” expands to “One man”, “nmen(2)” expands to “Two men” and so
    > on.
    >
    > Factoring the simple, repetitive parts of the verses:
    >
    >     define(`tomow', ` went to mow')
    >     define(`mow1', `tomow a meadow')
    >
    > This macro generates the first line of each verse:
    >
    >     define(`firstline', `nmen($1)`'tomow,mow1')
    >
    > The remaining lines of each verse:
    >
    >     define(`restlines', `ifelse($1, 1, `nmen(1) and his dog,mow1', `nmen($1)
    >     restlines(eval($1 - 1))')')
    >
    > Starting to come together now. Each complete verse:
    >
    >     define(`verse', `firstline($1)
    >     restlines($1)')
    >
    > This one generates all the verses from the specified one up to the last one:
    >
    >     define(`verses', `verse($1)`'ifelse($1, nrverses, `', `
    >
    >     verses(eval($1 + 1))')')
    >
    > So tell it to output from the first verse:
    >
    >     verses(1)
    >
    > et voilà, the complete output:
    >
    > One man went to mow, went to mow a meadow
    > One man and his dog, went to mow a meadow
    >
    > Two men went to mow, went to mow a meadow
    > Two men                                  
    > One man and his dog, went to mow a meadow
    >
    > Three men went to mow, went to mow a meadow
    > Three men                                  
    > Two men                                    
    > One man and his dog, went to mow a meadow  
    >
    > Four men went to mow, went to mow a meadow
    > Four men                                  
    > Three men                                
    > Two men                                  
    > One man and his dog, went to mow a meadow
    >
    > Five men went to mow, went to mow a meadow
    > Five men                                  
    > Four men                                  
    > Three men                                
    > Two men                                  
    > One man and his dog, went to mow a meadow
    >
    > Six men went to mow, went to mow a meadow
    > Six men                                  
    > Five men                                
    > Four men                                
    > Three men                                
    > Two men                                  
    > One man and his dog, went to mow a meadow
    >
    > Seven men went to mow, went to mow a meadow
    > Seven men                                  
    > Six men
    > Five men
    > Four men
    > Three men
    > Two men
    > One man and his dog, went to mow a meadow
    >
    > Eight men went to mow, went to mow a meadow
    > Eight men
    > Seven men
    > Six men
    > Five men
    > Four men
    > Three men
    > Two men
    > One man and his dog, went to mow a meadow
    >
    > Nine men went to mow, went to mow a meadow
    > Nine men
    > Eight men
    > Seven men
    > Six men
    > Five men
    > Four men
    > Three men
    > Two men
    > One man and his dog, went to mow a meadow
    >
    > Ten men went to mow, went to mow a meadow
    > Ten men
    > Nine men
    > Eight men
    > Seven men
    > Six men
    > Five men
    > Four men
    > Three men
    > Two men
    > One man and his dog, went to mow a meadow
    >
    > Of course, if you copied my code literally, you’ll end up with lots of
    > spurious blank lines interspersed. Inserting appropriate instances of the
    > necessary “dnl” calls in all the right places is left as an exercise for the
    > reader. :)


    Not sure what the point is Lawrence, but the same algorithm can be
    expresses in ordinary programming languages with a similar number of
    lines and far greater clarity. For instance in Java:

    package fiddle;

    public class MenMowing {
    private static final int MAX_MEN = 10;
    private static final String[] describeMen =
    {"No", "One man", "Two men", "Three men", "Four men",
    "Five men", "Six men", "Seven men", "Eight men", "Nine men",
    "Ten men"};

    public static void main(String[] args) {
    for (int i = 1; i <= MAX_MEN; i++) {
    System.out.println(describeMen + "" + " went to mow, went to
    mow a meadow");
    for (int j = i; j >= 1; --j){
    System.out.println(describeMen[j] + (j == 1 ? " and his dog
    went to mow a meadow" : ""));
    }
    System.out.println();
    }
    }
    }

    Regards

    Ron
     
    Ron McNulty, Nov 17, 2009
    #2
    1. Advertising

  3. In message <>, Ron McNulty wrote:

    > On Nov 17, 10:01 pm, Lawrence D'Oliveiro <l...@geek-
    > central.gen.new_zealand> wrote:
    >
    >> [my entire posting quoted]


    Tip: there’s no need to quote my entire posting, everybody knows what I said.

    > Not sure what the point is Lawrence, but the same algorithm can be
    > expresses in ordinary programming languages with a similar number of
    > lines and far greater clarity. For instance in Java:


    But you cannot embed Java in a data file. That’s the key point of macro
    processors, e.g.
    <http://sourceforge.net/mailarchive/forum.php?thread_name=494B6AF6.4090002%40geek-central.gen.nz&forum_name=dvdauthor-users>,
    <http://sourceforge.net/mailarchive/forum.php?thread_name=494C549B.40703%40geek-central.gen.nz&forum_name=dvdauthor-users>.
     
    Lawrence D'Oliveiro, Nov 18, 2009
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr Nice

    Advice on one-man PC Support business?

    Mr Nice, Feb 22, 2005, in forum: Computer Support
    Replies:
    36
    Views:
    1,222
    Blinky the Shark
    Feb 25, 2005
  2. Old Gringo

    Can One Man Make A Difference?

    Old Gringo, Mar 26, 2005, in forum: Computer Support
    Replies:
    6
    Views:
    472
    Old Gringo
    Mar 27, 2005
  3. Doug MacLean
    Replies:
    0
    Views:
    655
    Doug MacLean
    Aug 16, 2005
  4. DVD Verdict
    Replies:
    0
    Views:
    875
    DVD Verdict
    Nov 2, 2005
  5. joevan

    Mow the lawn. Engrish commercial

    joevan, Apr 7, 2009, in forum: Computer Support
    Replies:
    17
    Views:
    880
    §ñühw¤£f
    Apr 10, 2009
Loading...

Share This Page