<?xml version="1.0" encoding="UTF-8"?>
<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>web(cslai) &#187; Software Engineering</title>
	<atom:link href="http://cslai.coolsilon.com/category/software-engineering/feed/" rel="self" type="application/rss+xml" />
	<link>http://cslai.coolsilon.com</link>
	<description>Findings and Notes in Web Development</description>
	<lastBuildDate>Tue, 06 Sep 2011 08:15:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>How to solve all puzzles at 4clojure in a week</title>
		<link>http://cslai.coolsilon.com/2011/06/02/how-to-solve-all-puzzles-at-4clojure-in-a-week/</link>
		<comments>http://cslai.coolsilon.com/2011/06/02/how-to-solve-all-puzzles-at-4clojure-in-a-week/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 16:30:41 +0000</pubDate>
		<dc:creator>Jeffrey04</dc:creator>
				<category><![CDATA[Software Engineering]]></category>

		<guid isPermaLink="false">http://cslai.coolsilon.com/?p=230</guid>
		<description><![CDATA[I was trying to learn scala and clojure to find one that I may want to use in my postgraduate project. After trying to learn scala for a couple of days, I gave up because I really don&#8217;t like the syntax (too OO for my liking). Then I continued with clojure and found myself liking [...]]]></description>
			<content:encoded><![CDATA[<p>I was trying to learn <a href="http://www.scala-lang.org/">scala</a> and <a href="http://www.clojure.org/">clojure</a> to find one that I may want to use in my postgraduate project. After trying to learn scala for a couple of days, I gave up because I really don&#8217;t like the syntax (too OO for my liking). Then I continued with clojure and found myself liking the syntax better.</p>
<p><span id="more-230"></span></p>
<p>I briefly tried <a href="http://www.haskell.org/">haskell</a> through <a href="http://tryhaskell.org/">this interactive tutorial</a> before starting scala, so I first started with this <a href="http://try-clojure.org/">clojure equivalent web-app</a>. It is a great tutorial, but not quite enough to get myself started to code, so I went on with this <a href="https://github.com/relevance/labrepl">Labrepl</a> tutorial guide. The first few sessions was great but it became a bit difficult to follow due to the lack of instruction. Probably I am just being impatient.</p>
<p>A guy nicknamed raek at #clojure irc then suggested <a href="http://blip.tv/clojure">a couple of</a> <a href="http://learn-clojure.com/">other</a> <a href="http://java.ociweb.com/mark/clojure/article.html">resources</a> that I may be interested in. One of them is a web-app called <a href="https://4clojure.com/">4clojure</a>. Basically it is an app that creates a series of puzzles that let u fill in the blanks so that the statement becomes valid.</p>
<p>After about a week (started last Thursday, and finished on 1st June!), I have solved all posted puzzles (99 in total, and new puzzles are frequently added). The first few puzzles are kinda straight forward, but the later ones took me like hours to half a day to actually came out with a rough idea. Implementing it also took quite some time as I am still not used to programming in functional way.</p>
<p>Some of the puzzles that I kinda like, although the code count is on the high side of the histogram (most people solves the same problem with less code). Besides, I don&#8217;t really care about computation complexity because I have not learned it in proper manner (lol, that means I don&#8217;t really understand Big-O notation)</p>
<h2><a href="https://4clojure.com/problem/94">Game of Life</a> (Problem 94)</h2>
<p>Assuming everyone knows about the game, I guess I would just post the solution straight away.</p>
<pre><code>(fn [i-board]
     (let [
           c-count (count (first i-board))
           r-count (count i-board)
           in-board (fn [i-coor]
                            (let [[i-row i-col] i-coor]
                              (and
                                (>= i-row 0)
                                (< i-row r-count)
                                (>= i-col 0)
                                (< i-col c-count))))
           has-life (fn [i-coor]
                        (= \# (nth (nth i-board (first i-coor)) (last i-coor))))
           board-coor (reduce
                        concat
                        '()
                        (map
                          (fn [my-row]
                              (map #(vector my-row %) (range c-count)))
                          (range r-count)))
           live-list (filter has-life board-coor)
           dead-list (filter #(not (has-life %)) board-coor)
           neighbour (fn [i-coor]
                         (let [[i-row i-col] i-coor]
                           (filter
                             #(let [[my-row my-col] %] (not (and (= my-row i-row) (= my-col i-col))))
                             (reduce
                               concat
                               '()
                               (map
                                 (fn [i-coors]
                                     (filter in-board i-coors))
                                 (map
                                   (fn [my-row]
                                       (map
                                         (fn [my-col]
                                             (vector my-row my-col))
                                         (range (dec i-col) (+ i-col 2))))
                                   (range (dec i-row) (+ i-row 2))))))))
           living-neighbour (fn [i-coor] (filter has-life (neighbour i-coor)))
           lives-on (fn [i-coor]
                        (let [n-count (count (living-neighbour i-coor))]
                          (or (= 2 n-count) (= 3 n-count))))
           reproducible (fn [i-coor]
                            (= 3 (count (living-neighbour i-coor))))
           new-lives (group-by
                       #(first %)
                       (concat
                         (filter lives-on live-list)
                         (filter reproducible dead-list)))
           draw-row (fn plot-lives
                        ([i-row] (plot-lives [] 0 (sort (map last (get new-lives i-row)))))
                        ([result i-pos i-lives]
                         (if (= c-count i-pos)
                           (apply str result)
                           (let [c-life (first i-lives) n-pos (inc i-pos)]
                             (if (= i-pos c-life)
                               (plot-lives (conj result \#) n-pos (rest i-lives))
                               (plot-lives (conj result \space) n-pos i-lives))))))
           ]
       (map draw-row (range r-count))))</code></pre>
<p>OK, I know this is one of the longest solution one can write (and perhaps not the most efficient way).</p>
<h2><a href="https://4clojure.com/problem/92">Roman Numbers</a> (Problem 92)</h2>
<p>Completing this also mean I need to be able to read the numbers properly too.</p>
<pre><code>(fn roman
     ([i-literal] (roman 0 i-literal))
     ([i-result i-literal]
      (if (zero? (count i-literal))
        i-result
        (let [
              v-map {\I 1, \V 5, \X 10, \L 50, \C 100, \D 500 \M 1000}
              head (first i-literal)
              tail (rest i-literal)
              t-head (first tail)
              ]
          (if (and (not (nil? t-head)) (> (get v-map t-head) (get v-map head)))
            (roman (+ i-result (- (get v-map t-head) (get v-map head))) (rest tail))
            (roman (+ i-result (get v-map head)) tail))))))</code></pre>
<p>I really hate graphs/trees related puzzles, like this following puzzle.</p>
<h2><a href="https://4clojure.com/problem/91">Graph Connectivity</a> (Problem 91)</h2>
<p>Given a set of edges, find if the graph is connected.</p>
<pre><code>(fn [i-set]
     (let [
           nodes (reduce
                   #(conj (conj %1 (first %2)) (last %2))
                   #{}
                   i-set)

           n-count (count nodes)
           n-range (range n-count)
           n-map (apply hash-map (interleave nodes n-range))
           n-index (fn [i-node] (get n-map i-node))

           edges (concat i-set (map #(apply vector (reverse %)) i-set))
           grouped-edges (group-by #(n-index (first %)) edges)

           n-dest (fn [i-node]
                      (map last (get grouped-edges (n-index i-node))))
           walk-graph (fn discover
            ([i-node] (discover #{} (hash-set i-node)))
            ([result discovered]
             (if (zero? (count discovered))
               result
               (let [
                     current (first discovered)
                     n-result (conj result current)
                     new-nodes (filter #(not (contains? n-result %)) (n-dest current))
                     ]
                 (discover n-result (reduce conj (apply hash-set (rest discovered)) new-nodes))))))
           ]
       (= nodes (walk-graph (first (first i-set))))))</code></pre>
<p>This answer sort of gave me idea on how to solve the following 2 very similar questions (although most people don't agree). Note how I start not to care about the code length.</p>
<h2><del datetime="2011-06-01T15:57:37+00:00">Word Chain</del><a href="https://4clojure.com/problem/82">Word Ladder</a> (Problem 82)</h2>
<p>According to <a href="http://www.wikipedia.org/">Wikipedia</a>, the game is actually called <a href="http://en.wikipedia.org/wiki/Word_Ladder">Word Ladder</a> instead of <a href="http://en.wikipedia.org/wiki/Word_chain">Word Chain</a>.</p>
<pre><code>(fn [i-words]
     (let [
           n-count (count i-words)
           n-range (range n-count)
           n-map (apply hash-map (interleave i-words n-range))
           n-index (fn [i-word] (get n-map i-word))

           edit-distance (fn diff ([a-word b-word] (diff 0 a-word b-word))
                             ([distance a-word b-word]
                              (let [
                                    a-head (first a-word)
                                    b-head (first b-word)

                                    a-tail (rest a-word)
                                    b-tail (rest b-word)

                                    a-next (first a-tail)
                                    b-next (first b-tail)
                                    ]
                                (if (and (nil? a-head) (nil? b-head))
                                  distance
                                  (if (= a-head b-head)
                                    (diff distance a-tail b-tail)
                                    (if (= a-next b-head)
                                      (diff (inc distance) a-tail b-word)
                                      (if (= a-head b-next)
                                        (diff (inc distance) a-word b-tail)
                                        (diff (inc distance) a-tail b-tail))))))))
           edges (reduce
                   (fn [result i-word]
                       (reduce
                         #(conj %1 (vector i-word %2))
                         result
                         (filter #(= 1 (edit-distance i-word %)) i-words)))
                   #{}
                   i-words)
           grouped-edges (group-by #(n-index (first %)) edges)

           n-dest (fn [i-word]
                      (map last (get grouped-edges (n-index i-word))))

           build-chains (fn chain
                            ([i-word] (chain (dec n-count) (vector (vector i-word))))
                            ([i result]
                             (if (zero? i)
                               result
                               (chain
                                 (dec i)
                                 (reduce
                                   concat
                                   []
                                   (map
                                     (fn [i-chain]
                                         (map
                                           #(conj (apply vector i-chain) %)
                                           (filter #(not (contains? (apply hash-set i-chain) %)) (n-dest (last i-chain)))))
                                     result))))))
           ]
       (reduce
         (fn [result i-word]
             (if (false? result)
               (boolean (some #(= (count %) n-count) (build-chains i-word)))
               result))
         false
         i-words)))</code></pre>
<h2><a href="https://4clojure.com/problem/89">Graph Tour</a> (Problem 89)</h2>
<pre><code>(fn [i-edges]
     (let [
           nodes (reduce #(conj (conj %1 (first %2)) (last %2)) #{} i-edges)

           n-count (count nodes)
           n-range (range n-count)
           n-map (apply hash-map (interleave nodes n-range))
           n-index (fn [i-node] (get n-map i-node))

           e-count (count i-edges)

           edges-count (fn [my-edges]
                           (reduce
                             (fn [result i-edge]
                                 (let [[edge occurences] i-edge]
                                   (conj result (hash-map edge (count occurences)))))
                             {}
                             (group-by #(apply vector %) (map sort my-edges))))
           edge-count (fn [i-edge]
                          (let [e-count (edges-count i-edges)]
                            (get e-count i-edge 0)))

           edges (concat i-edges (map #(apply vector (reverse %)) i-edges))
           grouped-edges (group-by #(n-index (first %)) edges)

           n-dest (fn [i-node]
                      (reduce #(conj %1 (last %2)) #{} (get grouped-edges (n-index i-node))))

           build-chains (fn chain
                            ([i-edge] (chain (dec e-count) (vector (vector i-edge))))
                            ([i result]
                             (if (zero? i)
                               result
                               (chain
                                 (dec i)
                                 (reduce
                                   concat
                                   []
                                   (map
                                     (fn [i-chain]
                                         (let [
                                               t-node (last (last i-chain))
                                               n-edges (map #(vector t-node %) (n-dest t-node))
                                               ]
                                           (filter
                                             (fn [my-chain]
                                                 (reduce
                                                   (fn [result i-edge]
                                                       (let [[edge o-count] i-edge]
                                                         (and result (>= (edge-count edge) o-count))))
                                                   true
                                                   (edges-count my-chain)))
                                             (map #(conj i-chain %) n-edges))))
                                     result))))))
           ]
       (reduce
         (fn [result i-edge]
             (if (false? result)
               (boolean (some #(= (count %) e-count) (build-chains i-edge)))
               result))
         false
         i-edges)))</code></pre>
<p>I guess that's all for now lol. Oh, my supervisor's reaction (his primary language is probably JAVA) to scala and clojure was - try not to learn strange (weird) language. Then he mentioned about bad employment opportunity or something I don't really care to remember (I am actually trying very hard to avoid learning JAVA because I don't like it). So I guess this is it.</p>
<p>There may be some other interesting questions that I may have missed. Hopefully I will have the time to revisit on this and post more solutions.</p>
<div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://cslai.coolsilon.com/2011/06/02/how-to-solve-all-puzzles-at-4clojure-in-a-week/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>FSM-based Workflow System</title>
		<link>http://cslai.coolsilon.com/2008/07/22/fsm-based-workflow-system/</link>
		<comments>http://cslai.coolsilon.com/2008/07/22/fsm-based-workflow-system/#comments</comments>
		<pubDate>Mon, 21 Jul 2008 23:07:09 +0000</pubDate>
		<dc:creator>Jeffrey04</dc:creator>
				<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[FSM]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://cslai.coolsilon.com/?p=45</guid>
		<description><![CDATA[Recently I am being assigned to work on a FSM based workflow system to enable my other colleagues to use it in their application. I am rather impressed with the simplicity of the workflow system (initially designed by my Technical Director) and decided to post some notes here. The workflow system was developed for CodeIgniter [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I am being assigned to work on a FSM based workflow system to enable my other colleagues to use it in their application. I am rather impressed with the simplicity of the workflow system (initially designed by my Technical Director) and decided to post some notes here. The workflow system was developed for <a href="http://www.codeigniter.com/">CodeIgniter</a> PHP framework and Drupal CMS.</p>
<p><span id="more-45"></span></p>
<h2>What is <abbr title="Finite State Machine">FSM</abbr>?</h2>
<p>FSM, or Finite State Machine, as quoted from my good old lecture notes, is as follows:</p>
<blockquote><p>
A machine is a device which accepts some inputs, possibly produces some output, and has some memory sorting information on the overall results of all previous inputs.</p>
<p>The condition of the machine at a particular instance is called a state of the machine. New input changes the state, may be to another state, and may be to the same state. The effect of a new input depends on the present state the machine is in.</p>
<p>&#8230;If the total number of possible states is finite, the machine is called finite state machine, eg. a computer.</p></blockquote>
<h2>Why FSM?</h2>
<p>Because I find it easy to implement. In a work flowed application, for example a form processing system. Each form submitted has a state. After being reviewed by the supervisor (for example), then the state changes. With FSM, we can predict the next state of the record because it has to follow the state transition function defined.</p>
<h2>What about Access Control? What if the user tries to mess up the system?</h2>
<p>Because the system was designed to work together with <a href="http://www.drupal.org/">Drupal</a> <abbr title="Content Management System">CMS</abbr>, therefore we uses whatever Drupal is able to deliver to us. We have setup a couple of roles so that a user can be assigned to a number of roles. Then we define in our state transition table what role the user must play in order to perform the transition. Besides that, we also defined access control to the record in each state &#8211; only user playing one of the certain roles can read the record in specific state.</p>
<h2>Example Application</h2>
<p>Let&#8217;s say we have a FSM that models a simple Article Publshing System as follows:-</p>
<p><a href="http://cslai.coolsilon.com/wp-site/uploads/2008/07/fsm.png"><img class="size-medium wp-image-46 alignnone" title="Article Publishing System" src="http://cslai.coolsilon.com/wp-site/uploads/2008/07/fsm-300x245.png" alt="article publishing system" /></a></p>
<p>For simplicity&#8217;s sake we do not touch on access control here. As shown on the diagram (which is generated by <a href="http://www.graphviz.org/">graphviz</a>), this is a simple publishing system that shows a life-cycle of an article. Probably there should be more details (more states, more transitions) to be in but adding them in would make this article out of scope. You would probably notice that this does not look like a finite state machine that you see in your Discrete Mathematics textbook but we talk about this some other day.</p>
<p>Alright, the diagram should be self-explanatory enough. Each directed path/edge (arrowed lines) shows the transition flow from one state to another <strong>but not in reverse direction</strong>, i.e. an article in <em>Draft</em> state is not allowed to go back to <em>NEW</em> state. Next we see how are we going to represent the FSM in our database. First we need the record row,</p>
<p><em>posts (<span style="text-decoration: underline;">post_id</span>, title, content, state_id *)</em></p>
<p>where the <em>state_id</em> references the <em>post_states</em> below,</p>
<p><em>post_states (<span style="text-decoration: underline;">state_id</span>, name, description)</em></p>
<p>Followed by possible transitions:</p>
<p><em>post_transitions (<span style="text-decoration: underline;">transition_id</span>, name, description, from_state *, to_state *)</em></p>
<p>Before updating record in <em>posts</em> table, we should first check whether the transition is possible. Hence we need to gather two pieces of information before updating the record in the <em>posts</em> table. First is the post&#8217;s <em>state_id</em>, second is the transition <em>name</em>. If there is a record returned from <em>post_transitions</em>, we can obtain the next <em>state_id</em> of the post by referring to the <em>to_state</em> field. Otherwise the transition is invalid and should be canceled.</p>
<h2>Advantage</h2>
<p>Easy to understand, easy to maintain.</p>
<h2>Disadvantage</h2>
<p>Basically what we are doing right now is that we define the states and transition in a <abbr title="YAML Ain't Markup Language">YAML</abbr> configuration file. Then my work flow library will generate the corresponding <abbr title="Structured Query Language">SQL</abbr>, dot file to be used to generate <abbr title="Finite State Machine">FSM</abbr> diagram (as you can see above) and flowchart (yes, the <a href="http://en.wikipedia.org/wiki/Flowchart">flowchart</a>). Hence the main disadvantage with this approach is that changes must be handled carefully. Otherwise if you are not using an automated tool to maintain the FSM model in database, it shouldn&#8217;t cause much trouble.</p>
<p>Having a FSM based workflow system can greatly reduce the time taken to model and develop a workflowed system. What&#8217;s more exciting is that with this FSM based workflow system we can use this to as a base for history logging system. Unfortunately I have still doing some research in implementing the history logging system. However I found this article on <a href="http://database-programmer.blogspot.com/2008/07/history-tables.html">history table</a> posted by Downs on <a href="http://reddit.com/">reddit</a> yesterday and it definitely helps if you want to go on further.</p>
<p>You may be interested in the actual code but I do not think I am allowed to post the code. Anyway I am going to rewrite the workflow system to be used in my personal project which will be built with <a href="http://framework.zend.com/">Zend Framework</a>. However, I don&#8217;t think I will be offering the exactly same feature set that I develop for my company as I do not require all of them <img src='http://cslai.coolsilon.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> . After having the component written, I would post it online so that you can see how it is being implemented.</p>
<div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://cslai.coolsilon.com/2008/07/22/fsm-based-workflow-system/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

