Begin forwarded message:

> From: "btbeal" <btbeal / swbell.net>
> Date: April 22, 2006 5:00:23 PM CDT
> To: <submission / rubyquiz.com>
> Subject: Please Forward: Ruby Quiz Submission
>
> Hello,
>
> This is my first submission to Ruby Quiz.  I wrote up a little  
> explanation
> of how the program works, which you can use or not, as you wish.  I  
> didn't
> include a data file to keep it short.  Hopefully the tabs will  
> expand again
> when you copy the code into a text editor.
>
> - Robert Beal (Austin, TX)
>
>
> ------------------------------------------------------------
> Program Explanation (Quiz 76--Text Munging)
>
> The heart of the program is the function "create_random_permutation".
> It creates an array of the numbers 0...length and a second, empty  
> array.
> Then it deletes a number randomly from the first array and appends  
> the number
> to the second array.  Afterwards, the second array is returned.   
> The optional
> arguments allow one to shift the range of numbers stored in the  
> array, and to
> shift the indices where the range is stored.
>
> The second function, "permute_word", first copies its string argument
> in order to have a target to copy the permuted letters to.  Next  
> the word
> length is calculated; words of 3 letters or less won't change.   
> Otherwise,
> 2 is subtracted from the word's length (to omit the first and last  
> letters)
> and a permutation is calculated in the range (1...length-1).  The  
> letters are
> copied from the original to the copy using the permuted values as
> subscripts into the target string. Finally, the copy is returned.
>
> The last function, "munge", reads in a file, munges it, and writes the
> results back out to another file.  The file is read in as one giant  
> string,
> and two indexes into the string are created.  Index #1 points at  
> the first
> letter of a word, and Index #2 points at the first letter past that  
> word.
> Each is moved forward in alternating turns until they bracket a  
> word, the word
> is munged in place, and the process repeats until both indexes wind  
> up at the
> end of the string.
>
> -------------------------------------------------------------
> The Program (Quiz 76--Text Munging)
>
>
> # Return a permutation of the values (0...length) in an array.
> # If "offset" is given, return [offset,...,length+offset].
> # If "pad" is given, return [nil,...,nil, <rest of perm>].
> # If offset == pad, you can index into the array with the
> # same set of values that you get out of it.
> def create_random_permutation(length, offset=0, pad=offset)
>  a = Array.new(length) {|i| i + offset}
>  b = Array.new(pad, nil)
>  (length - 1).downto(0) {|i| b.push(a.delete_at(rand(i + 1)))}
>  b
> end
> alias crp create_random_permutation
>
> # Given a string, permute the characters in the interior of (a copy  
> of) the string
> # (i.e. leave the first and last characters alone) and return the  
> result.
> def permute_word(word)
>  word2 = word.clone
>  if word.length > 3
>   p = crp(word.length - 2, 1)
>   1.upto(word.length - 2) {|i| word2[p[i]] = word[i]}
>  end
>  word2
> end
>
> # The main program.
> # Read a text file, munge all words, and write out the result.
> # "Munging" means to permute all the interior letters of a word.
> # The first and last letters in the word and all other characters
> # (punctuation, blanks, etc.) in the string are left where they are.
> # A simple filename (no path, no extension) is the argument;
> # the file is assumed to be in the current directory, the input
> # extension is .txt, and the output extension is .out.
> def munge(name)
>  infile = name + ".txt"
>  outfile = name + ".out"
>  line = File.open(infile) {|f| f.read}
>  #i1 points at the first character in a word.
>  #i2 points at the first character after a word.
>  i1 = i2 = 0;
>  while i1 < line.length || i2 < line.length
>   i2 += 1 while i2 < line.length && line[i2, 1] =~ /[[:alpha:]]/  
> #in a word
>   line[i1...i2] = permute_word(line[i1...i2])
>   i1 = i2
>   i1 += 1 while i1 < line.length && line[i1, 1] !~ /[[:alpha:]]/  
> #not in a word
>   i2 = i1
>  end
>  File.open(outfile, "w") {|f| f.write(line)}
> # line
> end
>
> ---------------end--------------------------------
>