Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at cf.Objective() 2011 (Minneapolis, MN) with:

Selecting The Seven Languages In Seven Weeks Winners

By Ben Nadel on
Tags: ColdFusion

About a week or so ago, I finished working my way through Seven Languages in Seven Weeks by Bruce Tate. To celebrate my mostly triumphant reading of the book (shakes fist at Haskell, Day 3), I wanted to give away a few copies. But, in order to select the winners of the book, I wanted to have a little fun and try to play with the Mapping concepts that were often discussed within the book.

Given an array of players (those that submitted sample code on my wrap-up), I created an ArrayMap() function and a function that would randomly return a given value. The idea was to continue to reduce the collection of players until only 2 were left.

  • <!--- Set up the array of players. --->
  • <cfset players = [
  • "Wilkins",
  • "Mike",
  • "Seth Stone",
  • "Guganeshan.T",
  • "Joshua Caito",
  • "Joe Zack",
  • "Andrew",
  • "Rich",
  • "Hidde-Jan",
  • "dotnetCarpenter",
  • "Adam Coffman",
  • "Owen Pellegrin",
  • "Ross Pfahler",
  • "Marty",
  • "Jared Cacurak",
  • "Morten",
  • "Greg Mefford",
  • "Tracy Harms",
  • "Eric Mitchell",
  • "Jesse Riggins",
  • "Danny Philayvanh",
  • "Sharagoz",
  • "Joel Neley",
  • "Adam",
  • "Nelle",
  • "Matt Gutting",
  • "Cade Cannon"
  • ] />
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <!---
  • Define a map function that maps one array onto another using
  • the given function. When mapping, the following values will be
  • handles as such:
  •  
  • - Array - will be flattened and merged into the resultant array.
  • - Value - will be added to the resultant array.
  • - VOID - will not be added ot the resultant array.
  • --->
  • <cffunction
  • name="arrayMap"
  • access="public"
  • returntype="array"
  • output="false"
  • hint="I map one array onto another array.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="originalArray"
  • type="array"
  • required="true"
  • hint="I am the array being mapped."
  • />
  •  
  • <cfargument
  • name="mapper"
  • type="any"
  • required="true"
  • hint="I am the function used to perform the mapping."
  • />
  •  
  • <!--- Define the local scope. --->
  • <cfset var local = {} />
  •  
  • <!--- Define an array to hold the results of the mapping. --->
  • <cfset local.results = [] />
  •  
  • <!--- Loop over the array so we can map each value. --->
  • <cfloop
  • index="local.originalValue"
  • array="#arguments.originalArray#">
  •  
  • <!--- Hand this value off to the mapper function. --->
  • <cfset local.mappedValue = arguments.mapper(
  • local.originalValue
  • ) />
  •  
  • <!---
  • Check to make sure that a value exists. If it doesn't,
  • it means that VOID was returned; as such, no mapped
  • value will be added to the results.
  • --->
  • <cfif structKeyExists( local, "mappedValue" )>
  •  
  • <!---
  • We know we have a mapped value, so let's not figure
  • out how we are merging it into the results array.
  • Arrays will be flattened; single values will be
  • added as such.
  • --->
  • <cfif isArray( local.mappedValue )>
  •  
  • <!--- Add each value of the array individually. --->
  • <cfloop
  • index="local.mappedSubValue"
  • array="#local.mappedValue#">
  •  
  • <!--- Add the flattened values. --->
  • <cfset arrayAppend(
  • local.results,
  • local.mappedSubValue
  • ) />
  •  
  • </cfloop>
  •  
  • <cfelse>
  •  
  • <!--- Simply add the returned value. --->
  • <cfset arrayAppend(
  • local.results,
  • local.mappedValue
  • ) />
  •  
  • </cfif>
  •  
  • </cfif>
  •  
  • </cfloop>
  •  
  • <!--- Return the resultant array. --->
  • <cfreturn local.results />
  • </cffunction>
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <!---
  • Now that we have our map function defined, we need to create a
  • function that actually provides the mapping logic. For our
  • purposes, we're going to keep mapping the players array onto a
  • new array until we only have 2 people left. That means that our
  • mapper function will be popping people out of the collection.
  • --->
  • <cffunction
  • name="returnRandom"
  • access="public"
  • returntype="any"
  • output="false"
  • hint="I randomly return the given value or VOID.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="value"
  • type="any"
  • required="true"
  • hint="I am the value being returned (maybe!)."
  • />
  •  
  • <!---
  • Randomly decide to return this value or not. If it is
  • returned, it will be mapped onto the results array; if it
  • is not, it will be removed.
  • --->
  • <cfif (rand() gt .25)>
  •  
  • <!--- Return the given value. --->
  • <cfreturn arguments.value />
  •  
  • <cfelse>
  •  
  • <!--- Return void. --->
  • <cfreturn />
  •  
  • </cfif>
  • </cffunction>
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <!---
  • Now that we have all of our mapping functions in place, let's
  • reduce our players collection down to a collection of 2. As we
  • map, there is a chance that we will drop below 2. In that case,
  • we'll have to just start over again.
  • --->
  • <cfoutput>
  •  
  •  
  • <!---
  • Keep looping until we stop. If we get a collection of 2,
  • we will execute an explicit Break command.
  • --->
  • <cfloop condition="true">
  •  
  • <!--- Copy our players array (set by VALUE). --->
  • <cfset winners = players />
  •  
  •  
  • <!--- Output the staring length. --->
  • Starting Length: #arrayLen( winners )#<br />
  •  
  •  
  • <!---
  • Keep reducing the collection until it is less than
  • or equal to 2 (we are hoping it is 2).
  • --->
  • <cfloop condition="(arrayLen( winners ) gt 2)">
  •  
  • <!--- Reduce the collection randomly. --->
  • <cfset winners = arrayMap(
  • winners,
  • returnRandom
  • ) />
  •  
  • <!--- Output the new length. --->
  • Current Length: #arrayLen( winners )#<br />
  •  
  • </cfloop>
  •  
  •  
  • <!--- Check to see if the collection contains 2 values. --->
  • <cfif (arrayLen( winners ) eq 2)>
  •  
  • <!---
  • We have reduced properly. Stop the reduction loop
  • as we have found our winners.
  • --->
  • <cfbreak />
  •  
  • </cfif>
  •  
  • </cfloop>
  •  
  •  
  • <hr />
  •  
  • <!--- Output the winners. --->
  • Winner: #winners[ 1 ]#<br />
  • Winner: #winners[ 2 ]#<br />
  •  
  • </cfoutput>

Since the reduction mapping might result in an array of length less than 2, I had to continually loop until the final array contained exactly two elements. When I ran the above code, I got the following page output:

Starting Length: 27
Current Length: 18
Current Length: 15
Current Length: 13
Current Length: 11
Current Length: 11
Current Length: 5
Current Length: 3
Current Length: 3
Current Length: 1
Starting Length: 27
Current Length: 21
Current Length: 16
Current Length: 10
Current Length: 8
Current Length: 8
Current Length: 7
Current Length: 7
Current Length: 7
Current Length: 5
Current Length: 1
Starting Length: 27
Current Length: 22
Current Length: 21
Current Length: 13
Current Length: 10
Current Length: 6
Current Length: 6
Current Length: 5
Current Length: 5
Current Length: 3
Current Length: 3
Current Length: 2
-------------------------------------------------
Winner: Jared Cacurak
Winner: Matt Gutting

As you can see, the reduction mapping had to run 3 times before it ended up with an array of length 2. Of course, I know there are much more efficient ways of doing this; but, efficiency wasn't really the point - I just wanted to have some fun with it.

Congratulations to Jared and Matt! You're about to get seven languages deep!



Reader Comments

Stupid ColdFusion!
I thought the point of your blog was to make me like ColdFusion, now I am not so sure it will every happen :)

/A Loser

Reply to this Comment

@Morten,

Ha ha ha, the silver-lining to all of this is that if you use ColdFusion, you're already a winner :P

Reply to this Comment

Grats to the winners!

Thanks again for your creativity with the contest Ben. It would be cool to do something like this every once in a while even if there is no prize involved :)

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.