a23_useSelfMade #7
2023.03.19 Sun #1
- HL-9にはwhileがないです。+=とかもないです。これは不便だと感じてきたので直そうと思いました。
2023.03.20 Mon #1
- gccには関数内関数の機能があります。easy-Cの基本コンセプトは「mainの中だけ書く」なので、関数内関数が使えれば関数定義もできることになります。これはうれしい!
2023.03.22 Wed #1
- 今日はeasy-Cでの開発の様子を紹介します。数学の公式にcomb(n, k)で、kを0~nまでの和を取ると必ず2^nになるというものがありますが、それを実際に計算してみて検証するというのをやってみます。
- [1]まずはパーミュテーションの計算をする関数を作りたいと思います。
int perm(int n, int k)
{
int i = 1, j;
for (j = 0; j < k; j++) { i *= n--; }
return i;
}
- これを適当なテキストファイルに入力します。ここではとりあえず20230322.cにしました。その上で、ec_inc0.cを開いて
// ここに追加関数へのincludeを自由に書く.
#include "20230322.c"
と書き足します。これで準備完了です(コンパイルとかしません)。さて、まず、うまく動くかどうかテストします。
HL9>!pr perm(4, 0)
1
HL9>!pr perm(4, 1)
4
HL9>!pr perm(4, 2)
12
HL9>
- (知らない人のために説明しておくと!はgccモードでの実行を意味していて、prというのはprintf("%d", ?)の略です。)
- とてもうまく計算できているようです。よしよし。
- [2]次はコンビネーションの計算です。先ほどの20230322.cに書き足します。
int comb(int n, int k) { return perm(n, k) / perm(k, k); }
- そしてまたワンライナーでテストです。
HL9>!pr comb(4, 2)
6
HL9>!pr comb(5, 3)
10
- これまた合っているようです。絶好調です。
- [3]ここまでできれば後は簡単です。
HL9>![n = 0:<=10] { int sum = 0; sum += comb(n, 0:<=n); printf("n=%d sum=%d pow=%d\n", n, sum, (int) pow(2, n)); }
n=0 sum=1 pow=1
n=1 sum=2 pow=2
n=2 sum=4 pow=4
n=3 sum=8 pow=8
n=4 sum=16 pow=16
n=5 sum=32 pow=32
n=6 sum=64 pow=64
n=7 sum=128 pow=128
n=8 sum=256 pow=256
n=9 sum=512 pow=512
n=10 sum=1024 pow=1024
- おお、ちゃんと検証できました!
- [解説]
- HL-9にはgcc実行モードというのがあって、それを使うと後付けで作ったC言語の関数があたかも最初からあった組み込み関数のように使えます。今回はそれを使っています。
- [3]では簡易ループ演算子を多用しています。[n = 0:<=10]はfor (n = 0; n <= 10; n++)と同じ意味です。sum += comb(n, 0:<=n);は[tmp = 0:<=n] { sum += comb(n, tmp); }と同じ意味です。
- easy-Cでは、i~nの変数はintで宣言済みなので、自分で宣言しなくても自由に使えます。
- この作り方で作っていくと、関数を一つ作るたびに「ちゃんと動くかな?」と手軽に確かめられるので、テストをまめにするようになりました。できあがったら、必要な関数を全部切り出して(コピー&ペーストするだけですが)、別のファイルにまとめて清書とします。・・・easy-Cがなかったころは、こまめにテストをしたほうがいいと分かっていても面倒で実践できていませんでした。それでデバッグになってから苦労していました。
- このやり方になってから、C言語がコンパイラだとあまり感じなくなって、使用感的にはインタプリタだなーって思います。楽しいです。
2023.03.22 Wed #2
- OSCが近いので明日までで開発を切りのいいところまで進めて、いったんリリースすることにします。
2023.03.23 Thu #1
- [開発環境としてみたときのeasy-Cの特徴]
- ワンライナーができる。
- 別ファイルに関数を書いておくと、それを組み込み関数のように使える(参考: 2023.03.22 Wed #1)。
- プロンプトで$を使えばシェルコマンドが実行できる。
- インタープリタ実行モードもある。
- [言語拡張としてみたときのeasy-Cの特徴]
- prなどの便利命令が使える。
- 簡易ループ演算子が使える。
- AXFncを使うと、関数の返値を複数で受け取れる。従来は&yや&mなどのようにポインタを渡していた。
- → 例: AXFnc_i3(y, m, d, =, fixDate(2023, 1, 100)); // 2023年1月100日を4月10日に直してくれる.
- [プログラミング入門としてみたときのeasy-Cの特徴]
- 入門に最適なPLAY命令がある。
- 入門者が使いそうな命令については、大文字でも入力できる。PRやPLAYやIFなど。
- ソースファイル作成は「NEW ファイル名」、テキストエディタ起動は「$$ファイル名」でできるようになっていて、ファイルエクスプローラ無しで操作できる。
- I~N(i~n)については、変数がintで宣言済みなので、宣言せずに使える。
- グラフィック描画ライブラリが使える(簡単なゲームが作れるように)。
2023.03.23 Thu #2
int getMonthDays(int y, int m)
{
static int days[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
if (m == 2 && y % 4 == 0) return 29; // 手抜きの閏年判定.
return days[m - 1];
}
#define fixDate(y, m, d) ACA_fixDate(aCA, y, m, d)
void ACA_fixDate(AComArg *aCA, int y, int m, int d)
{
while (d > getMonthDays(y, m)) {
d -= getMonthDays(y, m); m++;
if (m > 12) { m -= 12; y++; }
}
aCA->com->retValInt[0] = y;
aCA->com->retValInt[1] = m;
aCA->com->retValInt[2] = d;
}
HL9>!int y, d; AXFnc_i3(y, m, d, =, fixDate(2023,1,100)); printf("%d/%d/%d", y, m, d)
2023/4/10
2023.03.24 Fri #1
- OSCで何を紹介するかを考え中です。2023.03.23 Thu #1 に書いた内容に自己採点をしてみました。
| [開発環境としてみたときのeasy-Cの特徴] | 小計+3.9点 | |
| ワンライナーができる。 | +1.0点 | |
| 別ファイルに関数を書いておくと、それを組み込み関数のように使える。 | +0.9点 | (参考: 2023.03.22 Wed #1)現状ではインタプリタモードで使えないのでその分を減点。 |
| プロンプトで$や$$を使えばシェルコマンドが実行できる。 | +1.0点 | |
| gcc実行モードのほかにインタープリタ実行モードがある。 | +1.0点 | |
| | |
| [言語拡張としてみたときのeasy-Cの特徴] | 小計+2.2点 | |
| prなどの便利命令が使える。 | +1.0点 | |
| 簡易ループ演算子が使える。 | +0.9点 | 現状の実装はまだちょっと手抜きがある。 |
| AXFncを使うと、関数の返値を複数で受け取れる。 | +0.3点 | インタプリタモードでも使えるようになれば+0.4にしてもいい。構文がもっとすっきりしたら+0.5にしてもいい。 |
| | |
| [プログラミング入門としてみたときのeasy-Cの特徴] | 小計+4.5点 | |
| 入門に最適なPLAY命令がある。 | +1.0点 | |
| 入門者が使いそうな命令については、大文字でも入力できる。PRやPLAYやIFなど。 | +1.0点 | |
| 「NEW ファイル名」「$$ファイル名」によって、ファイルエクスプローラ無しで操作できる。 | +1.0点 | すごく簡単な機能なのに効果は大きい。 |
| I~N(i~n)については、変数がintで宣言済みなので、宣言せずに使える。 | +0.5点 | |
| グラフィック描画ライブラリが使える(簡単なゲームが作れるように)。 | +1.0点 | |
- こうしてみると、言語拡張としてはまだまだ弱いことがよくわかります。私自身も直感的に感じていましたが、こうして可視化すると納得です。
- それで、まあ春のOSCには間に合わないものの、この先1~2か月で何とかできそうなことを考えてみました。いずれも言語拡張系です。
| インタプリタモードの時だけ、演算子の優先順位を変更できる。 | +0.3点 | (gccモードでもできるようにするには結構な改造が必要。でもそれができたら+0.5点にしてもいい。) |
| gccモードでの、#longdef, #endlongdef, #longuse | +0.8点 | (プリプロセッサ拡張、昨年別の開発のために作って便利だった) |
| Uniform Function Call Syntax に対応。 | +1.0点 | これはすぐにはできなさそう。でもいつかやりたい・・・。 |
こめんと欄