zOs/SQL/EXHANOI

-- tower of hanoi                                                       00010060
--                                                                      00020060
--     1                                             1                  00030060
--    222                        =====>             222                 00040060
--   33333                                         33333                00050060
--  *links*  *mitte*  *rechts*           *links*  *mitte*  *rechts*     00060060
--                                                                      00070060
--  Regeln: immer nur ein Scheibe bewegen, immer auf grössere legen     00080060
--                                                                      00090060
--  Lösung wir benutzen Rekursion mit From, To und Help Stapel          00100061
--      1: rekursiv die n-1 obersten Scheiben von From auf Help Stapel  00110064
--      2: die jetzt oberste (ursprünglich n.) Scheibe vom From auf To  00120064
--      3: (rekursiv) die n-1 obersten Scheiben von Help auf To Stapel  00130064
--  erst am Schluss schauen wir, was Links Mitte und Rechts war         00140064
--      (Trick: zuunterst in jedem Stapel fixe Scheibe l, m, bzw. r)    00141065
--                                                                      00150064
with h (f, t, h, anz, seq, lev) as                                      00160064
(                               -- start:                               00170064
     select cast('123456l' as varchar(9)),                              00180064
            cast('m'    as varchar(9)),                                 00190064
            cast('r'    as varchar(9)),                                 00200064
            5, cast(''    as varchar(9)), 0                             00210064
         from sysibm.sysDummy1                                          00220064
                                -- Schritt 1 :                          00230064
                                --   rekursiv anz-1 Scheiben von f auf h00240064
 union all select f, h, t, anz-1, seq || 'x', lev+1                     00250064
     from h                                                             00260064
     where anz > 1 and lev < 9                                          00270064
                                -- Schritt 2+3 :                        00280064
                                --   anz-te Scheibe von f nach t        00290064
                                --   rekursiv anz-1 Scheiben von h auf t00300064
 union all select left(f, anz-1) || h,                                  00310064
                  substr(f, anz, 1) || t,                               00320064
                  substr(f, anz+1),                                     00330064
         anz-1, seq || 'y', lev+1                                       00340064
     from h                                                             00350064
     where anz > 0 and lev < 9                                          00360060
)                               --- f,t,h auf Links Mitte Rechts legen  00370060
, lmr as                                                                00380054
( select  case when right(f, 1) = 'l' then f                            00390054
               when right(t, 1) = 'l' then t                            00400054
               when right(h, 1) = 'l' then h else '?' end l,            00410054
          case when right(f, 1) = 'm' then f                            00420054
               when right(t, 1) = 'm' then t                            00430054
               when right(h, 1) = 'm' then h else '?' end m,            00440054
          case when right(f, 1) = 'r' then f                            00450054
               when right(t, 1) = 'r' then t                            00460054
               when right(h, 1) = 'r' then h else '?' end r,            00470054
          h.*                                                           00480037
      from h                                                            00490037
)                               --- l,m,r rechtsbündig anzeigen         00500061
select substr('         ' || l, length(l), 9) l,                        00510059
       substr('         ' || m, length(m), 9) m,                        00520059
       substr('         ' || r, length(r), 9) r,                        00530059
       anz, seq, lev, f, t, h                                           00540058
    from lmr                                                            00550055
    where right(seq, 1) <> 'x'                                          00560053
    order by seq                                                        00570037
;                                                                       00580062
--                                                                      00590062
-- tower of hanoi                                                       00600061
-- muehsamere Lösung: wir arbeiten mit Links Mitte und Rechts           00610061
--     und müssen in der Rekursion alle Permutationen ausprogrammieren  00620061
--                                                                      00630061
with h (l, m, r, fth, anz, seq, lev) as                                 00640061
(                               -- start bewege Turm von links -> Mitte 00650063
     select cast('123456' as varchar(9)),                               00660037
            cast(''    as varchar(9)),                                  00670037
            cast(''    as varchar(9)),                                  00680037
            'lmr', 4,                                                   00690061
            cast(''    as varchar(9)), 0                                00700037
         from sysibm.sysDummy1                                          00710037
 union all select l, m, r ,     -- Schritt 1 anz-1 Scheiben von f auf h 00720063
         translate('132', fth, '123'),                                  00730037
         anz-1, seq || 'x', lev+1                                       00740037
     from h                                                             00750037
     where anz > 1 and lev < 9                                          00760037
                                -- Schritt f -> t und h -> t für lmr    00770063
 union all select substr(l, anz+1),                                     00780061
                  substr(l, anz, 1) || m,                               00790061
                  left(l, anz-1) || r,                                  00800061
                                                                        00810037
        'rml', anz-1, seq || 'y', lev+1                                 00820061
     from h                                                             00830037
     where anz > 0 and lev < 9 and fth = 'lmr'                          00840061
                                -- Schritt f -> t und h -> t für lrm    00850063
 union all select substr(l, anz+1),                                     00860061
                  left(l, anz-1) || m,                                  00870061
                  substr(l, anz, 1) || r,                               00880061
        'mrl', anz-1, seq || 'y', lev+1                                 00890061
     from h                                                             00900037
     where anz > 0 and lev < 9 and fth = 'lrm'                          00910061
                                -- Schritt f -> t und h -> t für mlr    00920063
 union all select substr(m, anz, 1) || l,                               00930061
                  substr(m, anz+1),                                     00940061
                  left(m, anz-1) || r,                                  00950061
        'rlm', anz-1, seq || 'y', lev+1                                 00960061
     from h                                                             00970037
     where anz > 0 and lev < 9 and fth = 'mlr'                          00980061
                                -- Schritt f -> t und h -> t für mrl    00990063
 union all select left(m, anz-1) || l,                                  01000061
                  substr(m, anz+1),                                     01010061
                  substr(m, anz, 1) || r,                               01020061
        'lrm', anz-1, seq || 'y', lev+1                                 01030061
     from h                                                             01040037
     where anz > 0 and lev < 9 and fth = 'mrl'                          01050061
                                -- Schritt f -> t und h -> t für rlm    01060063
 union all select substr(r, anz, 1) || l,                               01070061
                  left(r, anz-1) || m,                                  01080061
                  substr(r, anz+1),                                     01090061
        'mlr', anz-1, seq || 'y', lev+1                                 01100061
     from h                                                             01110037
     where anz > 0 and lev < 9 and fth = 'rlm'                          01120061
                                -- Schritt f -> t und h -> t für rml    01130063
 union all select left(r, anz-1) || l,                                  01140061
                  substr(r, anz, 1) || m,                               01150061
                  substr(r, anz+1),                                     01160061
        'lmr', anz-1, seq || 'y', lev+1                                 01170061
     from h                                                             01180037
     where anz > 0 and lev < 9 and fth = 'rml'                          01190061
)                                                                       01200037
select substr('         ' || l, 1+length(l), 9) l,                      01210061
       substr('         ' || m, 1+length(m), 9) m,                      01220061
       substr('         ' || r, 1+length(r), 9) r,                      01230061
       fth, anz, seq, lev                                               01240037
    from h                                                              01250037
--  where right(seq, 1) <> 'x'                                          01260041
    order by seq                                                        01270037