C to Go

オイラーはツイターなんてやっていないくせに、2冊目のツイター本を読んでみた。 『ツイッターで学んだいちばん大切なこと』(早川書房) 共同創業者のつぶやき。

共同創業者、ビズ・ストーンさんがツイートしてますよ。この会社、ぐぐるやフェイスブックや アプルと違って、きちんとした創業者がいない。3年の間に3回も社長が変わる、無鉄砲ぶり。

この本の140ページ目には、ツイターらしく、あっぱれな事が書いてあった。 なんで140字までかなんてのが披露されてた。その頃の通信標準は160文字が主流。これ、 課金の単位からくるやつね。だから、最初は1投稿160字にしたけど、この中身はユーザー名 込みのサイズ。ユーザー名の長さによって、本文のサイズが変わってくる。

これじゃ、ユーザー名の長さによって不公平になる。んなら、ユーザー名は15文字分で いいんじゃねぇ。すると本文は145文字だな。きりが悪いぞ。140文字でいいじゃん。これ、 秘密めいてるしね。まあ、こんなもんだよな。

そして無闇やたらにAPIを公開しちゃったものだから、やたらに重いアプリが作られ、この おかげで煩雑にサーバーが落ちる。落ちている時は、くじらさんが出て来る。これが人気に なって。。。人間は完全無欠じゃない。システムだってそうさ。明るく行こうよ。うん、そうだね。 いろいろな失敗が強くしてくれるんだよ。

所で、上に出てきた140字制限って、日本語ではどうよ。ツイター使って日本語を投げて いる人。日本語に限らずCJK世界の皆様。やっぱり英語と日本語違うよーっぽい。 Twitterは140文字ではない。と気づいた時の処方箋

Goの本を見ると、文字数とバイト数は違うよって書いてあるんですけど。

ああ、思い出した。オイラーのガラパゴス携帯。メールオプションを付けてるけど、この 所全く使っていない。ツイターとかやらないし、メールはCメールで十分だな。 メールオプションを解除しとこっと。

Cメールの文字制限はツイターっぽくていいな。五・七・五の国の人だもの。制限が有れば こそ、工夫するってもんです。

移植するぞ

いち
にー
さん
しー C の次だから
ごー Go
なんだろ?

今まで、血圧アプリを作ってきた訳だけど、一応完成を見たんで、すこし違う事でもやろう。 色々考えるに、自分で作りたいものは、無いな。以上、話終わりじゃ、本当に終わって しまうんでネタを考えてみる。

毎年と言うか毎月、どの言語が優勢かなんてのが発表されてて、一喜一憂してるだろ。 新しい言語に熱を上げて、チャートを駆け上がれば嬉しかったりする。まあ、流行おっかけって 事で、XXX48とかを追っかけるのと同じミーハー。

言語のヒットチャートでいつも不動の地位を占めてるのは、CとJava。紅白のトリだな。 ならば、これを追ってれば、若年であろうと老年であろうと問題無し。 JavaはつまんないのでC語だ。CをばんばんとGo語に変換出来たら楽しいな。 ハワイへ行って、日本語でしゃべられるより英語でやりとり出来たら、何倍か楽しいって 理屈だ。ああ、今年もハワイへ行けなかったな。

適当なフレーズをGoに翻訳して語学力を鍛えておこう。何か良い例題は無いかな? ふと、書籍棚を覗くと、アルゴリズム辞典なんてのに目が行った。平成3年の出版と いう事だから、もう20年前か。手に取ってみると、ソースが配布されてたのね。 配布場所が、パソコン通信の所って、時代がかっているな。どこかで手に入らないかしら。 ぐぐる様に聞いてみたら、 C言語による最新アルゴリズム事典 って、著者の奥村先生が、サポートページを公開されてた。

PASCALからC、そしてJava語へと改定を続けてきているみたい。この本は日本の名著100選に も入ってるんで、持っててよかった。Cじゃイヤって人向きには、 Ruby でアルゴリズムなんてのも あるんで、楽しめるぞ。

じゃ、何かの例文をGo語に翻訳してみよう。CとGoは親類関係にあるんで、そんなに 頭を使わなくても出来るだろう。例文には何を選ぼう?

おいらが好きなTV番組に、『Youは何しに日本へ?』がある。この番組で、スェーデン だからの高校生がガイドブック片手に日本へやってきたのを放映してた。 目をつむり、ガイドブックをパラパラさせて、適当な所を指す、指された所へ観光にGo。 ダーツを日本地図に投げて、当たった所へ行く、所さん番組と一緒だな。

こういう無計画と言う計画もいいもんだ。オイラーもそれに習ってやってみる。

C to Go その壱

素数を求めるのに当たりました。おめでとう、いきなり数学の深遠な所ですな。C語では 次にようになってた。

#define N 168
int prime[N];

void generate_primes(void)
{
    int j, k, x;

    prime[0] = 2;  x = 1;  k = 1;
    while (k < N) {
        x += 2;  j = 0;
        while (j < k && x % prime[j] != 0) j++;
        if (j == k) prime[k++] = x;
    }
}

N個の素数をもとめなさい問題。Goには#define無いよ。while無いよ。これをどうGo語で 言いまわすかが、争点もとえ工夫のしどころだな。 取り合えず、primes.cをprimes.goにrenameしてから、逐次変換してきます。適当な所で、Go コンパイラーにお伺いを立てて、まずい点は指摘して貰うってのが、正しい言語の学び方 でしょう。

オイラーの翻訳は、次のようになった。

package main
import "fmt"

const N = 100000
var prime [N]int

func generate_primes() {
        var j, k, x int
        prime[0] = 2
        x, k = 1, 1
        for {
                if !(k < N) {
                        break
                }
                x += 2
                j = 0
                for {
                        if !(j < k && x%prime[j] != 0) {
                                break
                        }
                        j++
                }
                if j == k {
                        prime[k] = x
                        k++
                }
        }
}

fmtをimportしてるのは、mainて結果表示用にPrintfを使っている為。頭に packageを入れるのを忘れ、変なエラーを喰らったのは、ここだけの話にしてね。

#defineは、constに変換。後は変数宣言の語順に気をつけて。行末にあるセミコロンはわざわざ 消さなくても、gofmtを通ると自動的に削除される。

問題のwhileは、forで永久ループを作っておいて、ループ内の冒頭で、whileのtest句判定条件を 論理反転させて、breakでループを抜け出るようにすれば良い。ここには出てこないけど、C語 には、do-whileも有る。Go語には無い。これもforの永久ループを書いておいて、ループの 最後部分でtest句を反転させたifで、breakさせれば良い。

求める素数の個数を上記のように多くして、C語とスピード比べしてみる。

sakae@uB:~/godev/src/sosu/C$ go build primes.go
sakae@uB:~/godev/src/sosu/C$ time ./primes > /dev/null
real    0m24.325s
user    0m24.220s
sys     0m0.076s
sakae@uB:~/godev/src/sosu/C$ cc primes.c
sakae@uB:~/godev/src/sosu/C$ time ./a.out > /dev/null
real    0m24.470s
user    0m24.432s
sys     0m0.016s
sakae@uB:~/godev/src/sosu/C$ cc -O2 primes.c
sakae@uB:~/godev/src/sosu/C$ time ./a.out > /dev/null
real    0m23.588s
user    0m23.528s
sys     0m0.040s

チューニングしたC語には負けたけど、普通のCとは互角の戦いをしてるな。

C to Go その弐

次は、観光名所を下調べして的を絞ってみる。コッホ曲線とかドラゴンカーブとか、再帰を 使ったお絵かきが出てた。再帰はもうゲップが出る程やってるんでパスするとして、お絵書き はどうやってるか興味が有るな。

国民機のPC9800用のグラフィック用コードが出てた。ハードを直接叩いて点を打つのが 基本。それを利用して直線を引いたり、円を書いたりするのが載ってた。 それを下敷きにして、もっと抽象化したものが二つのソースで提供されてた。

一つは、plotterルーチン。XY-plotter をシュミレートする。 penをUpした状態で移動するmoveってルーチンとpenを下ろして描画するdrawってルーチン。 (と、その変形)を、サポートしたplotter.c

もう一つは、plotterルーチンの下層にあるwindow.cってファイル。drawとかが使う仮想画面を 実画面の座標にマッピングするための係数を決める関数gr_windowと、実際にマッピングして 線を引くgr_wlineって関数で構成されてる。

これらをGo語に変換して、Goで絵してみよう。Go側の絵描きと言うと、以前にやった、gnuplotとか draw2dとかを思い出すけど、今回は不遇のsvgを応援してみよう。提供場所は、 Go Language Library for SVG generation

こちらに載ってるWebサーバーの例を借りてきて、上記ルーチン群を合体させれば いいだろう。C語とGo語のコラボ、Go寄りって塩梅にする。

Goに翻訳する要領が掴めてきたので、すいすい進んだよ。 で、書いたテストケースは下記

func mymain() {
    canvas.Circle(250, 250, 125, "fill:none;stroke:black")
    canvas.Circle(50, 250, 5, "fill:red;stroke:none")
    canvas.Line(0, 0, 250, 250, "stroke:blue")
    gr_window(-30, 0, 30, 60, 1, 1)
}

http://localhost:8080/ にアクセスして、黒枠と円、線が出てくれば、取り合えずOK。 下記は、Webサーバーに送られる描画データ。昔はPC98で絵を描いてたもんだけど、今は それをブラウザーが肩代わりしてくれるのね。svgってtagが打たれているけど、htmlの 拡張にしか見えないな。線を描くだけなら、わざわざパッケージを入れなくても、下記を 参考に直接htmlもどきを生成してもいいかな。

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by SVGo -->
<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="250" cy="250" r="125" style="fill:none;stroke:black"/>
<circle cx="50" cy="250" r="5" style="fill:red;stroke:none"/>
<line x1="0" y1="0" x2="250" y2="250" style="stroke:blue"/>
<line x1="0" y1="499" x2="0" y2="0" style="stroke:blue"/>
<line x1="0" y1="0" x2="499" y2="0" style="stroke:blue"/>
<line x1="499" y1="0" x2="499" y2="499" style="stroke:blue"/>
<line x1="499" y1="499" x2="0" y2="499" style="stroke:blue"/>
</svg>

Goでお絵かき

package main

import (
	"github.com/ajstarks/svgo"
	"math"
	"net/http"
)

func main() {
	http.Handle("/", http.HandlerFunc(show))
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		panic(err)
	}
}

const XMAX = 500    // Canvas size
const YMAX = 500

var (
	gr_xfac   = 1.0 // plotter -> canvas scale factor
	gr_yfac   = 1.0
	gr_xconst = 0.0 // offset
	gr_yconst = 0.0
	xpen      = 0.0 // current pen posisoin for plotter
	ypen      = 0.0
	canvas    *svg.SVG
)

// draw on canvas coordinate
func gr_wline(x1, y1, x2, y2 float64) {
	gr_xscr := func(x float64) int {
		return int(gr_xfac*x + gr_xconst)
	}
	gr_yscr := func(y float64) int {
		return int(gr_yfac*y + gr_yconst)
	}
	canvas.Line(gr_xscr(x1), gr_yscr(y1),
		gr_xscr(x2), gr_yscr(y2), "stroke:blue")
}

// calc plotter -> canvas coordinate factor
func gr_window(left, bottom, right, top float64,
	samescale, bordercolor int) {
	gr_xfac = (XMAX - 1) / (right - left)
	gr_yfac = (YMAX - 1) / (bottom - top)
	if samescale != 0 {
		if math.Abs(gr_xfac) > math.Abs(gr_yfac) {
			gr_xfac *= math.Abs(gr_yfac / gr_xfac)
		} else {
			gr_yfac *= math.Abs(gr_xfac / gr_yfac)
		}
	}
	gr_xconst = 0.5 - gr_xfac*left
	gr_yconst = 0.5 - gr_yfac*top
	if bordercolor != 0 {
		gr_wline(left, bottom, left, top)
		gr_wline(left, top, right, top)
		gr_wline(right, top, right, bottom)
		gr_wline(right, bottom, left, bottom)
	}
}

// plotter 
func move(x, y float64) {
	xpen = x
	ypen = y
}

func move_rel(dx, dy float64) {
	xpen += dx
	ypen += dy
}

func draw(x, y float64) {
	gr_wline(xpen, ypen, x, y)
	xpen = x
	ypen = y
}

func draw_rel(dx, dy float64) {
	gr_wline(xpen, ypen, xpen+dx, ypen+dy)
	xpen += dx
	ypen += dy
}

func show(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("Content-Type", "image/svg+xml")
	canvas = svg.New(w)
	canvas.Start(XMAX, YMAX)
	mymainB()      // <===== you can change any mymainX
	canvas.End()
}

func mymainA() { // Lissajous figure
	var i int
	var t float64

	gr_window(-1, -1, 1, 1, 1, 1)
	move(math.Cos(0), math.Sin(0))
	for i = 1; i <= 360; i++ {
		t = (math.Pi / 180.0) * float64(i)
		draw(math.Cos(3*t), math.Sin(5*t))
	}
}

const ( // for Lorenz
	A = 10.0
	B = 28.0
	C = (8.0 / 3.0)
	D = 0.01
)

func mymainB() {
	var k int
	var x, y, z, dx, dy, dz float64

	gr_window(-30, 0, 30, 60, 1, 0)
	x, y, z = 1, 1, 1
	for k = 0; k < 3000; k++ {
		dx = A * (y - x)
		dy = x*(B-z) - y
		dz = x*y - C*z
		x += D * dx
		y += D * dy
		z += D * dz
		if k > 100 {
			draw(x, z)
		} else {
			move(x, z)
		}
	}
}

XMAX,YMAXは、キャンバスのサイズ指定。firefoxでは、これがそのまま使われるけど、ぐぐる製 のブラウザーでは、この値を無視して、画面サイズにフィッティングしたものに拡大されたよ。 こんなものなんですかね。ipad付属のブラウザーもぐぐる様に習えしてたな。IEはどうなん だろう? わざわざ確かめる気は無い。オイラー、生まれ付きIE嫌いですから。

window.cの中に、マクロが出てきていた。

#define gr_xscr(x) (int)(gr_xfac * (x) + gr_xconst)
#define gr_yscr(y) (int)(gr_yfac * (y) + gr_yconst)

これをどうGo語に変換するか? 3秒考えて、関数でいいじゃんって思い付いたぞ。 使ってる所がgr_wlineの中だけだったので、関数の中へ押し込んでおいた。

描きたい絵を選択出来るように、httpサーバーから呼ばれるレンダリング関数(show)から、本質部分を 呼び出すようにしといた。mymainAとかがそれだ。絵を切り替えるには、この呼び出しを 変更してあげれば良い。本来なら、ちゃんとルーティングさせるんだろうけど、こういうのも 有りかなと。。。

観賞会

mymainAが、以前やったリサージュ波形。

mymainBは、 ローレンツアトラクタ と呼ばれるものだ。

大気の変動は天候に影響を与える。北京で蝶が羽ばたけば、ニューヨークが大雨に なる(かも知れない)っていう事を表している。しばしば、当たらない天気予報のいい訳に 使われる便利な方程式です。

HTML5のCANVASは

上でSVGのcanvasをやった。おかげで国民機PC9800が蘇った訳だ。これもそれも、現代風の ブラウザーのおかげだな。そうか、ブラウザーは、仮想PCでもあるんだな。

昔のPC9800は、電源入れるとBASICが立ち上がってくる変な仕様だったんで、おいらは、 シャープが出してた、クリーンコンピュータってのを使ってたけどね。だから、正直、PC9800は 長い時間使った事は無かった。

ブラウザーを仮想PCとして見た場合、やっぱり変な言語が付いてくる。そう、Javaxcriptがね。 全々、クリーンコンピュータじゃ無いじゃん。たとえ、Javascriptがtypescriptになろうが dartになろうが、そんなの関係ないね。所詮、同じ穴のむじなですよ。

で、この仮想PCが扱うグラフィック機構は、HTML5バーションでサポートされたCANVASなんだな。 他にもオーディオとか動画とかのサポートが有るみたいだけど、やはりそれはおまけの範疇と 思うぞ。

今年こそついにSVG元年?まだ間に合う!SVGの学習に役立つサイト紹介

SVGを制作できるアプリ,お絵描きソフトを徹底的に調べました! 114個

最近のHTML5系は良く知らないので、探っておくかなと思って調べてみたら、 CANVASの基本へと 辿りついた。SVGに喧嘩売るための仕様に見えるなあ。

発展系としては、

three.js

WebGLプログラミング

HTML5による物理シミュレーション

やっぱり、最近のブラウザは、仮想PC。機能満載で、時代と共に遅くなる運命にあるなあ。 いらないモジュールは削除するとか出来ないですかね?

今年の更新は、これで終了です。来年も宜しく!!