<?xml version="1.0" encoding="windows-1251"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Code First Blog</title>
	<atom:link href="http://protsyk.com/cms/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://protsyk.com/cms</link>
	<description>Coding, developing, living!</description>
	<lastBuildDate>Fri, 27 Apr 2012 08:07:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Solution of Facebook Hacker Cup 2012 problem – Squished status</title>
		<link>http://protsyk.com/cms/?p=482</link>
		<comments>http://protsyk.com/cms/?p=482#comments</comments>
		<pubDate>Fri, 20 Apr 2012 19:08:56 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[Puzzles]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=482</guid>
		<description><![CDATA[Squished Status Some engineers got tired of dealing with all the different ways of encoding status messages, so they decided to invent their own. In their new scheme, an encoded status message consists of a sequence of integers representing the &#8230; <a href="http://protsyk.com/cms/?p=482">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Squished Status</strong></p>
<p>Some engineers got tired of dealing with all the different ways of encoding status messages, so they decided to invent their own. In their new scheme, an encoded status message consists of a sequence of integers representing the characters in the message, separated by spaces. Each integer is between 1 and M, inclusive. The integers do not have leading zeroes. Unfortunately they decided to compress the encoded status messages by removing all the spaces!</p>
<p>Your task is to figure out how many different encoded status messages a given compressed status message could have originally been. Because this number can be very large, you should return the answer modulo 4207849484 (0xfaceb00c in hex).</p>
<p>For example, if the compressed status message is &#8220;12&#8243; it might have originally been &#8220;1 2&#8243;, or it might have originally been &#8220;12&#8243;. The compressed status messages are between 1 and 1000 characters long, inclusive. Due to database corruption, a compressed status may contain sequences of digits that could not result from removing the spaces in an encoded status message.</p>
<p><strong>Input</strong></p>
<p>The input begins with a single integer, N, the number of compressed status messages you must analyze. This will be followed by N compressed status messages, each consisting of an integer M, the highest character code for that database, then the compressed status message, which will be a string of digits each in the range &#8217;0&#8242; to &#8217;9&#8242;, inclusive. All tokens in the input will be separated by some whitespace.</p>
<p><strong>Output</strong></p>
<p>For each of the test cases numbered in order from 1 to N, output &#8220;Case #i: &#8221; followed by a single integer containing the number of different encoded status messages that could be represented by the corresponding compressed sequence modulo 4207849484. If none are possible, output a 0.</p>
<p><strong>Constraints</strong></p>
<p><em>5 &lt;= N &lt;= 25</em><br />
<em></em><em>2 &lt;= M &lt;= 255</em><br />
<em>1 &lt;= length of encoded status &lt;= 1000</em><em></em></p>
<p><strong>Example input</strong></p>
<p>5<br />
12<br />
12<br />
255<br />
219<br />
30<br />
1234321<br />
2<br />
101<br />
70 8675309</p>
<p><strong>Example output</strong></p>
<p>Case #1: 2<br />
Case #2: 4<br />
Case #3: 6<br />
Case #4: 0<br />
Case #5: 2</p>
<p><strong>Preliminaries</strong></p>
<p>Let’s assume that there is a routine which split input string into a sequence of the smallest valid numbers. Zero and numbers greater than max value M are invalid. Consider following examples:</p>
<p>Input: M=2, S=101<br />
Output: L= {} – Input is invalid</p>
<p>Input: M=11, S=101<br />
Output: L= {10, 1}</p>
<p>Input: M=124, S=18143<br />
Output: L= {1, 8, 1, 4, 3}</p>
<p>Now, we will concentrate on solving following problem. Given a sequence of numbers L, count all possible sequences that could be constructed from original sequence by combining consecutive numbers, such that obtained number is less than maximum value M.</p>
<p>Example, given M = 181 and L={1, 4, 3} we can construct 4 sequences:</p>
<ol>
<li>{1, 4, 3} – original sequence is valid</li>
<li>{1, 43}</li>
<li>{14, 3}</li>
<li>{143}</li>
</ol>
<p><strong>Na&#239;ve approach</strong></p>
<p>An obvious solution is to perform exhaustive search and actually construct all such sequences. The algorithm is as simple as:</p>
<ul>
<li>If sequence contains one value return 1.</li>
<li>Put <strong>count</strong> = 0</li>
<li>For each number in sequence
<ul>
<li>Try to combine it with the next number (if it exists).
<ul>
<li>If combination is not possible proceed to the next number.</li>
<li>Otherwise replace two consecutive numbers with combined value, recursively call this routine with modified sequence, put <strong>count</strong> = 1 + returned value, restore sequence. Proceed to the next number</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>No surprise this approach will only work for small sequences ~ 15-20 numbers.</p>
<p>But we can do better, by figuring out recurrent formula for possible number of valid sequences.</p>
<p><strong>Recurrent formula</strong></p>
<p>Let’s imagine that we calculated the number of different sequences S(L) for input of n numbers:</p>
<p align="center">S({x<sub>1</sub>, x<sub>2</sub>, &#8230;, x<sub>n</sub>} ) = S<sub>n</sub></p>
<p>What will happen if we add another number x<sub>n+1</sub>? We might notice that:</p>
<p style="text-align: center;">S({x<sub>1</sub>, x<sub>2</sub>, &#8230;, x<sub>n</sub>, x<sub>n+1</sub> } ) = S({x<sub>1</sub>, x<sub>2</sub>, &#8230;, x<sub>n</sub>})+ S({x<sub>1</sub>, x<sub>2</sub>, &#8230;, (x<sub>n</sub> x<sub>n+1</sub>)})<br />
+ S({x<sub>1</sub>, x<sub>2</sub>, &#8230;, (x<sub>n-1</sub> x<sub>n</sub> x<sub>n+1</sub>)}).<br />
S({x<sub>1</sub>, x<sub>2</sub>, &#8230;, (x<sub>n</sub> x<sub>n+1</sub>)}) = S({x<sub>1</sub>, x<sub>2</sub>, &#8230;, x<sub>n-1</sub>}).<br />
S({x<sub>1</sub>, x<sub>2</sub>, &#8230;, (x<sub>n-1</sub> x<sub>n</sub> x<sub>n+1</sub>)}) = S({x<sub>1</sub>, x<sub>2</sub>, &#8230;, x<sub>n-2</sub>}).</p>
<p>The structure of solutions is shown on this illustration:</p>
<p><a href="http://protsyk.com/cms/wp-content/uploads/2012/04/Sequence.png"><img class="size-full wp-image-483 aligncenter" title="Sequence" src="http://protsyk.com/cms/wp-content/uploads/2012/04/Sequence.png" alt="" width="468" height="356" /></a></p>
<p><strong>Links</strong></p>
<ul>
<li><a href="https://github.com/PetroProtsyk/Sources/blob/master/Facebook%20Hackerup%202012/Squished%20Status/Program.cs">Solution in C#</a></li>
<li><a href="http://ideone.com/Fn9qM">Execute on Ideone</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=482</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solution of Facebook Hacker Cup 2012 problem &#8211; Checkpoint</title>
		<link>http://protsyk.com/cms/?p=449</link>
		<comments>http://protsyk.com/cms/?p=449#comments</comments>
		<pubDate>Wed, 28 Mar 2012 17:36:08 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[Puzzles]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=449</guid>
		<description><![CDATA[Checkpoint You are racing on a 2D lattice grid starting from the origin (0,0) towards a goal (M,N) where M and N are positive integers such that 0 &#60; M &#60;= N. There is a checkpoint that&#8217;s neither on the &#8230; <a href="http://protsyk.com/cms/?p=449">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Checkpoint</strong></p>
<p>You are racing on a 2D lattice grid starting from the origin (0,0) towards a goal (M,N) where M and N are positive integers such that 0 &lt; M &lt;= N. There is a checkpoint that&#8217;s neither on the origin nor on the goal with coordinates (m,n) such that 0 &lt;= m &lt;= M and 0 &lt;= n &lt;= N. You must clear the checkpoint before you reach the goal. The shortest path takes T = M + N steps.</p>
<p>At each point, you can move to the four immediate neighbors at a fixed speed, but since you don&#8217;t want to lose the race, you are only going to take either a step to the right or to the top.</p>
<p>Even though there are many ways to reach the goal while clearing the checkpoint, the race is completely pointless since it is relatively easy to figure out the shortest route. To make the race more interesting, we change the rules. Instead of racing to the same goal (M,N), the racers get to pick a goal (x,y) and place the checkpoint to their liking so that there are exactly S distinct shortest paths.</p>
<p>For example, given S = 4, consider the following two goal and checkpoint configurations</p>
<p>Placing the checkpoint at (1, 3) and the goal at (2,3). There are 4 ways to get from the origin to the checkpoint depending on when you move to the right. Once you are at the checkpoint, there is only one way to reach the goal with minimal number of steps. This gives a total of 4 distinct shortest paths, and takes T = 2 + 3 = 5 steps. However, you can do better.</p>
<p>Placing the checkpoint at (1, 1) and the goal at (2,2). There are two ways to get from the origin to the checkpoint depending on whether you move to the right first or later. Similarly, there are two ways to get to the goal, which gives a total of 4 distinct shortest paths. This time, you only need T = 2 + 2 = 4 steps.</p>
<p>As a Hacker Cup racer, you want to figure out how to place the checkpoint and the goal so that you cannot possibly lose. Given S, find the smallest possible T, over all possible checkpoint and goal configurations, such that there are exactly S distinct shortest paths clearing the checkpoint.</p>
<p>Input</p>
<p>As input for the race you will receive a text file containing an integer R, the number of races you will participate in. This will be followed by R lines, each describing a race by a single number S. Lines are separated using Unix-style (&#8220;\n&#8221;) line endings.</p>
<p>Output</p>
<p>Your submission should contain the smallest possible length of the shortest path, T for each corresponding race, one per line and in order.</p>
<p>Constraints</p>
<p>5 &lt;= R &lt;= 20</p>
<p>1 &lt;= S &lt;= 10000000</p>
<p>Example input</p>
<pre>5
4
5
12
14
1</pre>
<p>Example output</p>
<pre>Case #1: 4
Case #2: 6
Case #3: 6
Case #4: 9
Case #5: 2</pre>
<p><strong>Source: </strong></p>
<ul>
<li>Facebook Hacker Cup 2012, Round 2, <a href="http://www.facebook.com/hackercup/problems.php?pid=191596157517194&amp;round=225705397509134">Checkpoint</a></li>
</ul>
<p><strong>Preliminaries</strong></p>
<p>Let&#8217;s start from the following problem. Given a lattice grid and a starting point (0,0), find how many there are ways to reach point (x,y) using no more than x steps to the left and y steps to the top. The problem is known as &#8220;<strong>Block walking&#8221;.<br />
</strong></p>
<p>The following picture shows two possible different ways to reach the point (2, 3) from the origin:</p>
<p><a href="http://protsyk.com/cms/wp-content/uploads/2012/03/checkpoint1.png"><img class="aligncenter size-full wp-image-455" title="checkpoint1" src="http://protsyk.com/cms/wp-content/uploads/2012/03/checkpoint1.png" alt="" width="256" height="230" /></a></p>
<p>It is easy to observe that the length of each such path consists of exactly x+y steps. Each path can be encoded as sequence of 0 and 1. Where, 0 means &#8220;move up&#8221; and 1 means &#8220;move right&#8221; respectively. For example, blue path might be encoded as 00011 and pink path 01100. Now, calculating the total number of different paths G(x,y) from (0,0) to (x,y) is equivalent to finding the number of different rearrangements of y zeros and x ones:</p>
<p style="text-align: center;"> G(x,y) = C(x, x+y) = C(y, x+y) = (n+k)!/(k!n!). (*)</p>
<p align="center">One important property of this equation is that G(x,y) = G(y,x).</p>
<p>Now, for each (x,y) the value of G(x,y) might be easily calculated. The grid with actual values looks like:</p>
<p><a href="http://protsyk.com/cms/wp-content/uploads/2012/03/checkpoint2.png"><img class="aligncenter size-full wp-image-454" title="checkpoint2" src="http://protsyk.com/cms/wp-content/uploads/2012/03/checkpoint2.png" alt="" width="256" height="235" /></a></p>
<p>Na&#239;ve calculation of this grid using formula (*) will be extremely inefficient. Let&#8217;s investigate some important properties that might be used to calculate this grid efficiently:</p>
<ul>
<li>The values in the grid are symmetrical G(x,y) = G(y,x).</li>
<li>G(x,0) = G(0,x) = 1</li>
<li>G(x,1) = G(1,x) = x+1</li>
<li>G(x,y) = G(x-1,y)+G(x,y-1)</li>
<li>G(x,x) = 2*G(x-1,x) = 2*G(x, x-1)</li>
</ul>
<p>These formulas lead to a very efficient algorithm for building such a table:</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">           for (int i = 0; i &lt; max; i++) {
            for (int j = i; j &lt; max; j++) {
                if (i == 0) {
                    d[i, j] = 1;
                    d[j, i] = 1;
                } else if (i == j)
                    d[i, i] = 2 * d[i - 1, i];
                else {
                    d[i, j] = d[i - 1, j] + d[i, j - 1];
                    d[j, i] = d[i, j];
                }
            }
        }</pre>
<p>The program doesn&#8217;t even have to store the complete grid, only the previously calculated row or column. There is no need to perform calculations when any of coordinates is equal to 0 or 1. This will be implemented in the final solution.</p>
<p>It&#8217;s time to introduce checkpoint into consideration. And the next sub-task that should be solved is finding how many shortest paths S(m,n,M,N) exist from origin (0,0) to the goal (M,N) through checkpoint (m,n), such that (**):</p>
<ul>
<li>(m,n)!=(0,0)</li>
<li>(m,n)!=(M,N)</li>
<li>0 &lt;= m &lt;= M and 0 &lt;= n &lt;= N</li>
</ul>
<p><a href="http://protsyk.com/cms/wp-content/uploads/2012/03/checkpoint3.png"><img class="aligncenter size-full wp-image-453" title="checkpoint3" src="http://protsyk.com/cms/wp-content/uploads/2012/03/checkpoint3.png" alt="" width="256" height="230" /></a></p>
<p align="center">Path from the origin through checkpoint towards the goal</p>
<p>Combinatorial rule of product gives us the answer:</p>
<p align="center">S(m,n,M,N) = G(m,n) * G(M-m, N-n)</p>
<p>So, the ultimate task is the following. Over all possible combinations of (m,n) and (M,N) find such that:</p>
<p align="center">S = S(m,n,M,N)</p>
<p align="center">T = argmin<sub>M,N</sub>(M+N) where m,n,M,N satisfy conditions (**)</p>
<p>There is one more sub-task left before we can formulate final algorithm to solve the problem: given an integer number S find all possible positive integers S1 and S2 such that:</p>
<ul>
<li>S = S1*S2</li>
<li>S1&lt;=S2</li>
</ul>
<p>This problem is a special case of integer factorization problem. The algorithm to factor any integer number into two multipliers is as simple as:</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">        int s1 = 1;
        int threshold = (int)Math.Sqrt(s) + 1;

        while (s1 &lt; = threshold) {
            int ost = s % s1;
            if (ost == 0) {
                int s2 = s / s1;
                if (s2 &lt; s1) break;
	        // Output s1*s2 = s
            }
            s1++;
        }</pre>
<p><strong>Problem solution</strong></p>
<p>It is time to formulate an algorithm that solves given task:</p>
<ul>
<li><strong>1)</strong>If S = 1 output 2.</li>
<li><strong>2)</strong>Factor input number S into all possible multipliers S1*S2, S1&lt;=S2
<ul>
<li>a. For each S1, S2
<ul>
<li>i.  Find all points (m1,n1) and (m2,n2) such that G(m1,n1)=S1, G(m2,n2)=S2. To calculate point (m1, n1). Build rows of triangular matrix G until numbers in the row are less than S1. If number G(x,y) = S1, then use m1=x, n1 = y. There are might be several such (m1,n1) in the matrix.
<ul>
<li>1. For each found (m1,n1),(m2,n2) find minimum T<sub>0 </sub> of m1+n1+m2+n2.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><strong>3)</strong>The smallest found T<sub>0</sub> is a solution.</li>
</ul>
<p>There is always a solution for any number S. If S is a prime, then there is only one factorization: S = 1*S and one possible solution: from origin (0,0) go to closest checkpoint (1,0) and to the point (1,S-1); T = 1+0+1+S-1 = S+1;</p>
<p>Example: consider S = 9.</p>
<p><strong>1) </strong>Factorization gives us two pairs (1,9) and (3,3).</p>
<ol>
<li>For S1 = 1, this is boundary case, take one point (1,0)</li>
<li>For S2 = 9, there is one point (1,8)
<ul>
<li>i. T<sub>0</sub> = 1+0+1+8=10</li>
</ul>
</li>
</ol>
<ol>
<li>For S1 = 3, this is boundary case, take one point (1,2)</li>
<li>For S2 = 3, this is boundary case, take one point (1,2)
<ul>
<li>i. T<sub>0</sub> = 1+2+1+2=6</li>
</ul>
</li>
</ol>
<p><strong>2) </strong>The smallest found T<sub>0</sub> is <strong>6</strong>.</p>
<p>There is no need to recalculate matrix G for each number S. Instead in the solution the rows of the matrix G will be built until numbers in the row are less than 10000000 (task constraint). Based on the matrix, a mapping from integer to a list of points &lt; (x1,y1), (x2,y2), &#8230; &gt; will be created, such that for each point (x,y) in the list of number N: N = G(x,y). Which means that step <strong>2.a.i</strong> is no more than two lookups in such a mapping. The program can build a mapping once and reuse it while processing all test cases.</p>
<p><strong>Time complexity analysis</strong></p>
<p>The program should complete 20 test cases in less than 6 minutes. Building a mapping takes around 13 seconds on my laptop and ~1Gb of RAM which is acceptable. The rest is spent on factorizing and finding minimum values. There are two things I checked before I was convinced that my solution works fast enough to finish execution in 6 minutes:</p>
<ul>
<li><strong>The longest list of points in the mapping</strong>. Surprisingly enough, the longest list appears for the number 3003 and the length is 4. So, in the worst case it will lead to a loop of 4*4=16 iterations at the step <strong>2.a.i.1. </strong>That should not be of any performance problem.</li>
<li>The number in the range of [0.. 10000000] that factorized into maximum number of two different multipliers. I have performed factorization of all numbers, it took about ~3 minutes. This magic number is 8648640 giving 224 pairs of numbers.</li>
</ul>
<p>So the worst possible input is 20 numbers equal to 8648640. Running the program on this input proves that on my machine it will take less than 15 seconds for any possible input. Most of that time spent on building the mapping.</p>
<p><strong>Results</strong></p>
<p>The initial solution was coded in C#, submitted and accepted by Facebook:</p>
<p><a href="http://protsyk.com/cms/wp-content/uploads/2012/03/Round2.png"><img class="aligncenter size-full wp-image-456" title="Round2" src="http://protsyk.com/cms/wp-content/uploads/2012/03/Round2.png" alt="" width="625" height="82" /></a></p>
<p>The code that uses all above mentioned optimizations runs much faster and completes all test cases almost instantly. The code could be obtained by the following link: <a href="https://github.com/PetroProtsyk/Sources/blob/master/Facebook%20Hackerup%202012/Checkpoint/Checkpoint.cs">Final Checkpoint Solution</a> or executed at <a href="http://ideone.com/8FVw5">Ideone.com</a></p>
<p><strong>Links</strong></p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Block_walking">http://en.wikipedia.org/wiki/Block_walking</a></li>
<li><a href="http://en.wikipedia.org/wiki/Rule_of_product">http://en.wikipedia.org/wiki/Rule_of_product</a></li>
<li><a href="http://en.wikipedia.org/wiki/Factorization">http://en.wikipedia.org/wiki/Factorization</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=449</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Happy New 2012 Year!!!</title>
		<link>http://protsyk.com/cms/?p=423</link>
		<comments>http://protsyk.com/cms/?p=423#comments</comments>
		<pubDate>Sat, 31 Dec 2011 13:27:10 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[Posts]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=423</guid>
		<description><![CDATA[Best of luck in new Year!]]></description>
			<content:encoded><![CDATA[<p><center><br />
<a href="http://protsyk.com/cms/wp-content/uploads/2011/12/2011-12-21-13.25.38-e1325337927488.jpg"><img src="http://protsyk.com/cms/wp-content/uploads/2011/12/2011-12-21-13.25.38-e1325337927488.jpg" alt="" title="2011-12-21 13.25.38" width="292" height="571" class="aligncenter size-full wp-image-424" /></a></p>
<p>Best of luck in new Year!<br />
</center></p>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=423</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++ 11 regex based tokenizer</title>
		<link>http://protsyk.com/cms/?p=394</link>
		<comments>http://protsyk.com/cms/?p=394#comments</comments>
		<pubDate>Fri, 30 Dec 2011 19:49:33 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[C++ Blacksmith]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=394</guid>
		<description><![CDATA[Tokenization is quite common task in many software applications. Tokenization is a process of splitting text into tokens. For example, text: &#8220;This is an example&#8221;. Might be split into following tokens: &#8220;this&#8221; &#8220;is&#8221; &#8220;an&#8221; &#8220;example&#8221;. Recently I saw nice video &#8230; <a href="http://protsyk.com/cms/?p=394">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Tokenization is quite common task in many software applications. Tokenization is a process of splitting text into tokens. For example, text: &#8220;This is an example&#8221;. Might be split into following tokens: &#8220;this&#8221; &#8220;is&#8221; &#8220;an&#8221; &#8220;example&#8221;.</p>
<p>Recently I saw nice video from Stephan T. Lavavej where he presents <a href="http://blogs.msdn.com/b/vcblog/archive/2010/11/18/regular-expressions-video-introduction-to-the-stl-part-8.aspx">regular expressions</a>  from C++&#8217;s STL library. In this video he mention an interesting use case, where regular expressions might be used to create tokenizers. Usually when writing tokenizers one would express rules for matching tokens, while in the proposed approach you are expected to write rules for matching token separators. Piece of the text that does not match regex for separator is your token.</p>
<p>I have tried to write something more complicated than just splitting text using whitespace characters as separators. Tokenization then became a two phase process:</p>
<ul>
<li> At the first stage, tokenizer will split input text using whitespaces. </li>
<li> At the second stage, tokens will be matched against a set of regular expressions. This set contains regular expressions for matching:
<ul>
<li> numbers, </li>
<li> urls, </li>
<li> e-mail addresses, </li>
<li> dates. </li>
</ul>
<p>      Once text from the first stage match one of the given regexes it will be converted into token of specific type. Otherwise the text will be split into sub-tokens using punctuation characters.
 </li>
</ul>
<p>Here is an example. The text: &#8220;My birthday is 20/01/1984&#8243;, will be first split into following tokens:<br />
<br />
 &#8220;My&#8221; &#8220;birthday&#8221; &#8220;is&#8221; &#8220;20/01/1984&#8243;<br />
<br />
Then each token will be matched against more restrictive regular expressions. &#8220;20/01/1984&#8243; will be recognized as date.</p>
<p>As mentioned in the video there are specializations of regex type for string types: string and wstring. However, I wanted my tokenizer to work well with files. According to standard regex require bidirectional iterators. So, I&#8217;ve decided to write very simple implementation of a custom bidirectional file based iterator. It provides buffered access to ASCII text files and might be found in attached solution.</p>
<p>Downloads: <a href="/cms/wp-content/uploads/2011/12/RegExpTokenizer.zip">Regex tokenizer C++ solution</a>.</p>
<p><i>Final thoughts.</i> Even though presented approach looks promising, regular expressions are very powerful in capturing various patterns, implementation appears to perform slow comparing to handwritten tokenizer. So, it is only practical for parsing small files. On my Dell Studio 1555 laptop (Intel Core 2 Duo P8700 2.53GHz with 4GB of RAM and x64 Windows 7) the speed of tokenization is only about 400-800 Kilobytes per second comparing to handwritten tokenizer reaching about 5-10 megabytes per second.</p>
<p>In my example I&#8217;ve used some regular epxressions from the following website: http://regexlib.com.</p>
<p>A good introduction to TR1 C++ regular expressions might be found <a href="http://www.johndcook.com/cpp_regex.html">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=394</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Measure 9 minutes with 7 and 4 minutes hourglasses</title>
		<link>http://protsyk.com/cms/?p=415</link>
		<comments>http://protsyk.com/cms/?p=415#comments</comments>
		<pubDate>Thu, 29 Dec 2011 20:55:22 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[Puzzles]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=415</guid>
		<description><![CDATA[Today, I&#8217;ve read a blog about this year oddest job interview questions. Among really odd questions there is actually an interesting one that gave me today about 5 minutes of pleasant thinking and about half of hour drawing the solution &#8230; <a href="http://protsyk.com/cms/?p=415">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Today, I&#8217;ve read a blog about this year <a href="http://mashable.com/2011/12/27/glassdoor-interview-questions-2011/">oddest job interview questions</a>. Among really odd questions there is actually an interesting one that gave me today about 5 minutes of pleasant thinking and about half of hour drawing the solution which am about to share.</p>
<p>Here is a puzzle: <strong>Using only a four-minute hourglass and a seven-minute hourglass, measure exactly nine minutes–without the process taking longer than nine minutes</strong></p>
<p>Here is my solution:<br />
<a href="http://protsyk.com/cms/wp-content/uploads/2011/12/Hourglass.png"><img src="http://protsyk.com/cms/wp-content/uploads/2011/12/Hourglass.png" alt="" title="Hourglass" width="388" height="735" class="aligncenter size-full wp-image-417" /></a></p>
<p><a href="http://protsyk.com/cms/wp-content/uploads/2011/12/Hourglass-legend.png"><img src="http://protsyk.com/cms/wp-content/uploads/2011/12/Hourglass-legend.png" alt="" title="Hourglass - legend" width="195" height="288" class="aligncenter size-full wp-image-416" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=415</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Approximation of circle with rectangles</title>
		<link>http://protsyk.com/cms/?p=374</link>
		<comments>http://protsyk.com/cms/?p=374#comments</comments>
		<pubDate>Mon, 26 Dec 2011 18:53:47 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[.NET Corner]]></category>
		<category><![CDATA[Puzzles]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=374</guid>
		<description><![CDATA[Quad tree is an interesting data structure. It is used for solving various geometrical problems, such as fast collision detection, indexing of geospacial data, etc. I am going to show how it might be used for approximation of different 2D &#8230; <a href="http://protsyk.com/cms/?p=374">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Quadtree">Quad tree</a> is an interesting data structure. It is used for solving various geometrical problems, such as fast collision detection, indexing of geospacial data, etc. I am going to show how it might be used for approximation of different 2D shapes. (There is also 3D version of quad trees, called <a href="http://en.wikipedia.org/wiki/Octree">octal tree</a>).</p>
<p>Let&#8217;s start with a final result of the algorithm:<br />
<a href="/cms/wp-content/uploads/2011/12/QuadCircle_1.png"><img src="/cms/wp-content/uploads/2011/12/QuadCircle_1.png" alt="" title="Quad tree for circle" width="305" height="305" class="aligncenter size-full wp-image-376" /></a></p>
<p>Small white rectangles approximate circle&#8217;s border. Red rectangles form an inner area of the circle. Yellow does not belong to the circle and might be removed.</p>
<p>Building quad tree is simple. We start from the bounding rectangle. Then it will be split into four smaller rectangles of the equal size. Let&#8217;s say, input rectangle is defined by following points (x1,y1) -> (x2,y2). Then rules for splitting it into four smaller rectangles are following:</p>
<ul>
<li> (x1, y1) -> (x2-width/2,y2-height/2) </li>
<li> (x1, y1+height/2) -> (x1+width/2,y2) </li>
<li> (x2-width/2, y2-height/2) -> (x2,y2) </li>
<li> (x2-width/2, y1) -> (x2,y2-height/2) </li>
</ul>
<p>This procedure might be recursively applied to all leafs in the tree until new leaf rectangles reach certain size.</p>
<p>In order to make a decision if given leaf rectangle should be split, we need a function <b>f</b>, which for a given rectangle <b>r</b> will return how many of its verteces belong to the figure. There are obviously four cases:</p>
<ul>
<li> f(r) = 4 &#8211; Rectangle belongs to the inner area of the figure. No further split required. (Such rectangles are red) </li>
<li> f(r) = 3 or 2 &#8211; These rectangles touch the border of the figure and about half of the rectangle belongs to figure. (White rectangles) </li>
<li> f(r) = 1 &#8211; Less than half of the rectangle belongs to figure. (Gray rectangles) </li>
<li> f(r) = 0 &#8211; Rectangle lays outside the figure. No further split required. (Yellow rectangles) </li>
</ul>
<p>For a circle, function <b>f</b> is quite simple:</p>
<ul>
<li>f(x1,y1,x2,y2) = belongs(x1,y1)+belongs(x1,y2)+belongs(x2,y2)+belongs(x2,y2), </li>
</ul>
<p>Where </p>
<ul>
<li>belongs(x,y) = 1, if x*x+y*y< =r*r and 0 otherwise,</li>
</li>
<li>r &#8211; is the radius of the circle.</li>
</ul>
<p>There is a C# solution that shows this basic algorithm: <a href="/cms/wp-content/uploads/2011/12/QuadCircle.zip">Download</a>.</p>
<p>By modifying function <b>f</b>, one can adopt this algorithm for other 2D figures.</p>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=374</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>11:11:11 11.11.11</title>
		<link>http://protsyk.com/cms/?p=358</link>
		<comments>http://protsyk.com/cms/?p=358#comments</comments>
		<pubDate>Fri, 11 Nov 2011 10:11:18 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[Posts]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=358</guid>
		<description><![CDATA[What a date! What a time! Celebrate!]]></description>
			<content:encoded><![CDATA[<p>What a date! What a time! Celebrate!</p>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=358</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamic Code Execution &amp; Scripting in .NET 4.0</title>
		<link>http://protsyk.com/cms/?p=335</link>
		<comments>http://protsyk.com/cms/?p=335#comments</comments>
		<pubDate>Wed, 06 Jul 2011 19:05:48 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[.NET Corner]]></category>
		<category><![CDATA[Script.NET]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=335</guid>
		<description><![CDATA[In the modern software engineering extendibility (also known as extensibility, i.e. capable of being extended) is recognized as a key property of a software system. Extendibility is an extension of the software without changing existing code. Principles, guidelines and tools &#8230; <a href="http://protsyk.com/cms/?p=335">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the modern software engineering extendibility (also known as extensibility, i.e. capable of being extended) is recognized as a key property of a software system. Extendibility is an extension of the software without changing existing code.</p>
<p>Principles, guidelines and tools were developed to facilitate creation of extendible systems. For examples refer to the following links:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ee658124.aspx">Key Principles of Software Architecture</a>,</li>
<li><a href="http://mef.codeplex.com/">Managed Extensibility Framework</a>,</li>
<li><a href="http://unity.codeplex.com/">Unity Application Block</a>,</li>
</ul>
<p>In this post I am going to present two ways of implementing another common technique towards building extendible software using .NET Framework 4. In other words I am going to show how to create scriptable applications, i.e. applications controlled by script. Scriptable application allows extending its base functionality by means of user scripts, like Excel allows user creating a VBScript which performs common operations.</p>
<p>I have already posted few articles and solutions on this topic:</p>
<ul>
<li>Building DLR scripting language:
<ul>
<li><a href="http://protsyk.com/cms/?p=152">Simple DLR language</a></li>
<li><a href="http://protsyk.com/cms/?p=157">Creating Variable in DLR (DLR Language – Part 2)</a></li>
<li><a href="http://protsyk.com/cms/?p=161">DLR Language with Generated parser (Part 3)</a></li>
<li><a href="http://protsyk.com/cms/?p=233">Expression evaluator in 15 minutes with Irony &#038; Dlr</a></li>
</ul>
</li>
<li><a href="http://www.protsyk.com/scriptdotnet/">S# is a complete scripting solution for .NET</a>, </li>
</ul>
<p>However as development platforms and tools evolve, new efficient ways of doing certain things appear.  Approaches based on dynamic assembly generation and Lambda expressions will be presented.</p>
<p>Let’s start with Lambda expressions, as a preferred approach for simple scenarios. It is possible to construct expression at runtime and compile it to dynamic method (Dynamic method is a garbage collected object):</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
var argument = Expression&lt;Func&lt;int, bool&gt;&gt;
                      .Parameter(typeof(int), &quot;p&quot;);
var expression = Expression&lt;Func&lt;int, bool&gt;&gt;
  .Lambda&lt;Func&lt;int, bool&gt;&gt;(
   Expression&lt;Func&lt;int, bool&gt;&gt;
    .LessThan(argument, Expression&lt;Func&lt;int, bool&gt;&gt;.Constant(5)),
       argument);
</pre>
<p>Which is essentially the same as following lambda function in C#: <strong>p=>p&lt;5</strong>.</p>
<p>Now expression could be compiled and executed:</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
 Func&lt;int, bool&gt; function = (Func&lt;int, bool&gt;)expression.Compile();
 bool result = function(4);
</pre>
<p>So, what is required to build scripting language out of lambda expressions? Of course you will need a parser for your language. There are a lot of information and tools available on this topic. I will just mention following: <a href="http://www.antlr.org/">ANTLR</a> parser generator, <a href="http://www.devincook.com/goldparser/">GOLD Parsing System</a>, <a href="http://irony.codeplex.com/">Irony</a>, and of course <a href="http://dinosaur.compilertools.net/">Lex &#038; Yacc</a> . Excellent book describing underlying theory is also available: <a href="http://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools">Compilers: Principles, Techniques, and Tools</a></p>
<p>For demonstration purposes I’ve built simple <a href="http://en.wikipedia.org/wiki/Recursive_descent_parser">recursive descent parser</a> for arithmetic expressions. It could recognize arithmetic expressions composed of integer constants and +,-,*, / operations and build lambda expression out of it:</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
 LambdaExpression expression = Parser.ParseCode("3+(5-1)*2");
</pre>
<p>Lambda expression as we saw before could be compiled as delegate:</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
 Func&lt;double&gt; function = (Func&lt;double&gt;)expression.Compile();
</pre>
<p>The function might now be executed:</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
 double result = function(); // result = 11
</pre>
<p>This is already a step towards extendible software. Imagine that user could define expression as string value; input it to the application somehow (via GUI, configuration, services) and application can execute it. Of course to be of real value your expression language should provide ways to interact with application object model. This could be achieved via functions, objects, messages, etc.  Look for example at <a href="http://msdn.microsoft.com/en-us/library/wss56bz7(v=vs.80).aspx">Excel Object Model</a> and how it could be accessed from VBA.</p>
<p>Designing a language for an application and then writing a parser could be unrealistic task for many projects. Back in 2008 at PDC Anders Hejlsberg talked about rewriting the C# compiler and providing a &#8220;compiler as a service&#8221;. Unfortunately this does not happen, but there is an old API around csc command line compiler, which allows compiling code from managed .NET application into new assembly. This assembly could be then dynamically loaded and used from a host application. The main drawback of this approach is that in .NET, assembly can’t be unloaded from the memory once it had been loaded. The only possible way to do this is to create a dedicated AppDomain, load new assembly into this domain, execute it and then unload the whole domain. In some scenarios such approach could be beneficial, especially if overhead of compilation and creating new AppDomain could be neglected.</p>
<p>An approach based on dynamic assembly compilation could be found in DynamicCodeExecutor.cs. It has two classes: DynamicCompiler and DynamicCodeExecutor.</p>
<p>The purpose of DynamicCompiler is to compile provided C# code into assembly using CSharpCodeProvider and load it into current application domain. Then it might be used to execute static public method of any public class from generated assembly (see method Execute).</p>
<p>DynamicCodeExecutor creates a new application domain and instantiates an instance of DynamicCompiler object in this new domain. In order to perform that, DynamicCompiler should be serializable and inherited from MarshalByRefObject.</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
AppDomainSetup domainSetup = new AppDomainSetup();
domainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
domainSetup.DisallowBindingRedirects = false;
domainSetup.DisallowCodeDownload = true;
domainSetup.ConfigurationFile = AppDomain.CurrentDomain
                            .SetupInformation.ConfigurationFile;

AppDomain workerAppDomain = AppDomain
            .CreateDomain(&quot;Compiler&quot;, null, domainSetup);

DynamicCompiler compiler = (DynamicCompiler)workerAppDomain
            .CreateInstanceAndUnwrap(
                 typeof(DynamicCompiler).Assembly.GetName().Name,
                 typeof(DynamicCompiler).FullName);
</pre>
<p>After that, it invokes Compile method of DynamicCompiler. On successful compilation, it will call execute method with provided arguments. Finally, DynamicCodeExecutor unloads AppDomain and deletes generated assembly. </p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
 IEnumerable&lt;CompilerError&gt; results
                   = compiler.Compile(code, assemblies);
 object result = compiler.Execute(type, method, args);
 AppDomain.Unload(workerAppDomain);
</pre>
<p>Here is a code snippet that shows how DynamicCodeExecutor could be used in C# code:</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
Console.WriteLine(DynamicCodeExecutor.CompileAndExecute(
     @&quot;class DynamicClass{
         public static string DynamicMethod(string name){
              return name.ToUpper();
         }
          }&quot;,
         &quot;DynamicClass&quot;,
         &quot;DynamicMethod&quot;,
         new object[] { &quot;Hello World&quot; },
         new string[] { &quot;System.dll&quot; }));
</pre>
<p>There is however a third way available. Any .NET application could become scriptable by using S# scripting language. S# is a weakly-typed dynamic language and runtime infrastructure for making extendable, customizable and highly flexible applications. It allows introducing expressions and large code blocks within your applications in the similar way Microsoft Office deals with VBScript. It gives possibilities for providing rich formula evaluation capabilities like it can be seen in Microsoft Excel and other office applications.</p>
<p>Minimal usage scenario contains only 3 lines of code:</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
 RuntimeHost.Initialize();
 Script.RunCode(&quot;Console.WriteLine(&#39;This is Script&#39;);&quot;);
 RuntimeHost.CleanUp();
</pre>
<p>More about S# could be found at: <a href="http://www.protsyk.com/scriptdotnet/wiki/index.php?title=Main_Page">S# Wiki</a>.</p>
<p><strong>Conclusions</strong></p>
<p>I have demonstrated three different ways for introducing dynamic code execution in .NET application. Each of these approaches has different usage scenarios and strong points. Lambda expressions are good for simple arithmetic calculations. Generating dynamic assembly on the other hands allows utilizing full power of C# and .NET libraries; however it is not always suitable because of performance overhead on compilation and AppDomain creation, security limitations, etc. S# is a good compromise that combines expressive power of programming language and ability to use .NET libraries and efficient interpreter purely written in C #that does not involve any code generation and IL emitting.</p>
<p><strong>Downloads</strong></p>
<p><a href='http://protsyk.com/cms/wp-content/uploads/2011/07/DynamicCode.zip'>Example Source Code</a></p>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=335</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Facebook Hacker Cup 2011 Qualification – Studious Student (Solution in C#)</title>
		<link>http://protsyk.com/cms/?p=321</link>
		<comments>http://protsyk.com/cms/?p=321#comments</comments>
		<pubDate>Sun, 26 Jun 2011 17:37:24 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[Puzzles]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=321</guid>
		<description><![CDATA[Studious Student You’ve been given a list of words to study and memorize. Being a diligent student of language and the arts, you’ve decided to not study them at all and instead make up pointless games based on them. One &#8230; <a href="http://protsyk.com/cms/?p=321">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>Studious Student</em><br />
You’ve been given a list of words to study and memorize. Being a diligent student of language and the arts, you’ve decided to not study them at all and instead make up pointless games based on them. One game you’ve come up with is to see how you can concatenate the words to generate the lexicographically lowest possible string.</p>
<p><em>Input</em><br />
As input for playing this game you will receive a text file containing an integer N, the number of word sets you need to play your game against. This will be followed by N word sets, each starting with an integer M, the number of words in the set, followed by M words. All tokens in the input will be separated by some whitespace and, aside from N and M, will consist entirely of lowercase letters.</p>
<p><em>Output</em><br />
Your submission should contain the lexicographically shortest strings for each corresponding word set, one per line and in order.<br />
Constraints</p>
<p>1 < = N <= 100<br />
1 <= M <= 9<br />
1 <= all word lengths <= 10</p>
<p>Solution in C#:</p>
<pre class="brush:csharp; ruler: false; gutter:false; toolbar:false">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication6 {
    class Program {
        static int N;

        static void Main(string[] args) {
            string s = File.ReadAllText(args[0]);
            string[] splits = s.Split(new char[] { '\n', '\r' },
                              StringSplitOptions.RemoveEmptyEntries);

            N = int.Parse(splits[0]);
            for (int i = 1; i < N + 1; i++) {
                string[] words = splits[i]
                                         .Split(' ')
                                         .Skip(1)
                                         .ToArray();

                Console.WriteLine(Solve(words));
            }
        }

        private static string Solve(string[] words) {
            string prefix = string.Empty;
            List<string> sorted = new List<string>(words);

            while (true) {
                sorted = sorted.OrderBy(x => x).ToList();
                if (sorted.Count == 0) break;

                string pr = sorted.First();
                string sf = sorted.Skip(1)
                                .Where(a => a.StartsWith(pr))
                                .Select(s => s.Substring(pr.Length))
                                .Where(s => !string.IsNullOrEmpty(s))
                                .OrderBy(x => x + pr)
                                .FirstOrDefault();

                if (string.Compare(pr + pr, pr + sf) < 0)
                    sf = null;

                prefix += pr + sf;
                sorted.Remove(pr + sf);
            }

            return prefix;
        }
    }
}
</pre>
<p>Sources: <a href="https://github.com/PetroProtsyk/Sources/blob/master/Puzzles/StudiousStudent/StudiousStudent.cs">C# Implementation</a></p>
<p>Examples:</p>
<ul>
<li><a href='wp-content/uploads/2011/06/facebook1.txt'>Sample Input/Output 1</a></li>
<li><a href='wp-content/uploads/2011/06/facebook2.txt'>Sample Input/Output 2</a></li>
</ul>
<p></string></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=321</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Software Quality Assurance &amp; Testing</title>
		<link>http://protsyk.com/cms/?p=288</link>
		<comments>http://protsyk.com/cms/?p=288#comments</comments>
		<pubDate>Wed, 13 Apr 2011 18:12:45 +0000</pubDate>
		<dc:creator>ppp_extr</dc:creator>
				<category><![CDATA[Posts]]></category>

		<guid isPermaLink="false">http://protsyk.com/cms/?p=288</guid>
		<description><![CDATA[For those who are interested in Software Quality Assurance and Testing, I am proudly announcing a new blog devoted to the topic: link to posts. The blog will be maintained by Mariya Bezverkha, PhD and lecturer in Computer Science. It will &#8230; <a href="http://protsyk.com/cms/?p=288">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For those who are interested in Software Quality Assurance and Testing, I am proudly announcing a new blog devoted to the topic: <a href="http://protsyk.com/qa">link to posts</a>.</p>
<p>The blog will be maintained by Mariya Bezverkha, PhD and lecturer in Computer Science. It will contain various learning materials, lab practicums, book overviews, etc. Blog languages are: English, Ukrainian.</p>
<p>Published information targeted on students in computers science &amp; software engineering, quality assurance engineers (QA), and university teachers.</p>
]]></content:encoded>
			<wfw:commentRss>http://protsyk.com/cms/?feed=rss2&#038;p=288</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

