<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Chris Smith's completely unique view</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/chrsmith/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/chrsmith/feed.xml</link>
    <description>Algorithms, functional programming, CLR 4.0, and of course, F#!</description>
    <lastBuildDate>Fri, 26 Feb 2016 06:22:25 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Good News and Sad News - Leaving Microsoft</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/good-news-and-sad-news-leaving-microsoft</link>
      <pubDate>Tue, 13 Apr 2010 19:46:00 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2010/04/13/good-news-and-sad-news-leaving-microsoft/</guid>
      <description><![CDATA[The Good News
You might have heard, Visual Studio 2010 is done, launched, and out the door! That’s...]]></description>
      <content:encoded><![CDATA[<H2>The Good News</H2>
<P>You might have heard, <A href="https://www.microsoft.com/visualstudio/en-us/visual-studio-events"><FONT color=#669966>Visual Studio 2010</FONT></A> is done, launched, and out the door! That’s right, after several short years F# version 1.0 is generally available! While it’s been alive and well in CTP form for many years, now you can go to the <A href="https://store.microsoft.com/home.aspx"><FONT color=#669966>store</FONT></A> and buy it. This doesn’t just mean that F# is easier to obtain. It marks a significant step in the language’s evolution; by shipping it in a officially supported release F# is a <EM>real</EM> product and is backed by Microsoft for at least the next decade.</P>
<P>I’m super excited about the release and look forward to F# taking off. It has already far surpassed my expectations in awesomeness, adoption, and excitement. If you are reading this blog then you are probably an F# enthusiast and none of this would have been possible without <EM>your </EM>support. So really, you should be just as proud as me.</P>
<H2>The Sad News</H2>
<P>However, for me at least, the excitement and buzz of the Visual Studio 2010 launch will be short lived. Earlier this month I’ve accepted a position at another software company and will be leaving Microsoft. My departure will no doubt raise the average IQ of both companies.</P>
<P>I first started working at Microsoft in 2002 as an intern, and since then I have shipped three versions of Visual Studio, filed a few patents, and even managed to have dinner at Bill Gate’s house. Working at Microsoft has been a fantastic experience and I have nothing but fond memories for my time spent here. However, having worked at Microsoft since before I graduated college I’m eager to try something new. So this Friday I’ll be packing up my belongings and exploring not-necessarily-greener-but-certainly-different pastures.</P>
<P>How will this impact the F# team? Well, without their weakest link I think the team will do just fine. </P>
<P>However, I will still be part of the F# community and you will definitely see a&nbsp;second edition of <EM>Programming F#</EM> when the time comes.&nbsp; In fact, next Tuesday 4/20 I’ll be giving a talk: <A href="https://www.communityforfsharp.net/april-2010-live-meeting-detail"><FONT color=#669966>Writing a Java to x86 Compiler in F#</FONT></A>&nbsp;at 11:00AM PST. If you have that time free watch it LIVE over LiveMeeting!</P>
<P>Anyways, you should definitely keep an eye on F# as this language will absolutely transform the way we write software on the .NET platform. You can reach me via my new blog <A title=https://achrissmith.blogspot.com/ href="https://achrissmith.blogspot.com/"><FONT color=#669966>https://achrissmith.blogspot.com/</FONT></A>.</P>]]></content:encoded>
    </item>
    <item>
      <title>Writing a StarCraft Bot in F#</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/writing-a-starcraft-bot-in-f</link>
      <pubDate>Thu, 18 Mar 2010 00:51:00 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2010/03/18/writing-a-starcraft-bot-in-f/</guid>
      <description><![CDATA[Hi, I’m Chris Smith. You might know me as the world famous author of Programming F#, but outside of...]]></description>
      <content:encoded><![CDATA[<p>Hi, I’m Chris Smith. You might know me as the world famous author of <a href="https://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643">Programming F#</a>, but outside of my pseudo-tech-celebrity status I’m a real person. I’m a part time <a href="https://achrissmith.com/">movie critic</a>, <a href="https://www.facebook.com/photo.php?pid=32108220&amp;l=6e7c3c4aa2&amp;id=24902696">avid skier</a>, and a <a href="https://blogs.msdn.com/chrsmith/archive/2007/01/05/XBox-360-achievements-considered-awesome.aspx">gamer</a>. My passions are deep wide and one thing that has always excited me is the notion of programs playing computer games. Seriously, I know it’s strange. Anyways, I was overjoyed when I heard about the <a href="https://eis.ucsc.edu/StarCraftAICompetition"><strong>2010 Conference on Artificial Intelligence and Interactive Digital Entertainment StarCraft Competition</strong></a>.</p>  <p><a href="https://eis.ucsc.edu/StarCraftAICompetition"><img src="https://eis.ucsc.edu/sites/default/files/SCcomp.png" /></a></p>  <p>Artificial intelligence, programming, and StarCraft. It’s like peanut butter and jelly, only with Zerglets.</p>  <p>The day the contest was announced I worked feverishly on creating a StarCraft bot in F#. F# lends itself quite naturally to AI, asynchronous programming, and things which are awesome. However, I never blogged about this earlier on ethical grounds. Namely, that the API used to interact with Broodwar <strong>blatantly violates StarCraft’s EULA</strong>. Think about it, APIs to give programmatic access to computer games are dangerous. Encouraging bot development goes hand in hand with hacking, exploits, and ruining the game for everyone. While my own motives for modifying StarCraft are to write AI bots for my own use, I absolutely respect Blizzard’s wishes to prevent the reverse engineering of their software.</p>  <p>So, as a representative of Microsoft and one who respects license agreements, I kept my excitement quiet. That is, until the news came that Blizzard’s legal department gave the go ahead to the AIIDE. So, finally, let me introduce my StarCraft Bot in F#. (Which is really just a port of the <a href="https://eis.ucsc.edu/StarCraftRemote">Java Proxy Bot</a>.)</p>  <h1>Getting Setup</h1>  <h3>1. Buy and Install StarCraft</h3>  <p>The first order of business is to install StarCraft and the BroodWar expansion. You can pick it up for $15 at <a href="https://us.blizzard.com/store/details.xml?rhtml=y&amp;id=110000124">Blizzard's Online Store</a>.</p>  <p>Be sure to install StarCraft into an easily accessible folder, like “E:\StarCraft”. Otherwise copying StarCraft bot files into the admin-only Program Files folder will be a huge pain.</p>  <h3>2. Download and Install Chaos Launcher</h3>  <p><a href="https://www.teamliquid.net/forum/viewmessage.php?topic_id=65196">Chaos Launcher</a> is a tool which customizes how StarCraft loads and executes. Since the game originally came out in <a href="https://en.wikipedia.org/wiki/StarCraft">March, 1998</a> I won’t fault it for not rendering in a windowed-mode. However, for bot-development this is critical.</p>  <p>First, unzip the file into a folder, such as “E:\StarCraft\Chaos Launcher\”. Then, to test things out simply run ChaosLauncher.exe. Check W-Mode plugin and click Start. Now you can play StarCraft in a window!</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_4.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_1.png" width="644" height="286" /></a> </p>  <p></p>  <p></p>  <h3>3. Install the BWAPI</h3>  <p><a href="https://code.google.com/p/bwapi/wiki/BWAPIDevelopment">BWAPI</a> is an open source API for interacting with StarCraft: BroodWar and is the API we will use to control our AI bot. </p>  <p>Download <a href="https://code.google.com/p/bwapi/downloads/list">BWAPI_Beta_2.6.1.zip</a> and unzip it into a folder, such as “E:\StarCraft\BWLAPI_Beta_2.6.1\”. Note however, that you still have more registration to do. From the steps listed in the README file:</p>  <p>1. Copy the contents of the ChaosLauncher folder to your Chaos Launcher folder (“E:\StarCraft\Chaos Launcher&quot;\”)    <br />2. Copy the contents of the StarCraft folder to your StarCraft folder (“E:\StarCraft\”)     <br />3. Copy the contents of the Windows folder to your System folder (“C:\Windows\”)</p>  <h1>Introducing StarCraftBot 9K</h1>  <p>We now have all the pieces in place, but creating an AI-bot for a program not meant to be extended will be tricky. StarCraft Bot 9K has the following architecture, which follows the footsteps of the <a href="https://code.google.com/p/bwapi-proxy/">Java ProxyBot</a> available on the AIIDE Website. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_7.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_7.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_2.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_2.png" width="536" height="311" /></a>&#160;&#160; <br />1. You use Chaos Launcher to launch StarCraft     <br />2. When a StarCraft game starts, the BWAPI code executes on each game tick     <br />3. On each tick the StarCraftConnector project (C++) broadcasts all public game data     <br />4. The StarCraftBot9K Client (C#) will listen for those events     <br />5. And finally StarCraftBot9K (F#) will do decision making</p>  <h3>4. Download StarCraftBot9K</h3>  <p>At the very bottom of this blog post is a .zip file with all the source code. Download that and unzip it into a folder, such as “E:\StarCraftBot9K\”.</p>  <h3>5. Install the StarCraftConnector</h3>  <p>One output of building the StarCraftBot9K soolution is StarCraftConnector.dll, which is the C++ library built on top of BWAPI that broadcasts game state to a socket. Later a C# application will listen to that data and send messages back to the StarCraft game.</p>  <p>To ‘install’ StarCraftConnector, copy it to “E:\StarCraft\bwapi-data\AI\”. This is the folder that you copied when installing BWAPI.</p>  <p>Next, edit “E:\StarCraft\bwapi-data\bwapi.ini” and set the ai_dll field to “bwapi-data\AI\StarCraftConnector.dll”.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image8.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image8.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image8_thumb.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image8_thumb.png" width="434" height="362" /></a> </p>  <h3>6. Run StarCraftBot9K</h3>  <p>Finally, you are ready to unleash StarCraftBot9K! Simply start run the application. It will begin listening to the socket until StarCraftConnector begins broadcasting.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_19.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_19.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_8.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_8.png" width="349" height="250" /></a> </p>  <p>&#160;</p>  <p><strong>7. Launch StarCraft</strong></p>  <p>Next, run Chaos Launcher again, this time checking the “BWAPI Injector” module. <strong>Note that you must run it as an administrator</strong>.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_17.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_17.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_7.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_7.png" width="420" height="228" /></a> </p>  <p>You also need to check “BWAPI Injector” so that BWAPI get’s loaded with StarCraft. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_11.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_11.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_4.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_4.png" width="530" height="391" /></a> </p>  <p>When StarCraft starts everything will act as normal, BWAPI and the StarCraftConnector only come into play when starting a Custom Game.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_15.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_15.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_6.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_6.png" width="654" height="521" /></a> </p>  <p><strong>8. Give StarCraftBot 9K Control</strong></p>  <p>Once the game begins and you are connected you should see something like this. It is a mirroring of the internal StarCraft game state onto a simple WinForms app. There still is a lot of scaffolding to add, such as building up the object model to send proper commands to StarCraft.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_21.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_21.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_9.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_9.png" width="734" height="503" /></a> </p>  <p>When you check “Economy AI Module”, an F# asynchronous workflow will start up and monitor StarCraft trying to build up your basic economy. (Building SCVs, Drones, or Probes, and sending them to mine.)</p>  <pre class="code"><span style="color: green">/// AI module for managing your economy. Building drones, vespen geysers, etc.
</span><span style="color: blue">let private </span>getEconomyAI (mediator : GameMediator) =
    async {

        <span style="color: blue">while true do

            let </span>currentState = mediator.CurrentGameState

            <span style="color: green">// Build workers with all available cash
            </span><span style="color: blue">if </span>currentState.SupplyUsed &lt; currentState.SupplyTotal &amp;&amp;
               currentState.Minerals &gt;= 50 &amp;&amp;
               currentState.CanProduce.[ int (getWorkerType(g_GameMetadata.PlayerRace)) ] <span style="color: blue">then
               
                </span><span style="color: green">// BUG: Builds a worker at the first command center we find, this might not be the best one.
                // Ideally we'd have some higher level notion of a 'base' with a 'status' such as 'active' or 'out of resources'.
                </span><span style="color: blue">let </span>cmdCenter = 
                    currentState.Units 
                    |&gt; Seq.filter (<span style="color: blue">fun </span>unit <span style="color: blue">-&gt; </span>unit.Player = g_GameMetadata.PlayerID)
                    |&gt; Seq.tryFind (<span style="color: blue">fun </span>unit <span style="color: blue">-&gt; </span>isCommandCenter (enum&lt;UnitID&gt; unit.TypeID))
                    
                <span style="color: blue">if </span>Option.isSome cmdCenter <span style="color: blue">then
                    let </span>cmdCenterID = cmdCenter |&gt; Option.get |&gt; (<span style="color: blue">fun </span>unit <span style="color: blue">-&gt; </span>unit.ID)
                    <span style="color: blue">let </span>cmd = TrainUnit(cmdCenterID, int (getWorkerType(g_GameMetadata.PlayerRace)))
                    mediator.SendCommand(cmd)

            <span style="color: green">// Send idle workers to closest mineral patch
            </span><span style="color: blue">for </span>scunit <span style="color: blue">in </span>currentState.Units <span style="color: blue">do
                </span><span style="color: green">// If you own the unit, it's a worker, and it's sitting there then
                // send it to the closest mineral patch.
                </span><span style="color: blue">if </span>scunit.Player = mediator.GameMetadata.PlayerID &amp;&amp;
                   isWorker scunit &amp;&amp;
                   scunit.OrderID = int (UnitOrder.PlayerGuard) <span style="color: blue">then
                       
                    let </span>orderID = scunit.OrderID

                    <span style="color: blue">let </span>scunitLoc = { X = scunit.XPos; Y = scunit.YPos }

                    <span style="color: blue">let </span>mineralPatches = 
                        currentState.Units
                        |&gt; Seq.filter(<span style="color: blue">fun </span>unit <span style="color: blue">-&gt; </span>unit.TypeID = int UnitID.MineralField)
                        |&gt; Seq.map(<span style="color: blue">fun </span>minPatch <span style="color: blue">-&gt; let </span>patchLoc = { X = minPatch.XPos; Y = minPatch.YPos }
                                                   scunitLoc.FlyingDistanceTo(patchLoc), minPatch)
                        |&gt; Seq.sortBy(<span style="color: blue">fun </span>(dist, minPatch) <span style="color: blue">-&gt; </span>dist)
                        
                    <span style="color: blue">if </span>mineralPatches &lt;&gt; Seq.empty <span style="color: blue">then
                        let </span>targetMinPatch = mineralPatches |&gt; Seq.head |&gt; snd
                        <span style="color: blue">let </span>cmd = RightClickUnit(scunit.ID, targetMinPatch.ID)
                        mediator.SendCommand(cmd)

            <span style="color: green">// Sleep and check again later. If this agent gets canceled it will be right here.
            </span><span style="color: blue">do! </span>Async.Sleep(100)
        }</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>The AI isn’t anything earth shattering yet. But F#’s <a href="https://msdn.microsoft.com/en-us/library/dd233250(VS.100).aspx">asynchronous workflows</a>, the <a href="https://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html">reactive framework</a>, and&#160; <a href="https://blogs.msdn.com/dsyme/archive/2006/03/24/559582.aspx">first class events</a> should make for a very powerful and elegant model on top of asynchronous operations happening in game. </p>

<p><span style="color: blue"><font color="#000000">Consider asking a unit such as a <a href="https://starcraft.wikia.com/wiki/Goliath">goliath</a> to attack an enemy. Lots can happen! The goliath can kill the other unit, that unit can run away, the goliath can be killed, and so on. Even worse is that you won’t know the result of that action until several seconds later. F#’s asynchronous workflows provide a clean way to wrap those asynchronous actions. </font></span></p>

<pre class="code"><span style="color: blue">let! </span>result = tryEngage enemyUnit

<span style="color: blue">match </span>result <span style="color: blue">with
</span>| MarineWasKilled <span style="color: blue">-&gt; </span>printfn <span style="color: maroon">&quot;Sad.&quot;
</span>| UnitWasKilled   <span style="color: blue">-&gt; </span>printfn <span style="color: maroon">&quot;Horray! Now go find a medic to heal&quot;
</span>| UnitRanAway     <span style="color: blue">-&gt; </span>printfn <span style="color: maroon">&quot;Should you chanse? Maybe...&quot;</span></pre>
<a href="https://11011.net/software/vspaste"></a><span style="color: maroon"></span><a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste"></a>

<p>The tryEngage function could then simply be a union of several events (marine.OnKilled, unit.OnKilled, and new event when the unit is too far away). This concept may be difficult to grasp right now, I’ll try to post a follow up illustrating this concept later.</p>

<p>I’ve attached the source code. While it could stand to benefit from a lot of polishing it should be very straight forward. However, note that this post comes with not one but two disclaimers! Consider yourself blessed.</p>

<blockquote>
  <p>All code samples are provided &quot;AS IS&quot; without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose. So in other words, if using the BWAPI somehow gets you banned from <a href="https://us.battle.net/?rhtml=y&amp;rhtml=y">Battle.net</a> or causes damage to your system, don’t expect any sympathy.</p>
</blockquote>

<blockquote>
  <p>As you can tell there are a lot of moving parts here. I’m glad to provide technical support, but if you venture off the beaten path to don’t expect me to know why &lt;random thing&gt; isn’t working or how StarCraft is implemented.</p>
</blockquote>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_23.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_23.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_10.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/StarCraftBotinFPartI_11F60/image_thumb_10.png" width="1028" height="408" /></a></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/09/98/09/78/StarCraftBot9K%20-%202010-03-18.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-98-09-78/StarCraftBot9K-_2D00_-2010_2D00_03_2D00_18.zip">StarCraftBot9K - 2010-03-18.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>DAWG-fight, Optimizing text search in F# II</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/dawg-fight-optimizing-text-search-in-f-ii</link>
      <pubDate>Wed, 17 Feb 2010 20:25:50 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2010/02/17/dawg-fight-optimizing-text-search-in-f-ii/</guid>
      <description><![CDATA[Some of you may have seen Dr. Brian McNamara’s post refuting my credentials as an evil genius. Lies!...]]></description>
      <content:encoded><![CDATA[<p>Some of you may have seen <a href="https://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!1789.entry">Dr. Brian McNamara’s post</a> refuting my credentials as an evil genius. <strong>Lies! All lies propagated by the liberal media!</strong> Evidently, he thinks that his superior implementation of a <a href="https://en.wikipedia.org/wiki/Trie">trie</a>, which is faster and uses much less memory, is better than mine. If being an evil genius means having smaller, faster solutions then sure, he has out-eviled me. But seriously, come on. Being an evil genius is more than code efficacy, true evil comes from the passion to crush the will of men!</p>  <p> Even if Dr. McNamara’s code is better, I assure you I’ll have the last laugh. Muahhaha</p>  <h2>Striking the balance</h2>  <p>F# is a hybrid language and to truly harness its power for nefarious ends you need to embrace both function and object-oriented programming. Let’s review my trie implementation:</p>  <pre class="code"><span style="color: blue">type </span>TrieNode =
<span style="color: green">    </span>| Node <span style="color: blue">of </span>IDictionary&lt;char, TrieNode&gt; * bool
    | Eow
    
    <span style="color: blue">member </span>this.IsLegalWord = 
        <span style="color: blue">match </span>this <span style="color: blue">with
        </span>| Node(_, <span style="color: blue">true</span>)
        | Eow <span style="color: blue">-&gt; true
        </span>| _   <span style="color: blue">-&gt; false</span></pre>
<a href="https://11011.net/software/vspaste"></a>

<pre class="code"><span style="color: green">/// seq&lt;char list&gt; -&gt; TrieNode 
</span><span style="color: blue">let rec </span>generateTrieNode words =

    <span style="color: blue">let </span>hasEowNode = Seq.exists (<span style="color: blue">fun </span>word <span style="color: blue">-&gt; </span>word = []) words

    <span style="color: blue">if </span>Seq.isEmpty words <span style="color: blue">then
        </span>Eow    
    <span style="color: blue">else
</span><span style="color: green">        </span><span style="color: blue">let </span>nextWordFragments =
            words   
            |&gt; Seq.filter (<span style="color: blue">fun </span>word <span style="color: blue">-&gt; </span>word &lt;&gt; [])
            |&gt; Seq.groupBy (<span style="color: blue">fun </span>word <span style="color: blue">-&gt; </span>Seq.head word)
            |&gt; Seq.map (<span style="color: blue">fun </span>(firstLetter, words) <span style="color: blue">-&gt; </span>(firstLetter, words |&gt; Seq.map List.tail))
            |&gt; Seq.map(<span style="color: blue">fun </span>(firstLetter, rest) <span style="color: blue">-&gt; </span>(firstLetter, generateTrieNode rest))
            |&gt; Seq.fold
                (<span style="color: blue">fun </span>acc (letter, trieNode) <span style="color: blue">-&gt;
                    </span>(Char.ToUpper(letter), trieNode) :: (Char.ToLower(letter), trieNode) :: acc
                )
                []

        Node(dict nextWordFragments, hasEowNode)</pre>
<a href="https://11011.net/software/vspaste"></a>

<pre class="code"><span style="color: blue">let </span>searchStep (nodeInTrieTree : TrieNode) (tilesInChain : ITile list) =

<span style="color: blue">    if </span>nodeInTrieTree.IsLegalWord <span style="color: blue">then
        </span>foundWords.Add(getWordText tilesInChain)

    <span style="color: blue">let </span>currentTile = List.head tilesInChain

    <span style="color: blue">match </span>nodeInTrieTree <span style="color: blue">with
</span>    | Eow <span style="color: blue">-&gt; </span>None
    | Node(possibleLetterSteps, _) 
        <span style="color: blue">-&gt;  let </span>possibleSteps =
                currentTile.Neighbors<br />                |&gt; Seq.filter 
                    (<span style="color: blue">fun </span>neighborTile <span style="color: blue">-&gt; 
                        </span>not (List.exists 
                                (<span style="color: blue">fun </span>(prevTile : ITile) <span style="color: blue">-&gt; </span>prevTile.Location = neighborTile.Location) 
                                tilesInChain
                            )
                    )
                |&gt; Seq.filter (<span style="color: blue">fun </span>neighborTile <span style="color: blue">-&gt; </span>possibleLetterSteps.ContainsKey(neighborTile.Letter))
                |&gt; Seq.map 
                    (<span style="color: blue">fun </span>neighborTile <span style="color: blue">-&gt;
                        </span>(   possibleLetterSteps.[neighborTile.Letter],
                            neighborTile :: tilesInChain   )
                    )
                    
            <span style="color: blue">if </span>not (Seq.isEmpty possibleSteps) <span style="color: blue">then </span>Some(possibleSteps)
            <span style="color: blue">else                                    </span>None</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>Not to toot my own horn here, but this is very functional and very elegant. With little use of mutation, data just flows from one point into the next. You don’t need an army of Singularity AI bots to tell you that the code looks sexy.</p>

<p>Now let’s look at Brian’s implementation and see how they differ. First, how Dr. McNamara represented his trie tree:</p>

<pre class="code">[&lt;AllowNullLiteral&gt;]
<span style="color: blue">type </span>TrieNode() =
    <span style="color: blue">let </span>nextChar = Array.create 26 <span style="color: blue">null
    let mutable </span>isEndOfWord = <span style="color: blue">false
    member </span>this.IsEndOfWord = isEndOfWord
    <span style="color: blue">member </span>this.Item <span style="color: blue">with </span>get(c:char) = nextChar.[int c - int <span style="color: maroon">'A'</span>]
                     <span style="color: blue">and private </span>set(c:char) v = nextChar.[int c - int <span style="color: maroon">'A'</span>] &lt;- v
    <span style="color: blue">member </span>this.Add(word) = 
        <span style="color: blue">assert</span>(word |&gt; Seq.forall IsLetter)
        this.Add(word,0)
    <span style="color: blue">member private </span>this.Add(word:string,i) =
        <span style="color: blue">if </span>i = word.Length <span style="color: blue">then
            </span>isEndOfWord &lt;- <span style="color: blue">true
        else 
            match </span>this.[word.[i]] <span style="color: blue">with
            </span>| <span style="color: blue">null -&gt; let </span>newNode = <span style="color: blue">new </span>TrieNode()
                      newNode.Add(word,i+1)
                      this.[word.[i]] &lt;- newNode
            | node <span style="color: blue">-&gt; </span>node.Add(word,i+1)</pre>

<p></p>
<a href="https://11011.net/software/vspaste"></a>

<p>The problem with my purely functional approach, is that when you are initializing a recursive discriminated union you have to have the entire tree laid out in memory <em>before</em> it gets initialized. Because once that root node has been set, you can’t update it. The second implementation however just kept an array of child nodes. This allows for quick indexing and makes it much easier to ‘fill out’ the tree. There isn’t any need to have some six-stage pipeline, Brian just created new nodes as necessary.</p>

<p>I was even more impressed by how Brian actually went about searching the <a href="https://zone.msn.com/en/bookworm/default.htm">Bookworm</a> board for words. Each step I had to check that the word chain wasn’t ‘doubling back’ and using the same letter tile twice. Brian however gets around this by simply ‘zeroing out’ the tile once it is used and then restoring it later. I’ve added comments to point this out.</p>

<pre class="code"><span style="color: blue">let rec </span>Find(col, row, t:TrieNode) = seq {
<span style="color: blue">    let </span>c = board.[col,row]
    <span style="color: blue">if </span>c &lt;&gt; <span style="color: maroon">' ' </span><span style="color: blue">then
        </span>board.[col,row] &lt;- <span style="color: maroon">' '  </span><span style="color: green">// REMOVE TILE, SINCE IT'S BEEN USED</span></pre>
<a href="https://11011.net/software/vspaste"></a>

<pre class="code"><span style="color: blue">        match </span>t.[c] <span style="color: blue">with
        </span>| <span style="color: blue">null -&gt; </span>()
        | node <span style="color: blue">-&gt; 
            if </span>node.IsEndOfWord <span style="color: blue">then
                yield </span>[c]
            <span style="color: blue">for </span>suf <span style="color: blue">in </span>Find(col-1, row-1, node) <span style="color: blue">do yield </span>c::suf
            <span style="color: blue">for </span>suf <span style="color: blue">in </span>Find(col-1, row+1, node) <span style="color: blue">do yield </span>c::suf        
            <span style="color: blue">for </span>suf <span style="color: blue">in </span>Find(col  , row-2, node) <span style="color: blue">do yield </span>c::suf        
            <span style="color: blue">for </span>suf <span style="color: blue">in </span>Find(col  , row+2, node) <span style="color: blue">do yield </span>c::suf        
            <span style="color: blue">for </span>suf <span style="color: blue">in </span>Find(col+1, row-1, node) <span style="color: blue">do yield </span>c::suf
            <span style="color: blue">for </span>suf <span style="color: blue">in </span>Find(col+1, row+1, node) <span style="color: blue">do yield </span>c::suf        
        board.[col,row] &lt;- c    <span style="color: green">// RESTORE TILE, so other recursive calls can use.</span></pre>

<pre class="code"><span style="color: green">    </span>}</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>Inside <a href="https://www.amazon.com/Programming-comprehensive-writing-complex-problems/dp/0596153643">Programming F#</a> I wrote that at times imperative solutions can be much faster than functional. While some tech reviewers gave me crap for saying that, Brian’s implementation definitely strikes a good balance between functional and imperative. Kudos.</p>

<p>So, for Round 1 I’ll admit defeat. But I absolutely am not going to give up my (hard-earned) title of evil genius!</p>

<h2>Destroying that MOFO where he stands</h2>

<p>Fortunately I have a trick up my sleeve. To review, the following image is of a trie or prefix tree. (Stolen from wikipedia in an evil fashion.)</p>

<p><a href="https://upload.wikimedia.org/wikipedia/commons/b/be/Trie_example.svg"><img alt="File:Trie example.svg" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Trie_example.svg/400px-Trie_example.svg.png" width="400" height="375" /></a></p>

<p>But consider the words “button” and “mutton”, or more appropriately, “super-mega-evilgenius” (me) and “barely-an-evilgenius” (Brian). In both cases the words share a common suffix, –utton or –evilgenius. When represented in a trie tree that would mean a huge waste of memory, because the node for ‘B’ would have child nodes for ‘u-&gt;t-&gt;t-&gt;o-&gt;n’ and the letter ‘M’ would have child nodes for ‘u-&gt;t-&gt;t-&gt;o-&gt;n’. When in actuality, they could both share the same suffix nodes. That is, both ‘B’ and ‘M’ can go to ‘u-&gt;t-&gt;t-&gt;o-&gt;n’. This sharing of suffixes is just like how prefix trees share prefixes, and both “Button” and “Buttons” share ‘b-&gt;u-&gt;t-&gt;t-&gt;o-&gt;n’.</p>

<p>This property is exactly what gives rise to the <a href="https://en.wikipedia.org/wiki/Directed_acyclic_word_graph">DAWG</a> or <a href="https://en.wikipedia.org/wiki/Directed_acyclic_word_graph">directed-acyclic-word-graph</a>. (Again, evilly stolen from Wikipedia.) In the image, the words “TOP”, “TOPS”, “TAP”, and “TAPS” are present. On the left is the trie tree and on the right the DAWG which reuses common suffixes.</p>

<p><a href="https://upload.wikimedia.org/wikipedia/commons/a/a9/Trie-dawg.svg"><img alt="File:Trie-dawg.svg" src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Trie-dawg.svg/500px-Trie-dawg.svg.png" width="500" height="570" /></a></p>

<p>The advantage of a DAWG is that it uses far less memory, since you are no longer duplicating shared suffixes. However, as one would expect, they are a bit more tricky to implement than a Trie.</p>

<h2>Creating a DAWG in F#</h2>

<p>The simplest way to create a DAWG is to simply create a trie-tree, and then unify common suffixes between tree nodes. (That is, if two nodes can add “-S” and form a complete word, we can have both child pointers point to the same TrieNode object.) To get started, let’s blatantly steal the wannabe-evil-genius-Dr.-McNarama’s trie implementation and add a few new properties.</p>

<pre class="code"><span style="color: blue">type </span>TrieNode() =
    <span style="color: blue">let </span>nextChar = Array.create 26 <span style="color: blue">null
    let mutable </span>isEndOfWord = <span style="color: blue">false
</span><span style="color: green"></span></pre>

<pre class="code"><span style="color: green">    // ...</span></pre>

<pre class="code"><span style="color: green">    </span><span style="color: blue">member </span>this.Children   = nextChar
    <span style="color: blue">member </span>this.IsLeafNode = Array.forall (<span style="color: blue">fun </span>child <span style="color: blue">-&gt; </span>child = <span style="color: blue">null</span>) nextChar
    <span style="color: blue">member </span>this.NumChildren = 
        Array.fold
            (<span style="color: blue">fun </span>acc child <span style="color: blue">-&gt; if </span>child &lt;&gt; <span style="color: blue">null then </span>acc + 1 <span style="color: blue">else </span>acc)
            0
            nextChar
    <span style="color: blue">static member </span>CompareNodes(lhs : TrieNode, rhs : TrieNode) =
        <span style="color: blue">if </span>lhs = <span style="color: blue">null </span>&amp;&amp; rhs = <span style="color: blue">null then 
            true
        elif </span>(lhs = <span style="color: blue">null </span>&amp;&amp; rhs &lt;&gt; <span style="color: blue">null</span>) || (lhs &lt;&gt; <span style="color: blue">null </span>&amp;&amp; rhs = <span style="color: blue">null</span>) <span style="color: blue">then
            false
        elif </span>lhs.IsLeafNode &amp;&amp; rhs.IsLeafNode <span style="color: blue">then
            </span>(lhs.IsEndOfWord = rhs.IsEndOfWord)
        <span style="color: blue">elif </span>lhs.IsEndOfWord &lt;&gt; rhs.IsEndOfWord <span style="color: blue">then
            false
        else
            </span><span style="color: green">// For children, we can use a fast compare since we know that if they shared a common
            // suffix they would have been 'merged' already. (Going from the bottom of the tree up.)
            </span>[| 0 .. 25 |] |&gt; Array.forall(<span style="color: blue">fun </span>i <span style="color: blue">-&gt; </span>(lhs.Children.[i] = rhs.Children.[i]))</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>Exposing the child node array will make it easy for us to rewire the tree later, and we will use the CompareNodes function to identify if two suffixes are identical. (More on that later.)</p>

<p>Rather than try to explain the algorithm outright, let’s just walk through the code. The first step is to associate each trie node with its height in the tree. Height being the number of letters away it is from a leaf EOW node. In order to do the DAWG conversion efficiently, we want to unify nodes going from the bottom of the tree up. So knowing where each node stands is an important first step. (Note that the nodeHeightDict dictionary is filled up as a side effect of calling walkTree, this is evil imperative programming at its worst!)</p>

<pre class="code"><span style="color: green">// Walk the tree and add associate each node with its height
</span><span style="color: blue">let </span>nodeHeightDict = <span style="color: blue">new </span>Dictionary&lt;TrieNode, int&gt;()

<span style="color: blue">let rec </span>walkTree (node : TrieNode) =
    <span style="color: blue">if </span>node.IsLeafNode <span style="color: blue">then
        </span>nodeHeightDict.Add(node, 0)
        0
    <span style="color: blue">else
        let </span>depth =
            node.Children
            |&gt; Array.filter (<span style="color: blue">fun </span>child <span style="color: blue">-&gt; </span>child &lt;&gt; <span style="color: blue">null</span>)
            |&gt; Array.map walkTree
            |&gt; Array.max
        nodeHeightDict.Add(node, depth + 1)
        depth + 1

<span style="color: blue">let </span>maxTreeHeight = walkTree trieRoot</pre>
<a href="https://11011.net/software/vspaste"></a>

<p><span style="color: green"><font color="#000000">Once we have associated each node with a height in the tree, then group nodes into buckets based on height. So all nodes with height 0 should be terminal EOW nodes. All nodes with height 1 should only have children which are EOW nodes, and so on.</font></span></p>

<pre class="code"><span style="color: green">// Next, fill a separate dictionary mapping each height to a set of nodes. This
// allows us to efficiently 'merge' suffixes going from bottom up.
</span><span style="color: blue">let </span>heightNodesDict = <span style="color: blue">new </span>Dictionary&lt;int, HashSet&lt;TrieNode&gt;&gt;()
<span style="color: blue">for </span>i = 0 <span style="color: blue">to </span>16 <span style="color: blue">do
    </span>heightNodesDict.[i] &lt;- <span style="color: blue">new </span>HashSet&lt;_&gt;()

Seq.iter 
    (<span style="color: blue">fun </span>node <span style="color: blue">-&gt; let </span>height = nodeHeightDict.[node]
                 ignore(heightNodesDict.[height].Add(node)))
    nodeHeightDict.Keys</pre>
<a href="https://11011.net/software/vspaste"></a>

<p><span style="color: green"><font color="#000000">Now things start to get interesting. We need to store common tree suffixes for reuse. Rather than searching the suffix list at every node, we will index it by height of the tree and number of child nodes. (That way we can easily differentiate a suffix that leads to a word by adding “-ED” from a suffix that leads to a word by adding “-ING”.)</font></span></p>

<pre class="code"><span style="color: green">// Now add unique suffix nodes to our 'blessed' list, which
// should all be unique. We will then walk the tree bottom-up
// setting child nodes to the blessed/unique suffixes.
//
// We store our blessed suffix nodes in a (height * NumChildren) dictionary 
// for fast lookup if a suffix exists.
</span><span style="color: blue">let </span>suffixNodes = <span style="color: blue">new </span>Dictionary&lt;int * int, HashSet&lt;TrieNode&gt;&gt;()
<span style="color: blue">for </span>treeDepth = 0 <span style="color: blue">to </span>16 <span style="color: blue">do 
    for </span>numChildren = 0 <span style="color: blue">to </span>26 <span style="color: blue">do
        </span>suffixNodes.[(treeDepth, numChildren)] &lt;- <span style="color: blue">new </span>HashSet&lt;_&gt;()

<span style="color: green">// All nodes at height zero are EOW nodes (EOWNode and IsLeafNode are true)
// So add exactly one EOW node to the blessed suffixNodes dictionary. All
// nodes at height 0 can be replaced with the one EOW node.
</span>suffixNodes.[0, 0].Add(Seq.head heightNodesDict.[0]) |&gt; ignore</pre>
<a href="https://11011.net/software/vspaste"></a>

<p><span style="color: green"><font color="#000000">Finally, we walk the nodes in the tree and rewire the child nodes with blessed suffixes. Again, we work from the bottom of the tree up for efficiency reasons. We don’t need to start at heightOfNode 0, since all of those nodes are identical (EOW) and will be replaced by suffixNodes.[0, 0] anyways.</font></span></p>

<p><span style="color: green"><font color="#000000">We can compare child nodes using the TrieNode.CompareNodes methods. This checks if two child nodes contain essentially the same information.</font></span></p>

<pre class="code"><span style="color: blue">for </span>heightOfNode = 1 <span style="color: blue">to </span>16 <span style="color: blue">do   

    </span>printfn <span style="color: maroon">&quot;DAWGifying child nodes at height %2d. [%s]&quot; </span>heightOfNode (System.DateTime.Now.ToString(<span style="color: maroon">&quot;hh:mm:ss&quot;</span>))
<br /> <br />    <span style="color: blue">for </span>node <span style="color: blue">in </span>heightNodesDict.[heightOfNode] <span style="color: blue">do
    
        for </span>childIdx = 0 <span style="color: blue">to </span>25 <span style="color: blue">do
            
            let </span>childNode = node.Children.[childIdx]
            <span style="color: blue">if </span>childNode &lt;&gt; <span style="color: blue">null then
            
                let </span>validSuffixes = 
                    <span style="color: blue">let </span>childNodeHeight = nodeHeightDict.[childNode]
                    suffixNodes.[childNodeHeight, childNode.NumChildren]
                
                <span style="color: blue">let </span>foundValidSuffix = 
                    Seq.tryFind 
                        (<span style="color: blue">fun </span>validSuffix <span style="color: blue">-&gt; </span>TrieNode.CompareNodes(childNode, validSuffix))
                        validSuffixes

                <span style="color: green">// If this suffix has never been encountered, then add it to our list.
                // Otherwise, reuse the blessed suffix.
                </span><span style="color: blue">if </span>Option.isNone foundValidSuffix <span style="color: blue">then
                    </span>validSuffixes.Add(childNode) |&gt; ignore
                <span style="color: blue">else
                    </span>node.Children.[childIdx] &lt;- Option.get foundValidSuffix</pre>
<a href="https://11011.net/software/vspaste"></a>

<p><span style="color: green"><font color="#000000">Of course, once we go through this procedure we still have the same TrieNode for the root of the tree. How can we validate that our DAWG has fewer nodes? We can validate this by simply walking the tree and adding the hash code of each node to a set. (Note we are relying on the <a href="https://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx">default implementation</a> of GetHashCode.)</font></span></p>

<pre class="code"><span style="color: blue">let rec </span>getUniqueNodes (node : TrieNode)  =
    
    <span style="color: blue">let </span>theSet = Set.singleton (node.GetHashCode())

    <span style="color: blue">let </span>children'sNodes =
        node.Children
        |&gt; Array.filter (<span style="color: blue">fun </span>child <span style="color: blue">-&gt; </span>child &lt;&gt; <span style="color: blue">null</span>)
        |&gt; Array.map getUniqueNodes
        |&gt; Array.fold
            (<span style="color: blue">fun </span>acc uniqueNodes <span style="color: blue">-&gt; </span>Set.union acc uniqueNodes)
            Set.empty
        
    Set.union theSet children'sNodes</pre>
<a href="https://11011.net/software/vspaste"></a>

<p><span style="color: green"><font color="#000000">And, to drive the point home how much better our implementation is than that not-so-evil-genius Dr. McNamara we can use the following test function:</font></span></p>

<pre class="code">printfn <span style="color: maroon">&quot;Building trie...&quot;
</span><span style="color: blue">let </span>regularTrie = <span style="color: blue">new </span>TrieNode()
<span style="color: blue">for </span>w <span style="color: blue">in </span>words <span style="color: blue">do
    </span>regularTrie.Add(w)
printfn <span style="color: maroon">&quot;Trie: %d nodes&quot; </span>&lt;| (getUniqueNodes regularTrie).Count

printfn <span style="color: maroon">&quot;Building trie for DAWG conversion...&quot;
</span><span style="color: blue">let </span>dawg = <span style="color: blue">new </span>TrieNode()
<span style="color: blue">for </span>w <span style="color: blue">in </span>words <span style="color: blue">do
    </span>dawg.Add(w)
convertTrieToDawg dawg

printfn <span style="color: maroon">&quot;DAWG : %d nodes&quot; </span>&lt;| (getUniqueNodes dawg).Count
    
printfn <span style="color: maroon">&quot;Testing...&quot;
</span><span style="color: blue">for </span>w <span style="color: blue">in </span>words <span style="color: blue">do
    assert </span>IsWord(w, regularTrie)
    <span style="color: blue">assert </span>IsWord(w, dawg)</pre>
<a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste"></a>

<p><span style="color: green"><font color="#000000"><span style="color: green"><font color="#000000">That’s it! I’ll admit that my implementation for converting a trie tree to a DAWG is a little slow, taking several minutes, but the results are worth it</font></span>. The original trie tree required 393,960 nodes while the DAWG only needs 54,822. I’m not sure what I’ll do with all the memory savings. Perhaps use it to prepare for my next evil plan, which may or may not involve orbiting death lasers and the GPS coordinates of my enemy’s condo.</font></span></p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/DAWGfight_8938/image_2.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/DAWGfight_8938/image_2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/DAWGfight_8938/image_thumb.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/DAWGfight_8938/image_thumb.png" width="672" height="351" /></a> </p>

<p><span style="color: green"><font color="#000000"><strong>So <em>good</em>-genius Dr. McNamara, </strong><a href="https://en.wikipedia.org/wiki/How_do_you_like_them_apples"><strong>how do you like them apples</strong></a><strong>?</strong> </font></span></p>]]></content:encoded>
    </item>
    <item>
      <title>F# CTP Update!</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/f-ctp-update</link>
      <pubDate>Thu, 11 Feb 2010 11:48:24 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2010/02/11/f-ctp-update/</guid>
      <description><![CDATA[Hot on the heels of the Visual Studio 2010 Release Candidate comes the February, 2010 F# CTP. There...]]></description>
      <content:encoded><![CDATA[<p>Hot on the heels of the <a href="https://msdn.microsoft.com/en-us/vstudio/dd582936.aspx">Visual Studio 2010 Release Candidate</a> comes the <a href="https://www.microsoft.com/downloads/details.aspx?FamilyID=ba52e650-4e77-4b0b-b987-9f9ecd3bab3b&amp;displaylang=en">February, 2010 F# CTP</a>. There haven’t been too many changes since the last release, mostly bug fixes and getting the libraries in a consistent state. You can find more information on <a href="https://blogs.msdn.com/dsyme">Don’s blog</a>. </p>]]></content:encoded>
    </item>
    <item>
      <title>Trie-ing to optimize text search in F#</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/trie-ing-to-optimize-text-search-in-f</link>
      <pubDate>Tue, 09 Feb 2010 13:28:00 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2010/02/09/trie-ing-to-optimize-text-search-in-f/</guid>
      <description><![CDATA[Any evil genius knows that if you want to stay on top you need to exercise your mind. Most evil...]]></description>
      <content:encoded><![CDATA[<P>Any <A href="https://blogs.msdn.com/chrsmith/archive/2010/01/24/being-an-evil-genius-with-f-and-net.aspx" mce_href="https://blogs.msdn.com/chrsmith/archive/2010/01/24/being-an-evil-genius-with-f-and-net.aspx">evil genius</A> knows that if you want to stay on top you need to exercise your mind. Most evil geniuses stay strong by lifting weights with their <A href="https://www.ehow.com/how_2058097_become-telekinetic.html" mce_href="https://www.ehow.com/how_2058097_become-telekinetic.html">telekinetic abilities</A>, however I prefer video games. <A href="https://www.popcap.com/games/free/bookworm/?mid=bookworm_pcweb_en_full">PopCap.com’s Bookworm</A> is one mental exercise I am particularly fond of. 
<P>Bookworm is simple. You have&nbsp; 7x7 hexagonal grid of letters and your goal is to create words by forming chains of adjacent tiles. Once you pick the word, the tiles are remove from the board and new ones drop down to fill the void. 
<P>The following screen shot shows a five letter word being selected. Obviously it is harder to find longer words, and thus they are worth more points. 
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_2.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_2.png" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_thumb.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_thumb.png" width=570 height=452 mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_thumb.png"></A> 
<P>Eventually you start getting Green, Gold, and Diamond tiles worth bonus points. However, if you make too many short words, typically those with only three-letters, you get flaming tiles. Each round a flaming tile exists on the screen it will burn through the tile below it. Once a flaming tile reaches the bottom of the screen it’s <A href="https://www.bing.com/search?q=bill+paxton" mce_href="https://www.bing.com/search?q=bill+paxton">game over, man</A>. 
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_4.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_4.png" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_4.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_thumb_1.png" width=574 height=453 mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image_thumb_1.png"></A> 
<P>Mental exercise is important to keep any evil genius, well, a genius. However, a <STRONG><EM>true</EM></STRONG> evil genius would try to cheat. And that’s exactly what I intend to do in this blog post: write a program to find the longest word on a given Bookworm board. 
<H1>Hexgrid Data Structure</H1>
<P>In order to cheat at any game, first you need to write code to represent the game state. Which in the case of Bookworm is the hexagonal grid.&nbsp; Creating our grid data structure isn’t going to be super interesting, but bear with me as it is required in order to do word searches later. 
<P>We’ll start by creating an interface to represent each tile on the board, which has a letter, set of neighbors, and position. Then we create a class for the actual letter grid.<PRE class=code><SPAN style="COLOR: green">/// Representing a tile on the board
</SPAN>[&lt;AllowNullLiteral&gt;]
<SPAN style="COLOR: blue">type </SPAN>ITile =
    <SPAN style="COLOR: blue">abstract </SPAN>Letter    : char
    <SPAN style="COLOR: blue">abstract </SPAN>Neighbors : seq&lt;ITile&gt;
    <SPAN style="COLOR: blue">abstract </SPAN>Location  : int * int

<SPAN style="COLOR: green">/// Data structure for a hex grid of letters
</SPAN><SPAN style="COLOR: blue">type </SPAN>LetterGrid(tileColumns : string[]) = 
    
    <SPAN style="COLOR: green">// Store the grid of letters in an array. Note that it is jagged. In 
    // the flash version of Bookworm even columns have 8-tiles instead of 7.
    </SPAN><SPAN style="COLOR: blue">let mutable </SPAN>m_columns : char[][] = <SPAN style="COLOR: blue">null
    
    </SPAN><SPAN style="COLOR: green">// Cache of ITiles corresponding to tiles on the grid
    </SPAN><SPAN style="COLOR: blue">let mutable </SPAN>m_tileCache = Map.empty</PRE>
<P>Armed with these simple types, we can go about populating our LetterGrid class’ ITile cache. The following F# snippet shows using F# <A href="https://msdn.microsoft.com/en-us/library/dd233237(VS.100).aspx" mce_href="https://msdn.microsoft.com/en-us/library/dd233237(VS.100).aspx">object expressions</A> to create new instances of ITile. Note the recursive calls to getTile and then filtering out any tiles which are off the board. We can represent off-board tiles by simply having getTile return null. However, this requires some additional work. 
<P>By default any types defined in F# cannot be null, even interfaces like ITile. However, we can override this behavior by simply adding the [&lt;AllowNullLiteral&gt;] attribute.<PRE class=code><SPAN style="COLOR: green">/// Get an instance of an ITile from the given index. (Generating it if necessary.)
</SPAN><SPAN style="COLOR: blue">let rec </SPAN>getTile colIdx rowIdx =
<SPAN style="COLOR: blue"></SPAN></PRE><PRE class=code><SPAN style="COLOR: blue">    if </SPAN>not &lt;| isValidLocation colIdx rowIdx <SPAN style="COLOR: blue">then
        null
    else
        
</SPAN><SPAN style="COLOR: blue">        if </SPAN>Map.containsKey (colIdx, rowIdx) m_tileCache <SPAN style="COLOR: blue">then
            </SPAN>m_tileCache.[(colIdx, rowIdx)]
        <SPAN style="COLOR: blue">else
            let </SPAN>newTile = 
                {
                    <SPAN style="COLOR: blue">new </SPAN>ITile <SPAN style="COLOR: blue">with
                        member </SPAN>this.Letter = getTileLetter colIdx rowIdx
                        <SPAN style="COLOR: blue">member </SPAN>this.Neighbors =
                        
                            <SPAN style="COLOR: blue">let </SPAN>neighbors =
                                
                                <SPAN style="COLOR: blue">if </SPAN>(colIdx + 1) % 2 = 1 <SPAN style="COLOR: blue">then
                                    </SPAN><SPAN style="COLOR: green">// Odd column
                                    </SPAN>seq {
                                        <SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx - 1) (rowIdx + 0)  <SPAN style="COLOR: green">// NW
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx + 0) (rowIdx - 1)  <SPAN style="COLOR: green">// N
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx + 1) (rowIdx + 0)  <SPAN style="COLOR: green">// NE
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx + 1) (rowIdx + 1)  <SPAN style="COLOR: green">// SE
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx + 0) (rowIdx + 1)  <SPAN style="COLOR: green">// S
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx - 1) (rowIdx + 1)  <SPAN style="COLOR: green">// SW

                                    </SPAN>}
                                <SPAN style="COLOR: blue">else
                                    </SPAN><SPAN style="COLOR: green">// Even column
                                    </SPAN>seq {
                                        <SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx - 1) (rowIdx - 1)  <SPAN style="COLOR: green">// NW
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx + 0) (rowIdx - 1)  <SPAN style="COLOR: green">// N
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx + 1) (rowIdx - 1)  <SPAN style="COLOR: green">// NE
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx + 1) (rowIdx + 0)  <SPAN style="COLOR: green">// SE
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx + 0) (rowIdx + 1)  <SPAN style="COLOR: green">// S
                                        </SPAN><SPAN style="COLOR: blue">yield </SPAN>getTile (colIdx - 1) (rowIdx + 0)  <SPAN style="COLOR: green">// SW
                                    </SPAN>}
<SPAN style="COLOR: green">                                    
                            // Filter out null (neighbors off the board)
                            </SPAN>neighbors |&gt; Seq.filter ( (&lt;&gt;) <SPAN style="COLOR: blue">null </SPAN>)
                    
                        <SPAN style="COLOR: blue">member </SPAN>this.Location = (colIdx, rowIdx)
                }
        
            m_tileCache &lt;- Map.add (colIdx, rowIdx) newTile m_tileCache
            newTile</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>
<H1>Crappy Word Detection</H1>
<P>Great! Now that we have a way to represent the hex grid, all we need to do is start searching for words. First, we need a dictionary. Floating around on the internet<A href="https://en.wikipedia.org/wiki/Internets" mce_href="https://en.wikipedia.org/wiki/Internets">(s)</A> you can find a copy of the <A href="https://en.wikipedia.org/wiki/Tournament_Word_List" mce_href="https://en.wikipedia.org/wiki/Tournament_Word_List">Scrabble Tournament Word List</A> (TWL). The TWL contains all legal Scrabble words, however Bookworm only honors a subset of them. (For example, most curse words are not recognized.) 
<P>Once we have a word list, perhaps represented as a Set&lt;string&gt; we just need to start trying out all combinations of word chains and seeing if they are valid words, right? Wrong! That is a terrible idea and here is why: 
<P>Bookworm accepts words between 3 and 12-letters long. The board starts with 52 tiles, and each tile has six neighbors. Ignoring the fact that a tile cannot be used twice in the same word chain, we get: 
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/clip_image002_2.gif" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/clip_image002_2.gif" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/clip_image002_2.gif"><IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=clip_image002 border=0 alt=clip_image002 src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/clip_image002_thumb.gif" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/clip_image002_thumb.gif" width=108 height=80 mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/clip_image002_thumb.gif"></A> 
<P>which <A href="https://www.wolframalpha.com/input/?i=52*%286%5E2%2B6%5E3%2B6%5E4%2B6%5E5%2B6%5E6%2B6%5E7%2B6%5E8%2B6%5E9%2B6%5E10%2B6%5E11%29" mce_href="https://www.wolframalpha.com/input/?i=52*%286%5E2%2B6%5E3%2B6%5E4%2B6%5E5%2B6%5E6%2B6%5E7%2B6%5E8%2B6%5E9%2B6%5E10%2B6%5E11%29">WolframAlpha</A> tells me is 22,638,535,920, and that is just word chains! Once we are done permuting every single word chain we then have to look it up in our dictionary. Which would be O(log n), where n is the number of words. O(log n) is quite fast, but multiplied by 22 billion is still way too big. 
<P>What we need is a way to efficiently prune our search space. If you ever have a word prefixed with “AKVWOP”, and you know it isn’t a word, then it doesn’t make sense to continue looking in the vague hope of finding “AKVWOP<STRONG><EM>S</EM></STRONG>”, “AWKVWOP<STRONG><EM>ED</EM></STRONG>”, “AWKVWOP<STRONG><EM>ING</EM></STRONG>”, etc.&nbsp; 
<H1>The Trie Data Structure</H1>
<P>Fortunately, there is a classic data structure for doing this called a <A href="https://en.wikipedia.org/wiki/Trie" mce_href="https://en.wikipedia.org/wiki/Trie">trie</A>. (Pronounced ‘try’, as in I was trie-ing to be clever when I titled this post.) It is also referred to as a <EM>prefix tree</EM>. The data structure can be explained quite well with the following picture:&nbsp; 
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image8.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image8.png" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image8.png"><IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image8_thumb.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image8_thumb.png" width=410 height=385 mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/image8_thumb.png"></A> 
<P><A href="https://en.wikipedia.org/wiki/Trie" mce_href="https://en.wikipedia.org/wiki/Trie"></A><PRE class=code></PRE>
<P>You start with the root node, and the edge to any of its children requires a letter. For example ‘t’. The child of the root node associated with ‘t’, has a child using the letter ‘o’ and another child associated with the letter ‘e’. Since there is no child associated with the letter ‘q’, you can infer that there is no leaf nodes prefix with the string “tq”.</P>
<P>If we constructed a trie for the entire contents of the dictionary, we would then have an efficient way to determine if a given substring prefixes any valid word. (By simply checking if such a node exists in the tree or not.)</P>
<P>The code for implementing this in F# is straightforward. Each trie node stores a dictionary potentially mapping a letter to a child node, or the it is at a terminal node. Meaning that the prefix is a valid word, and there are no further words with that prefix.<PRE class=code><SPAN style="COLOR: blue">type </SPAN>TrieNode =
    <SPAN style="COLOR: green">// Letters go to other nodes, flag if it is a word node
    </SPAN>| Node <SPAN style="COLOR: blue">of </SPAN>IDictionary&lt;char, TrieNode&gt; * bool
    <SPAN style="COLOR: green">// You are at the end of a legal word
    </SPAN>| Eow
    
    <SPAN style="COLOR: blue">member </SPAN>this.IsLegalWord = 
        <SPAN style="COLOR: blue">match </SPAN>this <SPAN style="COLOR: blue">with
        </SPAN>| Node(_, <SPAN style="COLOR: blue">true</SPAN>)
        | Eow <SPAN style="COLOR: blue">-&gt; true
        </SPAN>| _   <SPAN style="COLOR: blue">-&gt; false</SPAN></PRE>
<P><SPAN style="COLOR: green"><FONT color=#000000>To generate our tree, we use the following function which takes a sequence of words, represented as <A href="https://blogs.msdn.com/chrsmith/archive/2008/07/10/mastering-f-lists.aspx" mce_href="https://blogs.msdn.com/chrsmith/archive/2008/07/10/mastering-f-lists.aspx">F# lists</A> of characters, and converts it into a TrieNode. </FONT></SPAN><SPAN style="COLOR: green"><FONT color=#000000>I’ve added a glut of comments to help explain things. The only bit of black magic is the use of the dict function. </FONT></SPAN></P>
<P><SPAN style="COLOR: green"><FONT color=#000000>dict works by taking a seq&lt;’k, ‘v&gt; and produces an IDictionary&lt;’k, ‘v&gt;. </FONT></SPAN></P><PRE class=code><SPAN style="COLOR: green">/// seq&lt;char list&gt; -&gt; TrieNode 
</SPAN><SPAN style="COLOR: blue">let rec </SPAN>generateTrieNode words =

    <SPAN style="COLOR: green">// Does this represent an EOW node for anything?
    </SPAN><SPAN style="COLOR: blue">let </SPAN>hasEowNode = Seq.exists (<SPAN style="COLOR: blue">fun </SPAN>word <SPAN style="COLOR: blue">-&gt; </SPAN>word = []) words

    <SPAN style="COLOR: blue">if </SPAN>Seq.isEmpty words <SPAN style="COLOR: blue">then
        </SPAN>Eow    
    <SPAN style="COLOR: blue">else
        </SPAN><SPAN style="COLOR: green">(* Now group all words by their first letter.
        [ "cat"; "cats"; "dogs" ] 
        =&gt;
        seq {
            ('c', seq { "at"; "ats" })
            ('d', seq { "ogs" })
        }
        *)
        </SPAN><SPAN style="COLOR: blue">let </SPAN>nextWordFragments =
            <SPAN style="COLOR: green">// [""; "a"; "act"; "acts"; "actor"; ... ]
            </SPAN>words   
            <SPAN style="COLOR: green">// ["a"; "act"; "acts"; "actor"; ... ]
            </SPAN>|&gt; Seq.filter (<SPAN style="COLOR: blue">fun </SPAN>word <SPAN style="COLOR: blue">-&gt; </SPAN>word &lt;&gt; [])
            <SPAN style="COLOR: green">// seq { ("a", seq { "act"; "acts"; "actor"; ... }); ... }
            </SPAN>|&gt; Seq.groupBy (<SPAN style="COLOR: blue">fun </SPAN>word <SPAN style="COLOR: blue">-&gt; </SPAN>Seq.head word)
            <SPAN style="COLOR: green">// seq { ("a", seq { "ct"; "cts"; "ctor"; ... }); ... }
            </SPAN>|&gt; Seq.map (<SPAN style="COLOR: blue">fun </SPAN>(firstLetter, words) <SPAN style="COLOR: blue">-&gt; </SPAN>(firstLetter, words |&gt; Seq.map List.tail))
            <SPAN style="COLOR: green">// seq { ("a", seq ("c", seq { ... } ...  }
            </SPAN>|&gt; Seq.map(<SPAN style="COLOR: blue">fun </SPAN>(firstLetter, rest) <SPAN style="COLOR: blue">-&gt; </SPAN>(firstLetter, generateTrieNode rest))
            <SPAN style="COLOR: green">// seq { ("a", seq ...); ("A", seq ...) ... }
            </SPAN>|&gt; Seq.fold
                (<SPAN style="COLOR: blue">fun </SPAN>acc (letter, trieNode) <SPAN style="COLOR: blue">-&gt;
                    </SPAN>(Char.ToUpper(letter), trieNode) :: (Char.ToLower(letter), trieNode) :: acc
                )
                []

        Node(dict nextWordFragments, hasEowNode)</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>Once you have the trie tree in memory, you can check if a string is a valid word or not by simply walking down the tree.<PRE class=code><SPAN style="COLOR: blue">let </SPAN>isWord word tree =
    
    <SPAN style="COLOR: blue">let </SPAN>letters = word |&gt; Seq.toList
    
    <SPAN style="COLOR: blue">let rec </SPAN>isWord currentNode letters =
        <SPAN style="COLOR: blue">match </SPAN>letters, currentNode <SPAN style="COLOR: blue">with
        </SPAN><SPAN style="COLOR: green">// When you are out of letters, check if you are on
        // an end-of-word node
        </SPAN>| [], Eow
        | [], Node(_, <SPAN style="COLOR: blue">true</SPAN>) 
            <SPAN style="COLOR: blue">-&gt; true

        </SPAN><SPAN style="COLOR: green">// Otherwise, walk down the tree...
        </SPAN>| nextLetter :: rest, Node(childNodes, _)
            <SPAN style="COLOR: blue">-&gt;  let </SPAN>hasNode, childNode = childNodes.TryGetValue(nextLetter)
                <SPAN style="COLOR: blue">if </SPAN>hasNode <SPAN style="COLOR: blue">then
                    </SPAN>isWord childNode rest 
                <SPAN style="COLOR: blue">else
                    false

        </SPAN>| _ <SPAN style="COLOR: blue">-&gt; false

    </SPAN>isWord tree letters </PRE>
<H1>Searching</H1>
<P>Searching through potential word chains can be parallelized trivially, but I’ll save that for a future blog post. For now we will use the following approach: 
<UL>
<LI>Start with each tile on the board and put them into a stack of ‘search states’</LI>
<LI>While the search stack is not empty do</LI>
<UL>
<LI>Pop the search stack</LI>
<LI>Check that state to see if there are any legal words from that position (adjacent tiles leading to valid word prefixes)</LI>
<LI>Push any legal, subsequent steps to our search stack</LI></UL></UL>
<P>Here is the F# code. Note that each state is represented by TrieNode * ITile list. This represents the current word prefix node in the trie tree and the list of tiles forming the word chain. We then seed that search stack with word chains starting at every tile in the board.<PRE class=code><SPAN style="COLOR: blue">let </SPAN>statesToExplore = <SPAN style="COLOR: blue">new </SPAN>Stack&lt;TrieNode * ITile list&gt;()

<SPAN style="COLOR: green">// Start with searching all tiles
</SPAN>gameGrid.AllTiles 
|&gt; Seq.iter (<SPAN style="COLOR: blue">fun </SPAN>tile <SPAN style="COLOR: blue">-&gt; 
                let </SPAN>firstStepDownTrieTree = 
                    <SPAN style="COLOR: blue">match </SPAN>trieRoot <SPAN style="COLOR: blue">with
                    </SPAN>| Node(nextSteps, _) <SPAN style="COLOR: blue">-&gt; </SPAN>nextSteps.[tile.Letter]
                    | _ <SPAN style="COLOR: blue">-&gt; </SPAN>failwith <SPAN style="COLOR: maroon">"Shouldn't get here"
                </SPAN>statesToExplore.Push(firstStepDownTrieTree, [tile]))

<SPAN style="COLOR: green">// Now explore the entire search space
</SPAN><SPAN style="COLOR: blue">while </SPAN>statesToExplore.Count &gt; 0 <SPAN style="COLOR: blue">do
    let </SPAN>trieNode, prevLetters = statesToExplore.Pop()
    
    <SPAN style="COLOR: blue">match </SPAN>searchStep trieNode prevLetters <SPAN style="COLOR: blue">with
    </SPAN>| None <SPAN style="COLOR: blue">-&gt; </SPAN>()
    | Some(nextSearchStates) <SPAN style="COLOR: blue">-&gt;
        </SPAN><SPAN style="COLOR: green">// Add possible states to explore to our stack
        </SPAN>Seq.iter (statesToExplore.Push) nextSearchStates</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>
<P>All we need is a function to take some given search state – current node in the trie tree and tiles used so far – and then check all of the neighboring tiles if they can continue down the trie tree towards valid words. <PRE class=code><SPAN style="COLOR: green">/// Given a spot in the Trie tree, a game tile, and a list of previously used tiles used
/// to form a word, return Some(seq&lt; all possible steps&gt;). If no legal words are possible
/// from this state, return None.
</SPAN><SPAN style="COLOR: blue">let </SPAN>searchStep (nodeInTrieTree : TrieNode) (tilesInChain : ITile list) =

    <SPAN style="COLOR: green">// Are we at a legal word in the Trie tree?
    </SPAN><SPAN style="COLOR: blue">if </SPAN>nodeInTrieTree.IsLegalWord <SPAN style="COLOR: blue">then
        </SPAN>foundWords.Add(getWordText tilesInChain)

    <SPAN style="COLOR: blue">let </SPAN>currentTile = List.head tilesInChain

    <SPAN style="COLOR: blue">match </SPAN>nodeInTrieTree <SPAN style="COLOR: blue">with
    </SPAN><SPAN style="COLOR: green">// Cannot make any valid words from this point, no purpose in stepping
    </SPAN>| Eow <SPAN style="COLOR: blue">-&gt; </SPAN>None
    <SPAN style="COLOR: green">// If you can form legal words beond where we are at in the tree, continue
    // searching.
    </SPAN>| Node(possibleLetterSteps, _) 
        <SPAN style="COLOR: blue">-&gt;  let </SPAN>possibleSteps =
                currentTile.Neighbors
                <SPAN style="COLOR: green">// Filter out neighbors already used for the word chain
                </SPAN>|&gt; Seq.filter 
                    (<SPAN style="COLOR: blue">fun </SPAN>neighborTile <SPAN style="COLOR: blue">-&gt; 
                        </SPAN>not (List.exists 
                                (<SPAN style="COLOR: blue">fun </SPAN>(prevTile : ITile) <SPAN style="COLOR: blue">-&gt; </SPAN>prevTile.Location = neighborTile.Location) 
                                tilesInChain
                            )
                    )
                <SPAN style="COLOR: green">// Filter out neighbors which couldn't lead to avalid word
                </SPAN>|&gt; Seq.filter
                    (<SPAN style="COLOR: blue">fun </SPAN>neighborTile <SPAN style="COLOR: blue">-&gt; </SPAN>possibleLetterSteps.ContainsKey(neighborTile.Letter))
                <SPAN style="COLOR: green">// Now map them to the next 'states' to search
                </SPAN>|&gt; Seq.map 
                    (<SPAN style="COLOR: blue">fun </SPAN>neighborTile <SPAN style="COLOR: blue">-&gt;
                        </SPAN>(   <SPAN style="COLOR: green">// Node in trie tree
                            </SPAN>possibleLetterSteps.[neighborTile.Letter],
                            <SPAN style="COLOR: green">// Tiles used in the word chain
                            </SPAN>neighborTile :: tilesInChain
                        )
                    )
                    
            <SPAN style="COLOR: blue">if </SPAN>not (Seq.isEmpty possibleSteps) <SPAN style="COLOR: blue">then
                </SPAN>Some(possibleSteps)
            <SPAN style="COLOR: blue">else
                </SPAN>None</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>
<P>And that’s it! We can use this efficient word search cheat to our heart’s content. Attached to this post is the source code.</P>
<P>I used BookwormBot9000 to spot this gem on my iPhone version of the game. But that begs the question <A href="https://www.wisegeek.com/what-is-madrilene.htm" mce_href="https://www.wisegeek.com/what-is-madrilene.htm">what the hell is a madrilene</A>?</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/photo_2.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/photo_2.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/photo_2.jpg"><IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=photo border=0 alt=photo src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/photo_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/photo_thumb.jpg" width=324 height=484 mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/TrieingtouseFforoptimizingtextsearch_F99C/photo_thumb.jpg"></A> </P>
<P><B>Disclaimer</B></P>
<BLOCKQUOTE>
<P>All code samples are provided "AS IS" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose. So in other words, if cheating at word games leads your brain to atrophy and turn to mush, don’t blame me or Microsoft. </P></BLOCKQUOTE>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/09/96/07/89/BookWormBot9K%20v1.0.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-96-07-89/BookWormBot9K-v1.0.zip">BookWormBot9K v1.0.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Being an Evil Genius with F# and .NET</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/being-an-evil-genius-with-f-and-net</link>
      <pubDate>Sun, 24 Jan 2010 21:57:00 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2010/01/24/being-an-evil-genius-with-f-and-net/</guid>
      <description><![CDATA[A couple weeks ago I was in glorious Sandusky, Ohio presenting at CodeMash. CodeMash is a community...]]></description>
      <content:encoded><![CDATA[<p>A couple weeks ago I was in glorious <a href="https://www.bing.com/maps/#JnE9eXAuc2FuZHVza3krb2hpbyU3ZXNzdC4wJTdlcGcuMSZiYj02Mi4xOTk3NDEzMjE1NDU2JTdlLTk4LjE2MzA3ODMwOCU3ZTI3LjQ3NTkwMDk1NDI0NTYlN2UtMTQ2LjUwMjkyMjA1OA==" mce_href="https://www.bing.com/maps/#JnE9eXAuc2FuZHVza3krb2hpbyU3ZXNzdC4wJTdlcGcuMSZiYj02Mi4xOTk3NDEzMjE1NDU2JTdlLTk4LjE2MzA3ODMwOCU3ZTI3LjQ3NTkwMDk1NDI0NTYlN2UtMTQ2LjUwMjkyMjA1OA==">Sandusky, Ohio</a> presenting at <a href="https://codemash.org/" mce_href="https://codemash.org/">CodeMash</a>. CodeMash is a community driven conference that’s less about product announcements and typical “rah rah” and more about getting smart people together to talk about what they are passionate about – coding.</p>  <p>Rather than doing the prototypical “<a href="https://blogs.msdn.com/chrsmith/archive/2009/08/20/f-for-architects-hitting-the-sweet-spot.aspx" mce_href="https://blogs.msdn.com/chrsmith/archive/2009/08/20/f-for-architects-hitting-the-sweet-spot.aspx">Intro to F# Talk</a>” I figured I go with something a bit more fun and relevant to the every day developer. Sure F# is neat and everything – but why bother to learn a new programming language unless you can use it to do something meaningful. Well, in addition excelling at both functional and object-oriented programming, F# is ideal for world domination.</p>  <p>------------------------------------------------------</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide1.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide1.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide1.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide1" border="0" alt="Slide1" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide1_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide1_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide1_thumb.jpg" /></a></p>  <p>To be honest, this may be the best talk abstract I’ll ever write.</p>  <p><b>Being an Evil Genius with F# and .NET</b></p>  <blockquote>   <p>In today's competitive global economy it's increasingly difficult to find quality henchmen to aid you in taking over the Earth. Fortunately the .NET platform has plenty of technological gems which can help you </p>    <p>in your quest. </p>    <p>Speech recognition APIs to automate your demands for ransom. The Parallel Extensions to .NET for distributing control of your nanobots. Even image recognition to identify CIA spies and kill them on sight! </p>    <p>This code-focused talk will show you the libraries you can use to make your next high-powered plot for world domination a success. (F# knowledge is not required, though will help any aspiring evil genius grep the demos.)</p> </blockquote>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide2.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide2.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide2.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide2" border="0" alt="Slide2" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide2_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide2_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide2_thumb.jpg" /></a></p>  <p>Someone once told me that at the beginning of a talk you should introduce yourself. Well, I’m much like you – except that my ambition isn’t to build a house or write the great American novel. It’s to take over the world!</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide3.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide3.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide3.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide3" border="0" alt="Slide3" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide3_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide3_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide3_thumb.jpg" /></a></p>  <p>I’ve been very fortunate in my career as an evil genius and 2007 was a hallmark year. I had just leased a new volcano lair, had a growing army of minions, and even got a hold of real nuclear missile. The movies these days make it look like just anybody with three billion dollars can get a hold of one of these babies – not true! I had to get my minions to stage a raid on an ex-Soviet munitions dump and then kidnap a scientist to rebuild the flight systems. Hard work, the work was well worth it.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/foreclosed_2.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/foreclosed_2.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/foreclosed_2.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="foreclosed" border="0" alt="foreclosed" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/foreclosed_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/foreclosed_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/foreclosed_thumb.jpg" /></a> </p>  <p>But the global economic disaster struck me just like everyone else. As embarrassing as it is to admit this, I couldn’t keep up the payments on my volcano and it got foreclosed on. Then my minions were all ambushed and killed by some CIA commandos. And worst of all I had to give up my nuclear missile.</p>  <p>Saddened, I trudged on.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide5.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide5.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide5.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide5" border="0" alt="Slide5" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide5_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide5_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide5_thumb.jpg" /></a></p>  <p>Then it dawned on me. Maybe being an effective evil genius doesn’t mean volcano lairs or orbiting space lasers, perhaps you can still terrorize the Earth with software.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide6.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide6.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide6.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide6" border="0" alt="Slide6" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide6_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide6_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide6_thumb.jpg" /></a></p>  <p>And that brings us to the meat of my CodeMash talk, being an evil genius with F# and .NET. The talk isn’t so much about F# as it is about being an evil genius. But we all know F# is the premier .NET language for aspiring villains, so along the way I’ll highlight some language constructs that are especially helpful when plotting to take over the world.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide7.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide7.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide7.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide7" border="0" alt="Slide7" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide7_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide7_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide7_thumb.jpg" /></a></p>  <p>The first problem you’ll encounter is how to actually strike your foes? What if they are behind a wall, in a bunker, or inside of a tank?</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide8.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide8.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide8.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide8" border="0" alt="Slide8" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide8_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide8_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide8_thumb.jpg" /></a></p>  <p>As it turns out the terrorist training organization ‘<a href="https://www.hasbro.com/nerf/en-us/" mce_href="https://www.hasbro.com/nerf/en-us/">Nerf’</a> had it right all along. Foam missiles are the ideal weapon.</p>  <ul>   <li>Ever hear of an evil genius getting caught while trying to sneak foam missiles onto an airplane? There’s a reason for that… </li>    <li>Since they are sponges after all, why not soak them in poison to make them more lethal? </li> </ul>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide9.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide9.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide9.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide9" border="0" alt="Slide9" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide9_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide9_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide9_thumb.jpg" /></a></p>  <p>In order to get your hands on a foam-missile-WMD you could enslave a few engineers to build you one, but if you are more in a time crunch you can pick one up at Amazon for about $40.</p>  <p><a href="https://www.amazon.com/Computer-Controlled-Foam-Missile-Launcher/dp/B00100K5RM/ref=pd_sim_t_3" mce_href="https://www.amazon.com/Computer-Controlled-Foam-Missile-Launcher/dp/B00100K5RM/ref=pd_sim_t_3">Dream Cheeky USB Missile Launcher</a></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide10.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide10.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide10.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide10" border="0" alt="Slide10" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide10_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide10_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide10_thumb.jpg" /></a></p>  <p>However, this piece of specialized military hardware isn’t quite ideal for terror operations. The software it comes with is a little clunky and doesn’t offer the degree of precision required for world domination. What would any evil genius do in this case? <a href="https://www.urbandictionary.com/define.php?term=haxor" mce_href="https://www.urbandictionary.com/define.php?term=haxor">Haxor</a>, of course!</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide11.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide11.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide11.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide11" border="0" alt="Slide11" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide11_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide11_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide11_thumb.jpg" /></a> </p>  <p>A great magician never reveals his tricks, however that rule didn’t stop <a href="https://dvlabs.tippingpoint.com/team/pamini" mce_href="https://dvlabs.tippingpoint.com/team/pamini">Pedram Amini</a> from detailing the process of reverse engineering how the USB Rocket Launcher works.</p>  <p><a href="https://dvlabs.tippingpoint.com/blog/2009/02/12/python-interfacing-a-usb-missile-launcher" mce_href="https://dvlabs.tippingpoint.com/blog/2009/02/12/python-interfacing-a-usb-missile-launcher">https://dvlabs.tippingpoint.com/blog/2009/02/12/python-interfacing-a-usb-missile-launcher</a></p>  <p>Once you know the protocol for communicating with the missile launcher, it’s just a matter of reading and writing to the underlying USB device. Which you can do using P/Invoke in .NET. The code provided is in C# and was written by level-9 ninja master <a href="https://msdn.microsoft.com/en-us/magazine/dd942829.aspx" mce_href="https://msdn.microsoft.com/en-us/magazine/dd942829.aspx">Matt Ellis</a>.</p>  <pre class="code">[<span style="color: #2b91af">DllImport</span>(<span style="color: #a31515">&quot;kernel32.dll&quot;</span>, SetLastError = <span style="color: blue">true</span>)]
[<span style="color: blue">return</span>: <span style="color: #2b91af">MarshalAs</span>(<span style="color: #2b91af">UnmanagedType</span>.Bool)]
<span style="color: blue">public static extern unsafe bool </span>ReadFile(<span style="color: #2b91af">SafeFileHandle </span>hHandle, <span style="color: blue">byte</span>* lpBuffer, <span style="color: blue">uint </span>nNumberOfBytesToRead, <span style="color: blue">ref uint </span>lpNumberOfBytesRead, <span style="color: #2b91af">IntPtr </span>lpOverlapped);

[<span style="color: #2b91af">DllImport</span>(<span style="color: #a31515">&quot;kernel32.dll&quot;</span>, SetLastError = <span style="color: blue">true</span>)]
[<span style="color: blue">return</span>: <span style="color: #2b91af">MarshalAs</span>(<span style="color: #2b91af">UnmanagedType</span>.Bool)]
<span style="color: blue">public static extern unsafe bool </span>WriteFile(<span style="color: #2b91af">SafeFileHandle </span>hHandle, <span style="color: blue">byte</span>* lpBuffer, <span style="color: blue">uint </span>nNumberOfBytesToWrite, <span style="color: blue">ref uint </span>lpNumberOfBytesWritten, <span style="color: #2b91af">IntPtr </span>lpOverlapped);

<span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">That is, call directly into the drivers for the Rocket Launcher
</span><span style="color: gray">/// &lt;/summary&gt;
/// </span><span style="color: green">On a 64-bit OS: [DllImport(@&quot;C:\Program Files (x86)\USb Missile Launcher\USBHID.dll&quot;)]
</span>[<span style="color: #2b91af">DllImport</span>(<span style="color: #a31515">@&quot;C:\Program Files\USb Missile Launcher\USBHID.dll&quot;</span>)]
<span style="color: blue">public static extern </span><span style="color: #2b91af">SafeFileHandle </span>OpenHID(<span style="color: blue">ushort </span>VendorId, <span style="color: blue">ushort </span>ProductId, <span style="color: blue">ushort </span>ReveisionId);</pre>
<a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></a>

<p>Once you have a wrapper on top of the rocket launcher, then it’s just a matter of writing some code to interact with it. For RocketLauncherOfDoom v1.0 we’ll just have a console interface. Something like this:</p>

<pre class="code"><span style="color: blue">let </span>ckInfo = Console.ReadKey(<span style="color: blue">true</span>)
<span style="color: blue">let </span>t = 
    <span style="color: blue">if </span>(ckInfo.Modifiers = ConsoleModifiers.Shift) <span style="color: blue">then 
        </span><span style="color: brown">15
    </span><span style="color: blue">else 
        </span><span style="color: brown">5

</span><span style="color: blue">let </span>action =
    <span style="color: blue">match </span>ckInfo.Key <span style="color: blue">with
    </span>| ConsoleKey.UpArrow    <span style="color: blue">-&gt; </span>MoveUp(t)
    | ConsoleKey.DownArrow  <span style="color: blue">-&gt; </span>MoveDown(t)
    | ConsoleKey.LeftArrow  <span style="color: blue">-&gt; </span>MoveLeft(t)
    | ConsoleKey.RightArrow <span style="color: blue">-&gt; </span>MoveRight(t)
    
    | ConsoleKey.Spacebar <span style="color: blue">-&gt; </span>Fire

    | ConsoleKey.Q  <span style="color: blue">-&gt; </span>(loop &lt;- <span style="color: blue">false</span>)
                       NoOp
  
    | _ <span style="color: blue">-&gt; </span>NoOp

performAction rocketLauncher action |&gt; ignore</pre>
<a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></a>

<p>However, we are far from done.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide12.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide12.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide12.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide12" border="0" alt="Slide12" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide12_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide12_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide12_thumb.jpg" /></a></p>

<p>Once you have control over your USB rocket launcher, the problem is that you spend the rest of your time either making demands for ransom or listening to people beg for their lives. Both are kind of annoying and tedious. Fortunately we can automate this.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide13.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide13.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide13.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide13" border="0" alt="Slide13" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide13_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide13_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide13_thumb.jpg" /></a></p>

<p>Build into Windows are the <a href="https://en.wikipedia.org/wiki/Microsoft_Speech_API" mce_href="https://en.wikipedia.org/wiki/Microsoft_Speech_API">Microsoft Speech APIs (SAPI)</a> which can do both speech recognition – transcribing feeble cries for help – and speech synthesis – giving your robo-army a verbal presence.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide14.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide14.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide14.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide14" border="0" alt="Slide14" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide14_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide14_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide14_thumb.jpg" /></a></p>

<p>Getting setup is simple. First, you need a quality microphone. I’ve been very pleased with my purchase of:</p>

<p><a href="https://www.amazon.com/Plantronics-Audio-995-Wireless-Headset/dp/B001SEQN3U/ref=sr_1_3?ie=UTF8&amp;s=electronics&amp;qid=1264092725&amp;sr=1-3" mce_href="https://www.amazon.com/Plantronics-Audio-995-Wireless-Headset/dp/B001SEQN3U/ref=sr_1_3?ie=UTF8&amp;s=electronics&amp;qid=1264092725&amp;sr=1-3">Plantronics Audio 995 Wireless Stereo Headset</a></p>

<p>Next, you can dramatically improve your computer’s accuracy at recognizing your voice by <a href="https://www.microsoft.com/enable/training/windowsvista/srtrain.aspx" mce_href="https://www.microsoft.com/enable/training/windowsvista/srtrain.aspx">training your computer</a>. Simply open up Control Panel and click ‘Speech Recognition’ and then ‘Train your computer to better understand you’. Essentially you will dictate to your computer for 10 minutes but the results are worth it.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide15.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide15.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide15.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide15" border="0" alt="Slide15" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide15_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide15_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide15_thumb.jpg" /></a></p>

<p>Once you dictate Windows into submission, it’s time for code! The System.Speech APIs come with .NET 3.0 and are quite straight forward. The following snippet prints all installed voices on your system and says “<b>Hello</b>, <i>World</i>!”</p>

<pre class="code"><span style="color: blue">#r </span><span style="color: maroon">&quot;System.Speech.dll&quot;

</span><span style="color: blue">open </span>System
<span style="color: blue">open </span>System.Speech.Synthesis

<span style="color: green">// Say &quot;Hello, World!&quot;
</span><span style="color: blue">let </span>prompt = <span style="color: blue">new </span>PromptBuilder()
prompt.StartParagraph() 
prompt.AppendText(<span style="color: maroon">&quot;Hello&quot;</span>, PromptEmphasis.Strong)
prompt.AppendText(<span style="color: maroon">&quot;World&quot;</span>, PromptEmphasis.Reduced)
prompt.EndParagraph()

<span style="color: green">// List installed voices
</span><span style="color: blue">let </span>synthesizer = <span style="color: blue">new </span>SpeechSynthesizer()
<span style="color: blue">let </span>installedVoices = synthesizer.GetInstalledVoices()
<span style="color: blue">for </span>installedVoice <span style="color: blue">in </span>installedVoices <span style="color: blue">do
    </span>printfn 
        <span style="color: maroon">&quot;Enabled:%b, Name:%s, Age:%A, Description:%s&quot; 
        </span>installedVoice.Enabled 
        installedVoice.VoiceInfo.Name 
        installedVoice.VoiceInfo.Age 
        installedVoice.VoiceInfo.Description

synthesizer.Speak(prompt)</pre>
<a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></a>

<p>Speech recognition is even easier. Once you instantiate the recognizer object, simply add an event handler to the ‘SpeechRecognized’ event. For more information about the inner workings of the System.Speech namespace, check out the documentation on <a href="https://www.microsoft.com/speech/default.aspx" mce_href="https://www.microsoft.com/speech/default.aspx">MSDN</a>. </p>

<pre class="code"><span style="color: blue">#r </span><span style="color: maroon">&quot;System.Speech.dll&quot;

</span><span style="color: blue">open </span>System
<span style="color: blue">open </span>System.Speech.Recognition

<span style="color: blue">let </span>sp = <span style="color: blue">new </span>SpeechRecognitionEngine()
<span style="color: blue">let </span>defaultDictationGrammar = <span style="color: blue">new </span>DictationGrammar()

defaultDictationGrammar.Name &lt;- <span style="color: maroon">&quot;Default Dictation&quot;
</span>defaultDictationGrammar.Enabled &lt;- <span style="color: blue">true

</span>sp.LoadGrammar(defaultDictationGrammar)
sp.SetInputToDefaultAudioDevice()

sp.RecognizeAsync(RecognizeMode.Multiple)

<span style="color: green">//sp.SpeechHypothesized.Add(fun args -&gt; printfn &quot;Hypothesized [%f] '%s'&quot; args.Result.Confidence args.Result.Text)
</span>sp.SpeechRecognized.Add(<span style="color: blue">fun </span>args <span style="color: blue">-&gt; </span>printfn <span style="color: maroon">&quot;Recognized [%f] '%s'&quot; </span>args.Result.Confidence args.Result.Text)</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>With a mastery of speech and sound, we can now upgrade our missile launcher software to be controlled via voice activation. The following snippet shows F#’s first-class events in action. Rather than interacting with the System.Speech APIs directly, the getRecognizer function returns an event object, to which you can add event handlers later. The result is a pretty clean implementation IMHO.</p>

<pre class="code"><span style="color: green">// Returns an event handler which fires when spoken text is
// recognized
</span><span style="color: blue">let </span>getWordRecognizer() =
    <span style="color: blue">let </span>sp = <span style="color: blue">new </span>SpeechRecognitionEngine()
    <span style="color: blue">let </span>defaultDictationGrammar = <span style="color: blue">new </span>DictationGrammar()

    defaultDictationGrammar.Name &lt;- <span style="color: maroon">&quot;Default Dictation&quot;
    </span>defaultDictationGrammar.Enabled &lt;- <span style="color: blue">true

    </span>sp.LoadGrammar(defaultDictationGrammar)
    sp.SetInputToDefaultAudioDevice()

    sp.RecognizeAsync(RecognizeMode.Multiple)

    <span style="color: green">// Return an instance of an event which fires when words are recognized.
    // Callers can then subscribe to that event.
    </span>sp.SpeechRecognized
    |&gt; Event.map(<span style="color: blue">fun </span>args <span style="color: blue">-&gt; </span>args.Result.Text.ToLower())</pre>
<a href="https://11011.net/software/vspaste"></a>

<p><span style="color: blue"><font color="#000000">With the speech recognized event, all we need to do is write two event handlers. One to simply interact with the rocket and another to listen for when the user wants to exit the program.</font></span></p>

<pre class="code"><span style="color: blue">let </span>recognizerEvent = getWordRecognizer()

<span style="color: green">// Main handler - convert spoken text into RL commands
</span><span style="color: blue">let </span>handleWord spokenText =
    printfn <span style="color: maroon">&quot;Recognized Word: %s&quot; </span>spokenText
    <span style="color: blue">let </span>action = 
        <span style="color: blue">match </span>spokenText <span style="color: blue">with
        </span>| <span style="color: maroon">&quot;up&quot;  </span><span style="color: green">// Has a hard time recognizing this :(
        </span>| <span style="color: maroon">&quot;north&quot; </span><span style="color: blue">-&gt; </span>MoveUp(<span style="color: brown">20</span>)
        | <span style="color: maroon">&quot;down&quot;  </span><span style="color: blue">-&gt; </span>MoveDown(<span style="color: brown">20</span>)
        | <span style="color: maroon">&quot;left&quot;  </span><span style="color: blue">-&gt; </span>MoveLeft(<span style="color: brown">20</span>)
        | <span style="color: maroon">&quot;right&quot; </span><span style="color: blue">-&gt; </span>MoveRight(<span style="color: brown">20</span>)

        | <span style="color: maroon">&quot;fire&quot;  </span><span style="color: blue">-&gt; </span>Fire

        | _ <span style="color: blue">-&gt; </span>NoOp
        
    performAction rocketLauncher action |&gt; ignore

<span style="color: green">// Exit handler - specifically look for exit/quit
</span><span style="color: blue">let </span>terminateLoop = ref <span style="color: blue">false
let </span>terminateLoopHandler = <span style="color: blue">function </span>| <span style="color: maroon">&quot;exit&quot; 
                                    </span>| <span style="color: maroon">&quot;quit&quot; </span><span style="color: blue">-&gt; </span>terminateLoop := <span style="color: blue">true
                                    </span>| _      <span style="color: blue">-&gt; </span>()

<span style="color: green">// Hook up event handlers
</span>recognizerEvent.Add(handleWord)
recognizerEvent.Add(terminateLoopHandler)

<span style="color: blue">while </span>terminateLoop.Value = <span style="color: blue">false do
    </span>System.Threading.Thread.Yield() |&gt; ignore

()</pre>
<a href="https://11011.net/software/vspaste"></a>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide16.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide16.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide16.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide16" border="0" alt="Slide16" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide16_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide16_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide16_thumb.jpg" /></a></p>

<p>Of course, the biggest challenge isn’t actually controlling your rocket launcher, but determining what to shoot.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide17.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide17.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide17.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide17" border="0" alt="Slide17" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide17_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide17_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide17_thumb.jpg" /></a></p>

<p>Next we’ll try to add in some computer vision to identify faces. This is where things get serious, computer vision truly is the rocket science of software. Think about it, I give you an image, which is a matrix of pixels, which are a tuple of color intensities, which are just values, and you tell me if there is a ‘face’ somewhere in that sea of numbers? The sheer idea is ludicrous, but somehow people much smarter than me have figured out how to do it.</p>

<p>Currently the best computer vision library is <a href="https://opencv.willowgarage.com/wiki/" mce_href="https://opencv.willowgarage.com/wiki/">Open CV</a>, which continues to evolve with active research. If you are interested in learning more, check out:</p>

<p><a href="https://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134" mce_href="https://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134"><img alt="Book cover of Learning OpenCV" src="https://covers.oreilly.com/images/9780596516130/cat.gif" mce_src="https://covers.oreilly.com/images/9780596516130/cat.gif" /></a></p>

<p>Learning OpenCV, O’Reilly </p>

<p>However, OpenCV is written in C/C++ and we all know that true evil geniuses use .NET. While you <i>could</i> just write a million P/Invoke calls and use the OpenCV library as-is, fortunately the <a href="https://www.emgu.com/wiki/index.php/Main_Page" mce_href="https://www.emgu.com/wiki/index.php/Main_Page">Egmu CV</a> is a .NET wrapper on top of OpenCV.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide18.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide18.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide18.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide18" border="0" alt="Slide18" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide18_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide18_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide18_thumb.jpg" /></a></p>

<p>&#160;</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide19.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide19.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide19.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide19" border="0" alt="Slide19" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide19_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide19_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide19_thumb.jpg" /></a></p>

<p>For the purposes of this blog post I’ll avoid the specifics of how face detection works in OpenCV. In general, OpenCV uses a technique developed by Paul Viola and Michael Jones to quickly identify ‘features’ of an image. If a region shares many ‘features’ of a human face, then a face is detected. However, the Viola-Jones method can be used for detecting more than just faces. You can actually train the computer to identify any custom ‘features’ as long as you have an ample set of example images.</p>

<p>For more information check out the following resources:</p>

<p><a href="https://www.cognotics.com/opencv/servo_2007_series/index.html" mce_href="https://www.cognotics.com/opencv/servo_2007_series/index.html">https://www.cognotics.com/opencv/servo_2007_series/index.html</a></p>

<p><a href="https://www.cognotics.com/opencv/servo_2007_series/part_2/sidebar.html" mce_href="https://www.cognotics.com/opencv/servo_2007_series/part_2/sidebar.html">https://www.cognotics.com/opencv/servo_2007_series/part_2/sidebar.html</a></p>

<p><a href="https://en.wikipedia.org/wiki/Viola-Jones_object_detection_framework" mce_href="https://en.wikipedia.org/wiki/Viola-Jones_object_detection_framework">https://en.wikipedia.org/wiki/Viola-Jones_object_detection_framework</a></p>

<p>Now let’s get back to sewing evil!</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide20.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide20.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide20.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide20" border="0" alt="Slide20" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide20_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide20_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide20_thumb.jpg" /></a></p>

<p>To get setup detecting faces you’ll need to install OpenCV, EmguCV, and optionally get a webcam. For a cheap and viable option, try:</p>

<p><a href="https://www.amazon.com/Microsoft-64L-00003-LifeCam-VX-1000/dp/B000GE9XQ2" mce_href="https://www.amazon.com/Microsoft-64L-00003-LifeCam-VX-1000/dp/B000GE9XQ2">Microsoft LifeCam VX-1000</a></p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide21.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide21.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide21.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide21" border="0" alt="Slide21" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide21_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide21_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide21_thumb.jpg" /></a></p>

<p>Using OpenCV to detect faces is very straightforward. The following code opens up a HaarCascade (or set of features to identify a specific thing in an image) and puts a square around the provided image file.</p>

<pre class="code"><span style="color: blue">let </span>detectFaces (filePath : string) =

    <span style="color: green">// Load the image file
    </span><span style="color: blue">let </span>img = <span style="color: blue">new </span>Image&lt;Bgr, byte&gt;(filePath)
    
    <span style="color: green">// Resize to something resonable
    </span><span style="color: blue">let </span>img = img.Resize(float <span style="color: brown">300 </span>/ float img.Width, CvEnum.INTER.CV_INTER_CUBIC)
    
    <span style="color: green">// Load the object detector
    </span><span style="color: blue">let </span>haarCascades = <span style="color: maroon">@&quot;C:\OpenCV2.0\data\haarcascades\&quot;
    </span><span style="color: blue">let </span>objectToDetect = <span style="color: blue">new </span>HaarCascade(haarCascades + <span style="color: maroon">&quot;haarcascade_frontalface_default.xml&quot;</span>)
    
    <span style="color: green">// Convert to grayscale
    </span><span style="color: blue">let </span>imgGray : Image&lt;Bgr, byte&gt; = img.Convert()
    
    <span style="color: blue">let </span>faces : MCvAvgComp[] = imgGray.DetectHaarCascade(objectToDetect).[<span style="color: brown">0</span>]
    <span style="color: blue">for </span>face <span style="color: blue">in </span>faces <span style="color: blue">do
        </span>img.Draw(face.rect, <span style="color: blue">new </span>Bgr(Color.White), <span style="color: brown">1</span>)
        
    <span style="color: green">// Display the image
    </span><span style="color: blue">let </span>viewer = <span style="color: blue">new </span>ImageViewer()
    viewer.Image &lt;- img
    viewer.Show() |&gt; ignore</pre>
<a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></a>

<p>OpenCV comes with a slew of these HaarCascades for detecting faces from different angles. I' wrote a simple WinForms application where you can open all the images in a directory and see what the HaarCascades identify. </p>

<p>The results are hit and miss, but overall I’m very impressed with the results. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/image_4.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/image_4.png" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/image_4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/image_thumb_1.png" width="609" height="355" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/image_thumb_1.png" /></a> </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide22.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide22.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide22.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide22" border="0" alt="Slide22" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide22_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide22_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide22_thumb.jpg" /></a> </p>

<p>While automating USB missile launchers and striking terror into the heart of men is fun, there are other worthwhile uses of these libraries. Using the System.Speech APIs you can write software to go hands free. For example, have a program <a href="https://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!1612.entry" mce_href="https://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!1612.entry">dictate new F# questions on StackOverflow as they are posted</a>. Or, training OpenCV to detect image features in real-time, such as defects in industrial manufacturing. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide23.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide23.jpg" mce_href="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide23.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Slide23" border="0" alt="Slide23" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide23_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide23_thumb.jpg" width="244" height="184" mce_src="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/BeinganEvilGeniuswithFand.NET_7E6A/Slide23_thumb.jpg" /></a> </p>

<p>If you are interested in learning more about F#, you should consider <a href="https://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643" mce_href="https://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643">buying my book</a>. Have fun conquering!</p>

<p><b>Disclaimer #1</b></p>

<blockquote>
  <p>All code samples are provided &quot;AS IS&quot; without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose. So in other words, if the attached source files cause you any grief, up to and including destroying your USB rocket launcher, you can’t blame me or Microsoft. </p>
</blockquote>

<p><b>Disclaimer #2</b></p>

<blockquote>
  <p>Theme of evil genius-ery aside, consider the following. If you have above average programming skills, such as knowledge of reverse engineering debuggers or decompilers, then just like Spiderman you have amazing powers. Please consider the <a href="https://www.wow.com/2008/07/15/blizzard-wins-lawsuit-against-bot-makers/" mce_href="https://www.wow.com/2008/07/15/blizzard-wins-lawsuit-against-bot-makers/">legal</a> and <a href="https://league.totalgamingnetwork.com/players/banned" mce_href="https://league.totalgamingnetwork.com/players/banned">ethical</a> ramifications of your actions. Pedram Amini showing how to reverse engineer a USB rocket launcher is innocent enough. But you can apply the same techniques to cause real evil in the world. (For example <a href="https://www.businessinsider.com/did-the-chinese-government-hack-google-2010-1" mce_href="https://www.businessinsider.com/did-the-chinese-government-hack-google-2010-1">spying on ordinary citizens</a>.)&#160; </p>

  <p>The point is, like Uncle Ben said, “with great power comes great responsibility.” This applies to super heroes and evil geniuses alike.</p></blockquote>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/09/95/27/79/RocketLauncher_v1.0.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-95-27-79/RocketLauncher_5F00_v1.0.zip">RocketLauncher_v1.0.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>The Halting Problem and the Church-Turing Thesis</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/the-halting-problem-and-the-church-turing-thesis</link>
      <pubDate>Mon, 30 Nov 2009 20:13:50 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2009/11/30/the-halting-problem-and-the-church-turing-thesis/</guid>
      <description><![CDATA[Two weeks ago at PDC Dustin “former blogger” Campbell and I sat down with Keith and Woody to record...]]></description>
      <content:encoded><![CDATA[<p>Two weeks ago at <a href="https://microsoftpdc.com/Sessions">PDC</a> <a href="https://diditwith.net/">Dustin “former blogger” Campbell</a> and I sat down with <a href="https://keithelder.net/blog/">Keith</a> and <a href="https://cloudsocket.com/graffiti/blog/">Woody</a> to record an episode of <a href="https://deepfriedbytes.com/">Deep Fried Bytes</a>. The show hasn’t been posted yet, but I’m sure it will turn out great. <p><img src="https://deepfriedbytes.com/files/media/image/WindowsLiveWriter/Media_8AE9/image_12.png"> <p>We talked about all sorts of things, from me shamelessly promoting <a href="https://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643">my book</a> to <a href="https://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx">Silverlight 4.0</a> to the new <a href="https://msdn.microsoft.com/en-us/library/dd264915(VS.100).aspx">IntelliTrace</a> feature of <a href="https://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx">Visual Studio 2010</a>. If you haven’t already heard about it, IntelliTrace is pretty kickass. Essentially it allows you to step <em>backwards in time </em>while debugging. Read <a href="https://blogs.msdn.com/ianhu/">this</a> for more info. <p>Anyways, while we were talking about historical debugging I believe it was Keith who asked if IntelliTrace could detect if a program was in an infinite loop. Being the true <a href="https://www.mcplusplus.com/">Computer Science gangsta</a> that I am, I took the opportunity to name drop <strong>BOTH</strong> the Halting Problem <strong>AND</strong> the Church-Turning Thesis. (Hell yeah!) <p>So this blog post is about explaining both of these somewhat pedantic but fundamentally important concepts. <h3>The Problem</h3> <p>I give you a program and you tell me through any form of analysis if that program will terminate or not. That sounds simple enough, I mean it’s the year 2009 for crying out loud. We might not have flying cars but we do have <a href="https://en.wikipedia.org/wiki/Algorithmic_trading">automated stock trading</a> and <a href="https://www.virginamerica.com/va/press/2009/Oct/Virgin_America_Teams_Up_With_Google_To_Offer_Free_In_Flight%20_WiFi_for_the_Holidays.html">WiFi on airplanes</a>. <p><font color="#ff0000"><strong>Spoiler alert</strong>:</font> it’s not possible. No matter how hard you try you cannot devise a general algorithm to determine if a program terminates or not. (Obviously you can determine if <i>some</i> programs terminate, but no <i>single</i> algorithm can determine if <i>any</i> program halts or not.) <p>However in order to prove this with rigor we need a more concrete notion of a program. (For example, are we talking about F# apps written on CLR 4.0 or a Perl script?) Fortunately, this guy already came up with a good theoretical notion of a algorithm and/or program. Enter the <a href="https://en.wikipedia.org/wiki/Turing_machine">Turing machine</a>. <p><img src="https://www.sdtimes.com/blog/post/2009/image.axd?picture=2009%2f9%2f1954_turing_large.jpg" width="197" height="247"> <p>In 1936 a British mathematician named <a href="https://en.wikipedia.org/wiki/Alan_Turing">Alan Turing</a> proposed a theoretical model of computation called a Turing machine. (Note that I didn’t say <em>computer</em> because those things hadn’t been invented yet. The first electronic computer came along a decade later in <a href="https://en.wikipedia.org/wiki/ENIAC">1946</a>.) Generally speaking, a Turing machine is a finite state machine operating over an infinite tape of input. At each step the machine reads a character from the tape, and then based on its current state and the character read, transitions to a new state, advances the tape one position left or right, and possibly write a character back to the tape.&nbsp; Eventually the Turing machine will wind up in a special state designated as either an <em>accept state</em> or <em>reject state</em>. <p>You use a Turing Machine to compute the answer to a Boolean problem (aka a <a href="https://en.wikipedia.org/wiki/Decision_problem">decision problem</a>). For example, given input “RACECAR”, answer whether or not it is a palindrome. The Turing Machine is obviously a far cry from the CLR, but in 1936 Turing machines were the <a href="https://www.phrases.org.uk/meanings/the-bees-knees.html">bee’s knees</a>. <p>Anyways, the specifics of how Turing machines work aren’t that important. Primarily they serve as a way describe the implementation of any algorithms in a mathematical context. We can use the Turning machine as the backdrop for proving whether or not any arbitrary program will terminate. This is known as the <a href="https://mathworld.wolfram.com/HaltingProblem.html">Halting Problem</a>. <h3>The Halting Problem</h3> <p>The halting problem is defined as: given a program (Turing machine) and its input (initial tape state), determine if the program will terminate (eventually land on an accept or reject state.)&nbsp; In other words, if you have a program that takes another program as an input return true if that program halts, otherwise return false. <p>This seems pretty obvious when you see programs like:<pre class="code"><span style="color: blue">open </span>System

<span style="color: blue">while true do
    </span>Console.WriteLine(<span style="color: maroon">"Not done yet..."</span>)</pre><a href="https://11011.net/software/vspaste"></a><pre></pre>
<p>But what about <em>any</em> program? Turing proved that this is <a href="https://en.wikipedia.org/wiki/Undecidable_problem">undecidable</a> which means that it is impossible to construct an algorithm that will produce a correct answer every time. A sketch of the proof can be found <a href="https://www.juniata.edu/faculty/rhodes/intro/theory2.htm">here</a>, but it goes something like this:
<p>1. Suppose by way of contradiction that you have a function H(p, i) that for a program p and input i returns true if the program halts and false if the program goes into an infinite loop. (That is, H is a solution to the halting problem.) Note that H always terminates.
<p>2. Now consider another function K(p) that is the somewhat of an inverse of H. K takes a Turing machine as input and calls H to check if K’s input halts or not. If K’s input halts, then K goes into an infinite loop. If K’s input does not halt then K returns true. (Note that we are taking K’s argument and converting into a valid input to H since a Turing machine can be encoded as the input into the same Turing machine.)</p><pre class="code"><span style="color: green">// H, determines if a program halts
</span><span style="color: blue">let </span>H (p : TuringMachine, i : TuringMachineInput) =
    <span style="color: blue">if </span>p.TerminatesWithInput(i) <span style="color: blue">then
        true
    else
        false
    
</span><span style="color: green">// K, designed to screw with H
</span><span style="color: blue">let </span>K (p : TuringMachine) =
    <span style="color: green">// If the input program/input DOES NOT halt...
    </span><span style="color: blue">if </span>H(p, p.ToString()) = <span style="color: blue">false then
        </span><span style="color: green">// return true
        </span><span style="color: blue">true
    else
        </span><span style="color: green">// Otherwise, go into an infinite loop
        </span><span style="color: blue">while true do 
            </span>()</pre><a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste"></a><pre></pre>
<p>Here’s where it gets crazy. What happens if we run program H with the program K and program input K? <pre class="code"><span style="color: blue">match </span>H(K, K.ToString()) <span style="color: blue">with
</span>| <span style="color: blue">true  -&gt; </span>printfn <span style="color: maroon">"K with itself as input terminates"
</span>| <span style="color: blue">false -&gt; </span>printfn <span style="color: maroon">"K with itself as input does not terminate"</span></pre><a href="https://11011.net/software/vspaste"></a>
<blockquote>
<p>Case 1.) H returns true. Thus, K terminates. However, inside of K it calls H(K, K.ToString()) which if that returned true would have caused an infinite loop – meaning K doesn’t terminate. A contradiction.
<p>Case 2.) H returns false. Thus, K does not terminate. By definition however, K only went into an infinite loop if H(K, K) returned true. (Meaning that by definition of H, K terminates.) Therefore, we arrive at another contradiction.</p></blockquote>
<p>Since we have found a situation where function H cannot return either true or false, we can conclude that no such program H exists. You can read the original paper <em>On computable numbers, with an application to the Entscheidungs problem</em> <a href="https://www.turingarchive.org/browse.php/B/12">here</a> but the main takeaway is that “no Turing machine can determine if an arbitrary Turing machine will halt or not”.
<p>While speaking in terms of Turing machines is great, but how does this relate to <em>real</em> programs? It’s highly unlikely that you are coding in<strong> Microsoft Visual Turing Machine .NET™</strong>. In order to apply our solution to the Halting Problem more broadly we need a way to compare different forms of computation. (In other words prove that Perl code is equivalent to Visual Basic .NET given enough if-statements and days spent in front of a debugger.)
<h3>Church-Turing Thesis</h3>
<p>Back in the mid 30’s the Turing machine wasn’t the only game in town. <a href="https://en.wikipedia.org/wiki/Alonzo_Church">Alonzo Church</a> had also come up with a theoretical notion of computation known as the <a href="https://en.wikipedia.org/wiki/Lambda_calculus">lambda calculus</a>. (Which serves as the theoretical underpinning of functional programming languages, like F#.)
<p><img alt="Alonzo Church, 1903-1995" src="https://diglib.princeton.edu/ead/bioghist-images/C0948.jpg" width="200" height="267">
<p>While Turing Machines were described in terms of states, transitions, and an infinite tape of values, the lambda calculus was really just a way of encoding mathematical functions.
<p>Anyways, the <a href="https://mathworld.wolfram.com/Church-TuringThesis.html">Church-Turing Thesis</a> postulated that Turing machines and the lambda calculus could compute the same things. In other words, any program you can write with a Turing machine could also be written with the lambda calculus. Any notion of computation which can convert any of its programs into a Turing machine is known as being <a href="https://en.wikipedia.org/wiki/Turing_completeness">Turing complete</a>. While I can’t cite any proofs off hand, it’s generally assumed that modern languages like F# or <i>&lt;your favorite language here&gt;</i> are Turing complete. (No matter how simple the language, if it supports recursion, while loops, and integers then it’s probably Turing complete.)
<p>While you can try to write some amazing library for detecting infinite loops, I can write the same code using a Turing machine. And, since it has been proving that no Turing machine can solve the Halting Problem, neither can your amazing library.
<h3><strong>Summary</strong></h3>
<p>This blog post covers a lot of ground, but the bottom line is as follows:
<ul>
<li>Turing machines are a theoretical notion of computation
<li>The Halting Problem asks if an arbitrary Turing machine will terminate or not
<li>The Halting Problem is undecideable
<li>The Church-Turing Thesis states that sufficiently advanced computational systems are all equivalent*
<li>Therefore, it is undecideable if an arbitrary program in your favorite language halts or not</li></ul>
<p>*Most people think that Turing machines (and equivalent forms of computation) offer all the computational power possible. Meaning no matter how fancy the computational scheme, you can do the same thing with a Turing machine. However, it is possible that quantum computers offer more computational power than Turing machines and thus could possibly solve the Halting problem. 
<p>Hopefully this blog post was general enough to be approach able but detailed enough to keep the <a href="https://www.merriam-webster.com/dictionary/pedant">pedants</a> at bay. If you are interested in theoretical Computer Science you should buy <a href="https://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643">Programming F#</a>. The book has absolutely nothing to do with any of this stuff, but if there were a program that could solve the Halting Problem I’m sure it would be written in F# ;)
]]></content:encoded>
    </item>
    <item>
      <title>Source Code for Programming F#</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/source-code-for-programming-f</link>
      <pubDate>Mon, 23 Nov 2009 18:09:00 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2009/11/23/source-code-for-programming-f/</guid>
      <description><![CDATA[I've gotten a few requests recently for the source code of the examples in Programming F#. I've...]]></description>
      <content:encoded><![CDATA[<P>I've gotten a few requests recently for the source code of the examples in <A title="Programming F#" href="https://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643" mce_href="https://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643">Programming F#</A>. I've attached them as a series of <A title="F# Script" href="https://blogs.msdn.com/chrsmith/archive/2008/09/12/scripting-in-f.aspx" mce_href="https://blogs.msdn.com/chrsmith/archive/2008/09/12/scripting-in-f.aspx">F# Script</A>&nbsp;files. In the ZIP file you'll find a few gems such as:</P>
<UL>
<LI>A 'state' computation expression</LI>
<LI>Examples of F# Asynchronous Workflows and the Parallel Extensions to .NET</LI>
<LI>References for writing OO code in F#, including advanced stuff like Delegates and Events</LI>
<LI>Code for F# interop such as P/Invoke signatures</LI></UL>
<P>And as always, any code released on this blog it comes with the standard disclaimer:</P>
<BLOCKQUOTE>
<P>All code samples are provided "AS IS" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose. So in other words, if the attached source files cause you any grief whatsoever you can’t blame me, O'Reilly Media,&nbsp;or Microsoft.</P></BLOCKQUOTE>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/09/92/76/78/ProgrammingFSharpCode.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-92-76-78/ProgrammingFSharpCode.zip">ProgrammingFSharpCode.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>F# Language Details (Gotchas)</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/f-language-details-gotchas</link>
      <pubDate>Mon, 09 Nov 2009 19:52:01 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2009/11/09/f-language-details-gotchas/</guid>
      <description><![CDATA[The ‘F’ in F# stands for fun. However, there are some details in F# that might lead to bugs,...]]></description>
      <content:encoded><![CDATA[<p>The ‘F’ in F# stands for <em>fun</em>. However, there are some details in F# that might lead to bugs, surprises, and/or un-fun. This post is to highlight a couple of random ‘gotchas’ when exploring some corners of the F# language.</p>  <p><img alt="Unicorn Image #13260" src="https://www.cornify.com/cornified/image_1257619523542.jpg" width="428" height="159" /></p>  <p>&#160;</p>  <h3>Overriding Equals and Not Equals</h3>  <p>F# allows you to overload operators so you can better map mathematical concepts to your code. For example, consider this simple vector type. Notice how it overrides the Equals operator to compare just the vector’s magnitudes, not their actual values. </p>  <pre class="code"><span style="color: blue">type </span>Vector =
    | Vector <span style="color: blue">of </span>float * float * float

    <span style="color: blue">member </span>this.Length =
        <span style="color: green">// Extract values via ninja pattern match
        // hidden in a let binding
        </span><span style="color: blue">let </span>(Vector(x,y,z)) = this
        sqrt &lt;| x * x + y * y + z * z

    <span style="color: blue">static member </span>(+) (lhs, rhs) =
        <span style="color: blue">let </span>(Vector(x1,y1,z1)) = lhs
        <span style="color: blue">let </span>(Vector(x2,y2,z2)) = rhs

        Vector(x1 + x2, y1 + y2, z1 + z2)
        
    <span style="color: green">// Equals
    </span><span style="color: blue">static member </span>(==) (lhs : Vector, rhs : Vector) =
        lhs.Length = rhs.Length

    <span style="color: green">// Not equals
    </span><span style="color: blue">static member </span>(!=) (lhs : Vector, rhs) =
        not (lhs == rhs)</pre>
<a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste"></a>

<p>When you run this code in FSI, it doesn’t work.</p>

<pre class="code">&gt; // Bug?
let vec1 = Vector(10.0, 0.0, 0.0)
let vec2 = Vector(0.0, 0.0, 10.0);;

val vec1 : Vector = Vector (10.0,0.0,0.0)
val vec2 : Vector = Vector (0.0,0.0,10.0)

&gt; vec1 = vec2;;
val it : bool = false
&gt; vec1.Length = vec2.Length;;
val it : bool = true</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>The key here is to understanding a bit more about how operator overloading in F# and .NET works. When you override an operator such as (+) the compiler generates a method named op_Addition. So when a .NET compiler sees “x + y” it looks for a method with that name. Similarly it loops for op_Subtraction, op_BitwiseOr, etc.</p>

<p>Since F# allows you to define symbolic operators (functions with symbols for names) you can overload operators that aren’t valid in C# or VB.NET, for example (==&gt;):</p>

<pre class="code"><span style="color: green">// Rotate the vector about the X axis
</span><span style="color: blue">static member </span>(==&gt;) (vec : Vector, rads : float) =
    <span style="color: blue">let </span>(Vector(x,y,z)) = vec
    
    <span style="color: blue">let </span>x' = x * cos rads - y * sin rads
    <span style="color: blue">let </span>y' = x * sin rads + y * cos rads
    <span style="color: blue">let </span>z' = z

    Vector(x', y', z)</pre>
<a href="https://11011.net/software/vspaste"></a>

<pre class="code">&gt; let v = Vector(10.0, 0.0, 0.0);;

val v : Vector = Vector (10.0,0.0,0.0)

&gt; v ==&gt; System.Math.PI;;
val it : Vector = Vector (-10.0,0.0,0.0)</pre>

<pre class="code">&gt; v ==&gt; (System.Math.PI / 2.0);;
val it : Vector = Vector (0.0,10.0,0.0)</pre>
<a href="https://11011.net/software/vspaste"></a><a href="https://11011.net/software/vspaste"></a>

<p>While F# recognizes these symbolic operators, to call them from C# you need to use the ‘long name’ which in the previous example would be op_EqualsEqualsGreater.</p>

<p>To override the equals operator in C# requires that you define (==), which in turn generate a method called op_Equality. However, defining (==) in F# generates a method called op_EqualsEquals.</p>

<p>To properly overload the equals and not equals operators in F# you must use the F# operators for equality (=) and (&lt;&gt;).</p>

<pre class="code"><span style="color: green">// Equals
</span><span style="color: blue">static member </span>(=) (lhs, rhs) =
    lhs.Length = rhs.Length

<span style="color: green">// Not equals
</span><span style="color: blue">static member </span>(&lt;&gt;) (lhs : Vector, rhs) =
    not (lhs == rhs)</pre>

<h3>Improper use of Range Expressions</h3>

<p>Consider the following two loops:</p>

<pre class="code"><span style="color: blue">for </span>i <span style="color: blue">in </span>[<span style="color: brown">1 </span>.. <span style="color: brown">10000000</span>] <span style="color: blue">do
    ...</span>

<span style="color: blue">for </span>i <span style="color: blue">in </span><span style="color: brown">1 </span>.. <span style="color: brown">10000000 </span><span style="color: blue">do
    ...</span></pre>

<p><a href="https://11011.net/software/vspaste"></a>They may not look that different, but they have dramatically different performance profiles. You can find these differences detailed in the recently updated <a href="https://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html">F# Language Specification</a>. Both are examples of <a href="https://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc245030821">range expression</a>, which is a way to create a sequence between to indexes. However, the subtlety here is that the first generates a full list, while the second is just the raw sequence.</p>

<p>So while one requires ten million memory allocations to generate the list, the second loop doesn’t. More importantly, the compiler can optimize the second loop into a standard for loop over a single integer. (And not need to do any memory allocation at all!)</p>]]></content:encoded>
    </item>
    <item>
      <title>Awesome F# - Decision Trees – Part II</title>
      <link>https://docs.microsoft.com/archive/blogs/chrsmith/awesome-f-decision-trees-part-ii</link>
      <pubDate>Mon, 02 Nov 2009 18:56:00 GMT</pubDate>
      <dc:creator><![CDATA[ChrSmith]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chrsmith/2009/11/02/awesome-f-decision-trees-part-ii/</guid>
      <description><![CDATA[In my previous post I went over the theory behind the ID3 algorithm. Now that we got all that...]]></description>
      <content:encoded><![CDATA[<p>In my <a href="https://blogs.msdn.com/chrsmith/">previous post</a> I went over the theory behind the <a href="https://en.wikipedia.org/wiki/ID3_algorithm">ID3 algorithm</a>. Now that we got all that painful math out of the way, let’s write some code! Here is an implementation of the algorithm in F#. (It is also attached to this blog post, download it via the link at the bottom.) </p>  <pre class="code"><span style="color: blue">open </span>System

<span style="color: blue">type </span>Record = 
    {
        Outlook     : string
        Temperature : string
        Humidity    : string
        Wind        : string
        PlayTennis  : bool 
    }

    <span style="color: green">/// Given an attribute name return its value
    </span><span style="color: blue">member </span>this.GetAttributeValue(attrName) =
        <span style="color: blue">match </span>attrName <span style="color: blue">with
        </span>| <span style="color: maroon">&quot;Outlook&quot;     </span><span style="color: blue">-&gt; </span>this.Outlook
        | <span style="color: maroon">&quot;Temperature&quot; </span><span style="color: blue">-&gt; </span>this.Temperature
        | <span style="color: maroon">&quot;Humidity&quot;    </span><span style="color: blue">-&gt; </span>this.Humidity
        | <span style="color: maroon">&quot;Wind&quot;        </span><span style="color: blue">-&gt; </span>this.Wind
        | _ <span style="color: blue">-&gt; </span>failwithf <span style="color: maroon">&quot;Invalid attribute name '%s'&quot; </span>attrName

    <span style="color: green">/// Make the %o format specifier look all pretty like
    </span><span style="color: blue">override </span>this.ToString() =
        sprintf
            <span style="color: maroon">&quot;{Outlook = %s, Temp = %s, Humidity = %s, Wind = %s, PlayTennis = %b}&quot; 
            </span>this.Outlook
            this.Temperature 
            this.Humidity
            this.Wind
            this.PlayTennis

<span style="color: blue">type </span>DecisionTreeNode =
    <span style="color: green">// Attribute name and value / child node list    
    </span>| DecisionNode <span style="color: blue">of </span>string * (string * DecisionTreeNode) seq
    <span style="color: green">// Decision and corresponding evidence
    </span>| Leaf         <span style="color: blue">of </span>bool * Record seq

<span style="color: green">// ----------------------------------------------------------------------------

/// Return the total true, total false, and total count for a set of Records
</span><span style="color: blue">let </span>countClassifications data = 
    Seq.fold 
        (<span style="color: blue">fun </span>(t,f,c) item <span style="color: blue">-&gt; 
            match </span>item.PlayTennis <span style="color: blue">with
            </span>| <span style="color: blue">true  -&gt; </span>(t + <span style="color: brown">1</span>, f, c + <span style="color: brown">1</span>)
            | <span style="color: blue">false -&gt; </span>(t, f + <span style="color: brown">1</span>, c + <span style="color: brown">1</span>))
        (<span style="color: brown">0</span>, <span style="color: brown">0</span>, <span style="color: brown">0</span>)
        data

<span style="color: green">// ----------------------------------------------------------------------------

/// Return the theoretical number of bits required to classify the information.
/// If a 50/50 mix, returns 1, if 100% true or false returns 0.
</span><span style="color: blue">let </span>entropy data = 
    <span style="color: blue">let </span>(trueValues, falseValues, totalCount) = countClassifications data        

    <span style="color: blue">let </span>probTrue  = (float trueValues)  / (float totalCount)
    <span style="color: blue">let </span>probFalse = (float falseValues) / (float totalCount)

    <span style="color: green">// Log2(1.0) = infinity, short circuiting this part
    </span><span style="color: blue">if </span>trueValues = totalCount || falseValues = totalCount <span style="color: blue">then
        </span><span style="color: brown">0.0
    </span><span style="color: blue">else
        </span>-probTrue * Math.Log(probTrue, <span style="color: brown">2.0</span>) + -probFalse * Math.Log(probFalse, <span style="color: brown">2.0</span>)

<span style="color: green">/// Given a set of data, how many bits do you save if you know the provided attribute.
</span><span style="color: blue">let </span>informationGain (data : Record seq) attr =
    
    <span style="color: green">// Partition the data into new sets based on each unique value of the given attribute
    // e.g. [ where Outlook = rainy ], [ where Outlook = overcast], [ ... ]
    </span><span style="color: blue">let </span>divisionsByAttribute = 
        data 
        |&gt; Seq.groupBy(<span style="color: blue">fun </span>item <span style="color: blue">-&gt; </span>item.GetAttributeValue(attr))

    <span style="color: blue">let </span>totalEntropy = entropy data
    <span style="color: blue">let </span>entropyBasedOnSplit =
        divisionsByAttribute
        |&gt; Seq.map(<span style="color: blue">fun </span>(attributeValue, rowsWithThatValue) <span style="color: blue">-&gt; 
                        let </span>ent = entropy rowsWithThatValue
                        <span style="color: blue">let </span>percentageOfTotalRows = (float &lt;| Seq.length rowsWithThatValue) / (float &lt;| Seq.length data)
                        -<span style="color: brown">1.0 </span>* percentageOfTotalRows * ent)
        |&gt; Seq.sum

    totalEntropy + entropyBasedOnSplit
    
<span style="color: green">// ----------------------------------------------------------------------------

/// Give a list of attributes left to branch on and training data,
/// construct a decision tree node.
</span><span style="color: blue">let rec </span>createTreeNode data attributesLeft =
    
    <span style="color: blue">let </span>(totalTrue, totalFalse, totalCount) = countClassifications data

    <span style="color: green">// If we have tested all attributes, then label this node with the 
    // most often occuring instance; likewise if everything has the same value.
    </span><span style="color: blue">if </span>List.length attributesLeft = <span style="color: brown">0 </span>|| totalTrue = <span style="color: brown">0 </span>|| totalFalse = <span style="color: brown">0 </span><span style="color: blue">then
        let </span>mostOftenOccuring = 
            <span style="color: blue">if </span>totalTrue &gt; totalFalse <span style="color: blue">then true
            else                           false
        </span>Leaf(mostOftenOccuring, data)
    
    <span style="color: green">// Otherwise, create a proper decision tree node and branch accordingly
    </span><span style="color: blue">else
        let </span>attributeWithMostInformationGain =
            attributesLeft 
            |&gt; List.map(<span style="color: blue">fun </span>attrName <span style="color: blue">-&gt; </span>attrName, (informationGain data attrName))
            |&gt; List.maxBy(<span style="color: blue">fun </span>(attrName, infoGain) <span style="color: blue">-&gt; </span>infoGain)
            |&gt; fst
        
        <span style="color: blue">let </span>remainingAttributes =
            attributesLeft |&gt; List.filter ((&lt;&gt;) attributeWithMostInformationGain)

        <span style="color: green">// Partition that data base on the attribute's values
        </span><span style="color: blue">let </span>partitionedData = 
            Seq.groupBy
                (<span style="color: blue">fun </span>(r : Record) <span style="color: blue">-&gt; </span>r.GetAttributeValue(attributeWithMostInformationGain))
                data

        <span style="color: green">// Create child nodes
        </span><span style="color: blue">let </span>childNodes =
            partitionedData
            |&gt; Seq.map (<span style="color: blue">fun </span>(attrValue, subData) <span style="color: blue">-&gt; </span>attrValue, (createTreeNode subData remainingAttributes))

        DecisionNode(attributeWithMostInformationGain, childNodes)</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>The entropy and informationGain functions were covered in my last post, so let’s walk through how the actual decision tree gets constructed. There’s a little work to calculating the optimal decision tree split, but with F# you can express it quite beautifully.</p>

<pre class="code"><span style="color: blue">let </span>attributeWithMostInformationGain =
    attributesLeft 
    |&gt; List.map(<span style="color: blue">fun </span>attrName <span style="color: blue">-&gt; </span>attrName, (informationGain data attrName))
    |&gt; List.maxBy(<span style="color: blue">fun </span>(attrName, infoGain) <span style="color: blue">-&gt; </span>infoGain)
    |&gt; fst</pre>

<p>First, it takes all the potential attributes left to split on…</p>

<pre class="code">attributesLeft </pre>
<a href="https://11011.net/software/vspaste"></a>

<p>… and then maps that attribute name to a new attribute name / information gain tuple …</p>

<pre class="code">|&gt; List.map(<span style="color: blue">fun </span>attrName <span style="color: blue">-&gt; </span>attrName, (informationGain data attrName))</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>… then from the newly generated list, pick out the tuple with the highest information gain …</p>

<pre class="code">|&gt; List.maxBy(<span style="color: blue">fun </span>(attrName, infoGain) <span style="color: blue">-&gt; </span>infoGain)</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>…finally returning the first element of that tuple, which is the attribute with the highest information gain.</p>

<pre class="code">|&gt; fst</pre>

<p>Once you can construct a decision tree in memory, how do get it out? The simplest way is to print it to the console.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_2.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_thumb.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_thumb.png" width="551" height="293" /></a> </p>

<p>The code is very straight forward. Note the use of ‘padding parameter’, so that recursive calls get indented more and more. This is a very helpful technique when printing tree-like data structures to the console.</p>

<pre class="code"><span style="color: green">/// Print the decision tree to the console
</span><span style="color: blue">let rec </span>printID3Result indent node =
    <span style="color: blue">let </span>padding = <span style="color: blue">new </span>System.String(<span style="color: maroon">' '</span>, indent)

    <span style="color: blue">match </span>node <span style="color: blue">with
    </span>| Leaf(classification, data) <span style="color: blue">-&gt;
        </span>printfn <span style="color: maroon">&quot;\tClassification = %b&quot; </span>classification
        <span style="color: green">// data |&gt; Seq.iter (fun item -&gt; printfn &quot;%s-&gt;%s&quot; padding &lt;| item.ToString())

    </span>| DecisionNode(attribute, childNodes) <span style="color: blue">-&gt;
        </span>printfn <span style="color: maroon">&quot;&quot; </span><span style="color: green">// Finish previous line
        </span>printfn <span style="color: maroon">&quot;%sBranching on attribute [%s]&quot; </span>padding attribute
        
        childNodes
        |&gt; Seq.iter (<span style="color: blue">fun </span>(attrValue, childNode) <span style="color: blue">-&gt;
                        </span>printf <span style="color: maroon">&quot;%s-&gt;With value [%s]...&quot; </span>padding attrValue
                        printID3Result (indent + <span style="color: brown">4</span>) childNode)</pre>
<a href="https://11011.net/software/vspaste"></a>

<p>However, it’s almost the year 2010. So in lieu of flying cars perhaps we can at least do better than printing data to the console. Ideally, we want to generate some sexy image like this:</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_4.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_thumb_1.png" width="403" height="295" /></a> </p>

<p>You <em>could </em>painstakingly construct the decision tree using <a href="https://office.microsoft.com/en-us/visio/FX100487861033.aspx">Microsoft Visio</a> but fortunately there are tools to do this for you. AT&amp;T Research has produced a great tool called <a href="https://www.graphviz.org/">GraphViz</a>. While the end result doesn’t quite have <em>sizzle</em>, it’s very easy enough to get going.</p>

<p>The following function dumps the decision tree into a format that GraphViz can plot. (Just copy the printed text into the tool and plot it using the default settings.)</p>

<pre class="code"><span style="color: green">/// Prints the tree in a format amenable to GraphViz
/// See https://www.graphviz.org/ for more format
</span><span style="color: blue">let </span>printInGraphVizFormat node =

    <span style="color: blue">let rec </span>printNode parentName name node = 
        <span style="color: blue">match </span>node <span style="color: blue">with
        </span>| DecisionNode(attribute, childNodes) <span style="color: blue">-&gt;

            </span><span style="color: green">// Print the decision node
            </span>printfn <span style="color: maroon">&quot;\&quot;%s\&quot; [ label = \&quot;%s\&quot; ];&quot; </span>(parentName + name) attribute

            <span style="color: green">// Print link from parent to this node (unless it's the root)
            </span><span style="color: blue">if </span>parentName &lt;&gt; <span style="color: maroon">&quot;&quot; </span><span style="color: blue">then
                </span>printfn <span style="color: maroon">&quot;\&quot;%s\&quot; -&gt; \&quot;%s\&quot; [ label = \&quot;%s\&quot; ];&quot; </span>parentName (parentName + name) name

            childNodes 
            |&gt; Seq.iter(<span style="color: blue">fun </span>(attrValue, childNode) <span style="color: blue">-&gt; 
                    </span>printNode (parentName + name) attrValue childNode)

        | Leaf(classification, _) <span style="color: blue">-&gt;
            let </span>label =
                <span style="color: blue">match </span>classification <span style="color: blue">with
                </span>| <span style="color: blue">true  -&gt; </span><span style="color: maroon">&quot;Yes&quot;
                </span>| <span style="color: blue">false -&gt; </span><span style="color: maroon">&quot;No&quot;
            
            </span><span style="color: green">// Print the decision node
            </span>printfn <span style="color: maroon">&quot;\&quot;%s\&quot; [ label = \&quot;%s\&quot; ];&quot; </span>(parentName + name) label

            <span style="color: green">// Print link from parent to this node
            </span>printfn <span style="color: maroon">&quot;\&quot;%s\&quot; -&gt; \&quot;%s\&quot; [ label = \&quot;%s\&quot; ];&quot; </span>parentName (parentName + name) name

    printfn <span style="color: maroon">&quot;digraph g {&quot;
    </span>printNode <span style="color: maroon">&quot;&quot; &quot;root&quot; </span>node
    printfn <span style="color: maroon">&quot;}&quot;</span></pre>

<p>So there you have it, ID3 in F#. With a little bit of mathematics and some clever output you can construct decision trees for all your machine learning needs. Think of the ID3 algorithm in the future the next time you want to mine customer transactions, analyze server logs, or program your killer robot to find Sarah Conner.</p>

<p>&lt;TotallyShamelessPlug&gt; If you would like to learn more about F#, check out <a href="https://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643">Programming F#</a> by O’Reilly. Available on <a href="https://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643">Amazon</a> and at other fine retailers. &lt;/TotallyShamelessPlug&gt;</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/09/91/65/36/ID3.fsx" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-91-65-36/ID3.fsx">ID3.fsx</a></p>]]></content:encoded>
    </item>
  </channel>
</rss>