● 再帰関数でも作ってみる ●

どこに分類すれば分からなかったので、VBとC言語のネタとして扱うことにした。だからわざわざC言語でも書いた。

[問題]
     P(90)
    K(30) 
   G(60) Q(70)
  D(50) L(50) 
 B(30) H(10) R(10)
  A(10) E(70) M(80) 
 C(40) I(70) S(60)
  F(20) N(10) 
   J(40) T(60)
    O(40) 
     U(70)

Aから始まるルートをABDGKP〜ACFJOUまですべて列挙し、かつルート毎に数字の合計を表示せよ!!

[Visual Basic]
Private Const COURCE_NUM As Long = 21
Private Const STOP_ROUTE As String = "#"
Private Const NO_COURCE As Long = (-1)

Private Type UdtCourceInfo
    Cource As String     'コース
    Price As Long        '料金
    NextUp As String     '次コース(↑)
    NextDown As String   '次コース(↓)
End Type

Dim UdtCI() As UdtCourceInfo

'-----------------------------------------------------------------------
' 関数名 : init
' 機能   : 構造体を初期化する
' 引数   : (in) なし
' 戻り値 : なし
' 備考   : VBは構造体や配列を初期化できないのがつらい…
'-----------------------------------------------------------------------
Public Sub init()

    Call SetCourceInfo(0, "A", 10, "B", "C")
    Call SetCourceInfo(1, "B", 30, "D", "E")
    Call SetCourceInfo(2, "C", 40, "E", "F")
    Call SetCourceInfo(3, "D", 50, "G", "H")
    Call SetCourceInfo(4, "E", 70, "H", "I")
    Call SetCourceInfo(5, "F", 20, "I", "J")
    Call SetCourceInfo(6, "G", 60, "K", "L")
    Call SetCourceInfo(7, "H", 10, "L", "M")
    Call SetCourceInfo(8, "I", 70, "M", "N")
    Call SetCourceInfo(9, "J", 40, "N", "O")
    Call SetCourceInfo(10, "K", 30, "P", "Q")
    Call SetCourceInfo(11, "L", 50, "Q", "R")
    Call SetCourceInfo(12, "M", 80, "R", "S")
    Call SetCourceInfo(13, "N", 10, "S", "T")
    Call SetCourceInfo(14, "O", 40, "T", "U")
    Call SetCourceInfo(15, "P", 90, STOP_ROUTE, STOP_ROUTE)
    Call SetCourceInfo(16, "Q", 70, STOP_ROUTE, STOP_ROUTE)
    Call SetCourceInfo(17, "R", 10, STOP_ROUTE, STOP_ROUTE)
    Call SetCourceInfo(18, "S", 60, STOP_ROUTE, STOP_ROUTE)
    Call SetCourceInfo(19, "T", 60, STOP_ROUTE, STOP_ROUTE)
    Call SetCourceInfo(20, "U", 70, STOP_ROUTE, STOP_ROUTE)

End Sub

'-----------------------------------------------------------------------
' 関数名 : SetCourceInfo
' 機能   : 構造体にデータを設定する
' 引数   : (in) UdtIndex  … 構造体配列のインデックス
'           (in) Cource … コース
'           (in) Price … 値段
'           (in) NextUp … 次コース(↑)
'           (in) Cource … 次コース(↓)
' 戻り値 : なし
'-----------------------------------------------------------------------
Private Sub SetCourceInfo(ByVal UdtIndex As Long, _
                          ByVal Cource As String, _
                          ByVal Price As Long, _
                          ByVal NextUp As String, _
                          ByVal NextDown As String)

    'メモリー再確保 Preserve は実に便利だ!!
    ReDim Preserve UdtCI(UdtIndex) As UdtCourceInfo
    With UdtCI(UdtIndex)
        .Cource = Cource
        .Price = Price
        .NextUp = NextUp
        .NextDown = NextDown
    End With

End Sub

'-----------------------------------------------------------------------
' 関数名 : PrintRoute
' 機能   : ルートと合計料金を算出し、表示する
' 引数   : (in) UdtIndex  … 構造体配列のインデックス
'           (in) CourceNum … 何個目のコースか
'           (in) Price … 値段合計
'           (in) Route … コース
' 戻り値 : なし
'-----------------------------------------------------------------------
Public Sub PrintRoute(ByVal UdtIndex As Long, _
                      ByVal CourceNum As Long, _
                      ByVal Price As Long, _
                      ByVal Route As String)
    Dim NextIndex As Long

    'ルート組み立てと値段合計
    Route = Route & UdtCI(UdtIndex).Cource
    Price = Price + UdtCI(UdtIndex).Price

    '上コース
    NextIndex = GetCourceIndex(UdtCI(UdtIndex).NextUp)
    If NextIndex <> NO_COURCE Then
        Call PrintRoute(NextIndex, CourceNum + 1, Price, Route)
    '上コースが無くなり行き止まったら表示
    Else
        Debug.Print Route & "(" & CStr(Price) & ")"
    End If

    '下コース
    NextIndex = GetCourceIndex(UdtCI(UdtIndex).NextDown)
    If NextIndex <> NO_COURCE Then
        Call PrintRoute(NextIndex, CourceNum + 1, Price, Route)
    End If

End Sub

'-----------------------------------------------------------------------
' 関数名 : GetCourceIndex
' 機能   : コース名から構造体配列のインデックスを取得する
' 引数   : (in) TargetCource … コース名
' 戻り値 : 構造体配列のインデックス
'-----------------------------------------------------------------------
Private Function GetCourceIndex(ByVal TargetCource As String) As Long

    Dim i As Long
    For i = 0 To UBound(UdtCI)
        If UdtCI(i).Cource = TargetCource Then
            GetCourceIndex = i
            Exit Function
        End If
    Next i

    GetCourceIndex = NO_COURCE

End Function

としたら、後は呼ぶだけ。

Private Sub Form_Load()
    Dim Route As String
    Call init
    Call PrintRoute(0, 0, 0, Route)
End Sub


[C言語]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define COURCE_NUM 21
#define STOP_ROUTE '#'
#define NO_COURCE  (-1)

struct UdtCourceInfo {
    char Cource;     /* コース */
    int  Price;      /* 料金 */
    char NextUp;     /* 次コース(↑) */
    char NextDown;   /* 次コース(↓) */
};

struct UdtCourceInfo UdtCource[COURCE_NUM] = {
        { 'A', 10, 'B', 'C' },
        { 'B', 30, 'D', 'E' },
        { 'C', 40, 'E', 'F' },
        { 'D', 50, 'G', 'H' },
        { 'E', 70, 'H', 'I' },
        { 'F', 20, 'I', 'J' },
        { 'G', 60, 'K', 'L' },
        { 'H', 10, 'L', 'M' },
        { 'I', 70, 'M', 'N' },
        { 'J', 40, 'N', 'O' },
        { 'K', 30, 'P', 'Q' },
        { 'L', 50, 'Q', 'R' },
        { 'M', 80, 'R', 'S' },
        { 'N', 10, 'S', 'T' },
        { 'O', 40, 'T', 'U' },
        { 'P', 90, STOP_ROUTE, STOP_ROUTE },
        { 'Q', 70, STOP_ROUTE, STOP_ROUTE },
        { 'R', 10, STOP_ROUTE, STOP_ROUTE },
        { 'S', 60, STOP_ROUTE, STOP_ROUTE },
        { 'T', 60, STOP_ROUTE, STOP_ROUTE },
        { 'U', 70, STOP_ROUTE, STOP_ROUTE }
};

static int GetCourceIndex(char TargetCource);
static void PrintRoute(int UdtIndex, int CourceNum, int Price, char *Route);

void main(void){
    char Route[10];
    memset(Route, '\0', sizeof(Route));
    PrintRoute(0, 0, 0, Route);
}

static void PrintRoute(int UdtIndex, int CourceNum, int Price, char *Route){
    int NextIndex;

    Route[CourceNum] = UdtCource[UdtIndex].Cource;
    Price += UdtCource[UdtIndex].Price;

    /* 上コース */
    NextIndex = GetCourceIndex(UdtCource[UdtIndex].NextUp);
    if(NextIndex != NO_COURCE){
        PrintRoute(NextIndex, CourceNum + 1, Price, Route);
    }
    /* 上コースが無くなり行き止まったら表示 */
    else {
        printf("%s(%d)\n", Route, Price);
        return;
    }

    /* 下コース */
    NextIndex = GetCourceIndex(UdtCource[UdtIndex].NextDown);
    if(NextIndex != NO_COURCE){
        PrintRoute(NextIndex, CourceNum + 1, Price, Route);
    }
}

static int GetCourceIndex(char TargetCource){
    int i;
    for(i=0;i<COURCE_NUM;i++){
        if(UdtCource[i].Cource == TargetCource) return i;
    }
    return NO_COURCE;
}


[ついでなんでJava??]
public class RecursiveFunc{

    public static final String STOP_ROUTE = "#";
    public static final int    COURCE_NUM = 21;
    public static final int    NO_COURCE  = (-1);

    public static final int    M_COURCE    = 0;
    public static final int    M_PRICE     = 1;
    public static final int    M_NEXTUP    = 2;
    public static final int    M_NEXTDOWN  = 3;

    public static final String udtCource[][] = {
        { "A", "10", "B", "C" },
        { "B", "30", "D", "E" },
        { "C", "40", "E", "F" },
        { "D", "50", "G", "H" },
        { "E", "70", "H", "I" },
        { "F", "20", "I", "J" },
        { "G", "60", "K", "L" },
        { "H", "10", "L", "M" },
        { "I", "70", "M", "N" },
        { "J", "40", "N", "O" },
        { "K", "30", "P", "Q" },
        { "L", "50", "Q", "R" },
        { "M", "80", "R", "S" },
        { "N", "10", "S", "T" },
        { "O", "40", "T", "U" },
        { "P", "90", STOP_ROUTE, STOP_ROUTE },
        { "Q", "70", STOP_ROUTE, STOP_ROUTE },
        { "R", "10", STOP_ROUTE, STOP_ROUTE },
        { "S", "60", STOP_ROUTE, STOP_ROUTE },
        { "T", "60", STOP_ROUTE, STOP_ROUTE },
        { "U", "70", STOP_ROUTE, STOP_ROUTE }
    };

    public static void main(String argv[]){
        RecursiveFunc rf = new RecursiveFunc();
        String route = "";
        rf.printRoute(0, 0, 0, route);
    }

    private void printRoute(int udtIndex, int courceNum, int price, String route){
        int nextIndex;

        route += udtCource[udtIndex][M_COURCE];
        price += Integer.parseInt(udtCource[udtIndex][M_PRICE]);

        //上コース
        nextIndex = getCourceIndex(udtCource[udtIndex][M_NEXTUP]);
        if(nextIndex != NO_COURCE){
            printRoute(nextIndex, courceNum + 1, price, route);
        }
        //上コースが無くなり行き止まったら表示
        else {
            System.out.println(route + "(" + Integer.toString(price) + ")");
            return;
        }

        //下コース
        nextIndex = getCourceIndex(udtCource[udtIndex][M_NEXTDOWN]);
        if(nextIndex != NO_COURCE){
            printRoute(nextIndex, courceNum + 1, price, route);
        }
    }

    private int getCourceIndex(String targetCource){
        for(int i=0;i<COURCE_NUM;i++){
            if(udtCource[i][M_COURCE].equals(targetCource)) return i;
        }
        return NO_COURCE;
    }
}


[実行結果]
Visual Basic  C言語  Java
ABDGKP(270) ABDGKP(270) ABDGKP(270)
ABDGKQ(250) ABDGKQ(250) ABDGKQ(250)
ABDGLQ(270) ABDGLQ(270) ABDGLQ(270)
ABDGLR(210) ABDGLR(210) ABDGLR(210)
ABDHLQ(220) ABDHLQ(220) ABDHLQ(220)
ABDHLR(160) ABDHLR(160) ABDHLR(160)
ABDHMR(190) ABDHMR(190) ABDHMR(190)
ABDHMS(240) ABDHMS(240) ABDHMS(240)
ABEHLQ(240) ABEHLQ(240) ABEHLQ(240)
ABEHLR(180) ABEHLR(180) ABEHLR(180)
ABEHMR(210) ABEHMR(210) ABEHMR(210)
ABEHMS(260) ABEHMS(260) ABEHMS(260)
ABEIMR(270) ABEIMR(270) ABEIMR(270)
ABEIMS(320) ABEIMS(320) ABEIMS(320)
ABEINS(250) ABEINS(250) ABEINS(250)
ABEINT(250) ABEINT(250) ABEINT(250)
ACEHLQ(250) ACEHLQ(250) ACEHLQ(250)
ACEHLR(190) ACEHLR(190) ACEHLR(190)
ACEHMR(220) ACEHMR(220) ACEHMR(220)
ACEHMS(270) ACEHMS(270) ACEHMS(270)
ACEIMR(280) ACEIMR(280) ACEIMR(280)
ACEIMS(330) ACEIMS(330) ACEIMS(330)
ACEINS(260) ACEINS(260) ACEINS(260)
ACEINT(260) ACEINT(260) ACEINT(260)
ACFIMR(230) ACFIMR(230) ACFIMR(230)
ACFIMS(280) ACFIMS(280) ACFIMS(280)
ACFINS(210) ACFINS(210) ACFINS(210)
ACFINT(210) ACFINT(210) ACFINT(210)
ACFJNS(180) ACFJNS(180) ACFJNS(180)
ACFJNT(180) ACFJNT(180) ACFJNT(180)
ACFJOT(210) ACFJOT(210) ACFJOT(210)
ACFJOU(220) ACFJOU(220) ACFJOU(220)


戻る