まずは

できそうなことからやってみます.2020/04~

フラクタル図形の描画(C)

基本情報技術者試験の勉強...!

ITを学ぶ第一歩として 基本情報技術者 (FE試験)の資格取得に向けて勉強しています.(令和2年度春は中止になってしまいました...)

フラクタル図形を描画するプログラム

午後のC対策に下の本勉強している中で平成28年度春の問題フラクタル図形を描く問題があったので, 写経しつつ,実際にプログラムを動かしてみました.

改訂3版 基本情報技術者試験 C言語の切り札 (情報処理技術者試験)

改訂3版 基本情報技術者試験 C言語の切り札 (情報処理技術者試験)

  • 作者:宮坂 俊成
  • 発売日: 2017/02/09
  • メディア: 単行本(ソフトカバー)
図形の一部を拡大すると,再び同じパターンの図形が現れる自己相似性を持つ図形をフラクタル図形と呼ぶ.


プログラム内で単位図形となる部分を与えています. フラクタルを生成する深さd(回数)は入力値を使い,深さ毎の .datファイル を出力, Gnuplot0は黒,1は白として .gifファイル を作成します(for文使って出力します).


出力例(d=7)

Fractal0は単位図形になります.なんか反転してます.

f:id:shino424:20200420180556j:plain 例1:単位図形 = { { 1, 1 },
         { 1, 0 }, };

f:id:shino424:20200420180600j:plain
例2:単位図形 = { { 1, 1, 1 },
         { 1, 0, 1 },
         { 1, 1, 1 }, };

f:id:shino424:20200420180604j:plain
例3:単位図形 = { { 1, 1, 1 },
         { 0, 1, 0 },
         { 1, 1, 1 }, };

f:id:shino424:20200420180608j:plain
例4:単位図形 = { { 1, 1, 1 },
         { 0, 1, 0 },
         { 0, 1, 0 }, };

ソースコード

C

#include <stdio.h>
#include <stdlib.h>

/* 単位図形,例1の場合 */
int pat[2][2] = {
    { 1, 1 },
    { 1, 0 },      
};  

/*2D配列のサイズ / 2D配列の行[0]のサイズ(列数) = 与えた行列の行数 */
int p_rn = sizeof pat / sizeof pat[0]; 
/* 2D配列の行[0]のサイズ / 2D配列の要素[0][0]のサイズ = 与えた行列の列数 */
int p_cn = sizeof pat[0] / sizeof pat[0][0];


/* プロトタイプ宣言*/
int exists_at(int, int, int);  

int main(void) {
int i, j, k, rn, cn, d; 
char filename[256];   
FILE *fp;

/* フラクタル作成ループ*/
printf("Fractalの生成回数(d)を入力.\n");
scanf("%d", &d);         
rn = cn = 1; 
    for (k = 0; k < d; k++) {
        sprintf(filename, "frac%d.dat", k);
        fp = fopen(filename, "w");
            if (fp == NULL) {
                printf("ファイルをオープンできません.\n");
                exit(1);
            }       
        rn *= p_rn;
        cn *= p_cn;
        for (i = 0; i < rn; i++) {
            for (j = 0; j < cn; j++) {
                fprintf(fp, exists_at(i, j, d) ? "0 " : "1 ");
                    /* cmd画面確認用:putchar(exists_at(i, j, d) ? '*': ' '); */                 
            }
            fprintf(fp, "\n");
        }
        fprintf(fp, "\n");          
    }
fclose(fp);
return 0;
}

int exists_at(int i, int j, int d) {
    if (d == 0) { 
        return 1;
    } else if (exists_at(i / p_rn, j / p_cn, d - 1) == 0) {
        return 0;
    } else {
        return pat[i % p_rn][j % p_cn];
    }
}



gunplot

cd '「.datが入っているディレクトリのパス」'
d = 7
set term gif size 400, 400

set size square
set nozeroaxis
unset colorbox
set palette grey                     #gray0 = 黒
set title font "Arial,20"
set key center below 

do for [i=0:d-1] {
   set output sprintf("frac%d.gif", i)
   set notics   
   data = sprintf("frac%d.dat", i)
   plot data matrix with image title sprintf("Fractal %d", i)
}

set output


本当は...
  • 単位図形の部分を画面から入力(単位図形のサイズを自由に).
  • .datファイルに各深さdの結果を改行しながら出力,gnuplotで深さd毎の .gifファイル をそれぞれ出力.
  • コンパイルから描画までを走らせるバッチファイルを作成して,深さdはコマンドプロンプト上でCのプログラムからgnuplotに渡す.

の3点も実装したかったんですけど,

  • 入力値を配列に格納する場合の配列の動的確保がいまいちわからない.
  • サイズが変わるマトリックスGnuplotでの描画がうまくいかない.
  • コマンドプロンプト上の変数の受け渡しがわからない.

ので,今回できませんでした... またわかったら更新します...


おわりに

2月くらいからこの辺の本をメインに勉強していますがー,

令和02年【春期】 基本情報技術者 パーフェクトラーニング過去問題集

令和02年【春期】 基本情報技術者 パーフェクトラーニング過去問題集

  • 作者:山本 三雄
  • 発売日: 2019/12/26
  • メディア: 単行本(ソフトカバー)

今回の試験が別日でやるのか,中止なのかまだわからないので一回勉強は休憩しようかなというところです...