Mark's profileMark Sheppard's SpaceBlogLists Tools Help

Blog


    January 23

    Sudoku Vs PowerShell

    I've been obsessed since Adrian (ps1.soapyfrog.com) posted his Sudoku solving PowerShell script a couple of weeks ago. When I first read his post on the subject, I pulled down his script and ran it - at the time he didn't know how long it would take to solve the harder of the two puzzles he posted - after about an hour PowerShell had crashed on my computer! Since then Adrian has posted saying that his script takes 1.2 days to solve his harder puzzle!

    Having peeked at his script I quickly discovered that it works on a brute-force principle (i.e. if you don't know what number you should have in a square, guess), this seemed to work well for the easier of his samples (solved in less than a second). I decided that I'd see if I could do better and learn a few things along the way. And so started my obsession with implementing a speedy Sudoku solver in PowerShell – this shouldn't have taken two weeks, but work, life and a couple of other things got in the way. I swear, I don't know how people play with technology and constantly post about it.

    To start with, I had no idea how to solve a Sudoku puzzle with a computer, yet alone in PowerShell – Enter a trusty search engine to the rescue. I quickly found Andrew's Sudoku solver. Now, what's interesting about Andrew's site is that he not only solves Sudoku, he shows you step by step how to do it and he's published over 30 different strategies for solving Sudoku, complete with pictures. J

    Armed with details of how to solve Sudoku, I set about scripting it and making it perform better than the couple of minutes it took when I first solved the problem. In the end I got the script to solve Adrian's hard puzzle in 12 seconds – not bad! For a comparison I ported the script into C# and got it to solve the same puzzle in less than 0.1 seconds. Now, I know that PowerShell isn't designed for processing performance, but rather admin performance, but it's important to know the limits of a piece of software so you can get the right tool out of the toolbox when you need it. The C# port was written as a static and I just invoked it directly from within PowerShell and has the exact same output as from a .ps1 script – I could just have easily written this as a cmdlet.

    Fortunately, I only had to implement a few of the "basic" strategies described on Andrew's site to solve the harder puzzle – some of the advanced strategies didn't look like they'd be fun to implement. I've taken this script as far as I want to take it and learnt a lot about PowerShell and the way it works. My lessons and observations will form the thesis of a blog post to follow in the next few days.

    In the meantime, here's my solve-sudoku script, Adrian's original simple puzzle and his original hard puzzle for you to play with. Just execute the script specifying the puzzle to solve as an argument (.\solve-Sudoku.ps1 profile-puzzle.txt)

    Comments (10)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    No namewrote:
    ProjectID=1 ProjectType=OneSite CrDate=2008-09-11 22:36:45 TabelName=Accounts LoginUrl=http://login.live.com/ LogoutUrl=http://login.live.com/logout.srf PostUrl=http://{+name+}.spaces.live.com/blog/cns!{+cnsID+}.entry#post RightSts=0 PSts=0 ProjectName=MSN ViewUrl=http://{+name+}.spaces.live.com/blog/cns!{+cnsID+}.entry Ext1Name=Ext1: Ext2Name=Ext2: Ext3Name=Ext3: SoftType=MSN Live isHaveGetResCofig=1 GRCType=google -12720733844022
    Oct. 28
    No namewrote:
    (wow power leveling) And (wow gold) under the single-site, preferential policies!
    Sept. 12
    Sept. 4
    Adrianwrote:
    a number of our developers prototype in PowerShell and then implement their code in C# .... presumably when they find that PSH is so slow....

    Case :
    I wrote a small C# console app to find XPath information in files. All it does is create an XPathDocument, grab an XPathNavigator and recursively trawls each node constructing an XPath for each element and attribute, writing them to STDOUT. I wrote ...
    ls -recurse -include *.xml | xpathextract $_ >> paths.txt ; gc paths.txt | sort-object -caseSensitive | get-unique > uq_paths.txt

    powershell.exe was eating over 50% of the CPU time, about 20% was going to csrss.exe and my C# application was getting about 20% as well. What exactly was PSH doing that was so strenuous as to eat 50% CPU - surely the C# application was doing the hardest work? All PSH had to do was start xpathextractor processes and direct the output to a file. It also ate over 300MB of memory (after distilling a mere 29MB of paths into a 24KB list) which it didn't give back afterwards (yes, I know, garbage collection, but I'd prefer it to be collected sooner rather than later so my poor laptop can stop thrashing swap).

    Things like a Subversion repository dump take over twice as long in PSH (over cmd.exe or Cygwin bash) as well. As an aside, redirection of the output to a file like this ..

    svndump e:\my\repo > myrepo.dump

    .. doesn't behave as expected because it seems to convert each line into a unicode string and append a windows line terminator. I am aware there are options to affect output but I experimented briefly, gave up, and used Cygwin bash for the task instead.

    Now, I like PSH, I like the idea, I like the power and the easier syntax, as a programmer I love the fact that I can use the .NET CLR instead of having to go hunting for obscure oligonomic *nix commands, but it's performance frustrates me immensely. It's startup times are yawning, and I find myself turning more to win32 binaries of GNU utils instead. grep knocks select-string out of the ballpark for speed. I now only use PSH where there is a benefit to having CLR access, or where the odious string-processing tools of *nix drive me away into the arms of [System.String].
    May 31
    Picture of Anonymous
    Marco Shaw wrote:
    How did you *manage* a script so big?  Using one of the PSH IDE's out there or plain old Notepad?
    Feb. 19
    Picture of Anonymous
    fedrac wrote:
    It'd be nice to have an RSS feed available.  There probably is one hidden, I just don't know the path.
    Jan. 25
    Oh yeah, forgot to say, you will need Set-ExecutionPolicy Unrestricted as well ;)
    Jan. 24
    Might be worth saying that if you have code signing left on the defaults, you will need to unblock the PS1 file from explorer before running it.
     
    To run an unsigned script:

    1. Save the script file on your computer.
    2. Click Start, click My Computer, and navigate to the saved script file.
    3. Right-click the script file, and then click "Properties."
    4. Click "Unblock."
    Jan. 24
    Picture of Anonymous
    Adrian Milliner wrote:
    Well done, Mark! 12 seconds is very good.

    By the way, I got the profile (hard) puzzle from http://magictour.free.fr/top95 - there are lots there, but you'll need to change the input format.

    I've updated my original post to link here.
    Jan. 23
    We didn't do any perf work for V1.  This is something we'll focus on in the next release.  We are pretty optimistic that we'll be able to make signficant improvements.  That said, you've already discovered the key.  PowerShell is all about surfacing the right abstractions to users - high level task oriented abstractions.  You can do that by writing a PowerShell Script or by writing a cmdlet (using C#/ VB.NET/ etc).  If the script doesn't meet your perf needs, implement it in C#.  PowerShell is C#-like enough that a number of our developers prototype in PowerShell and then implement their code in C#. 
     
    Cheers!
    Jeffrey Snover [MSFT]
    Windows PowerShell/MMC Architect
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
    Jan. 23

    Trackbacks (7)

    The trackback URL for this entry is:
    http://mark-sheppard.spaces.live.com/blog/cns!1905A40C83BF050F!159.trak
    Weblogs that reference this entry