<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.conchango.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Fat man and his mixed bag of goodies</title><link>http://blogs.conchango.com/manojoswal/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2.1 SP3 (Build: 20423.1)</generator><item><title>OO, Patterns and Sudoku Solver: Part 2</title><link>http://blogs.conchango.com/manojoswal/archive/2007/05/07/OO_2C00_-Patterns-and-Sudoku-Solver_3A00_-Part-2.aspx</link><pubDate>Mon, 07 May 2007 06:10:00 GMT</pubDate><guid isPermaLink="false">e847c0e7-38d9-45c0-b593-56747303e088:6884</guid><dc:creator>Manoj.Oswal</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.conchango.com/manojoswal/comments/6884.aspx</comments><wfw:commentRss>http://blogs.conchango.com/manojoswal/commentrss.aspx?PostID=6884</wfw:commentRss><description>




 &lt;div class="Section1"&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;In the &lt;a href="http://blogs.conchango.com/manojoswal/archive/2007/04/23/OO_2C00_-Patterns-and-Sudoku-Solver_3A00_--Part-1.aspx" title="Part 1" target="_blank"&gt;first part&lt;/a&gt; we covered the actual usage of the Sudoku solver and in this part we are going to cover the different techniques and logic used to solve&amp;nbsp;this problem and some statistics and pros and cons of each method.&lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;Brute force solver &lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Brute force solver is the simplest but not the most efficient method to solve problems like &lt;span class="SpellE"&gt;sudoku&lt;/span&gt;. It relies on the sheer speed and number crunching capability of a modern microprocessor. In simple terms it tries out each possibility till it finds a valid solution to a given problem. In the current context it tries putting different possible numbers in each unsolved cell till a valid solution is found. You can imagine this can take some time if there are lots of unsolved cells. To minimise the number of iterations we could use the &lt;em&gt;back tracking&lt;/em&gt; algorithm with brute force solver. Back tracking reduces the number of iterations by not starting from the beginning each time the loop fails at a particular point. Instead it tries different number in the current cell till all the valid numbers fail in the current cell and then it goes back just one step to previous cell tries different number there and then continues in this manner till a valid solution is found. This greatly reduces the number of iterations. The brute force solver I have implemented in this solution uses the backtracking technique.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;br /&gt;Quick solver (Serial cells)&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Brute force with backtracking improves the solving time but is only good enough for grid of a certain size as the solving time exponentially increases with number of unresolved cells. To give you an example, an empty grid of 4 X 4 (16 unresolved cells in total) takes typically 62 milliseconds on my pc but it takes 13 seconds to solve an empty grid of 9 X 9 (81 unresolved cells in total). That&amp;rsquo;s approximately 210 times increase in solving time for 5 folds increase in unresolved cell numbers. And for an empty 16 X 16 grid I stopped processing after 15 minutes. So effectively its performance becomes unacceptable at that size. This is when injecting domain knowledge in to brute force solving technique becomes essential. The quick solver does exactly that. We know the &lt;span class="SpellE"&gt;sudoku&lt;/span&gt; rules and we can use those rules to optimise our solver.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-family:Verdana;"&gt;No Duplicates Rule&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;We know that each unsolved cell can have a value from the possible number values set. &lt;span class="SpellE"&gt;&lt;span class="GramE"&gt;e.q&lt;/span&gt;&lt;/span&gt; in a 9 X 9 grid any unsolved cell can only have a value between 1 to 9. But we can reduce that possible values set by removing values that a particular cell can&amp;rsquo;t have. And according to the rules; no row, column or square can have duplicates. So if we take all the values from the solved cells and then remove them from the appropriate row, column and square then we can greatly reduce the number of possible values for each unsolved cell. Let me give you an example:&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;br /&gt;&lt;img height="690" id="_x0000_i1025" src="http://blogs.conchango.com/photos/conchango_bloggers/images/6890/original.aspx" width="650" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;In the figure given above, the cells with the single blue coloured values are resolved cells. And the cells with multiple black coloured values are the unresolved cells, each with initial possible values set. So if we apply the no duplicates rule then the yellow shaded cell (row 1 column 2) with value 2 can&amp;rsquo;t have the same value in its corresponding row (outlined in red), column (outlined in blue) or square (outlined in green). This means we can safely remove each blue or fixed value from its corresponding row, column and square. That leaves us with a &lt;span class="SpellE"&gt;sudoku&lt;/span&gt; as shown in the figure given below:&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;br /&gt;&lt;img height="690" id="_x0000_i1026" src="http://blogs.conchango.com/photos/conchango_bloggers/images/6889/original.aspx" width="650" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;As you can see the possible values set in each unresolved cell has greatly reduced. Apply this rule to most simple and some medium difficulty level &lt;span class="SpellE"&gt;sudoku&lt;/span&gt; that you find in a newspaper. And &lt;span class="GramE"&gt;after each iteration&lt;/span&gt; of removing duplicates; you will find at least one unresolved cell left with only one possible value. That is the resolved value for that cell. And now you can continue removing the recently solved value from all the unresolved cells of its corresponding row, column and square.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;If we keep doing that then one of the following two things is going to happen:&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin-left:72pt;text-indent:-18pt;"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;1.&lt;/span&gt;&lt;span style="font-size:7pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;We get a solved &lt;span class="SpellE"&gt;sudoku&lt;/span&gt;. (Hurray!)&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin-left:72pt;text-indent:-18pt;"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;2.&lt;/span&gt;&lt;span style="font-size:7pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;We still have some unresolved cells. &lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;If we arrive at 2, then is this the stage at which we start guessing values? &lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;No, there is at least one more rule we can implement. &lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-family:Verdana;"&gt;The Unique Square Value Rule&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Sometimes after all possible duplicates removal you will come across the &lt;span class="SpellE"&gt;sudoku&lt;/span&gt; state as shown below:&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;br /&gt;&lt;img height="690" id="_x0000_i1027" src="http://blogs.conchango.com/photos/conchango_bloggers/images/6888/original.aspx" width="650" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;You can place value 1 in the yellow shaded cell of row 2, column 8. Why? If you look at all the possible values for all the unresolved cells in that square you will find that 1 is only present once. And we need to put 1 somewhere in that square and only possible square we can put 1 is the yellow shaded cell and hence we can put 1 in that cell even though there are more than one possible values available for that cell. There are a few more cells with unique square values and they are all shaded in red.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;We can only run USV (unique square value) rule if there are no more duplicates to remove. If we run this rule before all the duplicates are removed then the &lt;span class="SpellE"&gt;sudoku&lt;/span&gt; solver can put wrong values in the cells. Now after applying USV rule we get a few more resolved cells hence a few more duplicates to remove. And now if we keep doing that in a loop, again we come across one of the following two situations:&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin-left:72pt;text-indent:-18pt;"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;1.&lt;/span&gt;&lt;span style="font-size:7pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;We get a solved &lt;span class="SpellE"&gt;sudoku&lt;/span&gt;. (Hurray!)&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin-left:72pt;text-indent:-18pt;"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;2.&lt;/span&gt;&lt;span style="font-size:7pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;We still have some unresolved cells. &lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;If we are still at 2 then we guess a value for the first unresolved cell found and then continue applying duplicates and USV rules. If we keep doing this then you are guaranteed to find a solution to any valid or solvable &lt;span class="SpellE"&gt;sudoku&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;br /&gt;Quick solver (Possible &lt;span class="SpellE"&gt;Vals&lt;/span&gt;)&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;What can we do to reduce the number of iterations further? The quick solver (serial cells) puts the guessed values in a serial order. It starts scanning for unresolved cell starting from row 1, column 1 and moves on to cell in row 1, column 2 till it finds an unsolved cell. If no such cell is found in row 1 then it moves to row 2 and so on. If we alter this order then we are bound to get different number of iterations. What if we order the unsolved cells by the possible number of values they can have? So the unsolved cell with two possible values remaining comes on top and the cell with three possible values remaining next and so on. With this sort of ordering, the numbers of different starting path are less and discarding the wrong path happens very early on. Thus the numbers of iterations are reduced drastically in most cases. In addition to that the amount of work needed to code this type of solver on top of previous one is trivial using the inheritance (More details on that in the next part.).&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;Is Brute Force Solver Bad?&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Here is the stats table for the numerical minded (all the solving times given are in milliseconds):&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table cellpadding="0" cellspacing="0" class="MsoNormalTable" style="width:513.5pt;border-collapse:collapse;"&gt;&lt;tr style="height:15pt;"&gt;&lt;td style="border-right:medium none;padding-right:5.4pt;border-top:windowtext 1pt solid;padding-left:5.4pt;background:black;padding-bottom:0cm;border-left:windowtext 1pt solid;width:142.95pt;padding-top:0cm;border-bottom:medium none;height:15pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:white;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td colspan="4" style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:windowtext 1pt solid;padding-left:5.4pt;background:black;padding-bottom:0cm;border-left:medium none;width:370.55pt;padding-top:0cm;border-bottom:medium none;height:15pt;"&gt;&lt;p align="center" class="MsoNormal" style="text-align:center;"&gt;&lt;strong&gt;&lt;span style="font-size:11pt;color:white;font-family:Verdana;"&gt;Grid size&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height:12.75pt;"&gt;&lt;td style="padding-right:5.4pt;padding-left:5.4pt;background:#969696;padding-bottom:0cm;width:142.95pt;padding-top:0cm;height:12.75pt;border:windowtext 1pt solid;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:windowtext 1pt solid;padding-left:5.4pt;background:#969696;padding-bottom:0cm;border-left:medium none;width:64.05pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;4 X 4&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:windowtext 1pt solid;padding-left:5.4pt;background:#969696;padding-bottom:0cm;border-left:medium none;width:72pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;9 X 9&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:windowtext 1pt solid;padding-left:5.4pt;background:#969696;padding-bottom:0cm;border-left:medium none;width:90pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;16 X 16&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:windowtext 1pt solid;padding-left:5.4pt;background:#969696;padding-bottom:0cm;border-left:medium none;width:144.5pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;25 X 25&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height:12.75pt;"&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:windowtext 1pt solid;width:142.95pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Brute Force&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:64.05pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;62&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:72pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;13000&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:90pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;30000&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:144.5pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Too long&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height:12.75pt;"&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:windowtext 1pt solid;width:142.95pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Quick Solver (Serial cell)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:64.05pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;45&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:72pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;750&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:90pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;1900&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:144.5pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Too long&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height:12.75pt;"&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:windowtext 1pt solid;width:142.95pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Quick Solver (Pos &lt;span class="SpellE"&gt;vals&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:64.05pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;45&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:72pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;250&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:90pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;2000&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style="border-right:windowtext 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;background:white;padding-bottom:0cm;border-left:medium none;width:144.5pt;padding-top:0cm;border-bottom:windowtext 1pt solid;height:12.75pt;"&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;9000&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;And here is the graphical view of the table (some values are changed in the graph to better illustrate the relative difference in the solving curves):&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;br /&gt;&lt;img height="366" id="_x0000_i1028" src="http://blogs.conchango.com/photos/conchango_bloggers/images/6887/original.aspx" width="578" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;This just re-emphasises the fact that after certain complexity threshold the brute force solving technique becomes unacceptable.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;But is the brute force technique always bad? In my opinion that&amp;rsquo;s not true. This technique definitely has its advantages and the most notable is the cheaper cost to develop and maintain it over others. In the scenario given above, the quick solver is always fast compared to the brute force solver. But in many other cases it&amp;rsquo;s quite possible that due to the added processing required, the quick solver kind of technique is slower to brute force at low complexity levels. And hence offer no real benefit at lower complexity levels. In those kinds of scenarios the Brute force is the winner. Let me illustrate it further with the help of the following hypothetical graph:&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;br /&gt;&lt;img height="362" id="_x0000_i1029" src="http://blogs.conchango.com/photos/conchango_bloggers/images/6886/original.aspx" width="577" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;strong&gt;&lt;span style="font-size:14pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;It is almost identical to the previous graph. Only the fast quick solver is kept and the red horizontal line is added; it is&amp;nbsp;a sample&amp;nbsp;ideal acceptable performance threshold for this app which is around 125 milliseconds in this case. The purple curve represents brute force solver and the green curve illustrate the quick solver. The point of intersection between these two curves is circled in red. This is the point where the quick solver starts getting faster compared to the brute force solver. Let&amp;rsquo;s call it the brute force performance cross over point. The point of intersection between the brute force curve and the performance threshold line is circled in green this is the point after which the performance of the brute force solver is consistently inferior to the ideal acceptable performance. Let&amp;rsquo;s call it the brute force performance cut-off point. So does this mean this is the point after which the brute force solver should be discarded as a rule of thumb? No, in many cases it is quite possible that the higher cost of developing better solution can push the acceptable performance threshold a little lower. That point is shown with filled brown circle. Let&amp;rsquo;s call it the brute force viability cut-off point. This is the point after which the brute force can&amp;rsquo;t be accepted as a solution.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;Let&amp;rsquo;s put some more colour around the brute force viability cut-off point:&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;br /&gt;&lt;img height="362" id="_x0000_i1030" src="http://blogs.conchango.com/photos/conchango_bloggers/images/6885/original.aspx" width="577" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;The yellow shaded region is the brute force operation zone.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;If your application is always going to operate within the brute force operation zone then the brute force solver is your winner and you can save some money by not investing in developing faster but costlier solutions. If you know for sure that your app is going to operate beyond this region then you need to have better solution like the quick solver. In case of uncertainty where you know at the start you are going to be operating within the brute force operation zone, but not sure whether you will operate beyond that zone in the future. In such cases you need to implement something that will allow you to plug in better solver if and when the need arises.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;This is where the design patterns can come to your rescue. In this particular case you can implement the Strategy pattern. This particular pattern allows you to plug in different strategies depending on the requirements. So you can have your application running with brute force solver strategy and in the future you can swap it with quick solver strategy if required. I have implemented the strategy pattern in the &lt;span class="SpellE"&gt;Sudoku&lt;/span&gt; Solver.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Verdana;"&gt;More details about the strategy pattern and the code walkthrough of the critical areas will be covered in the next part. I will also be posting the complete source code in the next part. Some of the comments on the previous posting have mentioned the very obvious short comings of the UI. And I had replied that the actual code have many hidden goodies that are not utilised in the front end due to the time constraints and the lack of focus in that UI. I will cover those areas and will explain how to use those goodies to help you make a better &lt;span class="SpellE"&gt;sudoku&lt;/span&gt; solver.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.conchango.com/aggbug.aspx?PostID=6884" width="1" height="1"&gt;</description><category domain="http://blogs.conchango.com/manojoswal/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/.NET2/default.aspx">.NET2</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/Sudoku/default.aspx">Sudoku</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/Object+Oriented+Programming/default.aspx">Object Oriented Programming</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/Design+Patterns/default.aspx">Design Patterns</category></item><item><title>OO, Patterns and Sudoku Solver:  Part 1</title><link>http://blogs.conchango.com/manojoswal/archive/2007/04/23/OO_2C00_-Patterns-and-Sudoku-Solver_3A00_--Part-1.aspx</link><pubDate>Sun, 22 Apr 2007 23:11:00 GMT</pubDate><guid isPermaLink="false">e847c0e7-38d9-45c0-b593-56747303e088:6691</guid><dc:creator>Manoj.Oswal</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.conchango.com/manojoswal/comments/6691.aspx</comments><wfw:commentRss>http://blogs.conchango.com/manojoswal/commentrss.aspx?PostID=6691</wfw:commentRss><description>&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;p&gt;Primary focus of this blog entry is to demonstrate some of the power and flexibility offered by object orientated programming and design patterns.&amp;nbsp;I will try to demonstrate these techniques and how to use them to solve complex problems like Sudoku.&lt;/p&gt;&lt;p&gt;I chose Sudoku rather than &amp;quot;Hello world&amp;quot; because it&amp;#39;s fun, complex and seems like all the rage at the moment.&lt;/p&gt;&lt;p&gt;I have divided this entry in to multiple parts for the benefit of all.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Part 1&lt;/strong&gt; is for people who are only interested in acquiring a free Sudoku solver but don&amp;#39;t necessarily give a damn about any of the programming techniques mentioned above.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Part 2&lt;/strong&gt; is for those who are interested in knowing the different techniques and logic used to solve the problem and some statistics and pros and cons of each method. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Part 3&lt;/strong&gt; will be for developers who are interested into the actual code walkthrough.&lt;/p&gt;&lt;p&gt;Well without any further babble I will describe the usage of the Sudoku solver.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;The main screen of Sudoku Solver&lt;/strong&gt;&lt;/p&gt;&lt;img border="0" height="326" src="http://blogs.conchango.com/photos/conchango_bloggers/images/6692/original.aspx" width="650" /&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Starting a new sudoku.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Click on New menu item and it will pop up the following dialog box&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;img border="0" height="373" src="http://blogs.conchango.com/photos/conchango_bloggers/images/6693/original.aspx" width="272" /&gt; &lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Choose the required grid size (9 X 9 is the standard size).&lt;/li&gt;&lt;li&gt;Choose the solving strategy (quick solver possible vals is the fastest one).&lt;/li&gt;&lt;li&gt;Tick the populate sample data check box if you want to populate a sample sudoku.&lt;/li&gt;&lt;li&gt;Click OK button.&amp;nbsp;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Now you will have a sudoku on the main screen as shown before.&lt;/p&gt;&lt;p&gt;Click on any blank cell you want to put a value in and it will show you a drop down box with values as shown below&lt;/p&gt;&lt;img border="0" height="347" src="http://blogs.conchango.com/photos/conchango_bloggers/images/6694/original.aspx" width="400" /&gt; &lt;p&gt;Select a value and it will be placed in that cell.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Solving sudoku&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Once you have finished placing all the values click on the &lt;em&gt;Solve&lt;/em&gt; menu item to solve the sudoku.&lt;/p&gt;&lt;p&gt;The tool will solve any sudoku with a valid solution.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Restarting a Sudoku.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;If you want to start a new sudoku based on the same grid and solving strategy then click on &lt;em&gt;Reset&lt;/em&gt; menu else start over a new sudoku based on new options by clicking on &lt;em&gt;New&lt;/em&gt; menu item again.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;More...&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;You can also use this tool as a sudoku generator by placing just a couple of random values and clicking solve button.&lt;/p&gt;&lt;p&gt;Any grid bigger than 25 X 25 will be pure academic and with no fun value to the sudoku fans. So I have restricted it to that size through UI but for the benefit of the geeks the underlying code is made capable of solving sudoku of any grid size and is only restricted by the memory and processing power.&lt;/p&gt;&lt;p&gt;You can download the zip file for this sudoku solver at the end of this post. Please note that you will need .NET 2 runtime on your machine in order to run this programme. If you dont have it then you can download it from Microsoft website &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=0856EACB-4362-4B0D-8EDD-AAB15C5E04F5&amp;amp;displaylang=en" target="blank"&gt;here.&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.conchango.com/aggbug.aspx?PostID=6691" width="1" height="1"&gt;</description><enclosure url="http://blogs.conchango.com/manojoswal/attachment/6691.ashx" length="66881" type="application/x-zip-compressed" /><category domain="http://blogs.conchango.com/manojoswal/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/.NET2/default.aspx">.NET2</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/Sudoku/default.aspx">Sudoku</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/Patterns/default.aspx">Patterns</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/Object+Oriented+Programming/default.aspx">Object Oriented Programming</category></item><item><title>SQL generic split function</title><link>http://blogs.conchango.com/manojoswal/archive/2007/01/31/SQL-generic-split-function.aspx</link><pubDate>Wed, 31 Jan 2007 11:02:00 GMT</pubDate><guid isPermaLink="false">e847c0e7-38d9-45c0-b593-56747303e088:5754</guid><dc:creator>Manoj.Oswal</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.conchango.com/manojoswal/comments/5754.aspx</comments><wfw:commentRss>http://blogs.conchango.com/manojoswal/commentrss.aspx?PostID=5754</wfw:commentRss><description>&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;Last Friday I was discussing with &lt;a href="http://blogs.conchango.com/jamiethomson/" target="_blank"&gt;Jamie&lt;/a&gt; one of the SQL function I was working on. At the end of it Jamie gave me some encouragement to blog it (&amp;ldquo;If I don&amp;rsquo;t see a blog on it by Monday, I will be having a word with you!&amp;rdquo; Jamie)&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;With that support here I am, finally writing my first blog.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;My current assignment is with the world&amp;rsquo;s leading, specialist insurance market. The situation I came across was like this, I was receiving a comma delimited string in one of my stored procedures and it was meant to be used in a where clause.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;e.q.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:fuchsia;"&gt;&amp;hellip;&lt;/span&gt; &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; &amp;hellip; &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt;&lt;span style="color:gray;"&gt; ITEMID IN (&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;Comma delimited string&lt;/span&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';"&gt;)&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;The first solution that sprang to my mind was to construct a dynamic SQL in stored procedure utilising the delimited string and executing it at the end of it. This would have taken away all the obvious benefits a stored procedure offers plus would have opened the doors to potential abuse of this stored proc. Another solution would have been to use OPENXML but I didn&amp;#39;t have a choice of getting input string in XML format.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;After some further thinking and search the better solution seemed to be a SQL function accepting comma delimited string and returning a resultset which then could be used in a &lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;WHERE&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt; clause or a &lt;/span&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';"&gt;JOIN&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;The first function developed worked to the expectations and I was delighted with it. But after a few minutes, questions started popping up in my head about the inflexibility of this function. First it was assuming the string would always be delimited with a comma and hence the other implication was a delimiter would always be a single character. Secondly the function was returning a single column table of type int. So the input and output format were fixed (arrrrrrggh!!!).&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;So before letting those limitations haunt me in the middle of the night, I decided to make this function a bit more generic and what follows is the result of those efforts:&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';"&gt;-- ===========================================================&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';"&gt;-- Author:&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Manoj Oswal (Conchango)&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';"&gt;-- Create date:&amp;nbsp;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;26 Jan 2007&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';"&gt;-- Description:&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Generic Split function&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';"&gt;--&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Accepts List and separator as string&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';"&gt;--&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Returns single variant column TABLE of items &lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';"&gt;-- ===========================================================&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;CREATE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;FUNCTION&lt;/span&gt; [dbo]&lt;span style="color:gray;"&gt;.&lt;/span&gt;[GenericStringSplit]&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';"&gt;(&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;@List &lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;8000&lt;span style="color:gray;"&gt;),&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;@Separator &lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;10&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';"&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;RETURNS&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;@ItemsList &lt;span style="color:blue;"&gt;TABLE&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';"&gt;(&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Item &lt;span style="color:blue;"&gt;SQL_VARIANT&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';"&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;AS&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;BEGIN&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;DECLARE&lt;/span&gt; @CurrItem &lt;span style="color:blue;"&gt;SQL_VARIANT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @Pos &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @List &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;LTRIM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;RTRIM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;@List&lt;span style="color:gray;"&gt;))+&lt;/span&gt; @Separator&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @Pos &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;CHARINDEX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;@Separator&lt;span style="color:gray;"&gt;,&lt;/span&gt; @List&lt;span style="color:gray;"&gt;,&lt;/span&gt; 1&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;IF&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;REPLACE&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;@List&lt;span style="color:gray;"&gt;,&lt;/span&gt; @Separator&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:red;"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span style="color:red;"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;BEGIN&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;WHILE&lt;/span&gt; @Pos &lt;span style="color:gray;"&gt;&amp;gt;&lt;/span&gt; 0&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;BEGIN&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @CurrItem &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;LTRIM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;RTRIM&lt;/span&gt;&lt;span style="color:gray;"&gt;(LEFT(&lt;/span&gt;@List&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:gray;"&gt;(&lt;/span&gt;@Pos&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;1 &lt;span style="color:gray;"&gt;))))&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;IF&lt;/span&gt; @CurrItem &lt;span style="color:gray;"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span style="color:red;"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;BEGIN&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT&lt;/span&gt; &lt;span style="color:blue;"&gt;INTO&lt;/span&gt; @ItemsList &lt;span style="color:gray;"&gt;(&lt;/span&gt;Item&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt; &lt;span style="color:gray;"&gt;(&lt;/span&gt;@CurrItem&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @List &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:gray;"&gt;RIGHT(&lt;/span&gt;@List&lt;span style="color:gray;"&gt;,(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;LEN&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;@List&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;-&lt;/span&gt; &lt;span style="color:gray;"&gt;(&lt;/span&gt;@Pos &lt;span style="color:gray;"&gt;+&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;LEN&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;@Separator&lt;span style="color:gray;"&gt;)-&lt;/span&gt;1&lt;span style="color:gray;"&gt;)))&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @Pos &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;CHARINDEX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;@Separator&lt;span style="color:gray;"&gt;,&lt;/span&gt; @List&lt;span style="color:gray;"&gt;,&lt;/span&gt; 1&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;RETURN&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;END&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;The above function now accepts a delimited string and a separator up to 10 char and returns a single column table of &lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;sql_variant. &lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;The consuming SQL can&amp;nbsp;then cast the return of this function with the desired type.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;strong&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;strong&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;strong&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;strong&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;Usage:&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:fuchsia;"&gt;CAST&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;Item &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; [GenericStringSplit]&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;&amp;#39;1;-2;-3;-4;-5&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:red;"&gt;&amp;#39;;-&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:fuchsia;"&gt;CAST&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;Item &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:blue;"&gt;DATETIME&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; [GenericStringSplit]&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;&amp;#39;12 feb 2005~~~10 Jan 2006~~~15 Jan 2006&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:red;"&gt;&amp;#39;~~~&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;One of the limitations of this function is the input list size is limited to 8000. &lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;VARCHAR&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;(&lt;/span&gt;&lt;span style="font-size:10pt;color:fuchsia;font-family:'Courier New';"&gt;MAX&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;) is the possible solution for this problem but that also means some more changes in the function namely changing @CurrItem type to something like&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;100&lt;span style="color:gray;"&gt;). &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;This is due to the incompatibility of &lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;VARCHAR&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;(&lt;/span&gt;&lt;span style="font-size:10pt;color:fuchsia;font-family:'Courier New';"&gt;MAX&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;) and &lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;SQL_VARIANT.&lt;/span&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;Interestingly enough the same day I had to write something to do the opposite of the above mentioned function. I had to write something that returned a comma separated list of items from a table. The solution I used is as follows:&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @List &lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;SET&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @List &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @List &lt;span style="color:gray;"&gt;=&lt;/span&gt; @LIST &lt;span style="color:gray;"&gt;+&lt;/span&gt; &lt;span style="color:red;"&gt;&amp;#39;,&amp;#39;&lt;/span&gt; &lt;span style="color:gray;"&gt;+&lt;/span&gt; COLNAME &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; TABLE &lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;IF&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @List &lt;span style="color:gray;"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span style="color:red;"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;BEGIN&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @List &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;STUFF&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;@List&lt;span style="color:gray;"&gt;,&lt;/span&gt;1&lt;span style="color:gray;"&gt;,&lt;/span&gt;1&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:red;"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;END&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @List&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;Please send any feedback/suggestions you have, to further improve this work.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin:0cm 0cm 0pt;"&gt;&lt;span style="font-size:11pt;font-family:Arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;img src="http://blogs.conchango.com/aggbug.aspx?PostID=5754" width="1" height="1"&gt;</description><category domain="http://blogs.conchango.com/manojoswal/archive/tags/SQL+Function/default.aspx">SQL Function</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/Generic+split/default.aspx">Generic split</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/Utility/default.aspx">Utility</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/SQL2005/default.aspx">SQL2005</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/SQL+split+function/default.aspx">SQL split function</category><category domain="http://blogs.conchango.com/manojoswal/archive/tags/SQL+2005/default.aspx">SQL 2005</category></item></channel></rss>