2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ペントミノ・ソルバーをいろんな言語で書いてみる

Last updated at Posted at 2024-04-29

概要

プログラム言語の文法はいろいろなので Hello World だけではその言語の特徴は把握できないですよね。
そこで、基本的な文法の理解&比較&備忘録として、ペントミノのソルバーを30種類のプログラミング言語で書いてみました。

https://github.com/sense-n-react/PentominoSolvers

どの言語も200~300行程度のコードなので全体を把握するのは難しくないと思います。

output.png Ruby Python Lua Squirrel Julia JavaScript TypeScript Groovy Perl AWK PHP C C++ C# Java Kotlin Go Rust Swift LISP Crystal Elixir F# D Dart Zig Nim Pascal Bash VisualBasic Scala Prolog

比較のポイント

  • 関数の宣言方法:引数、返り値
  • 変数の宣言方法:型指定、ローカル、グローバル、mutable/immutable
  • 配列:作り方、操作メソッド、多次元
  • 文字列:操作メソッド、変数埋込、複数行文字列
  • 連想配列
  • NULL値: null, nil, nothing, ....
  • print文: 書式指定方法
  • コメント文
  • ブロックの書式: {} 、~ end
  • for, foreach, if の構文
  • 三項演算子
  • lambda、closure、アロー関数
  • クラス:メンバ変数、メソッド、コンストラクタ
  • コマンドライン引数
  • 実行時間

プログラム

ソースコード

https://github.com/sense-n-react/PentominoSolvers

プログラムの特徴としては、ひたすら配列アクセスや関数呼び出しを行うものです。これだけで言語の良し悪しを評価することはできませんが、素(す)の言語の使い勝手を感じることはできると思います。

プログラム全体の処理の流れ、構成(見た目)、クラス名、関数名、変数名はできるだけ同じにしています。オブジェクト指向的な作りを心掛けましたが、AWK、Perl、LISP はベタな書き方で妥協しています。

実行方法

ソルバープログラムは個別に実行できます。表示はキャラクターベースです。

普通に実行
$ ruby solver.rb
+---+---------------+---+
|   |               |   |
|   +-------+   +---+   |
|           |   |       |
+-------+   +---+   +---+
|       |   |       |   |
|       +---+-------+   |
|       |           |   |
+---+   +-------+   |   |
|   |   |       |   |   |
|   +---+---+   |   |   |
|           |   |   |   |
|   +---+---+   +---+   |
|   |   |       |   |   |
+---+   +---+---+   +---+
|           |   |       |
+---+   +---+   +---+   |
|   |   |           |   |
|   +---+-------+   |   |
|               |   |   |
+---------------+---+---+ 
                            2339

盤面のサイズ指定

デフォルトでは 6x10 の盤面で解を求めます。コマンドラインに 8x8 のように盤面のサイズを指定できます。指定可能なサイズは 3x20 4x15 5x12 6x10 10x6 12x5 14x5 20x3 8x8 4x16 16x4 のいずれかです。これ以外だと 6x10 として実行します。
8x84x16 では中央に 4x4 のスペースを配置して解を求めます。

8x8を指定して実行
$ ruby solver.rb 8x8
+---+-----------+---------------+
|   |           |               |
|   +-------+   |   +-----------+
|           |   |   |           |
+-------+   |   +---+   +-------+
|       |   |   |       |       |
+---+   +---+---+---+---+   +---+
|   |       |       |       |   |
|   +---+   |       +---+   |   |
|       |   |       |   |   |   |
|   +---+---+---+---+   +---+   |
|   |   |       |           |   |
|   |   |       +---+   +---+   |
|   |   |       |   |   |   |   |
+---+   +---+   |   +---+   |   |
|           |   |           |   |
+-----------+---+-----------+---+
                                    65

run-solver

言語が20種類もあると言語のコマンドをいちいち覚えてられない(特にコンパイル系)ので、run-solver というRubyスクリプトを作りました。
ファイルの拡張子を指定すれば対応する言語のプログラムを実行します。
コンパイル系言語ではコンパイルしてから実行します。

拡張子(言語)を指定して実行
$ ./run-solver rb                # ruby solver.rb を実行
$ ./run-solver rb js cpp         # 複数指定可
$ ./run-solver ruby              # 言語名でもOK
$ ./run-solver --all             # 全ての言語で実行
$ ./run-solver py --size 5x12    # 5x12 を python で実行

感想

プログラム言語の数が増えたので、本章の内容は「ペントミノ・ソルバーをいろんな言語で書いてみた感想」に移動しました。

動作環境

Linux ubuntu:22.04、Mac OS (Sonoma or later)、Cygwin(Windows)で動作確認しました。確認時点での各言語のバージョンは下表のとおりです。

言語 ubuntu 22.04 Mac OS Cygwin
Ruby 3.0.2 3.2.0 3.2.2
Python 3.10.12 3.13.0 3.9.16
Lua 5.1.5 5.4.7 5.3.6
Squirrel 3.2 3.2 ** 3.2
Julia 1.10.2 1.11.1 *1.8.2
JavaScript node 12.22.9 node 23.1 *node 20.12.2
TypeScript tsc 4.9.5 tsc 4.9.5 *tsc 4.9.5
Groovy 2.4.21 4.0.24 *2.5.23
Perl 5.34.0 5.34.1 5.36
AWK mawk 1.3.4 gawk 5.3.1
nawk 20200816
gawk 5.3.0
PHP 8.1.2 8.3.13 7.3.7
C gcc 11.4.0
clang 15.0
clang 15.0.0 gcc11.4.0
clang 8.0.1
C++ g++ 11.4.0
clang++ 15.0
clang++ 15.0.0 g++ 11.4.0
clang++ 8.0.1
C# mcs 6.8.0.105 mcs 6.12.0.182
csc 3.9.0
csc 4.8.4084.0
Java javac 11.0.22 javac 23.0.1 *javac 21.02
Kotlin kotlinc-jvm 1.3 kotlinc-jvm 2.0.21 * kotlinc-jvm 1.7.20
Go 1.18.1 1.23.2 * 1.19.4
Rust rustc 1.75.0 rustc 1.76.0 * rustc 1.70.0
Swift 5.10 1.90.1 * 5.10
LISP sbcl 2.1.11
clisp 2.49.93
sbcl 2.4.10
clisp 2.49.92
*sbcl 2.3.2
clisp 2.49
Crystal 1.14.0 LLVM: 18.1.6 1.14.0 *1.13.3 LLVM: 18.1.1
Elixir 1.12.2 1.17.3 *1.17.3
F# 6.0 fsi 12.0.0.0 dotnet 6.0.135 fsi12.9.100.0, dotnet 9.0.101 *fsi 12.9.100.0
D LDC 1.28.0 LDC 1.40.0 *DMD32 v2.109.1
Dart 2.15.1 and 3.6.2 3.6.2 N/A
Zig N/A 0.15.1 *0.15.0
Nim N/A 2.2.4 N/A
Pascal fpc 3.2.2 fpc 3.2.2 N/A
Bash 5.1.16 5.2.37 5.2.15
Visual Basic dotnet 6.0.136 dotnet 9.0.101 *dotnet 10.0.101
Scala 3.7.4 JVM(17) 3.7.4 JVM(25) *3.7.4 JVM(17)
Prolog SWI-Prolog 8.4.2 SWI-Prolog 9.2.9 SWI-Prolog 10.0.0

tsc (TypeScript Compiler) では、npm i --save-dev @types/node を一度だけ実行しておく必要があります。 実行していないとエラーがでます。

TypeScript の初回実行
$ tsc -t es2019 -m commonjs --strict solver-ts.ts
solver-ts.ts(202,18): error TS2580: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.

$ npm i --save-dev @types/node  # 指示通りに npm i ...を実行
$ ls node_modules              # node_modules ディレクトリが作られる
@types/   undici-types/
$ tsc -t es2019 -m commonjs --strict solver-ts.ts   # エラーにならずに実行できる

ubuntu 22.04

Mac と Windows(WSL2) 上のコンテナで全ての言語をインストールして動作確認しました。Dockerfile で x86_64 でなければ arm64 の Julia と Swift をダウンロードするように設定しています。
apt-get でインストールしましたが、Julia, Swift, Squirrel はパッケージが見つかりませんでした。Julia と Swift はバイナリイメージがあったのでそれをダウンロードし、Squirrel はソースからビルドしています。
Crystal は Dcokerfile に反映していないですが、x86_64版 tarball で動作確認しました。Dart は Dockerイメージで動作確認しました。
(Crystal 以降、Dockerfile のメンテが追いついていないです。)

Mac OS(Sonoma or Tahoe)

brew install でインストールしました。
(追記)F# は Microsoftの.NETのダウンロードサイトからダウンロードしました。

Cygwin(Windows)

Cygwin Ports にないものは Windows版をインストールし(*印)、 Windows版もないものはソースからビルド(**印)しました。

実行時間

やはり気になる実行時間をグラフにしてみました。MacBook M2 Sonoma の環境で、6x10 の全解(2,339通り)を求めるのにかかった時間をプロットしました。
スクリプト系とコンパイル系とでは桁が違ってくるので対数表示にしています。

time-6x10-20260106.png

なお、アルゴリズムを改良すれば全ての言語において10倍以上の高速化が可能ですが、ここでは言語間の比較が目的なので最適化には触れません。

履歴

(2024/4/29:投稿)
(2024/12/9: Crystal、Elixir を追加、実行速度グラフの修正)
(2025/2/10: D、Dartを追加、実行速度グラフの修正)
(2025/8/31: Zig, Nim を追加、実行速度グラフの修正)
(2025/9/5 : Pascal版 を追加、実行速度グラフの修正)
(2025/9/5 : Bash版 を追加)
(2025/12/14: Visual Basic版 を追加)
(2025/12/15:Scala版を追加、感想を別記事に移動)
(2026/1/6:Prolog版を追加、ページ構成見直し)

連記事

ペントミノ・ソルバーをいろんな言語で書いてみた感想
ペントミノ・ソルバーのアルゴリズム
ペントミノ・ソルバー(簡素版)のアルゴリズム
立体ペントミノ・ソルバー

参考記事

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?