これは、コマンドプロンプト(cmd.exe) Advent Calendar 2015 - Qiitaの14日目の記事です。※Windows 10 Home 64bit 搭載のcmd.exeにて検証を行っています。
さて、お代の通り、BATファイルでfibコマンドを実装します。
……が、普通に作ってしまうと再帰呼び出しになってしまってアレなので、まずは別言語で試してみます。

  • ①ただの再帰で実装
  • ②末尾再帰で実装
  • ③展開してGOTOに
  • ④BATファイル化
という順番でやります。

①ただの再帰で実装

後でGOTOを使うことも考えて、とりあえずCで実装します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <stdio.h></stdio.h>
int main(void){
    printf("%i", fib(10));
}
int fib(n) {
    if (n == 0) {
        return 0;
    } else if (n == 1) {
        return 1;
    } else {
        return fib(n-1) + fib(n-2);
    }
}

②末尾再帰で実装

つまり、1つ前の結果と2つ前の結果を足す、ってことなので・・・
(aが1つ前の結果、bが2つ前の結果)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h></stdio.h>
int main(void){
    printf("%i", fib(10));
}
int fib(n) {
    return fib_sub(n, 1, 0);
}
int fib_sub(n, a, b) {
    if (n == 0) {
        return 0;
    } else if (n == 1) {
        return a;
    } else {
        return fib_sub(n - 1, a + b, a);
    }
}

③展開してGOTOに

末尾再帰にできたので、gotoを使ったループに展開します

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h></stdio.h>
int main(void){
    printf("%i", fib(10));
}
int fib(n) {
    int a;
    int b;
    int swap;
    
    a = 1;
    b = 0;
    swap = 0;
    
loop:
    if (n == 0) {
        return 0;
    } else if (n == 1) {
        return a;
    } else {
        n = n - 1;
        swap = a + b;
        b = a;
        a = swap;
        goto loop;
    }
}

④BATファイル化

ではこれを、BATファイルで書き直します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@echo off

set /a n = %~1
set /a a = 1
set /a b = 0
set /a swap = 0

:LOOP
	if "%n%"=="0" echo 0 &amp;&amp; goto :eof
	if "%n%"=="1" echo %a% &amp;&amp; goto :eof
	set /a n = n - 1
	set /a swap = a + b
	set /a b = a
	set /a a = swap
	goto :LOOP

実行してみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
C:\Users\kunst\Desktop>fib 0
0

C:\Users\kunst\Desktop>fib 1
1

C:\Users\kunst\Desktop>fib 10
55

C:\Users\kunst\Desktop>fib 20
6765


できあがり!


1
2
3
C:\Users\kunst\Desktop>fib 50
-298632863

ありゃりゃ……