<?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>OraQA &#187; SQL</title>
	<atom:link href="http://oraqa.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://oraqa.com</link>
	<description>Oracle Question and Answer</description>
	<lastBuildDate>Tue, 06 Jul 2010 00:08:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to find the Longest Common Subsequence (LCS) in SQL</title>
		<link>http://oraqa.com/2010/07/05/how-to-find-the-longest-common-subsequence-lcs-in-sql/</link>
		<comments>http://oraqa.com/2010/07/05/how-to-find-the-longest-common-subsequence-lcs-in-sql/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 00:08:52 +0000</pubDate>
		<dc:creator>Frank Zhou</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=607</guid>
		<description><![CDATA[The following is an interesting problem posted on the programming praxis website:
Longest Common Subsequence  
Finding the longest common subsequence of two sequences is a classic computer science problem with an equally
classic solution that dates to the folklore of computing. The longest common subsequence is the longest set of
elements that appear in order (not necessarily [...]]]></description>
			<content:encoded><![CDATA[<p>The following is an interesting problem posted on the <a href="http://programmingpraxis.com/contents/chron/">programming praxis</a> website:</p>
<p><a href="http://programmingpraxis.com/2009/06/09/longest-common-subsequence/">Longest Common Subsequence  </a><br />
Finding the longest common subsequence of two sequences is a classic computer science problem with an equally<br />
classic solution that dates to the folklore of computing. The longest common subsequence is the longest set of<br />
elements that appear in order (not necessarily contiguous) in two sequences, the solution can be used in matching DNA sequences and it is also the basis of Unix &#8220;DIFF&#8221; utility. </p>
<p>The following SQL pattern can be used to find the Longest Common Subsequences  in different group of strings.</p>
<pre>
COLUMN Largest_Common_Sequences FORMAT  A38
COLUMN in_str FORMAT  A18
<code>
CREATE TABLE  DATA AS
(Select 1 as id, 10 as grp_id, 'ABRACADABRA'       as in_str from dual
union all
select 2 as id, 10 as grp_id, 'BARRACUDA'          as in_str from dual
union all
select 3 as id, 20 as grp_id, 'HHTHHTHHT'          as in_str from dual
union all
select 4 as id, 20 as grp_id, 'THHTHTTHT'          as in_str from dual
union all
select 5 as id, 30 as grp_id, 'PROGRAMMING'        as in_str from dual
union all
select 6 as id, 30 as grp_id, 'PRAXIS'             as in_str from dual
union all
select 7 as id, 40 as grp_id, 'HUMAN'              as in_str from dual
union all
select 8 as id, 40 as grp_id, 'CHIMPANZEE'         as in_str from dual
union all
select 9 as id, 50 as grp_id,  '!T@E#N$o%n^e'      as in_str from dual
union all
select 10 as id, 50 as grp_id, 'TE*No()n+e{'       as in_str from dual
union all
select 11 as id, 50 as grp_id, '=T8EN7o?ne'        as in_str from dual
);

--------------------------------------------------------SQL Solution------------------------------------------------------

WITH MAX_COM_SEQ  AS
(SELECT DISTINCT id, grp_id, in_str, seq_str
  FROM
    (SELECT a.*, length(seq_str) len, MAX(LENGTH(seq_str)) OVER (PARTITION BY grp_id) max_len
      FROM
      (SELECT a.*,COUNT(DISTINCT id) OVER (PARTITION BY grp_id,seq_str) seq_cnt
       FROM
       (SELECT a.*, REPLACE(SYS_CONNECT_BY_PATH(chr,','),',') seq_str
         FROM (SELECT *
                FROM (SELECT a.*,COUNT(DISTINCT id) OVER(PARTITION BY grp_id, chr) cnt_chr
                       FROM (SELECT a.*, trim(COLUMN_VALUE) chr, rownum as rn
                              FROM (SELECT data.*, COUNT(*) OVER (PARTITION BY grp_id) cnt FROM data ) a,
                                    xmltable(rtrim(REGEXP_REPLACE(a.in_str,'(.)', '"\1",'), ','))
                             ) a
                     )
                WHERE cnt=cnt_chr
               ) a
         CONNECT BY id=PRIOR id AND rn &gt; PRIOR rn
       ) a
      ) a
     WHERE cnt = seq_cnt
  )
  WHERE max_len = len
)
SELECT id, grp_id, in_str, CASE WHEN rank = 1 THEN '[ '|| STRAGG||' ]' END AS Largest_Common_Sequences
 FROM
 (SELECT id, grp_id, in_str, STRAGG, rank() OVER (PARTITION BY grp_id ORDER BY id ) AS RANK
  FROM
  (SELECT DISTINCT id, grp_id, in_str, LISTAGG(seq_str, '-&gt;') WITHIN GROUP (ORDER BY seq_str) OVER(PARTITION BY id) STRAGG
   FROM (SELECT * FROM MAX_COM_SEQ )
  )
 );

        ID     GRP_ID IN_STR             LARGEST_COMMON_SEQUENCES
---------- ---------- ------------------ --------------------------------------
         1         10 ABRACADABRA        [ ARACDA-&gt;BRACDA ]
         2         10 BARRACUDA
         3         20 HHTHHTHHT          [ HHTHTHT-&gt;THHTHHT ]
         4         20 THHTHTTHT
         5         30 PROGRAMMING        [ PRAI ]
         6         30 PRAXIS
         7         40 HUMAN              [ HMAN ]
         8         40 CHIMPANZEE
         9         50 !T@E#N$o%n^e       [ TENone ]
        10         50 TE*No()n+e{
        11         50 =T8EN7o?ne

11 rows selected.
SQL&gt;

</code>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/07/05/how-to-find-the-longest-common-subsequence-lcs-in-sql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to solve the Zebra Puzzle in SQL</title>
		<link>http://oraqa.com/2010/07/05/how-to-solve-the-zebra-puzzle-in-sql/</link>
		<comments>http://oraqa.com/2010/07/05/how-to-solve-the-zebra-puzzle-in-sql/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 00:03:38 +0000</pubDate>
		<dc:creator>newkid</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=621</guid>
		<description><![CDATA[From Wikipedia http://en.wikipedia.org/wiki/Zebra_Puzzle:
The Zebra Puzzle is a well-known logic puzzle. It is often called Einstein&#8217;s Puzzle or Einstein&#8217;s Riddle because it is said to have been invented by Albert Einstein as a boy. Some claim that Einstein said &#8220;only 2 percent of the world&#8217;s population can solve it.&#8221; It is also sometimes attributed to Lewis [...]]]></description>
			<content:encoded><![CDATA[<p>From Wikipedia <a href="http://en.wikipedia.org/wiki/Zebra_Puzzle">http://en.wikipedia.org/wiki/Zebra_Puzzle</a>:</p>
<p>The Zebra Puzzle is a well-known logic puzzle. It is often called Einstein&#8217;s Puzzle or Einstein&#8217;s Riddle because it is said to have been invented by Albert Einstein as a boy. Some claim that Einstein said &#8220;only 2 percent of the world&#8217;s population can solve it.&#8221; It is also sometimes attributed to Lewis Carroll. </p>
<p>However, there is no known evidence for Einstein&#8217;s or Carroll&#8217;s authorship; and the original puzzle mentions brands of cigarette, such as Kools, that did not exist during Carroll&#8217;s lifetime or Einstein&#8217;s boyhood.</p>
<p>There are several versions of this puzzle, below is one of them:</p>
<p>The British lives in the red house.<br />
The Swede keeps dogs as pets.<br />
The Dane drinks tea.<br />
The green house is on the left of the white house.<br />
The green homeowner drinks coffee.<br />
The man who smokes Pall Mall keeps birds.<br />
The owner of the yellow house smokes Dunhill.<br />
The man living in the center house drinks milk.<br />
The Norwegian lives in the first house.<br />
The man who smokes Blend lives next to the one who keeps cats.<br />
The man who keeps the horse lives next to the man who smokes Dunhill.<br />
The man who smokes Bluemaster drinks beer.<br />
The German smokes Prince.<br />
The Norwegian lives next to the blue house.<br />
The man who smokes Blend has a neighbor who drinks water.</p>
<p>Question: Who owns the fish?</p>
<p>SQL solution:</p>
<pre>
WITH comb as (  ----- Permutations of number 1-5. they can be interpreted as other properties, and the position of number in string p means room number
         SELECT REPLACE(SYS_CONNECT_BY_PATH(rn,'\'),'\') AS p
           FROM (SELECT ROWNUM rn FROM DUAL CONNECT BY ROWNUM&lt;=5)
          WHERE LEVEL=5
          CONNECT BY NOCYCLE LEVEL&lt;=5 AND rn&lt;&gt;PRIOR rn
          )
     ,nationality AS (
       SELECT INSTR(p,'1') AS Englishman
             ,INSTR(p,'2') AS Swede
             ,INSTR(p,'3') AS Dane
             ,INSTR(p,'4') AS Norwegian
             ,INSTR(p,'5') AS German
        FROM comb
      )
    ,house AS (
       SELECT INSTR(p,'1') AS red
             ,INSTR(p,'2') AS white
             ,INSTR(p,'3') AS green
             ,INSTR(p,'4') AS yellow
             ,INSTR(p,'5') AS blue
        FROM comb
     )
    ,beverages AS (
       SELECT INSTR(p,'1') AS tea
             ,INSTR(p,'2') AS coffee
             ,INSTR(p,'3') AS milk
             ,INSTR(p,'4') AS beer
             ,INSTR(p,'5') AS water
        FROM comb
     )
    ,cigarettes AS (
       SELECT INSTR(p,'1') AS pall_mall
             ,INSTR(p,'2') AS dunhill
             ,INSTR(p,'3') AS blends
             ,INSTR(p,'4') AS blue_master
             ,INSTR(p,'5') AS prince
        FROM comb
        )
    ,pets AS (
       SELECT INSTR(p,'1') AS dog
             ,INSTR(p,'2') AS bird
             ,INSTR(p,'3') AS cat
             ,INSTR(p,'4') AS horse
             ,INSTR(p,'5') AS fish
        FROM comb
        )
    ,res AS (
       SELECT *
         FROM nationality
             ,house
             ,beverages
             ,cigarettes
             ,pets
       WHERE  Englishman     = red   ---- join condition: different properties appear in the same room number, or number of next room
              AND  Swede     = dog
              AND  Dane      = tea
              AND  green     = white -1
              AND  green     = coffee
              AND  pall_mall = bird
              AND  yellow    = dunhill
              AND  milk      = 3
              AND  Norwegian = 1
              AND  ABS(blends - cat)    =1
              AND  ABS(dunhill - horse) =1
              AND  blue_master = beer
              AND  German    = prince
              AND  blue      = 2
              AND  ABS(blends - water)  =1
       )
SELECT room_num
      ,DECODE(room_num,Englishman,'Englishman',Swede   ,'Swede'  ,Dane  ,'Dane'  ,Norwegian  ,'Norwegian'  ,German,'German') as nationality
      ,DECODE(room_num,red       ,'red'       ,white   ,'white'  ,green ,'green' ,yellow     ,'yellow'     ,blue  ,'blue'  ) as house
      ,DECODE(room_num,pall_mall ,'pall mall' ,dunhill ,'dunhill',blends,'blends',blue_master,'blue master',prince,'prince') as beverages
      ,DECODE(room_num,tea       ,'tea'       ,coffee  ,'coffee' ,milk  ,'milk'  ,beer       ,'beer'       ,water ,'water' ) as cigarettes
      ,DECODE(room_num,dog       ,'dog'       ,bird    ,'bird'   ,cat   ,'cat'   ,horse      ,'horse'      ,fish  ,'fish'  ) as pets
  FROM res,(SELECT ROWNUM room_num FROM DUAL CONNECT BY ROWNUM&lt;=5)
ORDER BY room_num;

Output:
  ROOM_NUM NATIONALIT HOUSE  BEVERAGES   CIGARE PETS
---------- ---------- ------ ----------- ------ -----
         1 Norwegian  yellow dunhill     water  cat
         2 Dane       blue   blends      tea    horse
         3 Englishman red    pall mall   milk   bird
         4 German     green  prince      coffee fish
         5 Swede      white  blue master beer   dog
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/07/05/how-to-solve-the-zebra-puzzle-in-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to calculate the factorial of a large number in SQL</title>
		<link>http://oraqa.com/2010/07/01/how-to-calculate-the-factorial-of-a-large-number/</link>
		<comments>http://oraqa.com/2010/07/01/how-to-calculate-the-factorial-of-a-large-number/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 01:59:51 +0000</pubDate>
		<dc:creator>newkid</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=569</guid>
		<description><![CDATA[

10G solution to calculate 400!

WITH tmp AS
        (SELECT *
           FROM (SELECT rn,col,prod
                  FROM (  SELECT ROWNUM rn
    [...]]]></description>
			<content:encoded><![CDATA[<pre>

10G solution to calculate 400!

WITH tmp AS
        (SELECT *
           FROM (SELECT rn,col,prod
                  FROM (  SELECT ROWNUM rn
                            FROM DUAL
                          CONNECT BY ROWNUM&lt;=400
                        )
                      ,(  SELECT ROWNUM col
                            FROM DUAL
                          CONNECT BY ROWNUM&lt;=30
                        )
                MODEL IGNORE NAV RETURN UPDATED ROWS
                DIMENSION BY (rn,col)
                MEASURES (0 prod )
                   RULES (
                   prod[any,any] order by rn,col=(CASE WHEN cv(rn)=1 AND cv(col)=1 THEN 1
                                                       ELSE MOD(prod[cv()-1,cv()],1E30)*cv(rn) + TRUNC(prod[cv(),cv()-1]/1E30)
                                                  END )
                   )
                )
         WHERE rn=400
        )
SELECT LTRIM(REPLACE(MAX(SYS_CONNECT_BY_PATH(LPAD(MOD(prod,1E30),30,'0'),'*')),'*'),'0') AS result
  FROM tmp
START WITH col=(SELECT MAX(col) FROM tmp WHERE prod&gt;0)
CONNECT BY col = PRIOR col-1
/

RESULT
-----------------------------------------------
640345228466238952623479703195030058507025830260029594586844459428023971691868314362784786474632646762943505750358568108482981628835174352289619886468
029979373416541508381624264619423523070462443250151144486708906627739149181173319559964407095496713452904770203224349112107975932807951015453726672516
278778900093497637657103263503315339653498683868313393520243737881577867915063118587026182701698197400629830253085912983461622723045583395207596115053
022360868104332972551948526744322324386699484224042325998055516106359423769613992319171340638589965379701478272066063202173794720103213566246138090779
423045973606995675958360961587151299138222865785795493616176544804532220078258184008484364155912294542753848035583745180226759000613995601455952061272
11192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

11GR2 solution using recursive subquery factoring:
WITH t (n,str,result,roundup) AS (
SELECT 1,CAST('' AS VARCHAR2(4000)),CAST('1' AS VARCHAR2(4000)),0 FROM DUAL
UNION ALL
SELECT CASE WHEN str IS NULL THEN n+1 ELSE n END
      ,CASE WHEN str IS NULL THEN (CASE WHEN roundup=0 THEN '' ELSE TO_CHAR(roundup) END)||result
            WHEN LENGTH(str)&gt;30 THEN SUBSTR(str,1,LENGTH(str)-30)
            ELSE ''
       END
      ,CASE WHEN str IS NULL THEN ''
            ELSE SUBSTR(TO_CHAR(TO_NUMBER(CASE WHEN LENGTH(str)&gt;=30 THEN SUBSTR(str,-30)
                                                 ELSE str
                                          END)*n+roundup+1E30
                               )
                        ,-30)||result
       END
      ,CASE WHEN str IS NULL THEN 0
            ELSE TRUNC((TO_NUMBER(CASE WHEN LENGTH(str)&gt;=30 THEN SUBSTR(str,-30)
                                       ELSE str
                                  END)*n+roundup
                        )/1E30)
       END
  FROM t
 WHERE n&lt;=400
) CYCLE n,result SET cycle_flag TO 'Y' DEFAULT 'N'
SELECT LTRIM(result,'0') FROM t
WHERE n=400 AND str IS NULL;

LTRIM(RESULT,'0')
------------------------------------------------------------------------------------------------------------------------------------------------------
640345228466238952623479703195030058507025830260029594586844459428023971691868314362784786474632646762943505750358568108482981628835174352289619886468
029979373416541508381624264619423523070462443250151144486708906627739149181173319559964407095496713452904770203224349112107975932807951015453726672516
278778900093497637657103263503315339653498683868313393520243737881577867915063118587026182701698197400629830253085912983461622723045583395207596115053
022360868104332972551948526744322324386699484224042325998055516106359423769613992319171340638589965379701478272066063202173794720103213566246138090779
423045973606995675958360961587151299138222865785795493616176544804532220078258184008484364155912294542753848035583745180226759000613995601455952061272
11192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/07/01/how-to-calculate-the-factorial-of-a-large-number/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to solve the Feynman&#8217;s Puzzle in SQL</title>
		<link>http://oraqa.com/2010/06/09/how-to-solve-the-feynmans-puzzle-in-sql/</link>
		<comments>http://oraqa.com/2010/06/09/how-to-solve-the-feynmans-puzzle-in-sql/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 15:47:19 +0000</pubDate>
		<dc:creator>Frank Zhou</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=545</guid>
		<description><![CDATA[The following is an interesting puzzle posted on the programming praxis website:

Feynman’s Puzzle
This Puzzles was proposed by Richard Feyman ( An American physicist)
&#8216;A&#8217; can be any digit; each &#8216;.&#8217; can be any digit from 0 through 9 except &#8216;A&#8217;. There is only one solution. 


         ..A.
  [...]]]></description>
			<content:encoded><![CDATA[<p>The following is an interesting puzzle posted on the <a href="http://programmingpraxis.com/contents/">programming praxis </a>website:<br />
<a href="http://programmingpraxis.com/2009/06/12/feynmans-puzzle/"><br />
Feynman’s Puzzle</a></p>
<p>This Puzzles was proposed by Richard Feyman ( An American physicist)</p>
<p>&#8216;A&#8217; can be any digit; each &#8216;.&#8217; can be any digit from 0 through 9 except &#8216;A&#8217;. There is only one solution. </p>
<pre>

         ..A.
    ---------
.A. ) ....A..
      ..AA
      ----
       ...A
        ..A
       -----
        ....
        .A..
        -----
         ....
         ....
         ----
            0

COLUMN str FORMAT  A38
COLUMN d_e_A_f FORMAT A8
COLUMN b_A_c  FORMAT  A8

-----------------------------------------------------------SQL Solution----------------------------------------------------------------------------

WITH DATA1 AS
(SELECT LEVEL n FROM DUAL CONNECT BY LEVEL &lt; 10 ),
DATA2 AS
(SELECT LEVEL-1 n FROM DUAL CONNECT BY LEVEL  &lt; 11 )
SELECT d_e_A_f||chr(10)||'     ------------'||chr(10)||b_A_c||'  )'||Div as str, b_A_c, d_e_A_f
FROM
(SELECT b.n|| A.n|| c.n as b_A_c ,  d.n||e.n||A.n||f.n  as d_e_A_f , to_number(b.n|| A.n|| c.n )* to_number(d.n||e.n||A.n||f.n) as Div
 FROM data2 A,  data1 b, data2 c,  data1 d,  data2 e, data2 f
 WHERE b.n != A.n
 AND   c.n != A.n
 AND   d.n != A.n
 AND   e.n != A.n
 AND   f.n != A.n
 AND length ((b.n * 100 + A.n *10 + c.n) *  (d.n *1000 + e.n *100 + A.n *10 + f.n)) =7
 AND to_number(substr((b.n * 100 + A.n *10 + c.n) *  (d.n *1000 + e.n *100 + A.n *10 + f.n), 5, 1 ) ) = A.n
 AND to_number(substr((b.n * 100 + A.n *10 + c.n) * d.n, 3, 2 ))  = to_number(A.n||A.n)
 AND to_number(substr((b.n * 100 + A.n *10 + c.n)*e.n, 3, 1 )) = A.n
 AND to_number(substr((b.n * 100 + A.n *10 + c.n) * A.n , 2, 1 ) ) = A.n
 AND e.n &lt; d.n
);

STR                                    B_A_C      D_E_A_F
---------------------------           --------    --------
         7289                           484        7289
     ------------
484  )3527876

SQL&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/06/09/how-to-solve-the-feynmans-puzzle-in-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to find the relationships &amp; connections between people in SQL.</title>
		<link>http://oraqa.com/2010/06/09/how-to-find-the-relationships-connections-between-people-in-sql/</link>
		<comments>http://oraqa.com/2010/06/09/how-to-find-the-relationships-connections-between-people-in-sql/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 15:45:35 +0000</pubDate>
		<dc:creator>Frank Zhou</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=537</guid>
		<description><![CDATA[You go to a wedding reception, and there are a lot of people. All of these people &#8216;know&#8217; the bride or the groom in some manner. Additionally, a lot of them may know each other in one or more manner. For example, let&#8217;s take Ann and David, who meet by the front door. Ann is [...]]]></description>
			<content:encoded><![CDATA[<p>You go to a wedding reception, and there are a lot of people. All of these people &#8216;know&#8217; the bride or the groom in some manner. Additionally, a lot of them may know each other in one or more manner. For example, let&#8217;s take Ann and David, who meet by the front door. Ann is the bride&#8217;s sister. David is the groom&#8217;s boss at work. Ann is going out with David&#8217;s brother Tom.</p>
<p>So &#8211; if you look at the relationships between these two, you have:</p>
<p>Ann goes out with Tom. Tom is a brother of David.<br />
Ann is a sister of Bride. Bride is married to Groom. Groom works for David.</p>
<p>The problem is to write a program that will get the names of two people as input.<br />
It then needs to output a list of all the ways in which these people are related,<br />
much in the same fashion as we showed the list of relationships between Ann and David above.</p>
<pre>
CREATE TABLE RELATIONSHIP
  ( FROM_NAME VARCHAR2(38 BYTE),
    TO_NAME VARCHAR2(38 BYTE),
    Relation_DESC VARCHAR2(100 BYTE),
    PRIMARY KEY (FROM_NAME, TO_NAME)
  ) organization index;

insert into RELATIONSHIP values (  'bride', 'groom', 'is married to');
insert into RELATIONSHIP values (  'groom', 'bride', 'is married to');
insert into RELATIONSHIP values (  'Ann',   'bride', 'is a sister of');
insert into RELATIONSHIP values (  'bride', 'Ann',   'is a sister of');
insert into RELATIONSHIP values (  'David', 'Tom',   'is a brother of');
insert into RELATIONSHIP values (  'Tom',   'David', 'is a brother of');
insert into RELATIONSHIP values (  'David', 'groom', 'is the boss of');
insert into RELATIONSHIP values (  'groom', 'David', 'works for');
insert into RELATIONSHIP values (  'Ann',   'Tom',   'dates');
insert into RELATIONSHIP values (  'Tom',   'Ann',   'dates');

commit;

COLUMN RELATIONSHIP FORMAT  A68
variable P_FROM varchar2(38)
variable P_TO varchar2(38)
exec :P_FROM:='Ann'
exec :P_TO:='David'

--------------------------------SQL Solution using Recursive Subquery Factoring-------------------------------------

WITH DATA (root, path, TO_NAME) AS
(SELECT FROM_NAME,  FROM_NAME||' '||Relation_DESC||' '||TO_NAME, TO_NAME
 FROM  RELATIONSHIP
 WHERE FROM_NAME  = :P_FROM
 UNION ALL
 SELECT  root, d.path||','||e.FROM_NAME||' '||e.Relation_DESC||' '||e.TO_NAME as path , e.TO_NAME
 FROM  DATA d,  RELATIONSHIP e
 WHERE d.TO_NAME= e.FROM_NAME
 AND e.FROM_NAME != d.root
)
SEARCH DEPTH FIRST BY TO_NAME SET seq
CYCLE TO_NAME SET is_cycle to '1' DEFAULT '0'
SELECT grp, trim(COLUMN_VALUE) relationship
FROM
(SELECT path,  ROWNUM grp
 FROM DATA
 WHERE TO_NAME = :P_TO
 AND is_cycle = 0
 ) a,  xmltable(('"'||replace(a.path, ',', '","')||'"'));

       GRP RELATIONSHIP
---------- --------------------------------------------------------------------
         1 Ann dates Tom
         1 Tom is a brother of David
         2 Ann is a sister of bride
         2 bride is married to groom
         2 groom works for David

SQL&gt;

---------------------------------------------Alternative SQL Solution------------------------------------------------

WITH DATA AS
(SELECT ltrim(sys_connect_by_path(FROM_NAME||' '||Relation_DESC||' '||TO_NAME, ','), ',') as path, ROWNUM grp
 FROM  RELATIONSHIP
 WHERE  TO_NAME  = :P_TO
 START WITH FROM_NAME  = :P_FROM
 CONNECT BY NOCYCLE PRIOR TO_NAME = FROM_NAME
 AND FROM_NAME  != :P_FROM
)
SELECT grp, trim(column_value) AS RELATIONSHIP
FROM DATA a,  xmltable(('"'||replace(a.path, ',', '","')||'"'));

       GRP RELATIONSHIP
---------- --------------------------------------------------------------------
         1 Ann dates Tom
         1 Tom is a brother of David
         2 Ann is a sister of bride
         2 bride is married to groom
         2 groom works for David

SQL&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/06/09/how-to-find-the-relationships-connections-between-people-in-sql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to solve the Multiple Dwellings Puzzle in SQL</title>
		<link>http://oraqa.com/2010/06/08/how-to-solve-the-multiple-dwellings-puzzle-in-sql/</link>
		<comments>http://oraqa.com/2010/06/08/how-to-solve-the-multiple-dwellings-puzzle-in-sql/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 15:45:33 +0000</pubDate>
		<dc:creator>Frank Zhou</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=511</guid>
		<description><![CDATA[The following is an interesting puzzle posted on the programming praxis website:
Multiple Dwellings
Baker, Cooper, Fletcher, Miller and Smith live on different floors of an apartment house that contains only five floors.
Baker does not live on the top floor. Cooper does not live on the bottom floor.
Fletcher does not live on either the top or the [...]]]></description>
			<content:encoded><![CDATA[<p>The following is an interesting puzzle posted on the<a href="http://programmingpraxis.com/contents/"> programming praxis </a>website:</p>
<p><a href="http://programmingpraxis.com/2009/02/20/multiple-dwellings/">Multiple Dwellings</a><br />
Baker, Cooper, Fletcher, Miller and Smith live on different floors of an apartment house that contains only five floors.<br />
Baker does not live on the top floor. Cooper does not live on the bottom floor.<br />
Fletcher does not live on either the top or the bottom floor. Miller lives on a higher floor than does Cooper.<br />
Smith does not live on a floor adjacent to Fletcher’s.<br />
Fletcher does not live on a floor adjacent to Cooper’s. Where does everyone live?</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;SQL Solution&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<pre>

WITH DATA ( num ) AS
(select 1 from dual
 union all
 select d.num+1 from DATA d
 where d.num &lt;5
)
select Baker.num as Baker, Cooper.num as Cooper, Fletcher.num AS Fletcher ,
Miller.num AS Miller, Smith.num AS Smith
FROM DATA Baker, DATA Cooper, DATA Fletcher, DATA Miller, DATA Smith
WHERE Baker.num  NOT IN (Cooper.num, Fletcher.num, Miller.num,  Smith.num )
AND Cooper.num   NOT IN (Baker.num,  Fletcher.num, Miller.num , Smith.num )
AND Fletcher.num NOT IN (Baker.num,  Cooper.num,  Miller.num , Smith.num )
AND Miller.num   NOT IN (Baker.num,  Cooper.num, Fletcher.num,  Smith.num )
AND Smith.num    NOT IN (Baker.num,  Cooper.num, Fletcher.num,  Miller.num )
AND Baker.num != 5
AND Cooper.num NOT IN (1,5)
AND Fletcher.num NOT IN (1,5)
AND Miller.num &gt; Cooper.num  AND Miller.num NOT IN (1,2)
AND ABS(Smith.num -  Fletcher.num) &gt; 1
AND ABS (Fletcher.num -  Cooper.num) &gt;1;

     BAKER     COOPER   FLETCHER     MILLER      SMITH
---------- ---------- ---------- ---------- ----------
         3          2          4          5          1

SQL&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/06/08/how-to-solve-the-multiple-dwellings-puzzle-in-sql/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to solve the Anagrams Puzzle in SQL</title>
		<link>http://oraqa.com/2010/06/08/how-to-solve-the-anagrams-puzzle-in-sql/</link>
		<comments>http://oraqa.com/2010/06/08/how-to-solve-the-anagrams-puzzle-in-sql/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 15:41:28 +0000</pubDate>
		<dc:creator>Frank Zhou</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=521</guid>
		<description><![CDATA[The following is an interesting puzzle posted on the programming praxis website:
Anagrams
Words that are formed from the same set of letters are anagrams of each other. For instance, pots, post, stop, spot, opts, and tops are anagrams.
Your task is to write a program that, given a dictionary and an input word, prints all the anagrams [...]]]></description>
			<content:encoded><![CDATA[<p>The following is an interesting puzzle posted on the <a href="http://programmingpraxis.com/contents/">programming praxis </a>website:</p>
<p><a href="http://programmingpraxis.com/2009/04/10/anagrams/"><strong>Anagrams</strong></a><br />
Words that are formed from the same set of letters are anagrams of each other. For instance, pots, post, stop, spot, opts, and tops are anagrams.<br />
Your task is to write a program that, given a dictionary and an input word, prints all the anagrams of the input word.<br />
You are also to determine the largest anagram class in your dictionary. </p>
<p>The flat file &#8220;C:\oracle\word.txt&#8221; contains the following words :</p>
<p>pots<br />
post<br />
stop<br />
spot<br />
opts<br />
tops<br />
pares<br />
parse<br />
pears<br />
rapes<br />
reaps<br />
spare<br />
spear<br />
angor<br />
argon<br />
goran<br />
grano<br />
groan<br />
nagor<br />
orang<br />
organ<br />
rogan<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-SQL Solution&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<pre>

COLUMN largest_anagram_class FORMAT  A68
variable input_str varchar2(38)
exec :input_str:='tops'

create or replace directory tmp as 'C:\oracle'

CREATE  TABLE words (str VARCHAR2(38))
     ORGANIZATION EXTERNAL
     (
       TYPE ORACLE_LOADER
       DEFAULT DIRECTORY tmp
       ACCESS PARAMETERS
       (
         records delimited by newline
         fields terminated by whitespace
         missing field values are null
         ( str
         )
       )
       LOCATION ('word.txt')
     )
     REJECT LIMIT UNLIMITED;

--------------------------------------------------------------Find all the anagrams of the input word ---------------------------------------------------------

WITH DATA AS
(SELECT ordered_str, str,  COUNT(str) OVER (PARTITION BY ordered_str) as cnt
 FROM
 (SELECT DISTINCT REPLACE(LISTAGG(trim(column_value), ',') WITHIN GROUP (ORDER BY trim(column_value)) OVER (PARTITION BY str), ',') as ordered_str, str
  FROM words a,
  xmltable(rtrim(REGEXP_REPLACE(a.str,'(.)', '"\1",'), ','))
 )
),
INPUT AS (
SELECT DISTINCT REPLACE(LISTAGG(trim(column_value), ',') WITHIN GROUP (ORDER BY trim(column_value)) OVER (PARTITION BY str), ',') as ordered_input
  FROM (SELECT :input_str as str FROM dual) a,
  xmltable(rtrim(REGEXP_REPLACE(a.str,'(.)', '"\1",'), ','))
)
SELECT str, CASE WHEN ROWNUM = 1 THEN cnt END as cnt
FROM DATA
WHERE ordered_str IN
(SELECT ordered_input
FROM INPUT);

STR                                           CNT
-------------------------------------- ----------
tops                                            6
pots
opts
spot
post
stop

6 rows selected.

SQL&gt;

---------------------------------------------------Determine the largest anagram class in the dictionary---------------------------------------------------------

WITH DATA AS
(SELECT ordered_str, str,  COUNT(str) OVER (PARTITION BY ordered_str) as cnt
 FROM
 (SELECT DISTINCT REPLACE(LISTAGG(trim(column_value), ',') WITHIN GROUP (ORDER BY trim(column_value)) OVER (PARTITION BY str), ',') as ordered_str, str
  FROM words a,
  xmltable(rtrim(REGEXP_REPLACE(a.str,'(.)', '"\1",'), ','))
 )
)
SELECT  '[ '||anagrams||' ]' AS  largest_anagram_class,  max_ct
 FROM
 (SELECT DISTINCT LISTAGG(str, '-&gt;') WITHIN GROUP (ORDER BY str ) OVER (PARTITION BY ordered_str) AS anagrams, cnt, MAX(cnt) OVER() AS max_ct
  FROM DATA
 )
 WHERE max_ct = cnt;

LARGEST_ANAGRAM_CLASS                                                    MAX_CT
-------------------------------------------------------------------- ----------
[ angor-&gt;argon-&gt;goran-&gt;grano-&gt;groan-&gt;nagor-&gt;orang-&gt;organ-&gt;rogan ]             9

SQL&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/06/08/how-to-solve-the-anagrams-puzzle-in-sql/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How to solve the Dodgson’s Doublets Puzzle in SQL</title>
		<link>http://oraqa.com/2010/06/02/how-to-solve-the-dodgson%e2%80%99s-doublets-puzzle-in-sql/</link>
		<comments>http://oraqa.com/2010/06/02/how-to-solve-the-dodgson%e2%80%99s-doublets-puzzle-in-sql/#comments</comments>
		<pubDate>Thu, 03 Jun 2010 04:27:11 +0000</pubDate>
		<dc:creator>Frank Zhou</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=491</guid>
		<description><![CDATA[The following is an interesting puzzle posted on the programming praxis website:
Dodgson’s Doublets
Charles Dodgson was an English author, mathematician and logician of the nineteenth century;
In 1879, Dodgson published the Doublets word game in the Vanity Fair magazine:
The rules of the Puzzle are simple enough. Two words are proposed, of the same length; and the Puzzle [...]]]></description>
			<content:encoded><![CDATA[<p>The following is an interesting puzzle posted on the<a href="http://programmingpraxis.com/contents/"> programming praxis </a>website:</p>
<p><a href="http://programmingpraxis.com/2009/03/20/dodgsons-doublets/">Dodgson’s Doublets</a><br />
Charles Dodgson was an English author, mathematician and logician of the nineteenth century;<br />
In 1879, Dodgson published the Doublets word game in the Vanity Fair magazine:</p>
<p>The rules of the Puzzle are simple enough. Two words are proposed, of the same length; and the Puzzle consists in linking these together by interposing other words, each of which shall differ from the next word in one letter only. That is to say, one letter may be changed in one of the given words, then one letter in the word so obtained, and so on, till we arrive at the other given word. The letters must not be interchanged among themselves, but each must keep to its own place. As an example, the word ‘head’ may be changed into &#8216;tail&#8217; by interposing the words ‘heal, teal, tell, tall’. I call the given words &#8216;a Doublet&#8217;, the interposed words ‘Links’, and the entire series ‘a Chain’, of which I here append an example:</p>
<p>H E A D<br />
h e a l<br />
t e a l<br />
t e l l<br />
t a l l<br />
T A I L</p>
<p>Write a program that takes two words and finds a chain between them.</p>
<pre>

create table dictionary ( word varchar2(38) PRIMARY KEY );

insert into dictionary values ('HEAD');
insert into dictionary values ('heal');
insert into dictionary values ('teal');
insert into dictionary values ('tell');
insert into dictionary values ('tall');
insert into dictionary values ('TAIL');
insert into dictionary values ('toll');
commit;

COLUMN str FORMAT  A38
variable begin_str varchar2(38)
variable end_str varchar2(38)
exec :begin_str:='head'
exec :end_str:='tail'

------------------------------------------------SQL Solution-----------------------------------------------

WITH data as (
SELECT word
FROM  dictionary
WHERE length(word) = length(:begin_str)
),
Links as
(SELECT path
 FROM
 (SELECT ltrim(sys_connect_by_path( word, ','), ',') path
  FROM data
  WHERE upper(word) = upper(:end_str)
  START WITH upper(word) = upper(:begin_str)
  CONNECT BY NOCYCLE  utl_match.edit_distance(upper(PRIOR word), upper(word) ) =1
  ORDER BY LEVEL
 )
 WHERE ROWNUM = 1
)
SELECT  rownum as rn, trim(column_value) str
FROM links a, xmltable(('"'||replace(a.path, ',', '","')||'"'));

        RN STR
---------- --------------------------------------
         1 HEAD
         2 heal
         3 teal
         4 tell
         5 tall
         6 TAIL

6 rows selected.

SQL&gt;

--------------------------------SQL Solution using Recursive Subquery Factoring-------------------------------------

WITH data AS (
SELECT word  FROM dictionary
WHERE length(word) = length(:begin_str)
),
Links (path, h_level, word) AS
(SELECT word, 1 , word
 FROM data
 WHERE upper(word) = upper(:begin_str)
 UNION ALL
 SELECT d.path||','||e.word as path, d.h_level+1 AS h_level, e.word
 FROM Links d, data e
 WHERE utl_match.edit_distance(upper(d.word), upper(e.word) ) = 1
)
SEARCH DEPTH FIRST BY word SET seq
CYCLE word SET is_cycle to '1' DEFAULT '0'
SELECT ROWNUM as rn, trim(COLUMN_VALUE) str
FROM
(SELECT path
 FROM
 (SELECT path FROM Links
  WHERE upper(word) = upper(:end_str)
  AND is_cycle = 0
  ORDER BY  h_level
 )
 WHERE ROWNUM = 1 ) a, xmltable(('"'||replace(a.path, ',', '","')||'"'));

        RN STR
---------- --------------------------------------
         1 HEAD
         2 heal
         3 teal
         4 tell
         5 tall
         6 TAIL

6 rows selected.

SQL&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/06/02/how-to-solve-the-dodgson%e2%80%99s-doublets-puzzle-in-sql/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>How to solve the Landmarks Puzzle in SQL</title>
		<link>http://oraqa.com/2010/04/20/how-to-solve-the-landmarks-puzzle-in-sql/</link>
		<comments>http://oraqa.com/2010/04/20/how-to-solve-the-landmarks-puzzle-in-sql/#comments</comments>
		<pubDate>Wed, 21 Apr 2010 03:46:11 +0000</pubDate>
		<dc:creator>Frank Zhou</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=431</guid>
		<description><![CDATA[The following is an puzzle posted by Itasofware on the web :
The file landmarks.xml contains a list of landmarks near ITA Software, along with their latitude and longitude in degrees. Write a program which allows users to choose a landmark and search for others that are nearby.
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
This problem is solved by using the following formula [...]]]></description>
			<content:encoded><![CDATA[<p>The following is an puzzle posted by <a href="http://www.itasoftware.com/careers/puzzle_archive.html?catid=39">Itasofware </a>on the web :</p>
<p>The file <a href="http://www.itasoftware.com/careers/puzzles/landmarks.xml">landmarks.xml </a>contains a list of landmarks near ITA Software, along with their latitude and longitude in degrees. Write a program which allows users to choose a landmark and search for others that are nearby.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
This problem is solved by using the following formula and assumptions:</p>
<p>The radius of the Earth is assumed to be 3,963.0 miles.<br />
To convert latitude or longitude from decimal degrees to radians, divide the latitude and longitude values in this database by 57.29577951.</p>
<p>Distance (In Miles) Formula using radians:<br />
3963.0 * arccos[sin(latitude1) *  sin(latitude2) + cos(latitude1) * cos(latitude2) * cos(longitude2 - longitude1)]</p>
<pre>

COLUMN Input_landMark FORMAT  A32
COLUMN LandMark_nearBy FORMAT A32

variable input_name varchar2(38)
variable num_landMark number

exec :input_name:='11 Tewksbury Towers'
exec :num_landMark := 10

-----------------------------------SQL Solution----------------------------------

WITH DATA AS
(SELECT landmark_Name, latitude/57.29577951 as latitude  , longitude/57.29577951 as longitude
 FROM  XMLTABLE('//landmark'
                passing httpuritype('http://www.itasoftware.com/careers/puzzles/landmarks.xml').getXML()
                columns
                landmark_Name   varchar2(30) path 'name',
                latitude        number       path 'latitude',
                longitude       number       path 'longitude' )
)
SELECT CASE WHEN ROWNUM = 1 THEN Input_landMark  END AS Input_landMark,  LandMark_nearBy,  distance
FROM
(SELECT A.landmark_Name AS Input_landMark, B.landmark_Name AS LandMark_nearBy,
 3963 * ACOS (SIN(A.latitude) * SIN(B.latitude) + COS(A.latitude) * COS(B.latitude) * COS (B.longitude - A.longitude)) as distance
 FROM DATA A, DATA B
 WHERE A.landmark_Name = :input_name
 AND A.landmark_Name != B.landmark_Name
 ORDER BY  distance ASC
)
WHERE ROWNUM &lt;=:num_landMark; 

INPUT_LANDMARK                   LANDMARK_NEARBY                    DISTANCE
-------------------------------- -------------------------------- ----------
11 Tewksbury Towers              Dog Pound                        1.28621194
                                 Department of Public Works       1.30290585
                                 Tewksbury Cemetery               2.51978566
                                 Parlmont Park                    3.49041395
                                 River Place Towers               4.47299171
                                 Avalon Drive                     4.64667122
                                 Drum Hill Shopping Center        6.35347443
                                 Greenbriar Estates               6.66743013
                                 Hallmark Gardens                 8.02860427
                                 Scotty Hollow Drive              8.56254678

10 rows selected.

exec :input_name:='Dog Pound'

PL/SQL procedure successfully completed.

SQL&gt; /

INPUT_LANDMARK                   LANDMARK_NEARBY                    DISTANCE
-------------------------------- -------------------------------- ----------
Dog Pound                        Department of Public Works        .274595687
                                 11 Tewksbury Towers              1.28621194
                                 Parlmont Park                    2.2136777
                                 Tewksbury Cemetery               2.49289556
                                 River Place Towers               4.77456746
                                 Avalon Drive                     4.79217856
                                 Drum Hill Shopping Center        5.99881959
                                 Hallmark Gardens                 7.01671677
                                 Greenbriar Estates               7.02086724
                                 Bedford Village                  7.40305675

10 rows selected.

-------------------------------------------------------------------------------------

The "With DATA Clause" above can also be implemented as following :

WITH DATA AS
(SELECT EXTRACTVALUE(VALUE(P), '/landmark/name/text()') landmark_Name ,
 EXTRACT(VALUE(P), '/landmark/longitude/text()').getNumberVal()/57.29577951 longitude,
 EXTRACT(VALUE(P), '/landmark/latitude/text()').getNumberVal() /57.29577951 latitude
 FROM TABLE(XMLSEQUENCE(HTTPURITYPE('http://www.itasoftware.com/careers/puzzles/landmarks.xml').GETXML().EXTRACT('//landmark'))) P
)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/04/20/how-to-solve-the-landmarks-puzzle-in-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to solve the Optimal Ghost Puzzle in SQL</title>
		<link>http://oraqa.com/2010/01/13/how-to-solve-the-optimal-ghost-puzzle-in-sql/</link>
		<comments>http://oraqa.com/2010/01/13/how-to-solve-the-optimal-ghost-puzzle-in-sql/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 06:47:04 +0000</pubDate>
		<dc:creator>Frank Zhou</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://oraqa.com/?p=394</guid>
		<description><![CDATA[The following is an interesting puzzle posted by Itasofware on the web.
In the game of Ghost , two players take turns building up an English word from left to right.
Each player adds one letter per turn. The goal is to not complete the spelling of a word: if you add a letter that completes a [...]]]></description>
			<content:encoded><![CDATA[<p>The following is an interesting puzzle posted by <a href="http://www.itasoftware.com/careers/hiringpuzzles.html?catid=114">Itasofware</a> on the web.</p>
<p>In the game of <a href="http://www.kith.org/logos/words/lower/g.html">Ghost</a> , two players take turns building up an English word from left to right.</p>
<p>Each player adds one letter per turn. The goal is to not complete the spelling of a word: if you add a letter that completes a word (of 4+ letters), or if you add a letter that produces a string that cannot be extended into a word, you lose.</p>
<p>Write a program that allows a user to play Ghost against the computer. The computer should play optimally given the following dictionary: <a href="http://www.itasoftware.com/careers/puzzles/WORD.LST">WORD.LST</a>.</p>
<p>Allow the human to play first. If the computer thinks it will win, it should play randomly among all its winning moves; if the computer thinks it will lose, it should play so as to extend the game as long as possible (choosing randomly among choices that force the maximal game length).</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Here is the strategy for solving this problem: Try to add a letter to the current input string, so that there is only &#8220;one word&#8221; left in the whole dictionary for your opponent. Once your opponent adds the next letter to the input string, that will complete the spelling of the word.</p>
<p>Solution:<br />
Copy the word.lst from the web to a word.txt file on the database server ( \tmp directory).</p>
<pre>
create or replace directory tmp as 'C:\oracle\tmp';

CREATE  TABLE words (str VARCHAR2(38))
     ORGANIZATION EXTERNAL
     (
       TYPE ORACLE_LOADER
       DEFAULT DIRECTORY tmp
       ACCESS PARAMETERS
       (
         records delimited by newline
         fields terminated by whitespace
         missing field values are null
         ( str
         )
       )
       LOCATION ('word.txt')
     )
     REJECT LIMIT UNLIMITED;

COLUMN input FORMAT A18
COLUMN destination FORMAT A28
COLUMN next_char   FORMAT A12

variable input varchar2(38)
SQL&gt; exec :input :='tar'

PL/SQL procedure successfully completed.

------------------------------SQL Solution----------------- 

WITH data AS
(SELECT str, length(str) as len, :input as input, length(:input) as in_len,
        case when str like :input||'_'
             then  str
             end as flag_str
 FROM words
 WHERE str LIKE :input||'%' and length(str) &gt;=4
),
flag_data as
(
SELECT flag_str FROM data WHERE flag_str is not null
),
Filter_data as
(
SELECT distinct a.str FROM data a , flag_data b
WHERE substr(a.str, 1, length(b.flag_str)) = b.flag_str
),
Base_data as
(SELECT str, len , in_len, input FROM data
 WHERE str not in ( SELECT str FROM Filter_data)
)
SELECT input, destination, next_char
FROM
(SELECT input, str as destination, substr(str, in_len+1, 1) as next_char
  FROM
 (SELECT a.str, a.len, input, a.in_len,
         case when mod(a.len, 2) = 0 then 1
              else case when  REGEXP_LIKE (a.str, '^'||input||'[[:alpha:]]{2}$')
                        then case when
                                 (SELECT count(*) FROM data
                                  WHERE REGEXP_LIKE (str, '^'||substr(a.str,0,length(a.input)+1)||'[[:alpha:]]{2,}$')
                                  and  not REGEXP_LIKE (str, '^'||a.str||'[[:alpha:]]+$')
                                  ) = 0
                                  then 4
                                  else 3
                             end
                        else  2
                    end
         end as flag
  FROM Base_data a
 ) ORDER BY flag desc , case when flag = 1 then len else 0 end desc
)
WHERE ROWNUM = 1;

INPUT              DESTINATION                  NEXT_CHAR
------------------ ---------------------------- ------------
tar                targe                        g

SQL&gt; exec :input := 'bot'

SQL&gt; /

INPUT              DESTINATION                  NEXT_CHAR
------------------ ---------------------------- ------------
bot                botch                        c

SQL&gt; exec :input := 'aba'

SQL&gt; /

INPUT              DESTINATION                  NEXT_CHAR
------------------ ---------------------------- ------------
aba                abamp                        m</pre>
]]></content:encoded>
			<wfw:commentRss>http://oraqa.com/2010/01/13/how-to-solve-the-optimal-ghost-puzzle-in-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
