JavaScript を使ってアスキーアートで円を描くをやってみた

投稿日時:2014年7月19日 カテゴリー:JavaScript

どうも、JavaScript 世界ランキング 584321位の小善です。

今回は、

プログラマのためのコードパズル
~JavaScriptで挑むコードゴルフとアルゴリズム

プログラマのためのコードパズル

を購入しやってみました。
ちなみに、コードゴルフとは如何にコードを短くするかを競うゲームです。
コードを短くするなら、ハードコーディングや改行/空白/コメントの削除と言ったとても実践では使えない技術を駆使しますが、
アルゴリズムを理解しているからこそ短縮できると言える部分もあり、コードを読み理解を深めるにはもってこいのゲームかもしれません。

 

その1問目が以下の図を描く JavaScript の作成です。

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
------------------------------*********************-----------------------------
--------------------------*****************************-------------------------
-----------------------***********************************----------------------
--------------------*****************************************-------------------
------------------*********************************************-----------------
-----------------***********************************************----------------
---------------***************************************************--------------
--------------*****************************************************-------------
-------------*******************************************************------------
------------*********************************************************-----------
------------*********************************************************-----------
-----------***********************************************************----------
-----------***********************************************************----------
-----------***********************************************************----------
-----------***********************************************************----------
-----------***********************************************************----------
-----------***********************************************************----------
-----------***********************************************************----------
------------*********************************************************-----------
------------*********************************************************-----------
-------------*******************************************************------------
--------------*****************************************************-------------
---------------***************************************************--------------
-----------------***********************************************----------------
------------------*********************************************-----------------
--------------------*****************************************-------------------
-----------------------***********************************----------------------
--------------------------*****************************-------------------------
------------------------------*********************-----------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

 

下記のJavaScript のコードはサンプルでこれの文字数を如何に短くするかを考えます。

function yourCode() {
	// 変数の初期化
	var res = "";
	var w = 80;
	var h = 40;
	var sz = 30;

	// 処理
	for (var y = 0; y < h; y ++) {
		for (var x = 0; x < w; x ++) {
			var dstnc = Math.sqrt(
				  Math.pow(w / 2 - x, 2)
				+ Math.pow((h / 2 - y) * 2, 2)
			);
			if (dstnc < sz) {
				res += "*";
			} else {
				res += "-";
			}
		}
		res += "\n"
	}

	// 結果を戻して終了
	return res;
}

 

私が、驚愕したのはまず、難易度は一番低く簡単なプログラムですと紹介された上記のコードでなぜ円が書けるのか全く理解できないことです。
自信満々に買ってみたはいいのですが、さっぱりわかりません。
これが難易度一番低いなんて、これプログラムの分野はあきらめたほうがいいですかね、、、

 

どこが理解できないかはさすがにわかります。
以下の部分。

	for (var y = 0; y < h; y ++) {
		for (var x = 0; x < w; x ++) {
			var dstnc = Math.sqrt(
				  Math.pow(w / 2 - x, 2)
				+ Math.pow((h / 2 - y) * 2, 2)
			);

 

君何してるんですか?

Why can you draw a circle ?

ちなみに、

Math.sqrt は 引数の平方根を返します。
1 = 1
2 = 1.414….
4 = 2

Math.pow はべき乗を得ます。
Math.pow(x,y)
x=基数, y=指数
x=3, y=2
3の2乗 = 9

368文字のソースコードを最終的には、88文字まで短縮しています。
短縮コードの正解は書物を購入して確認していただければと思います。

私はこの簡単と紹介されているアルゴリズムを理解するのに 2日かかりました。

アルゴリズムの解読

まず Math.sqrt Math.pow の部分を大まかに数式に直します。
はい、「三平方の定理」の一番長い三角形の辺を求める式です。

三平方の定理の辺を求める式

これはすぐにわかりました。
次、

for 文の y は列を x は行を指していることはわかります。

図にすると以下
円の中点空の距離図1

 

そして注目すべきはMath.pow で指定された 2点
w / 2 – x
(h / 2 – y) * 2

(h / 2 – y)が×2になっているのは、 w が hの2倍だからでしょう。
さらに焦点を絞ると、、、、

w / 2
h / 2

が浮かびあがります。
これは、w h で構成される四角形の中点です。

 

円の中点空の距離図2

 

ここまで約2日かかりました。
後は、芋づる式でしたが。
ちなみにひらめいたのは、バイト中です。

さてここからは、思考を広げていきます。
中点から x や y を引いている。
図にすると以下です。

 

円の中点空の距離図3

 

この形もしや。。。この後とんでもない事実が発覚!!!
いったん、CM に入りませーん。

単純に「三平方の定理」で中点からの距離を求める式でした。

 

「円周内にいることを判定するには円の中点から半径以内の距離にいればよいことになります。」

 

つまり、あの難しかったプログラムは距離を求めるだけだったのでした。
後は、円周内にいれば円を表す「*」それ以外は「-」を表示するだけ。

感想

1問目からこれほど苦戦するとは、でも思考の訓練としては、なかなかおもしろそうです。

本によるとゲーム制作系のプログラマが敵が射程範囲にいるかを判定する際によく使われるとか何とか。
ゲーム系のプログラマは、複雑怪奇なアルゴリズムを理解する柔軟な思考が求められそうです。


コメントを残す