# \[QUIZ\] Text Munger (#76)

**URL:** <https://rubytalk.org/t/quiz-text-munger-76/26817>\
**Category:** ruby-talk\
**Created:** [21 April 2006 12:34 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817 "2006-04-21T12:34:35Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [21 April 2006 12:34 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/1 "2006-04-21T12:34:35Z")

</div>

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until  
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

[http://www.rubyquiz.com/](http://www.rubyquiz.com/)

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone  
on Ruby Talk follow the discussion.

> **···**
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
> 
> by Matthew Moss
> 
> &nbsp;&nbsp;Now terhe is a fnial rseaon I thnik that Jsues syas, "Lvoe your  
> &nbsp;&nbsp;emneies." It is tihs: taht love has wtiihn it a remvpidtee pewor. And  
> &nbsp;&nbsp;three is a pwoer three taht eellvtanuy tfranrmsos idvlinaidus. Taht's  
> &nbsp;&nbsp;why Juess syas, "Love your emeeins." Bsceaue if you hate your  
> &nbsp;&nbsp;enmeies, you have no way to reedem and to tarfnrsom your eenmeis. But  
> &nbsp;&nbsp;if you love yuor emienes, you wlil decsiovr that at the vrey root of  
> &nbsp;&nbsp;love is the pwoer of rdoemptein. You just keep loinvg pepole and keep  
> &nbsp;&nbsp;lnivog tehm, even tgouhh they're mteitnsiarg you. Hree's the porsen  
> &nbsp;&nbsp;who is a nhoeigbr, and tihs psoren is dnoig simhoetng wrong to you and  
> &nbsp;&nbsp;all of that. Just keep being fnrdliey to that preosn. Keep liovng  
> &nbsp;&nbsp;them. Don't do atnynhig to earsmrbas tehm. Just keep lvonig them, and  
> &nbsp;&nbsp;they can't stand it too long. Oh, they raect in mnay ways in the  
> &nbsp;&nbsp;bineningg. They react wtih brnetitess beucase they're mad bauesce you  
> &nbsp;&nbsp;lvoe them like that. Tehy raect wtih gluit flegines, and setioemms  
> &nbsp;&nbsp;they'll hate you a lltite more at that tinoiasrtn piroed, but just  
> &nbsp;&nbsp;keep lvniog them. And by the poewr of your love tehy will beark down  
> &nbsp;&nbsp;uendr the load. That's lvoe, you see. It is retpmevide, and tihs is  
> &nbsp;&nbsp;why Juess says love. Trehe's shimeotng aubot love that blidus up and  
> &nbsp;&nbsp;is cavrtiee. Trehe is stmeonihg aubot hate that tares dwon and is  
> &nbsp;&nbsp;disettvrcue. So lvoe your eenmeis.
> 
> On first glance, the above may appear to be gibberish, but you may find that you  
> can actually read this portion of a speech from Dr Martin Luther King Jr. The  
> brain has an amazing capacity to compensate for things that aren't quite right,  
> and one study has shown that when the first and last letters of words are left  
> alone but those in the middle are scrambled, the text is often still quite  
> comprehensible.
> 
> Your task for this quiz, then, is to take a text as input and output the text in  
> this fashion. Scramble each word's center (leaving the first and last letters of  
> each word intact). Whitespace, punctuation, numbers -- anything that isn't a  
> word -- should also remain unchanged.

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [21 April 2006 12:57 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/2 "2006-04-21T12:57:58Z")

</div>

Hi --

> by Matthew Moss
> 
> &nbsp;&nbsp;Now terhe is a fnial rseaon I thnik that Jsues syas, "Lvoe your  
> &nbsp;&nbsp;emneies." It is tihs: taht love has wtiihn it a remvpidtee pewor. And  
> &nbsp;&nbsp;three is a pwoer three taht eellvtanuy tfranrmsos idvlinaidus. Taht's  
> &nbsp;&nbsp;why Juess syas, "Love your emeeins." Bsceaue if you hate your  
> &nbsp;&nbsp;enmeies, you have no way to reedem and to tarfnrsom your eenmeis. But  
> &nbsp;&nbsp;if you love yuor emienes, you wlil decsiovr that at the vrey root of  
> &nbsp;&nbsp;love is the pwoer of rdoemptein. You just keep loinvg pepole and keep  
> &nbsp;&nbsp;lnivog tehm, even tgouhh they're mteitnsiarg you. Hree's the porsen  
> &nbsp;&nbsp;who is a nhoeigbr, and tihs psoren is dnoig simhoetng wrong to you and  
> &nbsp;&nbsp;all of that. Just keep being fnrdliey to that preosn. Keep liovng  
> &nbsp;&nbsp;them. Don't do atnynhig to earsmrbas tehm. Just keep lvonig them, and  
> &nbsp;&nbsp;they can't stand it too long. Oh, they raect in mnay ways in the  
> &nbsp;&nbsp;bineningg. They react wtih brnetitess beucase they're mad bauesce you  
> &nbsp;&nbsp;lvoe them like that. Tehy raect wtih gluit flegines, and setioemms  
> &nbsp;&nbsp;they'll hate you a lltite more at that tinoiasrtn piroed, but just  
> &nbsp;&nbsp;keep lvniog them. And by the poewr of your love tehy will beark down  
> &nbsp;&nbsp;uendr the load. That's lvoe, you see. It is retpmevide, and tihs is  
> &nbsp;&nbsp;why Juess says love. Trehe's shimeotng aubot love that blidus up and  
> &nbsp;&nbsp;is cavrtiee. Trehe is stmeonihg aubot hate that tares dwon and is  
> &nbsp;&nbsp;disettvrcue. So lvoe your eenmeis.
> 
> On first glance, the above may appear to be gibberish, but you may find that you  
> can actually read this portion of a speech from Dr Martin Luther King Jr. The  
> brain has an amazing capacity to compensate for things that aren't quite right,  
> and one study has shown that when the first and last letters of words are left  
> alone but those in the middle are scrambled, the text is often still quite  
> comprehensible.
> 
> Your task for this quiz, then, is to take a text as input and output the text in  
> this fashion. Scramble each word's center (leaving the first and last letters of  
> each word intact). Whitespace, punctuation, numbers -- anything that isn't a  
> word -- should also remain unchanged.

Question:

Given a word like "there's" or "that's", does the letter before the  
apostrophe count as a "last" letter? In other words, could "that's"  
become "ttha's"?

In the example above, there's no case where that letter gets  
scrambled. It's possible that that's coincidence, but it doesn't look  
like it.

David

> **···**
>
> On Fri, 21 Apr 2006, Ruby Quiz wrote:
> 
> --  
> David A. Black (dblack@wobblini.net)  
> Ruby Power and Light, LLC ([http://www.rubypowerandlight.com](http://www.rubypowerandlight.com))
> 
> "Ruby for Rails" PDF now on sale! [Ruby for Rails](http://www.manning.com/black)  
> Paper version coming in early May!

---

<div class="post-metadata">

**Author:** ![Florian\_Gross2](https://avatars.discourse-cdn.com/v4/letter/f/b4bc9f/32.png) [@Florian\_Gross2](https://rubytalk.org/u/Florian_Gross2)\
**Post date:** [21 April 2006 13:10 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/3 "2006-04-21T13:10:31Z")

</div>

Ruby Quiz wrote:

> Your task for this quiz, then, is to take a text as input and output the text in  
> this fashion. Scramble each word's center (leaving the first and last letters of  
> each word intact). Whitespace, punctuation, numbers -- anything that isn't a  
> word -- should also remain unchanged.

What about writing an unscrambler? Could that also be done for this quiz or might that be next week's task? 🙂

> **···**
>
> --  
> [http://flgr.0x42.net/](http://flgr.0x42.net/)

---

<div class="post-metadata">

**Author:** ![Jake\_McArthur](https://avatars.discourse-cdn.com/v4/letter/j/f19dbf/32.png) [@Jake\_McArthur](https://rubytalk.org/u/Jake_McArthur)\
**Post date:** [21 April 2006 18:52 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/4 "2006-04-21T18:52:10Z")

</div>

My first participation in Ruby Quiz, and it has to be easy. That said, I must really be missing something because some of you guys are mentioning one-liners, and mine is 26 lines. Maybe it's because I made mine highly abstracted, but I still don't really see how to do this in one line.

- Jake McArthur

---

<div class="post-metadata">

**Author:** ![Adam\_Shelly](https://avatars.discourse-cdn.com/v4/letter/a/e19b73/32.png) [@Adam\_Shelly](https://rubytalk.org/u/Adam_Shelly)\
**Post date:** [22 April 2006 01:55 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/5 "2006-04-22T01:55:25Z")

</div>

I know everyone here is Nice(tm), so I'm sure this is not the  
intent... but between this quiz and the Markov chain one, it seems we  
are building a set of utilities perfect for generating those 'Re:  
PHARmudMACY'  
spam emails selling 'vigara' and such that have been sneaking through  
my spam filter at work recently...

-Adam

> **···**
>
> On 4/21/06, Ruby Quiz \<james@grayproductions.net\> wrote:
> 
> > Your task for this quiz, then, is to take a text as input and output the text in  
> > this fashion. Scramble each word's center (leaving the first and last letters of  
> > each word intact). Whitespace, punctuation, numbers -- anything that isn't a  
> > word -- should also remain unchanged.

---

<div class="post-metadata">

**Author:** ![Himadri\_Choudhury](https://avatars.discourse-cdn.com/v4/letter/h/ecc23a/32.png) [@Himadri\_Choudhury](https://rubytalk.org/u/Himadri_Choudhury)\
**Post date:** [23 April 2006 09:45 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/6 "2006-04-23T09:45:07Z")

</div>

Here's my solution.

Usage : scramble.rb \<text\_file\>

I made 3 attempts.

1)  
print ARGF.read.gsub!(/\B[a-z]+\B/) {|x| x.split('').sort\_by{rand}.join}

Here I use gsub to find all the words. Use split to convert strings into  
arrays. And then use the sort\_by{rand} to scramble the arrays. And finally  
use join to convert the array back to a string.  
I'm assuming that words don't have upper case letters in the middle, so that  
I can get away with [a-z].

2)  
print ARGF.read.gsub!(/\B[a-z]+\B/) {|x| x.unpack  
('c\*').sort\_by{rand}.pack('c\*')}

I found this method of converting strings to and from arrays to be faster.  
I'm not sure what the standard idiom for doing this is. But, I'm sure I'll  
learn after seeing other people's solutions 😉

3 If sort\_by{rand} does what I think it does, it probably has a bias when  
the rand function returns the same value. So, this is my third  
implementation:

print ARGF.read.gsub!(/\B[a-z]+\B/) {|x|  
&nbsp;&nbsp;&nbsp;&nbsp;x.length.times {|i|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = rand(i+1)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x[j], x[i] = x[i] , x[j]  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;x  
}

Basically, this is an implementation of scrambling that uses swaps. I  
remember this method for scrambling from way back, but I can't seem to find  
a good reference for it at the moment.  
I also figured that this method would be faster since it is linear, while  
the sorts are n log(n) (n = length of the word)

To by surprise, I found this method to actually be slower for any normal  
text. One possible explanation is that when words are relatively short you  
don't gain much from the n vs. nlogn difference, and you lose because while  
this method always has n swaps, sorting may have less.

In order to see any performance benefit from the 3rd method I had to make up  
some horrifically long words which aren't terribly likely in the English  
language (maybe I should have tried German :)).

Himadri

> **···**
>
> On 4/21/06, Ruby Quiz \<james@grayproductions.net\> wrote:
> 
> > The three rules of Ruby Quiz:
> > 
> > 1. Please do not post any solutions or spoiler discussion for this quiz  
> > until  
> > 48 hours have passed from the time on this message.
> > 
> > 2. Support Ruby Quiz by submitting ideas as often as you can:
> > 
> > [http://www.rubyquiz.com/](http://www.rubyquiz.com/)
> > 
> > 3. Enjoy!
> > 
> > Suggestion: A [QUIZ] in the subject of emails about the problem helps  
> > everyone  
> > on Ruby Talk follow the discussion.
> > 
> > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
> > 
> > by Matthew Moss
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Now terhe is a fnial rseaon I thnik that Jsues syas, "Lvoe your  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;emneies." It is tihs: taht love has wtiihn it a remvpidtee pewor.  
> > And  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;three is a pwoer three taht eellvtanuy tfranrmsos idvlinaidus.  
> > Taht's  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;why Juess syas, "Love your emeeins." Bsceaue if you hate your  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enmeies, you have no way to reedem and to tarfnrsom your eenmeis.  
> > But  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if you love yuor emienes, you wlil decsiovr that at the vrey root  
> > of  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;love is the pwoer of rdoemptein. You just keep loinvg pepole and  
> > keep  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lnivog tehm, even tgouhh they're mteitnsiarg you. Hree's the  
> > porsen  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;who is a nhoeigbr, and tihs psoren is dnoig simhoetng wrong to you  
> > and  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;all of that. Just keep being fnrdliey to that preosn. Keep liovng  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;them. Don't do atnynhig to earsmrbas tehm. Just keep lvonig them,  
> > and  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;they can't stand it too long. Oh, they raect in mnay ways in the  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bineningg. They react wtih brnetitess beucase they're mad bauesce  
> > you  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lvoe them like that. Tehy raect wtih gluit flegines, and setioemms
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;they'll hate you a lltite more at that tinoiasrtn piroed, but just  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keep lvniog them. And by the poewr of your love tehy will beark  
> > down  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uendr the load. That's lvoe, you see. It is retpmevide, and tihs  
> > is  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;why Juess says love. Trehe's shimeotng aubot love that blidus up  
> > and  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is cavrtiee. Trehe is stmeonihg aubot hate that tares dwon and is  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;disettvrcue. So lvoe your eenmeis.
> > 
> > On first glance, the above may appear to be gibberish, but you may find  
> > that you  
> > can actually read this portion of a speech from Dr Martin Luther King  
> > Jr. The  
> > brain has an amazing capacity to compensate for things that aren't quite  
> > right,  
> > and one study has shown that when the first and last letters of words are  
> > left  
> > alone but those in the middle are scrambled, the text is often still quite  
> > comprehensible.
> > 
> > Your task for this quiz, then, is to take a text as input and output the  
> > text in  
> > this fashion. Scramble each word's center (leaving the first and last  
> > letters of  
> > each word intact). Whitespace, punctuation, numbers -- anything that isn't  
> > a  
> > word -- should also remain unchanged.

---

<div class="post-metadata">

**Author:** ![Ross\_Bamford4](https://avatars.discourse-cdn.com/v4/letter/r/ea666f/32.png) [@Ross\_Bamford4](https://rubytalk.org/u/Ross_Bamford4)\
**Post date:** [23 April 2006 12:53 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/7 "2006-04-23T12:53:10Z")

</div>

Seems like forty-eight hours are up now, so here are my solutions for  
this quiz, it was good to get a quick one 🙂 I wrote a simple random  
munging solution, and a slightly longer one that munges only part of the  
words. I went for a different way on the latter one, just to play with  
regexps a bit, but I expect its performance isn't great...

Both support unicode properly, as long as the -Ku stays on the ruby  
command line 😉 I could have used the u modifier instead but wanted to  
save on the repetition.

# ========= random munging  
#!/usr/local/bin/ruby -Ku  
$stdout \<\< ARGF.read.gsub(/\B((?![\d\_])\w{2,})\B/) do |w|  
&nbsp;&nbsp;$&.split(//).sort\_by { rand }  
end

# (easily compresses to:)

#!/usr/local/bin/ruby -npKu  
gsub(/\B((?![\d\_])\w){2,}\B/){$&.split(//).sort\_by{rand}}

# ========= slightly-less-random munging  
#!/usr/local/bin/ruby -Ku  
RX = Hash.new{|h,k|h[k]=/(.{#{(k/4.0).round}})#{'(.)'\*(k/2.0).round}(.\*)/}  
$stdout \<\< ARGF.read.gsub(/((?![\d\_])\w){4,}/) do |w|  
&nbsp;&nbsp;(caps = RX[w.split(//u).length].match(w).captures).first +  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;caps[1..-2].sort\_by { rand }.to\_s + caps.last  
end

> **···**
>
> --  
> Ross Bamford - [rosco@roscopeco.REMOVE.co.uk](mailto:rosco@roscopeco.REMOVE.co.uk)

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard6](https://avatars.discourse-cdn.com/v4/letter/a/958977/32.png) [@Ara.T.Howard6](https://rubytalk.org/u/Ara.T.Howard6)\
**Post date:** [23 April 2006 15:32 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/8 "2006-04-23T15:32:54Z")

</div>

> Your task for this quiz, then, is to take a text as input and output the  
> text in this fashion. Scramble each word's center (leaving the first and  
> last letters of each word intact). Whitespace, punctuation, numbers --  
> anything that isn't a word -- should also remain unchanged.

> **···**
>
> \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> solution one  
> \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class String  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def scramble on = ''  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re = %r/( (?:\b \w \w{2,} \w \b) | \s+ | . )/iox  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scan(re){|words| on \<\< words.first.scrambled}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;on  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def scrambled  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[1..-2] = self[1..-2].split(%r//).sort\_by{rand}.to\_s if size \>= 4  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ARGF.read.scramble STDOUT
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb \< a.rb  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cslas Srntig  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def srbcamle on = ''  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re = %r/( (?:\b \w \w{2,} \w \b) | \s+ | . )/iox  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sacn(re){|wrods| on \<\< wodrs.fisrt.salbercmd}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;on  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def sclmaebrd  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slef[1..-2] = slef[1..-2].split(%r//).s\_botry{rnad}.t\_os if size \>= 4  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slef  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ARGF.read.srcalbme SUDOTT
> 
> \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> solution two (golfing) \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;harp:~ \> ruby -npae 'gsub!(/\b(\w)(\w{2,})(\w)\b/){\_=$3;[$1,$2.split(//).sort\_by{rand},\_]}' a.rb  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calss Snrtig  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def sbcarlme on = ''  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re = %r/( (?:\b \w \w{2,} \w \b) | \s+ | . )/iox  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sacn(re){|wdros| on \<\< wdros.first.slramcebd}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;on  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def smlcbaerd  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[1..-2] = slef[1..-2].siplt(%r//).srbt\_oy{rand}.t\_os if size \>= 4  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ARGF.read.smclarbe SUTODT
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;harp:~ \> wc -c  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gsub!(/\b(\w)(\w{2,})(\w)\b/){\_=$3;[$1,$2.split(//).sort\_by{rand},\_]}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;70
> 
> thanks for the fun quiz!
> 
> -a  
> --  
> be kind whenever possible... it is always possible.  
> - h.h. the 14th dali lama

---

<div class="post-metadata">

**Author:** ![Andrew\_Johnson](https://avatars.discourse-cdn.com/v4/letter/a/e9c0ed/32.png) [@Andrew\_Johnson](https://rubytalk.org/u/Andrew_Johnson)\
**Post date:** [23 April 2006 17:11 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/9 "2006-04-23T17:11:49Z")

</div>

Well, the simple regex based one-liner seems to have gotten  
plenty of airplay, so I decided to expand mine in an attempt  
to improve the readability of the munged text. For example:

A naive munging:

&nbsp;&nbsp;Noumeurs idavilundis have dneoatrstmed the ieneascrd  
&nbsp;&nbsp;dfifclutiy oinrcrucg wehn leihngter wdors are slipmy  
&nbsp;&nbsp;reiondmazd. Raionizdnmg wiihtn hntyahoeipn buadoreins  
&nbsp;&nbsp;offers smoe irnmoeemvpt.

A slightly more readable munging:

&nbsp;&nbsp;Nuemruos inididvuals hvae dnometrtsaed the insecraed  
&nbsp;&nbsp;dfiifulcty ocucrinrg when lghetnier wrods are smiply  
&nbsp;&nbsp;rnamodized. Randomzinig wihtin hyphenatoin bonduiares  
&nbsp;&nbsp;offres some imvoepremnt.

Original text:

&nbsp;&nbsp;Numerous individuals have demonstrated the increased  
&nbsp;&nbsp;difficulty occurring when lengthier words are simply  
&nbsp;&nbsp;randomized. Randomizing within hyphenation boundaries  
&nbsp;&nbsp;offers some improvement.

The hyphen-boundary randomizer:

&nbsp;&nbsp;require 'text/hyphen'  
&nbsp;&nbsp;hyp = Text::Hyphen.new :left =\> 1, :right =\> 1  
&nbsp;&nbsp;text = ARGF.read  
&nbsp;&nbsp;text.gsub!(/[^\W\d\_]+/) do |m|  
&nbsp;&nbsp;&nbsp;&nbsp;hyp.visualize(m).split(/(^\w|\w$)|-/).map{|t|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.split(//).sort\_by{rand}.join  
&nbsp;&nbsp;&nbsp;&nbsp;}.join  
&nbsp;&nbsp;end  
&nbsp;&nbsp;puts text  
&nbsp;&nbsp;\_\_END\_\_

cheers,  
andrew

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Daniel\_Harple](https://avatars.discourse-cdn.com/v4/letter/d/5daacb/32.png) [@Daniel\_Harple](https://rubytalk.org/u/Daniel_Harple)\
**Post date:** [23 April 2006 17:52 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/10 "2006-04-23T17:52:58Z")

</div>

Can you also suggest that people reply to the original thread instead of making new ones when they send their solutions? Right now there is:

- Original ruby quiz thread  
- [QUIZ][SOLUTION] ...  
- [QUIZ] ... A solution  
- [QUIZ] ... A simplistic solution  
- [SOLUTION] ...

-- Daniel

> **···**
>
> On Apr 21, 2006, at 2:34 PM, Ruby Quiz wrote:
> 
> > The three rules of Ruby Quiz:  
> > [...]  
> > Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone  
> > on Ruby Talk follow the discussion.

---

<div class="post-metadata">

**Author:** ![Tom\_Moertel](https://avatars.discourse-cdn.com/v4/letter/t/a9a28c/32.png) [@Tom\_Moertel](https://rubytalk.org/u/Tom_Moertel)\
**Post date:** [24 April 2006 01:55 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/11 "2006-04-24T01:55:08Z")

</div>

Ruby Quiz wrote:

> Your task for this quiz, then, is to take a text as input and output the text in  
> this fashion. Scramble each word's center (leaving the first and last letters of  
> each word intact). Whitespace, punctuation, numbers -- anything that isn't a  
> word -- should also remain unchanged.

My solution:

=== snip ===

# Ruby Quiz 76  
# [Ruby Quiz - Text Munger (#76)](http://www.rubyquiz.com/quiz76.html)

> **···**
>
> #  
> # Solution of Tom Moertel  
> # [http://blog.moertel.com/](http://blog.moertel.com/)  
> # 2006-04-21  
> #  
> # Usage: munge.rb [inputs...]
> 
> class String  
> &nbsp;&nbsp;&nbsp;&nbsp;def munge!  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(length - 2).downto(2) do |i|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = rand(i) + 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[i], self[j] = self[j], self[i]  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self  
> &nbsp;&nbsp;&nbsp;end  
> end
> 
> while line = gets  
> &nbsp;&nbsp;&nbsp;puts line.gsub(/\w+/) { |s| s.munge! }  
> end
> 
> === end ===
> 
> A few notes:
> 
> I took the term "scramble" in the task definition to mean randomly permute because some occurrences of words in the example text were apparently unchanged by the scrambling transformation (e.g., "keep" and "being" in the tenth line) and some words that had multiple occurrences were scrambled differently for each occurrence (e.g., "remvpidtee" in the second line vs. "retpmevide" in the fourth from the last line).
> 
> str.munge! (fairly) permutes the inner characters of +str+ and has no effect on strings of three or fewer characters.
> 
> I used +gets+ in the main I/O loop in order to get sensible command-line input handling for free.
> 
> Cheers,  
> Tom

---

<div class="post-metadata">

**Author:** ![Yoann\_Guillot](https://avatars.discourse-cdn.com/v4/letter/y/51bf81/32.png) [@Yoann\_Guillot](https://rubytalk.org/u/Yoann_Guillot)\
**Post date:** [24 April 2006 11:35 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/12 "2006-04-24T11:35:27Z")

</div>

Hello,

Here is my solution to the quiz.  
It's not a one-liner anymore - i've left the first version in the  
comments, for historical purposes.

# 1st try:  
# does not scramble abcd123, which may or not be a good thing  
# no support for accented characters  
# \_ is considered a letter  
#puts ARGF.read.gsub(/\b(?=\D+\b)(\w)(\w+)(?=\w\b)/) { $1 + $2.split('').sort\_by{rand}.join }

class String  
&nbsp;&nbsp;# returns the string with characters randomly placed  
&nbsp;&nbsp;def randomize  
&nbsp;&nbsp;&nbsp;&nbsp;split('').sort\_by{rand}.join  
&nbsp;&nbsp;end

&nbsp;&nbsp;# character class to identify a word's letter  
&nbsp;&nbsp;# arbitrarily ripped from iso-8859-1  
&nbsp;&nbsp;WordChars = '[a-zA-Z\xc0-\xd6\xd8-\xf6\xf8-\xfd\xff]'  
&nbsp;&nbsp;  
&nbsp;&nbsp;# randomizes each word (defined by +chars+), leaving alone the  
&nbsp;&nbsp;# first and last letters  
&nbsp;&nbsp;# uses a default argument to fit in 80 cols 🙂  
&nbsp;&nbsp;def scramble\_words(chars = WordChars)  
&nbsp;&nbsp;&nbsp;&nbsp;gsub(/(#{chars})(#{chars}+)(?=#{chars})/) { $1 + $2.randomize }  
&nbsp;&nbsp;end  
end

puts ARGF.read.scramble\_words if \_\_FILE\_\_ == $0

> **···**
>
> --  
> Yoann

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [21 April 2006 13:14 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/13 "2006-04-21T13:14:25Z")

</div>

It's not part of the challenge this week or next, but you know I'm always for setting your own goals. 🙂

James Edward Gray II

> **···**
>
> On Apr 21, 2006, at 8:10 AM, Florian Groß wrote:
> 
> > Ruby Quiz wrote:
> > 
> > > Your task for this quiz, then, is to take a text as input and output the text in  
> > > this fashion. Scramble each word's center (leaving the first and last letters of  
> > > each word intact). Whitespace, punctuation, numbers -- anything that isn't a  
> > > word -- should also remain unchanged.
> > 
> > What about writing an unscrambler? Could that also be done for this quiz or might that be next week's task? 🙂

---

<div class="post-metadata">

**Author:** ![Matthew\_D\_Moss](https://avatars.discourse-cdn.com/v4/letter/m/b9e5f3/32.png) [@Matthew\_D\_Moss](https://rubytalk.org/u/Matthew_D_Moss)\
**Post date:** [21 April 2006 14:47 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/14 "2006-04-21T14:47:18Z")

</div>

> Given a word like "there's" or "that's", does the letter before the  
> apostrophe count as a "last" letter? In other words, could "that's"  
> become "ttha's"?
> 
> In the example above, there's no case where that letter gets  
> scrambled. It's possible that that's coincidence, but it doesn't look  
> like it.

Do it whichever way you like it...

I don't know what the study said about contractions, if anything.  
Personally, I think I would consider the parts before and after as  
separate words, which would be slightly less scrambled, but my  
intuition (which could be wrong) says that counting it as one whole  
word might throw off legibility more than expected.

---

<div class="post-metadata">

**Author:** ![Ryan\_Leavengood](https://avatars.discourse-cdn.com/v4/letter/r/a587f6/32.png) [@Ryan\_Leavengood](https://rubytalk.org/u/Ryan_Leavengood)\
**Post date:** [21 April 2006 19:09 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/15 "2006-04-21T19:09:07Z")

</div>

Strictly speaking, any Ruby code can be made into one line with  
liberal use of the semi-colon (;). It would just be an extremely long  
line!

My full, nicely abstracted solution for this quiz is 36 lines  
(including empty lines), but I also wrote a somewhat obfuscated  
one-line version which is 104 characters. But it is missing some of  
the features of the full one. But overall it solves the quiz. It is  
probably possible to make an even shorter version.

Ryan

> **···**
>
> On 4/21/06, Jake McArthur \<jake.mcarthur@gmail.com\> wrote:
> 
> > My first participation in Ruby Quiz, and it has to be easy. That  
> > said, I must really be missing something because some of you guys are  
> > mentioning one-liners, and mine is 26 lines. Maybe it's because I  
> > made mine highly abstracted, but I still don't really see how to do  
> > this in one line.

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [22 April 2006 02:00 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/16 "2006-04-22T02:00:32Z")

</div>

Hi --

> **···**
>
> On Sat, 22 Apr 2006, Adam Shelly wrote:
> 
> > On 4/21/06, Ruby Quiz \<james@grayproductions.net\> wrote:
> > 
> > > Your task for this quiz, then, is to take a text as input and output the text in  
> > > this fashion. Scramble each word's center (leaving the first and last letters of  
> > > each word intact). Whitespace, punctuation, numbers -- anything that isn't a  
> > > word -- should also remain unchanged.
> > 
> > I know everyone here is Nice(tm), so I'm sure this is not the  
> > intent... but between this quiz and the Markov chain one, it seems we  
> > are building a set of utilities perfect for generating those 'Re:  
> > PHARmudMACY'  
> > spam emails selling 'vigara' and such that have been sneaking through  
> > my spam filter at work recently...
> 
> Maybe we can use the techniques to filter those messages out 🙂
> 
> David
> 
> --  
> David A. Black (dblack@wobblini.net)  
> Ruby Power and Light, LLC ([http://www.rubypowerandlight.com](http://www.rubypowerandlight.com))
> 
> "Ruby for Rails" PDF now on sale! [Ruby for Rails](http://www.manning.com/black)  
> Paper version coming in early May!

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [22 April 2006 04:04 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/17 "2006-04-22T04:04:36Z")

</div>

I vote we assume the best instead of the worst.

James Edward Gray II

> **···**
>
> On Apr 21, 2006, at 8:55 PM, Adam Shelly wrote:
> 
> > On 4/21/06, Ruby Quiz \<james@grayproductions.net\> wrote:
> > 
> > > Your task for this quiz, then, is to take a text as input and output the text in  
> > > this fashion. Scramble each word's center (leaving the first and last letters of  
> > > each word intact). Whitespace, punctuation, numbers -- anything that isn't a  
> > > word -- should also remain unchanged.
> > 
> > I know everyone here is Nice(tm), so I'm sure this is not the  
> > intent... but between this quiz and the Markov chain one, it seems we  
> > are building a set of utilities perfect for generating those 'Re:  
> > PHARmudMACY'  
> > spam emails selling 'vigara' and such that have been sneaking through  
> > my spam filter at work recently...

---

<div class="post-metadata">

**Author:** ![Robin\_Stocker1](https://avatars.discourse-cdn.com/v4/letter/r/ce7236/32.png) [@Robin\_Stocker1](https://rubytalk.org/u/Robin_Stocker1)\
**Post date:** [23 April 2006 10:42 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/18 "2006-04-23T10:42:37Z")

</div>

Himadri Choudhury wrote:

> In order to see any performance benefit from the 3rd method I had to make up  
> some horrifically long words which aren't terribly likely in the English  
> language (maybe I should have tried German :)).

Try Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz 🙂

---

<div class="post-metadata">

**Author:** ![Albert\_Vernon\_Smith](https://avatars.discourse-cdn.com/v4/letter/a/6f9a4e/32.png) [@Albert\_Vernon\_Smith](https://rubytalk.org/u/Albert_Vernon_Smith)\
**Post date:** [23 April 2006 12:57 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/19 "2006-04-23T12:57:46Z")

</div>

Is the performance better if you skip swaps when i == j ?

Also, for a swap method to give random results doesn't one need to swap from a random position in the array which has not been passed through yet? (see [Shuffling - Wikipedia](http://en.wikipedia.org/wiki/Shuffle) noting Fisher-Yates shuffling.)

-a

> **···**
>
> On 23.4.2006, at 09:45, Himadri Choudhury wrote:
> 
> > print ARGF.read.gsub!(/\B[a-z]+\B/) {|x|  
> > &nbsp;&nbsp;&nbsp;&nbsp;x.length.times {|i|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = rand(i+1)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x[j], x[i] = x[i] , x[j]  
> > &nbsp;&nbsp;&nbsp;&nbsp;}  
> > &nbsp;&nbsp;&nbsp;&nbsp;x  
> > }
> > 
> > Basically, this is an implementation of scrambling that uses swaps. I  
> > remember this method for scrambling from way back, but I can't seem to find  
> > a good reference for it at the moment.  
> > I also figured that this method would be faster since it is linear, while  
> > the sorts are n log(n) (n = length of the word)
> > 
> > To by surprise, I found this method to actually be slower for any normal  
> > text. One possible explanation is that when words are relatively short you  
> > don't gain much from the n vs. nlogn difference, and you lose because while  
> > this method always has n swaps, sorting may have less.

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [23 April 2006 14:50 UTC](https://rubytalk.org/t/quiz-text-munger-76/26817/20 "2006-04-23T14:50:22Z")

</div>

Just a gentle reminder here folks, please remember that Ruby Quiz has a 48 hour no-spoiler period before solutions should be posted. I'm not a big stickler on this, but I know some people do like the time. It's super easy to figure in your head, just look at the quiz date and time and bump it forward two days. That's when it's OK to submit.

For the record, I do consider posting solutions in other languages (like Perl) a spoiler.

Thank you.

James Edward Gray II

> **···**
>
> On Apr 23, 2006, at 4:45 AM, Himadri Choudhury wrote:
> 
> > Here's my solution.

[Next page](https://rubytalk.org/t/quiz-text-munger-76/26817.md?page=2)
