一次セルオートマトン
学類のシミュレーション物理の課題。
オートマトンを作れとか。
で、なぜか思いっきり作り込んでしまった。
getoptとかgdとか。
正直こんだけ作り込んでもただの課題。
無駄だ。
どうやら最近使い方覚えたので使いたかったらしい > 2時間前の俺
ということで2時間の成果物↓
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <string.h> #ifdef USE_GETOPT #include <getopt.h> #endif /* USE_GETOPT */ #ifdef USE_GD #include <gd.h> #endif /* USE_GD */ #define DEFAULT_RULE 184 #define DEFAULT_DENSITY (RAND_MAX * 0.3) #define DEFAULT_SEED 149 #define DEFAULT_LENGTH 32 #define DEFAULT_STEPS 16 #ifdef USE_GD #define DEFAULT_OUTPUT "out.png" #endif /* USE_GD */ #define BOOL int #define TRUE (0==0) #define FALSE (0!=0) #ifdef USE_GETOPT void usage( int argc, char** argv ) { printf( "使用法: %s [オプション]...\n", argv[0] ); printf( "\n" ); printf( "一次セルオートマトンを行います\n" ); printf( "\n" ); printf( " -r, --rule=NUM オートマトンルール[\"0x%X\"]\n", DEFAULT_RULE ); printf( " -d, --density=FLOAT 初期密度[\"%f\"]\n", DEFAULT_DENSITY / RAND_MAX ); printf( " -s, --seed=NUM 乱数のシード[\"%d\"]\n", DEFAULT_SEED ); printf( " -l, --length=NUM オートマトン長[\"%d\"]\n", DEFAULT_LENGTH ); printf( " -g, --generation=NUM 試行回数[\"%d\"]\n", DEFAULT_STEPS ); #ifdef USE_GD printf( " -o, --output=FILE pngの出力先[\"%s\"]\n", DEFAULT_OUTPUT ); #endif /* USE_GD */ printf( " -h, --help このメッセージを表示する\n" ); printf( "\n" ); } #endif /* USE_GETOPT */ /* ループした配列アクセス */ int* nth( BOOL* buf, int index, int length ) { while( index < 0 ) { index += length; } while( index >= length ) { index -= length; } return &buf[index]; } int main ( int argc, char** argv ) { int rule = DEFAULT_RULE; int density = DEFAULT_DENSITY; int seed = DEFAULT_SEED; int length = DEFAULT_LENGTH; int steps = DEFAULT_STEPS; #ifdef USE_GD const char* output = DEFAULT_OUTPUT; #endif /* USE_GD */ #ifdef USE_GETOPT while( 1 ) { static struct option longopts[] = { { "rule", required_argument, NULL, 'r' }, { "density", required_argument, NULL, 'd' }, { "seed", required_argument, NULL, 's' }, { "length", required_argument, NULL, 'l' }, { "generation", required_argument, NULL, 'g' }, { "help", no_argument, NULL, 'h' }, #ifdef USE_GD { "output", required_argument, NULL, 'o' }, #endif /* USE_GD */ { 0, 0, 0, 0 } }; #ifdef USE_GD int c = getopt_long( argc, argv, "r:d:s:l:g:ho:", longopts, NULL ); #else /* USE_GD */ int c = getopt_long( argc, argv, "r:d:s:l:g:h", longopts, NULL ); #endif /* USE_GD */ if( c == -1 ) { break; } switch( c ) { case 'r': rule = atoi( optarg ); break; case 'd': density = RAND_MAX * atof( optarg ); break; case 's': seed = atoi( optarg ); break; case 'l': length = atoi( optarg ); break; case 'g': steps = atoi( optarg ); break; case 'h': usage( argc, argv ); exit( 0 ); #ifdef USE_GD case 'o': output = optarg; break; #endif /* USE_GD */ default: usage( argc, argv ); exit( 1 ); } } #else /* USE_GETOPT */ /* getoptが無い環境用の簡易引数処理 */ /* ルール 密度 シード 長さ ステップ数 出力ファイル名 の順で指定 */ /* オプションは省略可能で無い場合はDEFAULT_*が使われる */ if( argc > 1 ) { rule = atoi( argv[1] ); } if( argc > 2 ) { density = RAND_MAX * atof( argv[2] ); assert( density >= 0 ); } if( argc > 3 ) { seed = atoi( argv[3] ); assert( seed > 0 ); } if( argc > 4 ) { length = atoi( argv[4] ); assert( length > 0 ); } if( argc > 5 ) { steps = atoi( argv[5] ); assert( steps > 0 ); } #ifdef USE_GD if( argc > 6 ) { output = argv[6]; } #endif /* USE_GD */ #endif /* USE_GETOPT */ /* 引数処理ここまで */ srand( seed ); /* 表バッファと裏バッファを用意 */ /* 表から裏へ結果を落とし込みswap */ /* 表示は常にprimaryBuf */ BOOL* primaryBuf = (BOOL*)calloc( length, sizeof( BOOL ) ); if( !primaryBuf ) { perror( NULL ); } BOOL* secondaryBuf = (BOOL*)calloc( length, sizeof( BOOL ) ); if( !secondaryBuf ) { perror( NULL ); } BOOL* swap; /* 初期化 */ int i; for( i = 0; i < length; i++ ) { *nth( primaryBuf, i, length ) = rand() < density; } #ifdef USE_GD /* gdイメージを作成 */ gdImagePtr im = gdImageCreate( length, steps ); if( !im ) { perror( NULL ); exit( 1 ); } int white = gdImageColorAllocate( im, 0xff, 0xff, 0xff ); int black = gdImageColorAllocate( im, 0x00, 0x00, 0x00 ); #endif /* USE_GD */ /* セルオートマトンスタート */ int t; for( t = 0; t < steps; t++ ) { /* primaryBufにセルオートマトンの結果を書いていく */ for( i = 0; i < length; i++ ) { /* 表示 */ printf( "%d", *nth( primaryBuf, i, length ) ); #ifdef USE_GD if( *nth( primaryBuf, i, length ) ) { gdImageSetPixel( im, i, t, black ); } else { gdImageSetPixel( im, i, t, white ); } #endif /* USE_GD */ /* 裏バッファへオートマトンの結果をいれる */ int n = (( *nth( primaryBuf, i - 1, length ) ? 1 : 0 ) << 2) + (( *nth( primaryBuf, i , length ) ? 1 : 0 ) << 1) + ( *nth( primaryBuf, i + 1, length ) ? 1 : 0 ); *nth( secondaryBuf, i, length ) = ( rule & 1 << n ) != 0; } printf( "\n" ); /* スワップ */ swap = primaryBuf; primaryBuf = secondaryBuf; secondaryBuf = swap; } #ifdef USE_GD FILE* fp = fopen( output, "w" ); if( !fp ) { perror( NULL ); exit( 1 ); } gdImagePng( im, fp ); fclose( fp ); #endif /* USE_GD */ return 0; }
ifdef切り分けしてるのでlibgdやgetoptがない環境でもばっちこい。
オートマトンルール184は渋滞シミュレーションらしい。ほむ。
makefaileはこちら
CC=g++ CFLAGS=-Wall -DUSE_GETOPT -DUSE_GD LDFLAGS=-lgd SRCS=$(wildcard *.c) BINS=$(subst .c,,$(SRCS)) .PHONY: clean all: $(BINS) clean: $(RM) $(BINS)
wildcardは授業とかeasyなプログラムをまとめてコンパイルする時乱用したり...。
wildcar→substの組み合わせは覚えておくと吉。かも。
あ、そうそう。
コピペして自分の課題として提出すんのは禁止ね。
まぁ、こんなの出そうとは思わないだろうけどね。
- 8< - - - 切 - り - 取 - り - 線 - - - - -
2008/12/12 追記。
なんか後輩の子がまさにこの課題やってた。
懐かしいなとか思いつつ、
http://d.hatena.ne.jp/goth_wrist_cut/20071215/1197744772
に追記したことをこっちに書き忘れてたので追記。