いろんな言語でハノイの塔
差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
| いろんな言語でハノイの塔 [2021/04/23 06:34] – [性能] araki | いろんな言語でハノイの塔 [2025/06/03 05:51] (現在) – [Batch (Cmd.exe)] araki | ||
|---|---|---|---|
| 行 31: | 行 31: | ||
| ^bash |4.3.42 |Celeron N3150 (1.60GHz) |Vine Linux 6.5 |122 | | ^bash |4.3.42 |Celeron N3150 (1.60GHz) |Vine Linux 6.5 |122 | | ||
| ^awk (gawk) |3.1.8 |Celeron N3150 (1.60GHz) |Vine Linux 6.5 |8 | | ^awk (gawk) |3.1.8 |Celeron N3150 (1.60GHz) |Vine Linux 6.5 |8 | | ||
| - | ^go|1.16.0|Core i3 5010U (2.1GHz) |Ubuntu 20.4 LTS|4 | | + | ^go|1.16.0|Core i3 5010U (2.1GHz) |Ubuntu 20.4 LTS|0.004 | |
| + | ^Rust|1.47.0|Core i3 5010U (2.1GHz) |Ubuntu 20.4 LTS|0.004 | | ||
| ===== プログラム ===== | ===== プログラム ===== | ||
| ==== PowerShell ==== | ==== PowerShell ==== | ||
| 行 48: | 行 49: | ||
| ((管理者権限でPowerShellを起動して'' | ((管理者権限でPowerShellを起動して'' | ||
| 管理者権限を使ってシステム全体のポリシーを変更するのがコワイ場合は、 | 管理者権限を使ってシステム全体のポリシーを変更するのがコワイ場合は、 | ||
| - | < | + | < |
| PS C: | PS C: | ||
| </ | </ | ||
| 行 64: | 行 65: | ||
| '' | '' | ||
| 分かりにくいので、気づきにくいミス。 | 分かりにくいので、気づきにくいミス。 | ||
| - | < | + | < |
| Param([Int]$n = 3) | Param([Int]$n = 3) | ||
| 行 91: | 行 92: | ||
| === 実行結果 === | === 実行結果 === | ||
| 第2世代Core i7のVAIO Z2(VPCZ2)上のWindows 10/ | 第2世代Core i7のVAIO Z2(VPCZ2)上のWindows 10/ | ||
| - | < | + | < |
| PS C: | PS C: | ||
| Disc 1 moved from 1 to 3. | Disc 1 moved from 1 to 3. | ||
| 行 130: | 行 131: | ||
| これを回避するために'': | これを回避するために'': | ||
| - | < | + | < |
| @echo off | @echo off | ||
| 行 205: | 行 206: | ||
| === 実行結果 === | === 実行結果 === | ||
| PowerShell版と同じ環境で実行したが、恐ろしく遅い。 | PowerShell版と同じ環境で実行したが、恐ろしく遅い。 | ||
| - | < | + | < |
| C: | C: | ||
| Disc 1 moved from 1 to 3 | Disc 1 moved from 1 to 3 | ||
| 行 240: | 行 241: | ||
| '' | '' | ||
| 本体は'' | 本体は'' | ||
| - | < | + | < |
| #include < | #include < | ||
| #include < | #include < | ||
| 行 301: | 行 302: | ||
| 速すぎて計測に意味がない。 | 速すぎて計測に意味がない。 | ||
| 多分、'' | 多分、'' | ||
| - | < | + | < |
| araki@chive[117]% time ./hanoic -n 4 | araki@chive[117]% time ./hanoic -n 4 | ||
| Disc 1 moved from 1 to 3. | Disc 1 moved from 1 to 3. | ||
| 行 330: | 行 331: | ||
| Boostを使っているのは、コマンドライン引数の処理をしてくれる手頃なライブラリだからというだけで、別にGNU のparseoptなんかを使っても良かったのだが、まあ、そんな感じで、多分このせいでCに比べてやや遅くなっている。 | Boostを使っているのは、コマンドライン引数の処理をしてくれる手頃なライブラリだからというだけで、別にGNU のparseoptなんかを使っても良かったのだが、まあ、そんな感じで、多分このせいでCに比べてやや遅くなっている。 | ||
| === コード === | === コード === | ||
| - | < | + | < |
| #include < | #include < | ||
| #include < | #include < | ||
| 行 380: | 行 381: | ||
| === 実行結果 === | === 実行結果 === | ||
| - | < | + | < |
| araki@chive[131]% time ./hanoicc -n 4 | araki@chive[131]% time ./hanoicc -n 4 | ||
| Disc 1 moved from 1 to 3 | Disc 1 moved from 1 to 3 | ||
| 行 411: | 行 412: | ||
| でも、なんというか、C言語との食い合わせがいまいちなスタイルで、これが好きになれなかったんですよね。 | でも、なんというか、C言語との食い合わせがいまいちなスタイルで、これが好きになれなかったんですよね。 | ||
| - | < | + | < |
| #import < | #import < | ||
| #import < | #import < | ||
| 行 486: | 行 487: | ||
| そもそも、こういう題材に向いている言語ではないんだよね。 | そもそも、こういう題材に向いている言語ではないんだよね。 | ||
| Quick Sortとか書くと Lispっぽくていいんだけれどね。 | Quick Sortとか書くと Lispっぽくていいんだけれどね。 | ||
| - | < | + | < |
| ; | ; | ||
| (defun hanoi (n a b c) | (defun hanoi (n a b c) | ||
| 行 519: | 行 520: | ||
| </ | </ | ||
| === 実行結果 === | === 実行結果 === | ||
| - | < | + | < |
| araki@chive[171]% time clisp hanoi.cl -n 4 | araki@chive[171]% time clisp hanoi.cl -n 4 | ||
| 行 556: | 行 557: | ||
| GNU Prologの場合ブートストラップコードをCで書くことが出来るので、コマンドライン引数の処理なんかはそっちでやっているから、本体だけしかないのでこのようになっている。 | GNU Prologの場合ブートストラップコードをCで書くことが出来るので、コマンドライン引数の処理なんかはそっちでやっているから、本体だけしかないのでこのようになっている。 | ||
| 参考までにブートストラップのコードも載せておく。 | 参考までにブートストラップのコードも載せておく。 | ||
| - | < | + | < |
| hanoi(0, | hanoi(0, | ||
| 行 562: | 行 563: | ||
| </ | </ | ||
| - | < | + | < |
| /* | /* | ||
| * Prolog Wrapper | * Prolog Wrapper | ||
| 行 623: | 行 624: | ||
| === 実行結果 === | === 実行結果 === | ||
| - | < | + | < |
| araki@chive[177]% time ./hanoipro -n 4 | araki@chive[177]% time ./hanoipro -n 4 | ||
| Disc 1 moved from 1 to 3 | Disc 1 moved from 1 to 3 | ||
| 行 650: | 行 651: | ||
| コードにはコメントをつけてあります。 | コードにはコメントをつけてあります。 | ||
| 引数はなんとなくそんな感じになるように処理していますが、適当なので、あまり追求しないでください。 | 引数はなんとなくそんな感じになるように処理していますが、適当なので、あまり追求しないでください。 | ||
| - | < | + | < |
| # | # | ||
| 1000 !=^GETARG | 1000 !=^GETARG | ||
| 行 704: | 行 705: | ||
| === 実行結果 === | === 実行結果 === | ||
| 処理系が優秀だからか、あるいは、そもそも、関数呼び出しなどの処理が軽いからなのか、かなり高速だと思います。 | 処理系が優秀だからか、あるいは、そもそも、関数呼び出しなどの処理が軽いからなのか、かなり高速だと思います。 | ||
| - | < | + | < |
| araki@chive[109]% time ./hanoi.vtl -n 4 | araki@chive[109]% time ./hanoi.vtl -n 4 | ||
| Disc 1 moved from 1 to 3. | Disc 1 moved from 1 to 3. | ||
| 行 740: | 行 741: | ||
| '' | '' | ||
| あとは、'' | あとは、'' | ||
| - | < | + | < |
| # | # | ||
| 行 799: | 行 800: | ||
| </ | </ | ||
| === 実行結果 === | === 実行結果 === | ||
| - | < | + | < |
| araki@chive[125]% time ./hanoi.pl -n 4 | araki@chive[125]% time ./hanoi.pl -n 4 | ||
| Disc 1 moved from 1 to 3 | Disc 1 moved from 1 to 3 | ||
| 行 833: | 行 834: | ||
| 特にひねりもなく、普通に実装してあります。 | 特にひねりもなく、普通に実装してあります。 | ||
| 特筆するべきこともないかと思います。 | 特筆するべきこともないかと思います。 | ||
| - | < | + | < |
| # | # | ||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||
| 行 868: | 行 869: | ||
| </ | </ | ||
| === 実行結果 === | === 実行結果 === | ||
| - | < | + | < |
| araki@chive[131]% time ./hanoi.rb -n 4 | araki@chive[131]% time ./hanoi.rb -n 4 | ||
| Disc 1 moved from 1 to 3 | Disc 1 moved from 1 to 3 | ||
| 行 904: | 行 905: | ||
| '' | '' | ||
| つまり、クラスライブラリとそれに付随するサンプル、あるいはテストコードをひとまとめにしておくことも出来るのはなかなかに便利だと思います。 | つまり、クラスライブラリとそれに付随するサンプル、あるいはテストコードをひとまとめにしておくことも出来るのはなかなかに便利だと思います。 | ||
| - | < | + | < |
| # | # | ||
| 行 938: | 行 939: | ||
| </ | </ | ||
| === 実行結果 === | === 実行結果 === | ||
| - | < | + | < |
| araki@chive[146]% time ./hanoi.py -n 4 | araki@chive[146]% time ./hanoi.py -n 4 | ||
| Disc 1 moved from 1 to 3 | Disc 1 moved from 1 to 3 | ||
| 行 972: | 行 973: | ||
| このため再帰呼び出しの際に '' | このため再帰呼び出しの際に '' | ||
| - | < | + | < |
| # | # | ||
| 行 1003: | 行 1004: | ||
| </ | </ | ||
| === 実行結果 === | === 実行結果 === | ||
| - | < | + | < |
| araki@chive[152]% time ./ | araki@chive[152]% time ./ | ||
| Disc 1 moved from 1 to 3 | Disc 1 moved from 1 to 3 | ||
| 行 1027: | 行 1028: | ||
| awkは、AT& | awkは、AT& | ||
| 一行野郎などと言われるように、本来は、単機能を実装したコマンドを、パイプでつないで、複雑な処理を実現するのが主な使い方であり、コードそのものをコマンドラインにタイプしてしまい、わざわざスクリプトファイルにしたりしないことも多い。 | 一行野郎などと言われるように、本来は、単機能を実装したコマンドを、パイプでつないで、複雑な処理を実現するのが主な使い方であり、コードそのものをコマンドラインにタイプしてしまい、わざわざスクリプトファイルにしたりしないことも多い。 | ||
| - | < | + | < |
| $ cat resul.txt | awk ' | $ cat resul.txt | awk ' | ||
| </ | </ | ||
| 行 1037: | 行 1038: | ||
| === コード === | === コード === | ||
| 普通の関数型言語の側面もあるので、そのまま、ストレートに実装してある。 | 普通の関数型言語の側面もあるので、そのまま、ストレートに実装してある。 | ||
| - | < | + | < |
| # | # | ||
| function hanoi(n, a, b, c) | function hanoi(n, a, b, c) | ||
| 行 1066: | 行 1067: | ||
| </ | </ | ||
| === 実行結果 === | === 実行結果 === | ||
| - | < | + | < |
| araki@chive[157]% time ./hanoi.awk -n 4 | araki@chive[157]% time ./hanoi.awk -n 4 | ||
| Disc 1 moved from 1 to 3 | Disc 1 moved from 1 to 3 | ||
| 行 1085: | 行 1086: | ||
| 0.003u 0.005s 0:00.00 0.0% 0+0k 0+0io 0pf+0w | 0.003u 0.005s 0:00.00 0.0% 0+0k 0+0io 0pf+0w | ||
| araki@chive[158]% | araki@chive[158]% | ||
| + | </ | ||
| + | ==== Go ==== | ||
| + | === 能書き === | ||
| + | Goは比較的新しいコンパイラ言語である。 | ||
| + | 静的型付けを基本とする言語であるが、メモリ管理は言語側が行い、ガベージコレクションなどの機能も内包している。 | ||
| + | |||
| + | 関数型言語であり、構造体を使った、オブジェクト指向っぽい記述もできる。 | ||
| + | |||
| + | === コード === | ||
| + | |||
| + | コマンドラインの引数をとるために flagを、表示の加工用に fmtモジュールを利用している以外は、コード内で完結している。 | ||
| + | |||
| + | <code go> | ||
| + | package main | ||
| + | |||
| + | import ( | ||
| + | " | ||
| + | " | ||
| + | ) | ||
| + | |||
| + | type Discs int | ||
| + | |||
| + | type Hanoi struct { | ||
| + | N Discs | ||
| + | a int | ||
| + | b int | ||
| + | c int | ||
| + | } | ||
| + | |||
| + | func NewTower(n int) *Hanoi { | ||
| + | h := new(Hanoi) | ||
| + | h.N = Discs(n) | ||
| + | h.a = 1 | ||
| + | h.b = 2 | ||
| + | h.c = 3 | ||
| + | return h | ||
| + | } | ||
| + | |||
| + | func (n Discs) doit(a int, b int, c int) { | ||
| + | if n > 0 { | ||
| + | (n - 1).doit(a, c, b) | ||
| + | fmt.Printf(" | ||
| + | (n - 1).doit(c, b, a) | ||
| + | } | ||
| + | } | ||
| + | |||
| + | func (h Hanoi) run() { | ||
| + | h.N.doit(h.a, | ||
| + | } | ||
| + | |||
| + | func main() { | ||
| + | n := flag.Int(" | ||
| + | flag.Parse() | ||
| + | hanoi := NewTower(*n) | ||
| + | hanoi.run() | ||
| + | } | ||
| + | </ | ||
| + | === 実行結果 === | ||
| + | |||
| + | <code bash> | ||
| + | araki@cherry: | ||
| + | Disc 1 moved from 1 to 3. | ||
| + | Disc 2 moved from 1 to 2. | ||
| + | Disc 1 moved from 3 to 2. | ||
| + | Disc 3 moved from 1 to 3. | ||
| + | Disc 1 moved from 2 to 1. | ||
| + | Disc 2 moved from 2 to 3. | ||
| + | Disc 1 moved from 1 to 3. | ||
| + | Disc 4 moved from 1 to 2. | ||
| + | Disc 1 moved from 3 to 2. | ||
| + | Disc 2 moved from 3 to 1. | ||
| + | Disc 1 moved from 2 to 1. | ||
| + | Disc 3 moved from 3 to 2. | ||
| + | Disc 1 moved from 1 to 3. | ||
| + | Disc 2 moved from 1 to 2. | ||
| + | Disc 1 moved from 3 to 2. | ||
| + | |||
| + | real 0m0.004s | ||
| + | user 0m0.005s | ||
| + | sys | ||
| + | araki@cherry: | ||
| + | </ | ||
| + | |||
| + | ==== Rust ==== | ||
| + | === 能書き === | ||
| + | システム記述言語として注目を集めているRust。 | ||
| + | メモリの管理が静的に行われており、予期せぬメモリリークなどによるセキュリティホールなどを言語レベルで防止できる。 | ||
| + | |||
| + | cargoを使用してひな型を作り、getoptsによるオプション処理を加えた。 | ||
| + | ハノイの塔本体部分より、オプションの処理部分のほうが大きい。 | ||
| + | なお、ハノイの塔部分に関しては特にオブジェクト指向的なつくりにはしていない。 | ||
| + | === コード === | ||
| + | コードは、RubyやPythonなどのスクリプト型言語と似た感じになっているが、静的な片付けが行われているところが、これらの言語とは違っている。 | ||
| + | また、ガベージコレクションによる動的なメモリ管理ではなく、静的な管理が中心となる。 | ||
| + | |||
| + | <code rust> | ||
| + | use getopts:: | ||
| + | use std:: | ||
| + | use std::env; | ||
| + | |||
| + | fn print_usage(prog_name: | ||
| + | { | ||
| + | let brief = format!(" | ||
| + | print!(" | ||
| + | process:: | ||
| + | } | ||
| + | |||
| + | fn hanoi(n: i32, a: i32, b: i32, c: i32) | ||
| + | { | ||
| + | if n > 0 | ||
| + | { | ||
| + | hanoi(n - 1, a, c, b); | ||
| + | println!(" | ||
| + | hanoi(n - 1, c, b, a); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fn main() | ||
| + | { | ||
| + | let args: Vec< | ||
| + | let program = args[0].clone(); | ||
| + | |||
| + | let mut opts = Options:: | ||
| + | opts.optopt(" | ||
| + | opts.optflag(" | ||
| + | let matches = match opts.parse(& | ||
| + | { | ||
| + | Ok(m) => { m } | ||
| + | Err(f) => { panic!(f.to_string()) } | ||
| + | }; | ||
| + | if matches.opt_present(" | ||
| + | { | ||
| + | print_usage(& | ||
| + | return; | ||
| + | } | ||
| + | let n = match matches.opt_get_default::< | ||
| + | { | ||
| + | Ok(t) => { t } | ||
| + | Err(f) => { panic!(f.to_string()) } | ||
| + | }; | ||
| + | hanoi(n, 1, 2, 3); | ||
| + | } | ||
| + | </ | ||
| + | === 実行結果 === | ||
| + | <code bash> | ||
| + | araki@cherry: | ||
| + | Disc 1 moved from 1 to 3 | ||
| + | Disc 2 moved from 1 to 2 | ||
| + | Disc 1 moved from 3 to 2 | ||
| + | Disc 3 moved from 1 to 3 | ||
| + | Disc 1 moved from 2 to 1 | ||
| + | Disc 2 moved from 2 to 3 | ||
| + | Disc 1 moved from 1 to 3 | ||
| + | Disc 4 moved from 1 to 2 | ||
| + | Disc 1 moved from 3 to 2 | ||
| + | Disc 2 moved from 3 to 1 | ||
| + | Disc 1 moved from 2 to 1 | ||
| + | Disc 3 moved from 3 to 2 | ||
| + | Disc 1 moved from 1 to 3 | ||
| + | Disc 2 moved from 1 to 2 | ||
| + | Disc 1 moved from 3 to 2 | ||
| + | |||
| + | real 0m0.004s | ||
| + | user 0m0.003s | ||
| + | sys | ||
| + | araki@cherry: | ||
| </ | </ | ||
いろんな言語でハノイの塔.1619159663.txt.gz · 最終更新: by araki
