Posted April 1, 2007 at
9:37 PM
Tags:
ColdFusion
Ok, this has wasted waaay too much of my Sunday. Now, I am starving and need to go eat a whole chicken. But, at least it's done and I can sleep knowing that once again, all is well in the world.
As I described before, the rules here are the same: 10 to 15 random words (not contained within tag definitions) and for each word, 1 to 3 characters replaced out. Here is my initial HTML:
Launch code in new window » Download code as text file »
- <html>
- <head>
- <title>Ray's Puzzler - 03/30/2007</title>
- </head>
- <body>
-
- <p>
- My name is Bob. I am the coolest dude... perhaps ever?
- I am without a doubt the best programmer that has ever
- existed. No one will ever mess with my text cause I
- am feared in the office.
- </p>
-
- <p>
- I really like that new secretary, Niki. I should ask
- her out. Man, she would love that. But is she worthy?
- I mean, not just any old bird should get the privledge
- of going with me.
- </p>
-
- <p>
- Note to self: Fire Jen over in accounting. I don't like
- the way she dresses. Tell her the firing is over the
- payroll mess-up she made last month.
- </p>
-
- </body>
- </html>
-
-
- <cfset strUpdatedContent = MessWithBob() />
-
- <cfset GetPageContext().GetOut().ClearBuffer() />
-
- <cfset WriteOutput( strUpdatedContent ) />
... and running the above results in:
Launch code in new window » Download code as text file »
- <html>
- <head>
- <title>Ray's Puzzler - 03/30/2007</title>
- </head>
- <body>
-
- <p>
- My name is Bob. I ar the qoo46st dude... perhaps eoer?
- I am without 2 doubt the best programmer that has ever
- existed. No one will ever mess with my text 1ause l
- am feared in the office.
- </p>
-
- <p>
- m really like that new se5r0tgry, Niki. I should ask
- her out. Man, she would love that. But is she worthy?
- I mean, not just any old bird should hnt jot privledge
- of going with me.
- </p>
-
- <p>
- Note to 40lf: Fire Jen over rn accounting. I don'a like
- the way she dresses. Tell her the firing is over the
- payroll mess-up fdj made last month.
- </p>
-
- </body>
- </html>
Notice that 10-15 random words have been altered. Phew! Here's how it's done:
Launch code in new window » Download code as text file »
- <cffunction
- name="MessWithBob"
- access="public"
- returntype="string"
- output="false"
- hint="Ha ha ha ha ha... you are soo in trouble Bob!">
-
- <cfargument
- name="Text"
- type="string"
- required="false"
- default="#GetPageContext().GetOut().GetBuffer()#"
- hint="The text that we are going to mess with. Defaults to the current page's unflushed content buffer."
- />
-
-
- <cfset var LOCAL = StructNew() />
-
-
- <cfset LOCAL.CharSet = "abcdefghijklmnopqrstuvwxyz0123456789" />
-
-
- <cfset LOCAL.ReflectArray = CreateObject(
- "java",
- "java.lang.reflect.Array"
- ) />
-
-
- <cfset LOCAL.Pattern = CreateObject(
- "java",
- "java.util.regex.Pattern"
- ).Compile(
- "(?i)</?[a-z](""[^""]*""|[^>])*>"
- ) />
-
- <cfset LOCAL.Matcher = LOCAL.Pattern.Matcher(
- JavaCast( "string", ARGUMENTS.Text )
- ) />
-
-
- <cfset LOCAL.Words = ArrayNew( 1 ) />
-
- <cfset LOCAL.Tags = ArrayNew( 1 ) />
-
-
- <cfset LOCAL.Buffer = CreateObject(
- "java",
- "java.lang.StringBuffer"
- ).Init() />
-
-
- <cfloop condition="#LOCAL.Matcher.Find()#">
-
- <cfset LOCAL.Tag = StructNew() />
-
- <cfset LOCAL.Tag.HTML = LOCAL.Matcher.Group() />
- <cfset LOCAL.Tag.Start = LOCAL.Matcher.Start() />
- <cfset LOCAL.Tag.End = LOCAL.Matcher.End() />
-
- <cfset ArrayAppend(
- LOCAL.Tags,
- LOCAL.Tag
- ) />
-
- <cfset LOCAL.Matcher.AppendReplacement(
- LOCAL.Buffer,
- RepeatString(
- ".",
- Len( LOCAL.Matcher.Group() )
- )
- ) />
-
- </cfloop>
-
-
- <cfset LOCAL.Matcher.AppendTail(
- LOCAL.Buffer
- ) />
-
-
-
-
- <cfset LOCAL.Tokens = LOCAL.Buffer.ToString().Split( "\b" ) />
-
-
- <cfloop
- index="LOCAL.Index"
- from="1"
- to="#ArrayLen( LOCAL.Tokens )#"
- step="1">
-
-
- <cfif REFind( "\w", LOCAL.Tokens[ LOCAL.Index ] )>
-
- <cfset LOCAL.Word = StructNew() />
-
- <cfset LOCAL.Word.HTML = LOCAL.Tokens[ LOCAL.Index ] />
- <cfset LOCAL.Word.Index = LOCAL.Index />
-
- <cfset ArrayAppend(
- LOCAL.Words,
- LOCAL.Word
- ) />
-
- </cfif>
-
- </cfloop>
-
-
-
-
- <cfset LOCAL.WordAlterCount = Min(
- RandRange( 10, 15 ),
- LOCAL.Words.Size()
- ) />
-
-
- <cfset LOCAL.WordIndexes = StructNew() />
-
-
- <cfloop
- condition="(StructCount( LOCAL.WordIndexes ) LT LOCAL.WordAlterCount)">
-
- <cfset LOCAL.WordIndexes[ RandRange( 1, LOCAL.Words.Size() ) ] = true />
-
- </cfloop>
-
-
- <cfloop
- item="LOCAL.Index"
- collection="#LOCAL.WordIndexes#">
-
- <cfset LOCAL.Word = LOCAL.Words[ LOCAL.Index ].HTML />
-
- <cfset LOCAL.LetterAlterCount = Min(
- RandRange( 1, 3 ),
- LOCAL.Word.Length()
- ) />
-
-
- <cfset LOCAL.Word = LOCAL.Word.ToCharArray() />
-
-
- <cfloop
- index="LOCAL.CharIndex"
- from="1"
- to="#LOCAL.LetterAlterCount#"
- step="1">
-
- <cfset LOCAL.NewChar = LOCAL.CharSet.CharAt(
- JavaCast(
- "int",
- RandRange( 0, LOCAL.CharSet.Length() - 1)
- )
- ) />
-
-
- <cfset LOCAL.IndexToAlter = RandRange(
- 0,
- (ArrayLen( LOCAL.Word ) - 1)
- ) />
-
-
- <cfset LOCAL.ReflectArray.Set(
- LOCAL.Word,
- LOCAL.IndexToAlter,
- ToString( LOCAL.NewChar ).CharAt( 0 )
- ) />
-
- </cfloop>
-
-
- <cfset LOCAL.ReflectArray.Set(
- LOCAL.Tokens,
- JavaCast(
- "int",
- (LOCAL.Words[ LOCAL.Index ].Index - 1 )
- ),
- ArrayToList( LOCAL.Word, "" )
- ) />
-
- </cfloop>
-
-
-
-
- <cfset LOCAL.Buffer = CreateObject( "java", "java.lang.StringBuffer" ).Init() />
-
-
- <cfloop
- index="LOCAL.Index"
- from="1"
- to="#ArrayLen( LOCAL.Tokens )#"
- step="1">
-
- <cfset LOCAL.Buffer.Append(
- LOCAL.Tokens[ LOCAL.Index ]
- ) />
-
- </cfloop>
-
-
- <cfloop
- index="LOCAL.Index"
- from="1"
- to="#ArrayLen( LOCAL.Tags )#"
- step="1">
-
- <cfset LOCAL.Tag = LOCAL.Tags[ LOCAL.Index ] />
-
- <cfset LOCAL.Buffer.Replace(
- JavaCast( "int", LOCAL.Tag.Start ),
- JavaCast( "int", LOCAL.Tag.End ),
- LOCAL.Tag.HTML
- ) />
-
- </cfloop>
-
-
-
-
- <cfreturn LOCAL.Buffer.ToString() />
- </cffunction>
This solution is CRAZY complicated. It uses Java array reflection, string buffers, and lots of other stuff that is neat. If you can come up with a smaller, more elegant solution, I would love to know. My guess is, this is way more complicated than it as to be. But, as far as I can tell, it will ONLY alter the given words an absolutely nothing else in the content.
For extra brownie points, notice that the Function defaults the passed-in text to the current content buffer ;)
Download Code Snippet ZIP File
Comments (2) |
Post Comment |
Ask Ben |
Permalink |
Print Page
Jesus. Do you accept my apology for this being WAY more than 5 minutes?? ;)
Posted by Raymond Camden
on Apr 2, 2007
at 2:38 PM
@Ray,
Hey man, it was a blast. And just cause it took me a long time doesn't mean that it is the correct solution by any stretch of the imagination. Plus, it was super excellent practice with some Java methods.
Plus, I know for a fact that my solution doesn't work for mid-word punctuation. For instance, since I am splitting on "\b", it treats "Ray's" as three words: "Ray" and "'" and "s". I kept trying to make the RegEx for the split better, but nothing seemed to work.... but then, the more I thought about it, I came to peace with it. I felt that it would be too hard to tell which punctuations were which. For instance, Ray's might be one word, but is "hard-hitting" one word or two? Because punctuation feels like such an "English" language construct, I didn't feel like tearing my hair out trying to parse things appropriately.
But regardless, it was a lot of Fun :D
Posted by Ben Nadel
on Apr 2, 2007
at 4:03 PM
Post Comment |
Ask Ben