天天看點

樂在其中:無所不能用SQL挑戰經典遊戲漢諾塔

樂在其中:無所不能用SQL挑戰經典遊戲漢諾塔

蘇旭晖,網名 newkid

itpub開發版資深版主,sql開發專家

編輯手記:感謝蘇旭晖先生授權我們獨家轉載其系列精品文章,也歡迎大家向“oracle”社群投稿。

sql是一門非常靈活的語言,專家們用其挑戰一切看似不可能。

問題來源

  漢諾塔是源自印度神話裡的玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按大小順序摞着64片黃金圓盤。 

大梵天指令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次隻能移動一個圓盤。

傳說

在印度,有這麼一個古老的傳說:在世界中心貝拿勒斯(在印度北部)的聖廟裡,一塊黃銅闆上插着三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片:一次隻移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預言,當所有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就将在一聲霹靂中消滅,而梵塔、廟宇和衆生也都将同歸于盡。

題目要求

題目要求:用sql找出最少移動次數,并且給出一種移法。

例子:3個圓盤

輸入:n=圓盤個數

var n number; exec :n := 3;

輸出:

7 1->2,1->3,2->3,1->2,3->1,3->2,1->2

每個步驟表示将一個柱子上的最上面一個圓盤移到另一個柱子。比如1->2 就是将1号柱最上方的圓盤放到2号柱的最上方。

思路分析

假設有n個盤,最底下的n号盤在移動的時候,目标的柱子一定是空的。是以所有的其他n-1個盤子必定全部在另一柱子上。

把n号盤移過去之後,n-1要疊加到這個盤上面,和剛才移動n-1個盤子的方法是一樣的,隻不過柱子的編号不同。

用遞歸sql和model都可以輕易寫出來。

sql解答

遞歸with:

with h(n,path,ended) as ( select 1,cast('1->2' as varchar2(2000)),2 from dual union all select n+1       ,path        ||',1->'||decode(ended,2,3,2)||','        ||translate(path,'123',decode(ended,2,'231','312'))       ,decode(ended,2,3,2)   from h where n<:n ) select power(2,n)-1 as steps,path from h where n=:n;

model解法:

select power(2,:n)-1 as steps,path from (select cast('1->2' as varchar2(2000)) as path,2 as ended from dual) model return updated rows   dimension by (1 n)    measures (path,ended)    rules iterate(100) until(iteration_number=:n-2)    (     path[1]=path[1]        ||',1->'||decode(ended[1],2,3,2)||','       ||translate(path[1],'123',decode(ended[1],2,'231','312')),     ended[1]=decode(ended[1],2,3,2)    ) ;

大家是否已經能夠體會sql的無窮魅力,參與定期的線上和線下技術分享,請加入我們的“雲和恩墨大講堂”!