■ Icon > Icon日記(1) はじめに 風つかい 目次 Iconは AWKや Perlの仲間のテキスト処理言語です。Iconはデータ構造や制御構造 が豊富で、もっと使われてよい言語と思います。 しかし、未だ日本語の入門書がありませんので、 AWKについて、ある程度の知識を お持ちになっている方を対象として、入門講座を書きました。 この Icon日記はその続編として、その後作ったプログラムや Icon入門講座で書き 落としたところを解説したものを、まとめたものです。 Icon入門講座といっしょにご覧になって Iconを使って頂けるとうれしいです。 Iconのプログラムおよびライブラリーは、次のところから入手できます。 http://www.cs.arizona.edu/icon/index.html Iconは PDSですので、この入門講座も同じ扱いとします。(転載・編集自由) (This textbook is in the public domain.) 目次 (1)はじめに (2)ファイル分割 (3)linkって賢い (4)除夜の鐘なんぞを (5)top.icn (6)横のものを縦に(1) (7)横のものを縦に(2) (8)横のものを縦に(3) (9)suspend/generator (10)sort (11)Icon in Java (12)NURSE.ICN (13)Wicon ベータ7 (14)dump.icn (15)再びIconの特徴 (16)Recursive generator (17)文字の組み合わせ(1) (18)文字の組み合わせ(2) (19)文字の組み合わせ(3) (20)シフトJIS処理(1) (21)シフトJIS処理(2) (22)シフトJIS処理(3) (23)Backtracking (24)Generator (25)5クイーン(1) (26)5クイーン(2) (27)Wicon ベータ8 (28)idump2.icn (29)Record (30)むすび 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: ロング・バージョン/稲垣潤一 (icon_127.txt 1997/03/19 PCVAN PIG) ■ Icon > Icon日記(2) ファイル分割 風つかい 目次 HDDの容量が少なくなってきましたので、ログファイルをFDへセーブしようと 思いましたら、2Mのログファイルがありました。 エディターで分割するのも疲れるということで、適当な区切り文字のところで分割 するプログラムを作りました。 fsplit van1023.log #2500 とかやると、van1023.log を、行の先頭が "#2500"のところで分割して、van1023.001 と van1023.002 に分けてくれます。 fsplit fsplit.icn procedure とかやると、fsplit.icn を、procedure毎に区切って、fsplit.001 と fsplit.002 に 分けてくれます。 -----^ FSPLIT.ICN ( date:96-12-23 time:10:32 ) -------------<cut here procedure main(args) # ファイル分割:特定文字列の手前でファイルを分割する。 # 出力ファイル拡張子は順に 001,002,...と付けていく。 Usage := "Usage: fsplit filename keyword" if *args < 2 then stop(Usage) # パラメータ不足 filename := args[1] keyword := args[2] line_no := 0 # 行No 動作状態モニター用 ext_no := 1 # 拡張子番号 dir := open(filename) | stop("cannot open ",filename) # 元ファイルオープン f_name := top_get('\.',filename) || "\." # 元ファイル名の拡張子を除いた部分 out_dir := open(out_name := (f_name || right(ext_no,3,"0")),"a") | stop("cannot open ",out_name) # 出力ファイルオープン while line := read(dir) do { writes(&errout," ",line_no +:= 1) # モニター表示 if {not match(keyword,line)} | {line_no = 1 } # keywordチェック:不一致? then write(out_dir,line) # 不一致ならば、ファイルへ書き出し # 元ファイルの先頭行でも書き出し else { # 一致すれば... close(out_dir) # 出力ファイルクローズ ext_no +:= 1 # 拡張子No更新 out_dir := open(out_name := (f_name || right(ext_no,3,"0")),"a") | stop("cannot open ",out_name) # 新出力ファイルをオープン write(out_dir,line) # ファイルへ書き出し } } close(out_dir) # 出力ファイルクローズ close(dir) # 元ファイルクローズ write(&errout) # モニター表示カーサー戻し end procedure top_get(c,s) # 文字列の 先頭から特定文字の手前まで の部分 を得る。最短部分を得る。 # 指定文字が含まれなければ、文字列全体を返す。 /s := &subject # s の指定が無ければ &subject s ? { return tab(upto(c) | 0)} # c の手前か、文字列末尾まで返す end -----$ FSPLIT.ICN ( lines:41 words:161 ) -------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > (icon100.txt 1996/12/23 PCVAN PIG) ■ Icon > Icon日記(3) linkって賢い。 風つかい 目次 今年は年末・年始に休めるので、日頃やっていないHDDのバックアップとかIconで あやふやな理解しかしていない所とかを色々試してみたりしたいな〜と思っています。 HDDって結構飛びますね〜。年1回は飛ばしています。 でも、その頃には容量不足を感じていますので修理には出さず、大きな容量のものに 買い換えてしまいます。それと、修理期間を待っていられないということもあります。 中毒だな。もうこりゃ。 アル中、ヤニ中、パソ中か。 長生きしないな〜。 さて、Iconのコンパイラー(icont.exe)には、モジュール分割支援のために、linkと いう機能があります。 つぎのように、test02.icn を linkする test01.icn があるとします。 test02.icnを予め、icont -c test02.icn にて、コンパイルしておいて test01.icnを、icont test01.icn によりコンパイルすると、test02.icn がlinkされた、test01.exe ができあがります。 test01.icn ------------------- |link test02 | ----------> test02.icn |procedure main() | -------------------- | ... | ----> |procedure test02(s) | | test02("AAA") | ----- | ... | | ... | | return ... | |end | |end | ------------------- -------------------- -----^ TEST01.ICN ( date:96-12-28 time:11:26 ) -------------<cut here link test02 procedure main() write(test02("AAA")) # test02("AAA") の結果を書き出す。 end -----$ TEST01.ICN ( lines:4 words:9 ) ----------------------<cut here -----^ TEST02.ICN ( date:96-12-28 time:11:26 ) -------------<cut here procedure test02(s) return s || "BBB" # 文字列の後ろに、"BBB"を付加する。 end -----$ TEST02.ICN ( lines:3 words:9 ) ----------------------<cut here この例では、"AAABBB" が書き出されます。 この例では、2つのファイルの関係でしたが、3つ以上のファイルが linkで 結ばれていることも当然ある訳です。 で、link hogeという宣言が含まれるファイルをコンパイルする時に、hoge.icn は必ず先にコンパイルされていなければいけないと思っていました。 グラフィック関係のライブラリー (gipl)を眺めていましたら、どうもそうで はないらしいと気づきました。 main() が含まれるファイルをコンパイルするときは、linkされるファイルは すべてコンパイルされていないといけないのですが、linkされるファイル相互の 間でlinkがあってもその制限はありませんでした。 例えば、次のような関係のファイルがあったとき、test03のコンパイルの際には test04〜06はコンパイルされていないといけませんが、test04.icnのコンパイルの 前にtest05、test06はコンパイルされている必要はありません。 test03.icn ----------------- | link tst04 | --> test04.icn | procedure main()| -------------------- | ... | |link test05,test06 | ----> test05.icn | ... | -------------------- | ------------------- | tst01("ABC") | -------------------------> | |procedure tst01(s) | | ... | | | ... | | tst02("DEF") | ------------------- | | return ... | | ... | | | |end | | tst03("GHI") | ------------- | | | | | ... | | -----> | |procedure tst02(s) | | end | | | | ... | ----------------- | | | return ... | | | |end | | | ------------------- | | | -> test06.icn | ------------------- -----------> |procedure tst03(s) | | ... | | return ... | |end | ------------------- mainが含まれるファイルです。 -----^ TEST03.ICN ( date:96-12-28 time:12:50 ) -------------<cut here link test04 procedure main() write(tst01("ABC")) # test01("ABC") の結果を書き出す。 write(tst02("DEF")) # test02("DEF") の結果を書き出す。 write(tst03("GHI")) # test03("GHI") の結果を書き出す。 end -----$ TEST03.ICN ( lines:6 words:17 ) ---------------------<cut here link宣言だけのファイルです。 -----^ TEST04.ICN ( date:96-12-28 time:12:51 ) -------------<cut here link test05,test06 -----$ TEST04.ICN ( lines:1 words:2 ) ----------------------<cut here -----^ TEST05.ICN ( date:96-12-28 time:12:54 ) -------------<cut here procedure tst01(s) return s || "123" # s の末尾に "123" を追加します。 end procedure tst02(s) return s || "456" # s の末尾に "456" を追加します。 end -----$ TEST05.ICN ( lines:6 words:24 ) ---------------------<cut here -----^ TEST06.ICN ( date:96-12-28 time:12:56 ) -------------<cut here procedure tst03(s) return s || "789" # s の末尾に "789" を追加します。 end -----$ TEST06.ICN ( lines:3 words:12 ) ---------------------<cut here 結果はつぎのようになります。 ABC123 DEF456 GHI789 今、アリゾナ大の Icon WEB にアクセスすると、 12/21〜12/29迄は 大学の Holidayなので、サーバがダウンしたら復旧に時間が かかるかもしれない。 と、書いてあります。 時季からいって、クリスマス休暇の期間なんでしょうね。 でも12/30からは平常勤務で、こちらの年末・年始は普通の勤務なんですね。 では、皆様良いお年をお迎え下さい。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 熱くなれ/大黒摩季 BGD: 茉莉花茶 BGS: Mild Seven Menthol (icon_101.txt 1996/12/28 PCVAN PIG) ■ Icon > Icon日記(4) 除夜の鐘なんぞを 風つかい 目次 年末・年始の休みに入りましたので、日頃さぼっているHDDのバックアップを やりかけていましたが、ついこんなものを思い付いたりして、全然進みません。 -----^ JOYA.ICN ( date:96-12-29 time:11:43 ) ---------------<cut here procedure main(args) # Usage: joya number(あなたの煩悩の数) # 除夜の鐘 n1 := args[1] | 108 # 煩悩の数(デフォルト 108) s1 := "ご〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜ん" delay(500) # 神妙にして write("★★★★★ あなたの ",n1," 個の煩悩を払います。 ★★★★★") write() delay(500) # 心を清めて while n1 > 0 do { writes("煩悩はあと",right(n1,3),"個 ") s1 ? { while s2 := move(2) do { # 鐘の音 delay(100) writes(s2) } } write() delay(500) # 余韻 n1 -:= 1 # 煩悩を1つ消す。 } write() write("★★★★★ あけましておめでとうございます。 ★★★★★") end -----$ JOYA.ICN ( lines:27 words:65 ) ----------------------<cut here 実際に音が出せると良いのですが、これで我慢して下さい。 これをあなたのマシンで実行させますと、HDDが足りないとか、メモリーを 増やせとか、回線をISDNにしろとか文句を言わなくなります。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: なし BGD: 日本盛 BGS: Mild Seven Menthol (icon_102.txt 1996/12/28 PCVAN PIG, 1996/12/29 niftyserve FPL) ■ Icon > Icon日記(5) top.icn 風つかい 目次 HDDのバックアップをやっと済ませたところで、今年も暮れていきます。 バックアップ用FDがだいぶたまってきましたので、整理箱を近所のスーパーで捜し てみました。 文房具コーナーに「TVゲームソフトかたづけBOX」というのが売っていましたの で買いました。 ちょうど3.5インチのFDにサイズが合いましてなかなかいいです。 100枚位をまとめてしまっておけます。 500円でおつりがきました。 さて、Icon講座の中のプログラムに、top_get.icn top_cut.icn というのがありま す。 これは、ファイル名から拡張子を除いた部分を作ったり、パスつきファイル名 から、パスの部分を除いたりするために使っています。 Icon のライブラリー(bipl)の中にもそういう処理をおこなう procedureがあるの ですが、top_get.icn top_cut.icn を作った当時は、未だ biplのにどんな procedure が入っているのか知らなかったので、自前で作ってしまいました。 Icon講座を読みなおしてみますと、どうもこの procedureがひっかかります。 今ならこうは作らないだろうなということで、もう一度考えてみました。 当初のプログラムは、次のようになっています。 -----^ TOP2.ICN ( date:96-12-01 time:22:30 ) ---------------<cut here # 文字列の 先頭から特定文字までの部分 を取り去る。最長部分を取り去る。 procedure top_cut(c,s) s ? { repeat { if cp := upto(c,s) then s:= s[cp +1 :0] else return s } } end # 文字列の 先頭から特定文字までの部分 を得る。最短部分を得る。 procedure top_get(c,s) s ? { if cp := upto(c) then return s[1:cp] else return s } end -----$ TOP2.ICN ( lines:15 words:47 ) ----------------------<cut here この時には、未だ、tab() とか many() の使い方をよく理解していません でした。 そこで、走査位置を表にだしたプログラムとなっています。 今なら tab() と many()を使って、こう書きます。 -----^ TOP3.ICN ( date:96-12-31 time:15:13 ) ---------------<cut here procedure top_cut(c,s) # 文字列の 先頭から特定文字までの部分 を取り去る。最長部分を取り去る。 /s := &subject # sの指定がなければ &subject s ? { # sを走査対象とする。 while tab(upto(c)) do tab(many(c)) # cが見つかる限り、走査位置を # その文字の後に移動。 return tab(0) # 残りの文字列を返す。 } end procedure top_get(c,s) # 文字列の 先頭から特定文字までの部分 を得る。最短部分を得る。 /s := &subject # sの指定がなければ &subject s ? { # sを走査対象とする。 return tab(upto(c) | 0) # cまで走査位置を移動しその間の } # 文字列を返す。cがみつからなけ # れば、末尾まで返す。 end -----$ TOP3.ICN ( lines:18 words:60 ) ----------------------<cut here やっぱり言語というのは、ある程度使ってみないと、使い勝手がわかりませんね。 念のためテストプログラムも次に。 -----^ TOP3~.ICN ( date:96-12-31 time:16:32 ) --------------<cut here link top3 procedure main() # top_getのテストデータ(拡張子削除) write(top_get('.',"ab.cd")) write(top_get('.',"ab.cd.ef")) write(top_get('.',"ab")) # top_cutのテストデータ(ディレクトリー部削除) write(top_cut('\\',"foo.icn")) write(top_cut('\\',"a:\\foo.icn")) write(top_cut('\\',"a:\\icon\\foo.icn")) write(top_cut('\\',"a:\\icon\\")) end -----$ TOP3~.ICN ( lines:14 words:16 ) ---------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: なし BGD: ジャスミン・ティー BGS: Mild Seven Menthol (icon_103.txt 1996/12/31 PCVAN PIG) ■ Icon > Icon日記(6) 横のものを縦に(1) 風つかい 目次 明けましておめでとうございます。 横浜方面は、晴れて暖かい新年を迎えており ます。 今年もよろしくお願いいたします。 さて、「縦のものを横にもしない。」 というのは、いつもかみさんから言われて いる言葉ですが、今年も言われっぱなしになろうと、新年の誓いを新たにしたところ です。 さて、昨年に Iconの紹介のために、会議室のタイトルリストファイル(PCVANのTL コマンド結果をファイルに落としたもの)から、月別書込み数の棒グラフを作成する プログラムをアップロードしました。 ちなみに、テキストデータ処理会議室の96/12月までの結果は次のようになり ます。 -----^ TL9612.H ( date:97-03-20 time:23:15 ) ---------------<cut here 月別書き込み数グラフ 書込 10 20 30 40 50 60 70 80 90 100 110 120 月 件数 | | | | | | | | | | | | 9309 60 ****************************** 9310 75 ************************************* 9311 90 ********************************************* 9312 102 *************************************************** 9401 111 ******************************************************* 9402 117 ********************************************************** 9403 120 ************************************************************ 9404 117 ********************************************************** 9405 111 ******************************************************* 9406 102 *************************************************** 9407 90 ********************************************* 9408 75 ************************************* 9409 60 ****************************** 9410 44 ********************** 9411 30 *************** 9412 17 ******** 9501 8 **** 9502 2 * 9503 0 9504 2 * 9505 8 **** 9506 17 ******** 9507 29 ************** 9508 44 ********************** 9509 59 ***************************** 9510 75 ************************************* 9511 90 ********************************************* 9512 102 *************************************************** 9601 111 ******************************************************* 9602 117 ********************************************************** 9603 120 ************************************************************ 9604 117 ********************************************************** 9605 111 ******************************************************* 9606 102 *************************************************** 9607 89 ******************************************** 9608 75 ************************************* 9609 60 ****************************** 9610 44 ********************** 9611 30 *************** 9612 17 ******** -----$ TL9612.H ( lines:43 words:147 ) ---------------------<cut here (お〜、見事なサインカーブというのは冗談。PCVANにアップしたものでは実際 のデータを使ったグラフになっているのですが、PCVAN外にもアップしますので、 そのままのデータじゃまずいかな。 ということで、計算で生成したデータに変更し ました。) 作りやすい点から、書込み数に比例した横長の棒グラフを作成するプログラムと しましたが、縦棒グラフにしたいな〜と思っていました。 で、縦棒にするには、横棒を左へ90°回転すればよいわけです。 90°回転表示 コマンドはあいにく Iconには備わっていませんので、若干プログラムが必要となりま す。 (Windows対応版の procedureにあるかも知れませんが、未だよく勉強していな いもので...) そこで、横棒グラフのデータを月毎にリストに入れておいて、末尾から出力して いくというやり方で、プログラムを作ってみました。 リスト(Lgraphと名付けています。)は、 [年月,書込み数,グラフデータ] 3要素を持ちます。 更にその3要素自体も、93/09〜96/12月までの値を要素に持つ リストとなって います。 すなわち2重リストです。 Lgraph(リスト) [1] [2] [3] | | | <--末尾から、9309,9310,9311..と | | | 各1文字づつ出力していく。 9309 60 ******************************_______________ <-グラフデータは桁揃え 9310 75 *************************************________ しておく。 9311 90 ********************************************* このデータを順次、末尾から、各月につき1文字づつ、出力していけばよいわけ です。 というところで、字数制限がありますので、プログラムは次にまわして結果を先に。 -----^ TL9612.V ( date:97-03-20 time:23:15 ) ---------------<cut here 月別書き込み数グラフ 120- * * *** *** 110- ***** ***** ***** ***** 100- ******* ******* ******* ******* 90- ********* ******** ********* ********* 80- ********* ********* *********** *********** 70- *********** *********** *********** *********** 60- ************* ************ ************* ************* 50- ************* ************* ************* ************* 40- ************** *************** ************** *************** 30- *************** **************** *************** ***************** 20- *************** ***************** **************** ******************* 10- **************** ******************* ***************** ******************** --------------------------------------------- 月書 1111111 1111111 別込 6790112110976431 1245790112110876431 数 0502170712050407820287949502170712950407 --------------------------------------------- 年 9999999999999999999999999999999999999999 3333444444444444555555555555666666666666 月 0111000000000111000000000111000000000111 9012123456789012123456789012123456789012 -----$ TL9612.V ( lines:35 words:77 ) ----------------------<cut here う〜む。 期待に反して美しくない。 やはり、CRT画面で見るには、横長の 棒グラフの方が見やすいですね〜。 残念。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 愛の言霊/サザンオールスターズ BGD: ジャスミン・ティー BGS: Mild Seven Menthol (icon_104.txt 1997/01/02 PCVAN PIG) ■ Icon > Icon日記(7) 横のものを縦に(2) 風つかい 目次 昨年に作成した、PCVANの書き込みタイトルから月別書き込み数グラフを 作るプログラムです。 -----^ VPOS2GH.ICN ( date:97-01-02 time:23:14 ) ------------<cut here link chr_chk, month procedure main(args) # vpos2gh.icn Ver.1.1 1996/10/13 windy Ver1.2 1997/01/02 # This file is in the public domain. # Icon Programming Language(http://www.cs.arizona.edu/icon/index.html) # PCVANの書込みタイトルリストから月別の書込み数(グラフ)を作成 # 横棒グラフ # タイトルリストサンプル # 7 12 15 #1042 96/12/31 Icon > Icon日記 top.icnを改版 風つかい # 定数定義 Usage := "Usage: vpos2gh title_list" c_mark := "*" n_size := 3 # 月別書込み数カウントの桁数 step := 2 # グラフの刻み(マーク1個で何個分を示すか) mark := 5 # 目盛りの刻み(目盛りをマーク何個毎に出すか) mark_max := 12 # 最大目盛り (=目盛りの数) graph_max := (mark_max +1) * mark -1 # マークの数の最大 # タイトルリストファイルをオープン。コマンドラインの引数の1番目をファイル # 名としてファイルオープン。引数の数が1以外またはファイルオープンできなけ # ればストップ。 if *args = 1 then dir := open(args[1]) | stop("cannot open ",args[1]) else stop(Usage) # 書込み数テーブルを生成(初期値:0):awkの連想配列相当 Tyearmonth := table(0) # テーブルに書込み数の足し込み # key:YYMM(年月), value:number of posting(書込み数) while line := read(dir) do { # ファイルから1行ずつ line へ読み込み if chr_chk(' /' ++ &digits,line[1:15]) # タイトル行チェック # 行データの文字列から年月部分を取り出して、スペースは0に置換して # 年月データを作成しテーブルのキーとし、対応する値を+1 then Tyearmonth[map(line[7:9] || line[10:12]," ","0")] +:= 1 } # テーブルをキーでソートし、キー、値、キー、値、...と連なったリストを # 生成。 この場合は年月、書込み数、年月、書込み数、... Lyearmonth := sort(Tyearmonth,3) # 歯抜け月(書込みが無かった月)検出用の年月データ初期値セット。 # リストのトップのデータから1と月分減らした年月をセット。 YYMM_old := dec_month(Lyearmonth[1]) # グラフのタイトルを出力 write("月別書き込み数グラフ") # タイトル上段のはじめの部分を出力 writes(" 書込 ",repl(" ",mark -1)) # repl:文字列のくり返し # ここでは、" "を(mark-1)個 # 目盛り生成 目盛りにつける数を計算し、左寄せ桁あわせをおこない出力 # 目盛りの1番目から最大目盛りまでおこなう。 every writes(left(step * mark * (1 to mark_max),mark)) write() # 改行出力 # タイトル下段のはじめの部分出力 writes( " 月 件数 ") # " |"を目盛り数ぶん出力 every 1 to mark_max do { writes(repl(" ",mark -1), "|") } write() # グラフデータ書き出し while YYMM := get(Lyearmonth) do { # リストから順次取り出し # 歯抜け月検出および歯抜け月データ(書込み0データ)出力 # 直前の処理データ(YYMM_old)に+1月した値と、今取り出したデータを比較。 # 一致しなければ、直前のデータへ+1月した月のデータ(書込み無し)を # 出力。 ↓文字列の(不)一致比較 while (YYMM_next := inc_month(YYMM_old)) ~== YYMM do { write(YYMM_next," ",right("0",n_size)) # 書込み数 0のデータ出力 YYMM_old := YYMM_next # YYMM_oldを更新 } # リストから取り出したデータによりデータ出力 # 先に取り出していた年月と書込み数と書込み数に対応した数の c_markを出力 # YYMM_oldも更新。 write(YYMM," ",right(n := get(Lyearmonth),n_size)," ", trim(left(repl(c_mark,integer(n/step)),graph_max))) YYMM_old := YYMM } end -----$ VPOS2GH.ICN ( lines:84 words:262 ) ------------------<cut here タイトルリストファイルのごみ(番号または...等の行)を無視するための procedureです。 -----^ CHR_CHK.ICN ( date:97-01-01 time:20:19 ) ------------<cut here procedure chr_chk(c,s) # 文字列 sが 文字(セット)cのみで構成されていれば、成功し sを返す。 # This file is in the public domain. # Ver1.1 1997/01/01 windy /s := &subject s ? { if many(c) = (*s +1) then return s else fail } end # テストデータ #procedure main() # write(chr_chk('abcd1234',ss := "abcd1234") | (ss || ": error")) # write(chr_chk('abcd1234',ss := "abc123") | (ss || ": error")) # write(chr_chk('abcd1234',ss := "abcde1234") | (ss || ": error")) #end -----$ CHR_CHK.ICN ( lines:14 words:69 ) -------------------<cut here 年月データを+1月/−1月する procedureです。 -----^ MONTH.ICN ( date:97-01-01 time:20:32 ) --------------<cut here # 年月データ(YYMM)の+−1月計算 # This file is in the public domain. # Rev.01 1996/10/13 procedure dec_month(YYMM) # 年月データ −1月 yy := numeric(YYMM[1:3]) ; mm := numeric(YYMM[3:0]) # 年月を数字に変換 if mm = 1 then { yy -:= 1 ; mm := 12 } # 計算 else { mm -:= 1 } # 年データを文字列へ変換し、2桁で右寄せであまりに"0"を詰める。月も同じ。 # ↓文字列の連結 return right(string(yy),2,"0") || right(string(mm),2,"0") end procedure inc_month(YYMM) # 年月データ +1月 yy := numeric(YYMM[1:3]) ; mm := numeric(YYMM[3:0]) # 年月を数字に変換 if mm = 12 then { yy +:= 1 ; mm := 1 } # 計算 else { mm +:= 1 } return right(string(yy),2,"0") || right(string(mm),2,"0") end -----$ MONTH.ICN ( lines:20 words:97 ) ---------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > (pcv1013.txt 1996/10/13 PCVAN PIG) ■ Icon > Icon日記(8) 横のものを縦に(3) 風つかい 目次 縦棒グラフ作成のプログラムです。 前半は、横棒グラフのプログラムと殆ど 同じです。 # グラフデータ書き出し というコメントあたりが2重リストへの格納処理で、 # グラフを描く というコメントあたりからがその出力処理となっています。 -----^ VPOS2GV.ICN ( date:97-01-02 time:18:04 ) ------------<cut here link chr_chk, month procedure main(args) # vpos2gv.icn Ver.1.1 1997/01/02 windy # This file is in the public domain. # Icon Programming Language(http://www.cs.arizona.edu/icon/index.html) # PCVANの書込みタイトルリストから月別の書込み数(グラフ)を作成 # 縦棒グラフ # タイトルリストサンプル # 7 12 15 #1042 96/12/31 Icon > Icon日記 top.icnを改版 風つかい # 定数定義 Usage := "Usage: vpos2gv title_list" c_mark := "*" # 棒グラフ用文字 c_wall := "-" # 仕切り線用文字 n_size := 3 # 月別書込み数カウントの桁数 step := 5 # グラフの刻み(マーク1個で何個分を示すか) mark := 2 # 目盛りの刻み(目盛りをマーク何個毎に出すか) mark_max := 12 # 最大目盛り (=目盛りの数) graph_max := (mark_max +1) * mark -1 YYMM_size := 4 # 年月データサイズ mark_size := 4 # 目盛り欄サイズ sep_size := 1 # 目盛り欄とデータ欄の境の空きサイズ title := "月別書き込み数グラフ" # グラフタイトル s_post := ["月書","別込"," 数"] # 書込み数のタイトル s_YYMM := [" 年 "," "," 月 "," "] # 年月欄のタイトル # タイトルリストファイルをオープン。コマンドラインの引数の1番目をファイル # 名としてファイルオープン。引数の数が1以外またはファイルオープンできなけ # ればストップ。 if *args = 1 then dir := open(args[1]) | stop("cannot open ",args[1]) else stop(Usage) # 書込み数テーブルを生成(初期値:0) Tyearmonth := table(0) # テーブルに書込み数の足し込み # key:YYMM(年月), value:number of posting(書込み数) while line := read(dir) do { # ファイルから1行ずつ line へ読み込み if chr_chk(' /' ++ &digits,line[1:15]) # タイトル行かどうかのチェック # 行データの文字列から年月部分を取り出して、スペースは"0"に置換して # 年月データを作成し、テーブルのキーとし、対応する値を+1 then Tyearmonth[map(line[7:9] || line[10:12]," ","0")] +:= 1 } # テーブルをキーでソートし、キー、値、キー、値、...と連なったリストを # 生成。 この場合は年月、書込み数、年月、書込み数、... Lyearmonth := sort(Tyearmonth,3) # 歯抜け月(書込みが無かった月)検出用の年月データ初期値セット。 # リストのトップのデータから1と月分減らした年月をセット。 YYMM_old := dec_month(Lyearmonth[1]) # グラフデータ書き出し用リスト生成 Lgraph := [[],[],[]] # 年月、書き込み数、グラフデータ # グラフデータ書き出し while YYMM := get(Lyearmonth) do{ # リストから順次取り出し # 歯抜け月検出および歯抜け月データ(書込み0データ) # 直前の処理データ(YYMM_old)に+1月した値と、今取り出したデータを比較。 # 一致しなければ、直前のデータへ+1月した月のデータ(書込み無し)を # 格納。 ↓文字列の(不)一致比較 while (YYMM_next := inc_month(YYMM_old)) ~== YYMM do { # 書込み数 0の月のデータ格納。 put(Lgraph[1],YYMM_next) # 年月 put(Lgraph[2],right(0,n_size)) # 書込み数 put(Lgraph[3],left(" ",graph_max)) # グラフデータ YYMM_old := YYMM_next # YYMM_oldを更新 } # 書き込み数リストから取り出したデータによりグラフデータを生成。 # 先に取り出していた年月と書込み数と書込み数に対応した数の c_markを格納 # YYMM_oldも更新。 put(Lgraph[1],YYMM) put(Lgraph[2],right(n := get(Lyearmonth),n_size)) put(Lgraph[3],left(repl(c_mark,integer(n/step)),graph_max)) YYMM_old := YYMM } # グラフを描く write(title) # グラフデータ部出力 every i := graph_max to 1 by -1 do { # 月毎データの末尾から出力 # 目盛りの1行分を出力 if (i % mark) = 0 then writes(right(i * step,mark_size -1),c_wall) else writes(repl(" ",mark_size)) writes(repl(" ",sep_size)) # 棒グラフの1行分を出力 every j := 1 to *Lgraph[3] do writes(Lgraph[3][j][i]) # 全ての月につき行う write() } write(repl(c_wall,mark_size + sep_size + *Lgraph[1])) # 仕切り線 # 書込み数データ部出力 every i := 1 to n_size do { # 書込み数行につき writes(s_post[i],repl(" ",sep_size)) # 目盛り欄文字出力 every j := 1 to *Lgraph[2] do writes(Lgraph[2][j][i]) # 全ての月につき行う write() } write(repl(c_wall,mark_size + sep_size + *Lgraph[1])) # 仕切り線 # 年月データ every i := 1 to YYMM_size do { # 年月行につき writes(s_YYMM[i],repl(" ",sep_size)) # 目盛り欄文字出力 every j := 1 to *Lgraph[1] do writes(Lgraph[1][j][i]) # 全ての月につき行う write() } end -----$ VPOS2GV.ICN ( lines:112 words:382 ) -----------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 愛の言霊/サザンオールスターズ BGD: ジャスミン・ティー BGS: Mild Seven Menthol (icon_105.txt 1997/01/02 PCVAN PIG) ■ Icon > Icon日記(9) suspend/generator 風つかい 目次 年明け早々風邪をひいてしまいまして、グスン・グスンとやっています。 年を取る毎に直りが遅くなってきます。20代は酒を呑んで1晩あければ大抵 直っていました。 30代は2〜3日、 40代になると、一度ひくと春まで 体のどこかに残っているみたいです。 さて、Icon入門講座では、suspend/generator のあたりは、私が使いこなせ ていませんので、説明が手抜きですが、多少の補足をしたいと思います。 まず、generatorのほうから。 generatorは、複数のデータを順に発生するものです。データが無くなると 通常failします。(failするように procedureを作ります。) generatorの例としては次のようなものがあります。 ・read(file) fileから(改行で区切られた)データを順に読み込み、そのデータを値 として持ちます。 ・式1 | 式2 | 式3 | ... "a1" | "a2" | "a3" というような表記ですが、generatorとして考える と、式1、式2、式3の値を順に発生するもの となります。 ・i to j by k (by k は省略可) 5 to 10 や 50 to 100 by 10 というような表記です。 数字を順に 発生します。 ・! !は、なんらかのデータ構造から順にデータを取り出すものです。 !"abcdefg" は文字列 "abcdefg"から、順に1文字づつ文字を取り出し ます。 !["a1","a2","a3"] はリストから、順に1要素づつ取り出します。 BIPLの中には、generatorを集めた gener.icn という procedureがあります。 その中から参考にいくつか示します。 procedure days() # 週の名前を順に出してくれるものです。 suspend "Sunday" | "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" end procedure hex() # 16進コードの文字列 00-ffを順に出してくれます。 suspend !"0123456789abcdef" || !"0123456789abcdef" end procedure months() # 月の名前を順に出してくれます。 suspend "January" | "February" | "March" | "April" | "May" | "June" | "July" | "August" | "September" | "October" | "November" | "December" end procedure octal() # 8進コードの文字列を 000-377を順に出してくれます。 suspend (0 to 3) || (0 to 7) || (0 to 7) end で、サンプルプログラムです。 -----^ GENER~.ICN ( date:97-01-15 time:21:57 ) -------------<cut here link gener # gener.icn is in BIPL. # generatorのサンプル # This file is in the public domain. procedure main() write("曜日の書き出し") every write(days()) # 曜日の書き出し write("日本語曜日の書き出し") every write(daysj()) # days()日本語バージョン write("曜日の書き出し:3個まで") every write(days() \3) # generator の生成数を 3個に制限 write("16進数の書き出し") every writes(" ",hex()) # 16進数の書き出し write() write("月の書き出し") every write(months()) # 月の書き出し write("日本語月の書き出し") every write(monthsj()) # months()の日本語バージョン write("日本語月の書き出し:出雲") every write(monthsj("+")) # 出雲バージョン write("8進数の書き出し") every writes(" ",octal()) # 8進数の書き出し write() end procedure daysj() # days() の日本語バージョン suspend "日曜日" | "月曜日" | "火曜日" | "水曜日" | "木曜日" | "金曜日" | "土曜日" end procedure monthsj(s) # months() の日本語バージョン # 引数に何かを与えれば出雲対応 if /s then s10 := "神無月" # 出雲以外 else s10 := "神有月" # 出雲 suspend "睦月" | "如月" | "弥生" | "卯月" | "皐月" | "水無月" | "文月" | "葉月" | "長月" | s10 | "霜月" | "師走" end -----$ GENER~.ICN ( lines:39 words:133 ) -------------------<cut here で、Icon入門講座の split.icnは、テキストファイルの1行をスペースかタブで 分割して、リストに分割するものですが、リストにせずに各要素を suspendで返す ように修正しますと、 -----^ SAMP106A.ICN ( date:97-01-15 time:21:31 ) -----------<cut here procedure main() # suspend のサンプル # This file is in the public domain. s := " The Icon Programming Language" # 対象文字列 every write(s ? getword()) # スペースで区切った文字を書き出す。 end # 文字列を指定文字(セット)で区切る。 procedure getword(c,s) # function : split a string with c /s := &subject # 指定が無ければ &subject /c := ' \t' # 指定が無ければスペースかタブとみなす。 s ? { while tab(upto(~c)) do { word := tab(many(~c)) suspend word } } end -----$ SAMP106A.ICN ( lines:20 words:68 ) ------------------<cut here これを書いていて気がついたのですが、元の split.icnは引数の順が良くない ですね。 split(s,c)の順ではなく、逆の split(c,s)の方が良かったみたい。 それでは、今日はこれくらいで。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: Always/風の背中/篠原美也子 BGD: 小柴胡湯液(風邪薬です。ハイ) BGS: Mild Seven Menthol (icon_106.txt 1997/01/15 PCVAN PIG) ■ Icon > Icon日記(10) sort 風つかい 目次 アリゾナ大のWEBを眺めていましたら、学生さんのWEBコーナーがありました。 メニューに名前がずらっと並んでいます。 日本人みたいな名前がいくつかありましたので、入ってみましたらやっぱり日本から の留学生の方でした。結構いらっしゃるんですね。 関西の方で、関西弁講座(日本のコアラにあるもの。)にリンクを張っていらしゃる 方がいました。 発音例が聞けるようになっていて面白かったです。 こういう風に学生さんがWEBを作れると家族もアクセスできていいですね。親とし ては成績表も見れるといいんでしょうが。 まあ、声とか写真を載せられるというのは 便利だと思います。 さて、Windows-Iconの勉強が進んでいないもので、窓対応以外の部分の補足を相変わ らずやっていきます。 Iconでは、setや tableをソートすると、その後の処理がやりやすいように、listに 変換されます。 文字なら、アルファベット順、数字なら若番から順にソートされます。 で、逆順に ソートしたい場合は、ソートされたリストを後ろから順に使っていくというやり方にな ります。 アリゾナ大の Iconのドキュメントに、文章の中の単語を数え上げて、グラフィック 表示するプログラムの例がありましたので、グラフィックにする部分を除いたものを 次にあげます。 コメントで大体動作はおわかりいただけると思います。 実際は、バーグラフにする例になっているのですが、うまく動かせていないので今日 はその手前までにします。 -----^ CHUMP01C.ICN ( date:97-01-20 time:22:05 ) -----------<cut here # The Icon Programming Language #(http://www.cs.arizona.edu/icon/docs/chump.html)に載っている例題のプログラム # を少し変更したもの。英単語の出現数をカウントするプログラム # This file is in the public domain. procedure main() local dir,f_name,word_count,line,word,retrieve,result,data dir := open(f_name := "poe.txt") | stop("cannot open ",f_name) # word_count := table(0) # テーブル生成(初期値は、0) # while line := read(dir) do # ファイルから1行読み込み every word := genword(line) do # 単語を全部切り出して、 word_count[word] := word_count[word] + 1 # テーブルに登録/語数+1 # ソート # ソートされた[[キー,値],[キー,値],・・・]という並びのリストができる。 #result := sort(word_count,1) # キー(単語名称)でソート result := sort(word_count,2) # 値(出現数)でソート # ソート順に従って使う関数を変更する。 #retrieve := get # 昇順出力する場合:リストの先頭から要素を取り出す。 retrieve := pull # 降順出力する場合:リストの末尾から要素を取り出す。 # 書き出し while data := retrieve(result) do write(left(get(data),15),right(get(data),8)) # 桁を揃える。 end procedure genword(text) # 英文の文章から単語を切り出す。generatorになっている。 local word text ? { while tab(upto(&letters)) do { # 英文字に出会ったら、そこ迄走査位置を移動。 word := tab(many(&letters)) # 英文字以外に走査位置を移動。移動部分=単語 suspend word # 切り出した単語を返す。 単語は複数あるので } # suspendで返す。 } fail # 単語が無くなったら失敗させる。 end -----$ CHUMP01C.ICN ( lines:39 words:127 ) -----------------<cut here 単語数え上げ対象の文章です。 ファイル名から言ってポーの詩らしいです。 (BIPLのdataファイルに含まれているサンプル文章です。) -----^ POE.TXT ( date:92-03-27 time:06:00 ) ----------------<cut here On the Future!-how it tells Of the rapture that impells To the swinging and the ringing Of the bells, bells, bells- Of the bells, bells, bells, bells, Bells, bells, bells- To the rhyming and the chiming of the bells! -----$ POE.TXT ( lines:7 words:39 ) ------------------------<cut here 日本語でソートしたいと言う場合は、mtoyoさんの sortf.exeのような外部プログ ラムを sysem関数で呼んで助けを借りるのが良いと思いますが、アルファベット順や 数字順というような簡単なソートの場合は便利に使えます。 それでは、今日はこれくらいで。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: Good Friend/篠原美也子 BGD: 日本盛 BGS: Mild Seven Menthol (icon_107.txt 1997/01/20 PCVAN PIG) ■ Icon > Icon日記(11) Icon in Java 風つかい 目次 アリゾナ大の Iconサポートグループ icon-projectでは、定期的に The Icon News- letterを発行しています。 今は年2回発行されています。 以前は郵送配布でしたが、現在はWWWで見ることができます。46号からアリゾナ 大学のWWWに載っています。 現在の URLは以下の通りです。 http://www.cs.arizona.edu/icon/newsletter/inl.html にメニューがあります。 Icon Newsletter 51. December 1, 1996 Icon Newsletter 50. August 1, 1996 Icon Newsletter 49. April 1, 1996 Icon Newsletter 48. November 28, 1995 Icon Newsletter 47. July 15, 1995 Icon Newsletter 46. December 29, 1994 最新号は51号で、昨年12月の発行です。 http://www.cs.arizona.edu/icon/newsletter/inl51/inl51.html 目次は以下のようになっています。 Third Edition of The Icon Programming Language Graphics Programming Book Version 9.3 of Icon Version 9.3 of the Program Library New MS-DOS Implementation Icon in Java Teaching Icon Web Links Chicon Icon Programming Language の第3版の出版紹介とか、Graphic Progaramming Book の発行予告とかが載っています。 この中で、Icon in Java というのが興味を引きます。Iconは中間言語方式の言語で、 ・ソースプログラムをトランスレータで中間言語に翻訳し ・中間言語ファイルを解釈実行する。 というステップで動かします。 プラットフォーム(OS等)に応じたトランスレータ と中間言語実行ソフトを用意して、色んなプラットフォームで動作させます。 近頃、巷で噂の Javaも同じ考え方です。 で、 Javaも中間言語を持っていますので Iconが Javaの中間言語で動くようにすれば、Javaが動く環境なら Iconも動くようにで きる。 ということで、そのためのプロジェクトが発足したそうです。 年単位のプロジェクトと思いますので、リリース前に Javaがダージリンとかに取って 代わられていないように、願っていましょう。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 海になりたい青/篠原美也子 BGD: ジャスミン・ティー BGS: Mild Seven Menthol (icon_108.txt 1997/01/26 PCVAN PIG) ■ Icon > Icon日記(12) NURSE.ICN 風つかい 目次 (PCVANのテキストデータ処理会議室で、コントロールコードが混じったテキス トファイルから、コントロールコードを除去するプログラムが、話題にでました。 その話題に関連して作ったものです。 NURSE.ICNという名前もそのテキストファイル の名前に由来しています。) Icon でもコントロールコード除去のプログラムを作らないといけない。 というこ とで、作ってみました。 テキストファイルしか扱った事が無かったので手こずりました。ファイルオープン のパラメータに注意しないといけないようです。 -----^ NURSE.ICN ( date:97-02-01 time:16:32 ) --------------<cut here link c_ft procedure main() # Rev.01 1997/02/01 windy # kangohu.txtのコントロールコード除去 # This file is in the public domain. local dir, f_name, code, ss f_name := "kangohu.txt" # ファイル名 # 改行コードを除くコントロールコード以外のコード code := ~(c_ft('\x00','\x09') ++ c_ft('\x0b','\x1f')) #↑以外 # ファイルオープン dir := open(f_name,"ru") | stop("cannot open ",f_name) # ↑読込・改行非変換モード #ファイル読み込み・コントロールコード無視処理 while ss := reads(dir,256) do { # ↑バイナリー読込関数。サイズの256はいい加減。 ss ? { # ssをスキャン対象とする。 while tab(upto(code)) do { # コントロールコード以外の文字迄 # スキャンポイントを移動。 writes(tab(many(code))) # コントロールコード以外の文字以外の文字 } # (=コントロールコード)へスキャン } # ポイントを移動。移動部分の文字列を出力。 } # (=コントロールコード以外の文字列) end -----$ NURSE.ICN ( lines:25 words:82 ) ---------------------<cut here Icon本体では正規表現はサポートしていませんので、コントロールコードの判定 条件の際に、\x00-\x1f みたいに指定できません。ずらずらと文字コードを並べる のも芸が無いので、from - to 指定で csetを指定できる procedure を作りました。 -----^ C_FT.ICN ( date:97-02-01 time:16:26 ) ---------------<cut here procedure c_ft(c1,c2) # Rev.01 1997/02/01 windy # c1 から c2 迄の文字を含む csetを作る。正規表現 [c1-c2] 相当。 # c_ft('a','f') -> 'abcdef' # This file is in the public domain. local c, i c := '' # 空cset every i := ord(c1) to ord(c2) do c ++:= char(i) # cset足し込み # ↑キャラクタ番号関数 ↑キャラクタ番号→キャラクタ関数 return c end #テストデータ #procedure main() # write(c_ft('a','f')) # 'abcdef' # write(c_ft('0','5')) # '012345' #end -----$ C_FT.ICN ( lines:17 words:64 ) ----------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: アンバランス/大黒摩季 BGD: 月桂冠 BGS: Mild Seven Menthol (icon_109.txt 1997/02/01 PCVAN PIG) ■ Icon > Icon日記(13) Wicon ベータ7 風つかい 目次 icon-project では、Icon のグラフィック機能の整備を行っています。 Unixバージョンではグラフィック機能がサポートされていますが、Windows-95,NTでは 、未だ正式リリース版はありません。しかしベータ版はリリースされています。 http://www.cs.arizona.edu/icon からたどれますが、次の所にベータ版がおいてあ ります。 ftp://ftp.cs.arizona.edu/icon/beta/windows/ ここにベータ版をまとめた complete.zip 771 Kb Wed Nov 06 05:38:00 1996 Zip Compressed Data があります。 中身は次のようになっています。 (unzip -l complete.zip) Archive: COMPLETE.ZIP Length Date Time Name ("^" ==> case ------ ---- ---- ---- conversion) 4295 96-11-05 02:44 READ.ME 235876 96-10-12 16:35 ged.bat 228482 96-11-05 02:26 gipd.hlp 48828 96-11-05 02:26 iconintr.hlp 122456 96-11-05 02:26 iconref.hlp 28085 96-11-05 02:26 ipd271.doc 102133 96-11-05 02:26 ipd271.ps 3225 96-02-08 23:09 keysyms.icn 73 96-04-08 23:40 noop.bat 543042 96-10-12 16:36 vib.bat 382976 96-11-05 02:26 wicon.exe 46888 96-11-05 02:26 wicon.hlp 262144 96-11-05 02:53 wicont.exe 420352 96-11-05 02:26 wiconx.exe ------ ------- 2428855 14 主なプログラムは、 wicont.exe が、プログラムの中間言語へのトランスレータ。 wiconx.exe が、中間言語の実行プログラム。 wicon.exe が、ランチャー。(プログラムをエディットして、トランスレータ 中間言語実行プログラムを呼んで実行させる。) となっています。 尚、グラフィック機能を使うためには、ライブラリーの BIPL,GIPLは必須です。 グラフィック以外の機能は、BIPLが無くとも色々試せましたが、グラフィック関係 はBIPL,GIPLがリンクできるようになっていないと動かせません。 私の環境(Windows-95)で、ぼちぼち試していますが、 ・標準出力Windowが、日本語に対応していない。(エディットウィンドウは 日本語が使える。) 日本語をウィンドウに出さない(ファイルへ出力し てしまう。)と問題ないが、出すと日本語文字が化ける。 ウィンドウを生成してそこへ出力しても文字が化ける。 ・コマンドラインパラメータが渡せない。(みたい。) というような状況です。 使いはじめたばかりなので、私の設定とか使い方が間違っている可能性もありま す。 日頃、テキストファイルを加工して、別のテキストファイルへ変換する処理しか やっていないもので、あまりグラフィック機能の必要性を感じてませんので、勉強 のペースがいまいちです。 テキスト処理結果やテキスト処理マンマシンインターフェースを、グラフィック 処理できる言語と言えば、Tcl/Tk、Tkperl、Tkpython、Javaとかがあるようなので すが Iconでもやれるといいなという方はお試しを。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: roka/遊佐未森 BGD: 月桂冠 BGS: Mild Seven Menthol (icon_110.txt 1997/02/03 PCVAN PIG) ■ Icon > Icon日記(14) dump.icn 風つかい 目次 Nurse.icnでバイナリーファイルを初めて扱いましたが、ついでにバイナリーファイル のヘキサダンププログラムを作ってみましょう。 こんな風にバイナリーファイルの内容をヘキサ表示で出力するものです。 この例は、 idump idump.exe >idump.txt として、idump.exeの内容を表示した ものです。 -----^ IDUMP.TXT ( date:97-03-22 time:13:10 ) --------------<cut here 0000000 4d5a 7b00 0200 0100 0200 2700 ffff 2600 0000010 0001 0000 0000 0000 1c00 0000 0100 0000 0000020 b820 008e d88c 0662 0126 8b0e 2c00 890e (中略) 0000ea0 7369 676e 0030 002d 0030 3132 3334 3536 0000eb0 3738 3961 6263 6465 6600 3031 3233 3435 0000ec0 3637 3839 4142 4344 4546 00 -----$ IDUMP.TXT ( lines:252 words:2131 ) ------------------<cut here プログラムを次にしめします。 -----^ IDUMP.ICN ( date:97-02-05 time:22:13 ) --------------<cut here link hexcvt procedure main(args) # Rev.01 1997/02/05 windy # ファイルのヘキサダンプ # This file is in the public domain. local Usage, byte_count, dir, s, c Usage := "idump input_file > output_file" byte_count := 0 if *args[1] >1 then f_name := args[1] else stop(Usage) # ファイルオープン dir := open(f_name,"ru") | stop("cannot open ",f_name) # ↑読込・改行非変換モード #ファイル読み込み→16進変換出力 while s := reads(dir,256) do { # ↑バイナリー読込関数。サイズの256は適当な値です。 every c := !s do { # s から1文字ずつ取り出す。 if byte_count % 16 = 0 # 16バイト単位にバイト数を表示 then writes("\n",(hexstring(byte_count,7,""))," ") #↑バイト番号を7桁の16進数表記に変換。 else { # 2バイト毎にスペース挿入 if byte_count % 2 = 0 then writes(" ") } byte_count +:= 1 writes(hexstring(ord(c),2,"")) #↑文字を文字番号に変換し、2桁の16進数表記に変換。 } write() } end # hexstring(i,n,lowercase) は、ライブラリーBIPLの hexcvt.icn に含まれる関数。 # 10進数 iを16進数表記に変換する。nは桁数。3番目のパラメータに何か入れる # と a-fは小文字(デフォルトは A-Fは大文字)。 -----$ IDUMP.ICN ( lines:36 words:118 ) --------------------<cut here BIPL全体は1M強のサイズがありますので、hexcvt.icnを以下に BIPLから引用して おきます。 -----^ HEXCVT.ICN ( date:96-09-23 time:12:23 ) -------------<cut here ############################################################################ # # File: hexcvt.icn # # Subject: Procedures for hexadecimal conversion # # Author: Robert J. Alexander # # Date: June 7, 1994 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # hex(s) -- Converts string of hex digits into an integer. # # hexstring(i,n,lc) -- Returns a string that is the hexadecimal # representation of the argument. If n is supplied, a minimum # of n digits appear in the result; otherwise there is no minimum, # and negative values are indicated by a minus sign. If lc is # non-null, lowercase characters are used instead of uppercase. # ############################################################################ procedure hex(s) local a,c a := 0 every c := !map(s) do a := ior(find(c,"0123456789abcdef") - 1,ishift(a,4)) | fail return a end procedure hexstring(i,n,lowercase) local s,hexchars,sign i := integer(i) | runerr(101,i) sign := "" if i = 0 then s := "0" else { if /n & i < 0 then { sign := "-" i := -i } hexchars := if \lowercase then "0123456789abcdef" else "0123456789ABCDEF" s := "" until i = (0 | -1) do { s := hexchars[iand(i,15) + 1] || s i := ishift(i,-4) } } if \n > *s then s := right(s,n,if i >= 0 then "0" else hexchars[16]) return sign || s end -----$ HEXCVT.ICN ( lines:54 words:218 ) -------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: Vivien/篠原美也子 BGD: 月桂冠 BGS: Mild Seven Menthol (icon_111.txt 1997/02/05 PCVAN PIG) ■ Icon > Icon日記(15) 再びIconの特徴 風つかい 目次 プログラムは、AWKと Iconで精々1ページに納まる程度のものしか組んでいないので すが、プログラムミスの修正に相当の時間を費やしています。 一番の原因は、 思い込み ですね。 何でこんな数行の procedureがすんなり動かないんだろう! で、原因はデータタイプが違っていて、エラーメッセージもそう出ているんですけれ ど、合っていると思い込んでいて、何故か気づかず なして〜!? と悩んでいたというのが多いです。 思い込みと言えば、【スパゲッティミートソース】という料理がありますね。 昔これを、 【スパゲッティ meet ソース】 と思い込んでいました。 初めて、喫茶店か食堂のメニューでみたとき、何故かそう思い込んだんですね。 【 スパゲッティ と ソース の出会い】 お〜、割と粋な名前じゃん! 確か高校生位の頃だったと思います。 で、勘違いに気付いたのは、ずいぶん後の ことで、TVのCMで、ミートソースの宣伝を見て、ハタと meat だと...。 【え〜、そんなそっけない名前だったの〜。】 世の中には、美しく誤解したままの方が幸せということもあるという訳です。 思い込みの原因は、当時Jazzを聞きはじめていたんですが、有名なプレーヤー を2人共演させた、タイトルが だれだれ meets だれだれ というようなレコードが がいくつかありました。 それが頭にあったもんで、連想で meet だと。 なんで、スパゲッティなら meetsと3人称単数現在の sがつくと思わなかったんだ ろう? いや、スパゲッティは1本じゃなくて沢山あるんだから、複数扱いでいいの だ。 あれ、英語では単数かな? 複数かな?(笑) さて、今日は、再び Iconの特徴ということで、Icon入門講座では AWKと比べたIcon の特徴というかたちで説明しましたが、今回は、他の言語と比較しても 【だいぶ違うのではないだろうか】 という点をあげてみたいと思います。 だろうかというのは、私が他の言語は AWK以外ははよく知らないもので...(汗) 1)文字(列)検索をプログラムできる仕掛けが組み込まれている。 文字(列)パターンマッチについて、例えば正規表現以外のマッチのやり方も プログラムで組めるということです。 これは逆に正規表現も組まないといけ ないといけないということになります。 (と言っても正規表現以外のパターンマッチのというのは思い付きません。 無理矢理作ればできると思うんですが、実用的な用途であるのかしら?) 2)データ構造 set(集合)、list(リスト)、table(テーブル)は、その 要素にまた set(集合)、list(リスト)、table(テーブル)を含むことが できる。 例えば、setの要素に setや listや tableを持てて、 その setや listや tableの要素に、また setや listや tableを、持てて.. と幾重にも階層構造を作れるということです。 3)バックトラッキングの仕掛けが組み込まれている。 バックトラッキングというのは、後戻り探索ですよね。例えば、迷路があって ある道筋をたどって行き止まりなら、戻って別のルートを捜すようなしかけを 必要とするプログラムが組みやすいということです。 Icon教典(The Icon Programming Language)には、エイト・クイーン問題の例 が載っています。 8x8のチェス盤に8個のクイーンをお互いに取られない位置に置くとしたら 何通りあるか というような問題です。 私の思い込みでは、以上3つあげたなかで、3)のバックトラッキングが一番特徴的 かなとも思うのですが...。 エイト・クイーンの解を洗いだすプログラムは Iconのライブラリーにはいっていま す。 動かすと、これはスゴイ! と思います。 しかし〜。 エイト・クイーン問題が解けて何の役に立つんだろう? 他に良い利用法 が無いものかと考えている今日このごろです。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: Vivien/篠原美也子(http://www.j-plaza.or.jp/msap/ARTIST/SHINOHARA/) (icon_112.txt 1997/02/21 PCVAN PIG) ■ Icon > Icon日記(16) Recursive generator 風つかい 目次 金・土と春一番の突風が吹き荒れていました。すぐこういうのに影響されて、キャン ディーズの春一番が聞きたくなったりします。 近ごろ、自宅のパソコンを触っているときは、必ずCDを聞いています。 パソコンを買い換えたときCDドライブがついてたもので、遊ばせておくのも勿体ない ので音楽CDをレピートモードで掛けっぱなしで聞いています。 パソコンの売れ行きが伸びるとCDの売れ行きも伸びているのかしら? 私の場合は、手持ちのCDを聞き飽きてしまって、新しいCDを買うようになりまし た。 さて、今回は Recursive generator 再帰的ジェネレータです。 ジェネレータは、 次々に値を発生しますが、その構成に再帰的な構成を使ったものです。 再帰的というのは、procedureのプログラムの中に自分自身を呼んでいる部分がある ような構成になっているものです。 例えば、文字列 "ABC" があったとして、この3文字の組み合わせを全て作るとしま す。 "ABC","ACB","BAC",...というような組み合わせを全てあげていく訳です。 プログラムの考え方は、 まず、3文字の中から1文字を取り出します。これは3通りのやり方があります。 この3通りのやり方で取り出した1文字に、残りの2文字の組み合わせの文字列を つなげたものが、組み合わせの全てになります。 残りの2文字の組み合わせの作り方も同様のやり方で、 この2文字からまた1文字取り出します。 これは2通りあります。 この2通りのやり方で取り出した1文字に、残りの1文字の組み合わせの文字列 (1文字しか残っていないのですから1通りしかありませんが)をつなげたもの が全ての組み合わせとなります。 残りが1文字になったら、もう組み合わせる必要がありません。 ここで終わりにな るようにします。 再帰的構成では、残りの部分に同じやり方を適用するという部分で、自分自身を呼び ます。 Iconのライブラリーに以上の考え方で作られた procedureがあります。 strings.icnの中の permute.icnです。permute.icnでは、1文字でも再度しつこく、 同じやり方で残りが空文字列になって終わるようになっています。 多分、文字列に空文字が指定されたケースの事を配慮しているのだと思います。 では次にサンプルプログラムを。 -----^ PERM01.ICN ( date:97-02-23 time:23:57 ) -------------<cut here # 英文字の組み合わせ # Rev.01 1997/02/23 windy # This file is in the public domain. #link strings procedure main(args) # ↑args(コマンドライン引数(リスト)) Usage := "Usage: perm01 string" every write(permute(args[1])) # コマンドライン引数の文字の組み合わせ # を全て書き出す。 end # ライブラリー BIPL の strings.icn (日本語コメントを追加) procedure permute(s) #: string permutations # sを構成する英文字の組み合わせを生成する generator # 再帰構成(自分自身を呼んでいる) # 同一文字(例: aab)が指定された場合の手当は無い。 local i if *s = 0 then return "" # 再帰終了条件 # ↓文字列の連結 ↓文字列の連結 suspend s[i := 1 to *s] || permute(s[1:i] || s[i+1:0]) # ↑s[i]は、文字列 s ↑i番目の文字より手前 ↑i番目より後ろ # の i番目の文字 (すなわち i番目を除いた文字列) # 1番目から最後の文字まで順に1文字取り出して、残りの文字列の組み合わせ # とつないでその値を返す。残りの文字列の組み合わせを作るときに自分自身を # 呼んでいる。 残りの文字が無くなったら再帰は終了。 end -----$ PERM01.ICN ( lines:28 words:93 ) --------------------<cut here perm01 ABC >perm01.txt とした時の結果です。 -----^ PERM01.TXT ( date:97-02-23 time:23:58 ) -------------<cut here ABC ACB BAC BCA CAB CBA -----$ PERM01.TXT ( lines:6 words:6 ) ----------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 春一番/キャンディーズ (icon_113txt 1997/02/24 PCVAN PIG) ■ Icon > Icon日記(17) 文字の組み合わせ(1)風つかい 目次 先日、渋谷のレコード店で、近ごろ聞いている女性歌手のCDリリース記念ミニライ ブというのがありまして、聞きにいきました。 小さなステージに何故かパソコンがおいてありまして、何につかうんだろうと思って いました。 メンバーが、ベース、ギター、エレピ、歌手と登場して、曲が始まるとエレピの方が パソコンをちょっと触ると、なんとドラムの音がしてきて、やっと分かりました。 ライブは、10年位聞いていなかったのですが、今はパソコンも楽器になっているん ですね。 たまには、聞きにいってみるもんだ。 さて、Iconの Recursive generatorの続きです。 前回は、英文の文字列の組み合わ せでした。 やっぱ、日本人ならせめて、かな文字くらいは組み合わせないといけませ んね。 というわけで、かな文字の組み合わせです。文字が2バイトで表わされていま すので、2バイト単位に処理をしていきます。 -----^ PERM02.ICN ( date:97-02-26 time:19:30 ) -------------<cut here # 2bytes文字(漢字、かな、とか)の組み合わせ # Rev.01 1997/02/26 windy # This file is in the public domain. # Usage: perm02 2バイト文字列 procedure main(args) # ↑args(コマンドライン引数(リスト)) every write(jpermute(args[1])) # コマンドライン引数の文字の組み合わせ # を全て書き出す。 end # ライブラリー BIPL の strings.icn を 2byte文字用にしたもの。 procedure jpermute(s) #: string permutations # sを構成する 2byte文字の組み合わせを生成する generator # 再帰構成(自分自身を呼んでいる) # 同一文字が指定された場合(例: ああい)の手当は無い。 local i if *s = 0 then return "" # ←再帰終了条件 # ↓文字列の連結 suspend s[i := 1 to *s by 2 : i +2] || # ↑s[i:i+2]は、文字列 # sの i番目の文字 # ↓文字列の連結 jpermute(s[1:i] || s[i+2:0]) # ↑i番目の文字より手前 ↑i番目より後ろ # (すなわち i番目を除いた文字列) # 上のプログラムで i番目というのは半角で数えた位置。全角では (i+1)/2番目。 # 1番目から最後の文字まで順に 2byte単位で文字を取り出して、残りの文字列の # 組み合わせとつないでその値を返す。 # 残りの文字列の組み合わせを作るときに自分自身を呼んでいる。 # 残りの文字が無くなったら再帰は終了。 end -----$ PERM02.ICN ( lines:35 words:105 ) -------------------<cut here perm02 ゆかり >perm02.txt とした時の結果です。 -----^ PERM02.TXT ( date:97-02-26 time:19:29 ) -------------<cut here ゆかり ゆりか かゆり かりゆ りゆか りかゆ -----$ PERM02.TXT ( lines:6 words:6 ) ----------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: いとおしいグレイ/篠原美也子 (http://www.j-plaza.or.jp/msap/ARTIST/SHINOHARA/) (icon_114.txt 1997/02/26 PCVAN PIG) ■ Icon > Icon日記(18) 文字の組み合わせ(2)風つかい 目次 さて、文字の組み合わせのつづきです。 前々回の perm01.icn も、前回の perm02.icnも文字列の中に、同じ文字が 2つ出てきても配慮していません。 perm01 ABA >perm01b.txt とすると、 -----^ PERM01B.TXT ( date:97-02-26 time:20:12 ) ------------<cut here ABA AAB BAA BAA AAB ABA -----$ PERM01B.TXT ( lines:6 words:6 ) ---------------------<cut here となり、同じ文字列が2回出てきます。 という訳で、出てくる文字列がダブらない処理を入れてみました。 元の文字列で同じ文字を使っているのが検出しやすいように、文字をソートし ておきます。 perm01.icn の suspend s[i := 1 to *s] || permute(s[1:i] || s[i+1:0]) の i := 1 to *s は文字列中の文字を順に指定する generatorです。 その代わりに、手前の文字と同じなら文字だったら指定をスキップする generatorを 使います。 -----^ PERM03.ICN ( date:97-02-26 time:19:54 ) -------------<cut here # 英文字の組み合わせ(同一文字指定対応) # Rev.01 1997/02/26 windy # This file is in the public domain. # Usage: perm03 string #link strings procedure main(args) every write(expermute(args[1])) # コマンドライン引数の文字の組み合わせ # を全て書き出す。 end procedure expermute(s) # string permutations ss := csort(s) # 文字列をソートする。 if *s = 0 then return "" # suspend ss[i := new_pos(ss)] || expermute(ss[1:i] || ss[i+1:0]) # ↑手前と同一ならスキップする generator end procedure new_pos(s) # ソートされた文字列 sの左はじから、順に文字位置を出力する generator。 # 手前の文字と同一ならスキップする。 ss := "" # 手前の文字を記憶しておく変数 every i := 1 to *s do { if ss ~== s[i] then { # 手前の文字と違っていたら ss := s[i] # 手前文字を更新 suspend i # i を返す。 } } end procedure csort(s) #: lexically ordered characters # ライブラリー BIPL の strings.icn に含まれる(日本語コメントを追加) local c, s1 s1 := "" # 文字列足し込み用 every c := !cset(s) do # 全文字のセットから1文字づつ取り出す。 every find(c, s) do # その文字を見つけると s1 ||:= c # 足し込む。 return s1 end -----$ PERM03.ICN ( lines:40 words:141 ) -------------------<cut here perm03 ABA >perm03.txt としますと、違う文字列のみ発生します。 -----^ PERM03.TXT ( date:97-02-26 time:19:56 ) -------------<cut here AAB ABA BAA -----$ PERM03.TXT ( lines:3 words:3 ) ----------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: そのままの君でいて/岡本真夜 (icon_115.txt 1997/02/26 PCVAN PIG) ■ Icon > Icon日記(19) 文字の組み合わせ(3)風つかい 目次 さて、今回も文字の組み合わせのつづきです。 シフトJISの1バイト文字、2バイト文字が混在していても組み合わせできるよう に拡張します。 文字列から順に文字を取り出す処理にシフトJISコードの2バイト文字の判定処理 をいれています。 -----^ PERM04.ICN ( date:97-02-28 time:01:07 ) -------------<cut here # SJISコード文字の組み合わせ # Rev.01 1997/02/28 windy # This file is in the public domain. # Usage: perm04 string link sjis procedure main(args) every write(jpermute(args[1])) # コマンドライン引数の文字の組み合わせ # を全て書き出す。 end procedure jpermute(s) # string permutations ss := list2str(jsort(s)) # 文字列をソートする。 if *s = 0 then return "" # 再帰終了条件 suspend ss[(L := jnew_pos(ss))[1] : L[2]] || # ↑generator jnew_pos(ss)により指定される文字(左はじから順に指定) # ↓指定文字以外の文字列に同じ処理を行う。 jpermute(ss[1 : L[1]] || ss[L[2] : 0]) # ↑手前 ↑後ろ end procedure jnew_pos(s) # 文字列 sの左はじから、順に文字位置を出力する generator。 # 手前の文字と同一ならスキップする。 ss := "" # 手前の文字を記憶しておく変数 every L := jpos(s) do { # 文字位置 generatorから順に取り出す if ss ~== s[L[1]:L[2]] then { # 手前の文字と違っていたら ss := s[L[1]:L[2]] # 手前文字を更新 suspend L # L を返す。 } } end -----$ PERM04.ICN ( lines:32 words:114 ) -------------------<cut here シフトJIS文字に対応するための procedureです。 -----^ SJIS.ICN ( date:97-02-28 time:00:54 ) ---------------<cut here # SJIS関係 procedure # Rev.01 1997/02/28 windy # This file is in the public domain. #link show_l # for test driver # SJISコードの文字列の文字の先頭位置を発生する generator # value: list [1]:先頭位置,[2]:次の文字の先頭 # Rev.01 1997/02/27 windy procedure jpos(s) mode := 1 # 1バイト目チェック(/2バイト目)モード every i := 1 to *s do { n := ord(s[i]) case mode of { # SJISコードの1バイト目チェック(16rは16進数を示す。) 1 : if {16r80 < n < 16rA0} | {16rDF < n < 16rFD} then mode := 2 # ←2バイト目モードへ else suspend [i,i+1] # 1バイトコード 2 : { # 2バイトコードの2バイト目 mode := 1 # モードを1バイト目チェックへ suspend [i-1,i+1] # 2バイトコード } } } end # SJISコードの文字列の文字ソート # value: ソートされた文字のリスト # Rev.01 1997/02/27 windy procedure jsort(s) L1 := [] every L2 := jpos(s) do put(L1,s[L2[1]:L2[2]]) return sort(L1) end # 文字の連結 # value: 連結された文字(列) # Rev.01 1997/02/27 windy procedure list2str(L) s := "" every s ||:= !L return s end # test driver #procedure main(args) # ------------common part # s := args[1] # /s := "" # write(s) # ------------ # every L := jpos(s) do write(s[L[1]:L[2]]) # jpos(s) # show_sl(jsort(s)) # jsort # write(list2str(jsort(s))) # list2str #end -----$ SJIS.ICN ( lines:54 words:181 ) ---------------------<cut here perm04 あXあ >perm04.txt とやると、つぎのような結果になります。 -----^ PERM04.TXT ( date:97-02-28 time:01:21 ) -------------<cut here ああX あXあ Xああ -----$ PERM04.TXT ( lines:3 words:3 ) ----------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 海になりたい青/篠原美也子 (icon_116.txt 1997/02/28 PCVAN PIG) ■ Icon > Icon日記(20) シフトJIS処理(1)風つかい 目次 はやいもので、もう明日から3月ですね。 季節は、もう春だ。 春になったら、Icon日記のタイトルも変えたいな。 Icon日記は、来月で終わり にして、別のタイトルにしようと思います。 Icon日記では、あと シフトJIS処理、バックトラッキング、レコード にトラ イしてみようかと思います。 いずれも今まで使ったことが無いものですので、うま く説明ができるといいのですが。 さて、シフトJIS処理については、string scanning 関係の関数をシフトJIS 対応にしてみたいと思います。 string scanningに関係する関数は、upto,many,find,move などがあります。 upto,manyは、文字列に、指定された文字(の集合)が含まれるかどうか? に関す る動作をします。 シフトJISには2バイト文字がありますので、文字指定に cset(1バイト文字) ではなく、2バイト文字(Iconでは文字列)も扱える set(集合)を使う必要があり ます。 find は、文字列中に、別の文字列が含まれるかを調べます。 1バイト文字か2バイト文字かを意識せず、1バイトの文字のつながりとみなして検 索しても大丈夫なケースもあります。 しかし、厳密な照合をしたいときはシフトJISの文字の境をチェックして、2バイ ト文字の2バイト目から照合をはじめないようにする必要があります。 move は、1バイト文字・2バイト文字にかかわらず、指定文字数だけ走査位置を移 動させます。(必要無いような気もしますが、ものはついでと。) こういう文字列検索の事を考えていると、AWKやIconの検索は英文向きだな〜と思いま す。 単語やデータが、通常スペース区切りになっていますので、単語やデータを切り出す のが非常に楽なんですね。 日本語は、単語の区切りが検出しにくい言語ですね。 今回は、手始めに2バイト文字の集合を扱いやすくするために、2バイト文字の集合 を from-to指定できる procedureを作りました。 -----^ JC_FT.ICN ( date:97-02-28 time:22:39 ) --------------<cut here procedure jc_ft(s1,s2,step) # Rev.01 1997/02/28 windy # 2バイト文字 s1 から s2 迄 step指定バイト飛びのコードの文字の setを作る。 # 2バイト文字の from-to指定のため # jc_ft("0","4") -> "0","1","2","3","4" の set # jc_ft("あ","お",2) -> "あ","い","う","え","お" の set # This file is in the public domain. local S, i /step := 1 S := set() # 空のset # from指定文字とto指定文字を数に変換し、その間の数を2バイト文字へ変換し # setに加える。 every i := (ord(s1[1])*256 +ord(s1[2])) to (ord(s2[1])*256 +ord(s2[2])) by step do { insert(S,char(i/256) || char(i%256)) } return S end #テストデータ procedure main() local L L := sort(jc_ft("0","4")) # "0","1","2","3","4" while writes(get(L)) # リストデータの書き出し write() L := sort(jc_ft("あ","お",2)) # "あ","い","う","え","お" while writes(get(L)) write() end -----$ JC_FT.ICN ( lines:30 words:95 ) ---------------------<cut here jc_ft >jc_ft.txt とした結果です。 -----^ JC_FT.TXT ( date:97-02-28 time:22:42 ) --------------<cut here 01234 あいうえお -----$ JC_FT.TXT ( lines:2 words:2 ) -----------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: vivien/篠原美也子 (icon_117.txt 1997/02/28 PCVAN PIG) ■ Icon > Icon日記(21) シフトJIS処理(2)風つかい 目次 昨日も風が強かったのですが、TVのお天気コーナでは春一番だと言っていました。 今の季節で吹くと何回吹いても春一番なのかな〜。 確かにいちいち数えていられな いとは思いますし、春二番、春三番とは言いませんものね。 AWKや Iconには、便利な機能や表現がありますね。 でも、知らない人には、何が なんだか分からりませんね。 しかし、用語の点で英語圏の人は有利だな〜。 Iconの関数でも、write,tab,upto,many,every,while,repeat,until,... 皆、英語圏 の人にはすぐ意味が理解できるんでしょうね。 every write(1 to 100) なんて、英語圏の人は、読んだまま理解できますもんね。 さて、今回もシフトJIS関係です。 uptoと manyをシフトJIS対応にしてみました。 cset(1バイト文字セット)の 代わりに set(集合)に、1〜2バイト文字を入れて、csetの代わりとしています。 -----^ SJIS2.ICN ( date:97-03-02 time:14:58 ) --------------<cut here # SJIS関係 procedure その2 # Rev.01 1997/03/02 windy # This file is in the public domain. procedure jupto(S,s,i1,i2) # 文字列 sの中の 集合 Sに含まれる文字の位置を生成する generator # value: 文字の先頭位置 # Rev.01 1997/03/02 windy /i1 := 1 # default if /s then { # default s := &subject i1 := &pos } /i2 := *s +1 # default every L := jpos(s,i1,i2) do { # 文字を順次取り出す。 if member(S,s[L[1]:L[2]]) then { # 文字が Sに含まれるかテスト suspend L[1] } } end # 文字列 sの中 &pos以降で、集合 Sに含まれない文字の位置を生成する # value: 文字の先頭位置 # Rev.01 1997/03/02 windy procedure jmany(S,s,i1,i2) /i1 := 1 # default if /s then { # default s := &subject i1 := &pos } /i2 := *s +1 # default if i1 = i2 then return i2 # 行末手当 every L := jpos(s,i1,i2) do { # 順次取り出す。 if not member(S,s[L[1]:L[2]]) # 文字が Sに含まれないものかテスト then { return L[1] } else { if L[2] = i2 then { # 行末なら含まれない文字とみなす。 return L[2] } } } fail end # SJISコードの文字列の文字の先頭位置を発生する generator # value: list [1]:先頭位置,[2]:次の文字の先頭 # Rev.01 1997/02/27 windy, Rev.02 1997/03/02 windy procedure jpos(s,i1,i2) mode := 1 # 1バイト目チェック(/2バイト目)モード every i := i1 to (i2 -1) do { # n := ord(s[i]) case mode of { # SJISコードの1バイト目チェック(16rは16進数を示す。) 1 : if {16r80 < n < 16rA0} | {16rDF < n < 16rFD} then mode := 2 # ←2バイト目モードへ else suspend [i,i+1] # 1バイトコード 2 : { # 2バイトコードの2バイト目 mode := 1 # モードを1バイト目チェックへ suspend [i-1,i+1] # 2バイトコード } } } end # test driver procedure main() S := set(["a","あ","b","い","c","う"]) s := "abcdefあいうえおかabcあいう" write(s) # every L := jpos(s,3,22) do write(s[L[1]:L[2]]) # jpos(s,i1,i2) # every write(jupto(S,s,3,22)) # jupto(S,s,i1,i2) # write(jmany(S,s,9,22)) # jmany(S,s,i1,i2) # write(jmany(S,s,26)) # jmanyの行末手当 s ? { # juptoとjmanyの組み合わせ while tab(jupto(S)) do { write(tab(jmany(S))) } } end -----$ SJIS2.ICN ( lines:85 words:288 ) --------------------<cut here テストプログラムは、検索対象文字列 sから、指定文字 Sが含まれる部分を 検出して、書き出すものです。以下はその結果です。 -----^ SJIS2.TXT ( date:97-03-02 time:15:00 ) --------------<cut here abcdefあいうえおかabcあいう abc あいう abcあいう -----$ SJIS2.TXT ( lines:4 words:4 ) -----------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: そのままの君でいて/岡本真夜 (icon_118.txt 1997/03/02 PCVAN PIG) ■ Icon > Icon日記(22) シフトJIS処理(3)風つかい 目次 話し言葉の言語というのはいくつ位あるんでしょうね。 日本の言葉でもおおざっぱに九州弁、関西弁、名古屋弁、東北弁、...とか分け ますが、実際は市か郡の単位で微妙にアクセントやイントネーションが異なっていて、 その地方の方には聞き分けられます。 また世代によっても違います。 業界でも違いますし。 数えれば、人類数十億人で 数千人単位では、言葉が微妙に違う訳ですので、10万位はあるわけですね。 プログラム言語も言語の仲間ですから沢山あります。 リストを作らっれている方がいらっしゃいまして、以前数えましたら1000は越し ていたと思います。 OSも沢山あると思いますが、こちらの数はよくは知りません。 コンピュータを使うにあたって、OSは空気、プログラム言語は言葉のようなもの です。 空気や言葉は、無料で誰でも使えるようにすべきだ。 という主張をして、実践し れているのが、Richard Stallmanさんが率いるFSF(Free Software Foundation) です。 GNUというのは、そういうOS・基本ソフトウェアを作るプロジェクトです。 GNUソフトウェアは、GPL(General Public License)という規定によって配布さ れて、また再配布についても規定されています。(詳細はGPLを参照して下さい。 英文です。ハイ。和訳もあったと思いますが。) GPLはよくできた規定ですので、フリーソフトウェアの作成者の方が、そのまま 自分の作成したソフトウェアのライセンス規定として使われていることもあります。 Icon入門講座や Icon日記は、【公共物のように自由に使って!】ということで、 in the Public Domainとしています。 これは、Icon自体が in the Public Domainですのと、自由に引用や編集をしてよい ようにしておけば、そのうちどなたかが、もっと良いドキュメント書いていただくのに 便利だろうと思ったためです。 さて、今回もシフトJIS関係ですが、やっとシフトJIS関係も終わりです。 findと moveをシフトJIS対応にしてみます。 jposにミスがありましたので修正 しています。 -----^ SJIS3.ICN ( date:97-03-02 time:20:56 ) --------------<cut here # SJIS関係 procedure その3 # Rev.01 1997/03/02 windy # This file is in the public domain. procedure jfind(s1,s2,i1,i2) # 文字列 s2の中の 文字列 s1が含まれる位置を生成する generator # value: 文字の先頭位置 # Rev.01 1997/03/02 windy /i1 := 1 # default if /s2 then { # default s2 := &subject i1 := &pos } /i2 := *s2 +1 # default if *s2 < *s1 then fail # 対象文字列が短すぎる。 every L := jpos(s2,i1,i2 -*s1 +1) do { # 文字を順次取り出す。 if s2[L[1] +:*s1] == s1 then { # s1が含まれるかテスト suspend L[1] } } end procedure jmove(i) # &subject の &posの位置から i文字分の文字列を生成。&posを進める。 # value: 文字列 # Rev.01 1997/03/02 windy n := 0 # 文字数カウンター pos := &pos # &pos記憶 every L := jpos(&subject,&pos,*&subject +1) do { #1文字づつ取り出し n +:= 1 # 取り出し文字数更新 if n = i then { &pos := L[2] # &pos更新 return &subject[pos : L[2]] # i文字分の文字列 } } end # SJISコードの文字列の文字の先頭位置を発生する generator # value: list [1]:先頭位置,[2]:次の文字の先頭 # Rev.03 1997/03/02 windy 範囲末手当抜け対策 # Rev.02 1997/03/02 windy 範囲指定(i1,i2)追加 # Rev.01 1997/02/27 windy, Rev.03 1997/03/02 windy procedure jpos(s,i1,i2) # write("jpos:",s,":",i1,":",i2) mode := 1 # 1バイト目(/2バイト目)モード every i := i1 to (i2 -1) do { # n := ord(s[i]) case mode of { # SJISコードの1バイト目チェック(16rは16進数を示す。) 1 : if {16r80 < n < 16rA0} | {16rDF < n < 16rFD} then { # 2バイトコード if i = i2 -1 then { # 範囲末手当 suspend [i,i+2] } else mode := 2 # ←2バイト目モードへ } else suspend [i,i+1] # 1バイトコード 2 : { # 2バイトコードの2バイト目 mode := 1 # モードを1バイト目チェックへ suspend [i-1,i+1] # 2バイトコード } } } end # test driver procedure main() #1 5 9 11 15 19 22 2628 s2 := "abcdefあいうえおかabcあいう" s1a := "abc" s1b := "いう" # write(s2) # every write(jfind(s1a,s2,1,21)) # jfind(s1,s2,i1,i2) # every write(jfind(s1b,s2,3,26)) # jfind # every write(jfind(s1b,s2,3,28)) # jfind write("jfindテスト") write("対象文字列: ",s2) write("検索文字列: ",s1a) s2 ? { # jfind while tab(p := jfind(s1a)) do { write(tab(p +*s1a)) } } write("検索文字列: ",s1b) s2 ? { # jfind while tab(p := jfind(s1b)) do { write(tab(p +*s1b)) } } write("jmoveテスト") write("対象文字列: ",s2) s2 ? { write(n := 3,"文字移動: ",jmove(n)) write(n := 5,"文字移動: ",jmove(n)) write(n := 6,"文字移動: ",jmove(n)) write(n := 4,"文字移動: ",jmove(n)) } end -----$ SJIS3.ICN ( lines:103 words:356 ) -------------------<cut here テストプログラムの実行結果です。 -----^ SJIS3.TXT ( date:97-03-02 time:20:58 ) --------------<cut here jfindテスト 対象文字列: abcdefあいうえおかabcあいう 検索文字列: abc abc abc 検索文字列: いう いう いう jmoveテスト 対象文字列: abcdefあいうえおかabcあいう 3文字移動: abc 5文字移動: defあい 6文字移動: うえおかab 4文字移動: cあいう -----$ SJIS3.TXT ( lines:14 words:22 ) ---------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: そのままの君でいて/岡本真夜 (icon_119.txt 1997/03/02 PCVAN PIG) ■ Icon > Icon日記(23) Backtracking 風つかい 目次 前にプログラム言語のリストがあると書きましたが、次のところにあります。 The Language List http://cuiwww.unige.ch/cgi-bin/langlist Free Compilers and Interpreters http://cuiwww.unige.ch/cgi-bin/freecomp 2つ目の Free Compilers and Interpreters のリストは、comp.lang.misc 他 の ニュースグループに定期的にポストされています。今は月に1回、月はじめに ポストされているようです。 データのメンテが追い付いていないようで、情報は最新ではないようです。でも、 サポートサイトやニュースグループが載っていますので、更に調べてみようと言う方 には捜す手だてがあるわけで、何かプログラム言語について調べてみようと言う方に は役に立つのではないかと思います。 私は、生まれが福岡ですので母国語は博多弁です。現在は横浜に移民して来ていま すので、第一外国語の横浜弁を使っています。 パソコンを触っていますので、パソコン弁とかMS−DOS弁とか98弁とか DOS/V弁とかも使っているかもしれません。 Unix弁は分からないことが 多いですしC弁とかPascal弁は殆どわかりません。AWK弁は大体わかります が、Perl弁は殆ど分かりません。Icon弁を、今、勉強中というところです。 プログラム言語と言っても、要するに言葉の一種ですので、日頃しゃべらないと使 えるようにはなりません。Icon日記は、私のIcon弁の練習も兼ねています。 ということで、Icon弁の練習としまして、バックトラッキングをやってみよう と思います。 ところが、バックトラッキングというものが、何故必要になるのか? 私はよく分かっていません。そこで、Icon教典(The Icon programming Language) の例にあげてある 【8クイーン】 の例を眺めてみて、 こういうことかな? と、おぼろげながら理解した範囲で、説明しようと思います。 眺めて見ると要するに ・問題を【手抜き】して解くやり方 あるいは、 ・問題を【分割】 して解くやり方 ではないかと思います。 8クイーン問題とは、8x8のチェス盤に、クイーンをお互いに取られない位置 列 に置くものです。例えば左の図は1つ 12345678 の解です。 行1Q・・・・・・・ こういう解が72通りあるそうです。 2・・・・・・Q・ クイーンは垂直・水平・対角線方向 3・・・・Q・・・ の駒を取れます。 よって1つの行に 4・・・・・・・Q はクイーンは1個だけ、1つの列にも 5・Q・・・・・・ クイーンは1個だけ。 また対角線に 6・・・Q・・・・ も1個だけということになります。 7・・・・・Q・・ 8・・Q・・・・・ で、この後どうするかというと実際に クイーンを盤面に置いていってみよう うといういうのです。 ・・・この辺が、あっ、手抜きだ〜と私が思うところな んですが。 後はCPUパワーに任せて、しらみつぶしにやって試してみよう と いう訳です。 8個のクイーンを ・1行に1個づつ、順に、置いていきます。 ・既に置いたクイーンに取られる位置しか置くところが無くなったら、1つ前 のクイーンを置くところに戻って、別の置きかたを試してみよう という訳です。 この、【置けなくなったら、1つ前へ戻って、別のやり方】というところが、 バックトラッキングということになります。 【1個づつ、順に】というところは、generatorを使うということになります。 別の言い方をすると、 ・クイーンを順に置いてみる。 水平・垂直・対角線上に、別のクイーンがいれば、1つ戻って別の位置を 試す。 ・8個のクイーンが全部置ける。 という 2つの問題に分割して、解く と言うやり方です。 実際のプログラム例では、 ・1行目にクイーンを置く。 (左端から順に試します。) ・2行目にクイーンを置く。 (1行目の下・対角線になると失敗。) ・3行目にクイーンを置く。 (1・2行目の下・対角線になると失敗。) ・以下同様に8行目迄 ですから、 ・問題の条件を2つ(以上)に分割して、 ・1つ目の条件にあうデータを実際に作って、 ・2つ目(以降)の条件に実際に合うものを選びだす。 ということかな? そういうことなら、Iconで ・ generatorでデータを作って、 ・そのデータを別の条件でチェックしてOKのものだけ出力する。 というやり方をしているものは、全部、バックトラッキングの例ということになりま すね。 なんだ、そういう単純なことなのか! 早とちりかも知れませんが。(汗) すると、前回のシフトJIS用の文字列検索 procedureの jfindで、文字列を順に 左端から、指定文字と一致するかどうか試して、一致しなければ次の位置にいくやり 方もバックトラッキングですね。 別のサンプルプログラムです。かなり、強引なサンプルですが... -----^ NAME.ICN ( date:97-03-03 time:22:57 ) ---------------<cut here # 姓と名の組み合わせ # Rev.01 1997/03/03 windy # This file is in the public domain. procedure main() L1 := ["おかもと","ゆさ","しのはら"] L2 := ["まよ","みもり","みやこ"] # 全ての組み合わせを出力する。 write("全ての組み合わせ") every write(perm(L1,L2)) # 姓・名の文字数を足して6文字以上のものだけ出力 write("Backtracking の例: 6文字以上の条件付き") every write(s := perm(L1,L2)," ", 6 <= *s/2) # ↑6文字未満だとこの項が failし # write関数も failする。 end procedure perm(L1,L2) # L1,L2の要素の全ての組み合わせを出力する suspend !L1 || !L2 end -----$ NAME.ICN ( lines:22 words:56 ) ----------------------<cut here サンプルプログラムの結果です。 -----^ NAME.TXT ( date:97-03-03 time:22:57 ) ---------------<cut here 全ての組み合わせ おかもとまよ おかもとみもり おかもとみやこ ゆさまよ ゆさみもり ゆさみやこ しのはらまよ しのはらみもり しのはらみやこ Backtracking の例: 6文字以上の条件付き おかもとまよ 6 おかもとみもり 7 おかもとみやこ 7 しのはらまよ 6 しのはらみもり 7 しのはらみやこ 7 -----$ NAME.TXT ( lines:17 words:25 ) ----------------------<cut here 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 熱くなれ/大黒摩季 (icon_120.txt 1997/03/03 PCVAN PIG) ■ Icon > Icon日記(24) Generator 風つかい 目次 窓の外で、小鳥のさえずりが聞こえます。ホ〜ホケキョ。あっ、うぐいすだ。 春ですね〜。 聞いていると、少しづつ鳴きかたを変えていますね。 まるで 練習しているみたいに聞こえます。 ジェネレータって、綴りは語尾が erではなくて、orなんですね。今まで間違 いに気づきませんでした。(汗) erと orをつける規則みたいなものがあった かしら? (このテキストでは直っています。) さて今回は、generator関係の補足です。 【選択式】 前回のサンプルプログラムで、姓名の組み合わせで6文字以上のものを、出力 しました。 6文字以上という条件をつけるために、write関数では複数の出力 指定があるときに、それらの式がすべて成功した場合にだけ write動作が行われ る。 ということを利用しています。 every write(s := perm(L1,L2)," ", 6 <= *s/2) の部分です。 姓名組み合わせ↑ ↑6文字以上の条件 これだと、姓名の組み合わせの後ろに文字数が出力されます。 これは余計な ので、文字数を出さずに済む方法はないか? と調べてみました。 複数の式が全部成功したら成功して、かつ結果の値を複数の式の中から選らぶ という表現がサポートされていました。 選択式(式1,式2,式3,...) という形式で、選択式は結果として数 字でないといけません。 全体の値は、選択式の結果が 1なら式1、 2なら式2 3なら式3となります。 そこで、6文字以上の姓名の組み合わせは、次のように指定できます。 every write(1(s := perm(L1,L2), 6 <= *s/2)) # ↑結果に2つの式 ↑6文字未満だとこの項が failし # のうち1番目を 1(...,...)式も failする。 # 使う。 すると writeも failする。 【組み込み generator】 Iconでは、組み込みの Generatorがあります。 数字を1から順に生成でき るものです。 任意数から始まる、任意数飛びの、数字列を指定できます。 seq(i1,i2) : i3,i4,... # generate sequence of integers| Generates an endless sequence of integers starting at i1 with increments of i2. 【くり返し generator】 ある generatorの出力を繰り返す指定ができます。 例えば、(1 to 3)とか (1 | 2 | 3) は、1から 3迄の数を発生する generatorですが、そのパターンを 更に何回も繰り返す場合です。 |(1 to 3) という表記で、 1 2 3 1 2 3 1 2 3 ... というような generatorの指定ができます。 |1 としますと、 1 1 1 1 1 1 1 1 1 ... ということになります。 【generator の生成数限定】 seq()関数やくり返し generatorが、延々出力を続けたら、いつプログラムが 終わるんだろう? と思われるかも知れませんが、 ・その generatorを呼んでいる procedureが failまたは、終了すると終わ ります。 再度呼びますと続きから生成していきます。 ・生成数の限定ができます。 seq() \10 としますと、10個だけ生成されます。すなわち1から 10迄の数字が生成されます。 every write(|(0 to 7) \16) としますと、0から7の数字を2回 生成します。 PCVANの書込みタイトルリストのサンプルデータを生成するプログラムを を次に示します。 こんなデータを生成するものです。 -----^ TL9612.TXT ( date:97-03-20 time:23:11 ) -------------<cut here 1 93/09/01 タイトル一覧サンプルデータ 2 93/09/01 タイトル一覧サンプルデータ 3 93/09/01 タイトル一覧サンプルデータ (中略) 2748 96/12/01 タイトル一覧サンプルデータ 2749 96/12/01 タイトル一覧サンプルデータ 2750 96/12/01 タイトル一覧サンプルデータ -----$ TL9612.TXT ( lines:2750 words:8250 ) ----------------<cut here プログラムです。 seq()を使っています。 -----^ TITLE.ICN ( date:97-03-09 time:19:58 ) --------------<cut here # PCVANの書込みタイトル一覧サンプルデータ作成 # 書込み数はサインカーブ風に変化させる。 # Rev.01 1997/03/08 windy Rev.02 1997/03/09 終了判定修正 # This file is in public domain. procedure main() n_max := 120 # 書込み数max値 n_div := 24 # サインカーブの抜取り分割数 n_init := 1 # メッセージ番号初期値 YYMM := "9309" # 開始月 YYMM_end := "9702" # 終了月 s_title := "タイトル一覧サンプルデータ" # タイトルサンプルデータ YYMM_end2 := inc_month(YYMM_end) every num_msg := sin_data(n_max,n_div) do { # サインカーブ風データ取得 gen_title(n_init,YYMM,s_title,num_msg) # ひと月分データ出力 YYMM := inc_month(YYMM) # 月をひと月進める if YYMM == YYMM_end2 then fail # 終了判定 } end procedure gen_title(n_init,YYMM,s_title,num_msg) # ひと月分の書込みタイトル # タイトルサンプル↓ #1 7 8 #1007 96/10/13 Icon >月別書き込み数集計 風つかい # 初期メッセージNo :n_init # 初期メッセージ年月 :YYMM (日付は、YY年MM月01日) # メッセージタイトル :s (皆同じ) # 月当たりメッセージ数:num_msg static msg_no initial { # 最初に呼ばれた時、1回だけ実行 msg_no := n_init -1 } if num_msg = 0 then return # 書込み数 0 every 1 to num_msg do { # タイトル出力 write(right(msg_no +:=1,4)," ",YYMM[1:3],"/",YYMM[3:5],"/01 ",s_title) } return end procedure sin_data(n_max,n_div) # データ数生成部 # 初期値:n_max/2 、最大値:n_max、最小値:0 のサインカーブを n_div個に # 分けた位置のデータを作成する generator # n_max : 最大値 # n_div : サインカーブの360度分を何分割するか suspend integer(n_max * (1.0 +sin( 2.0*&pi * (seq() -1)/ n_div))/2) #↑順列作成 1〜 end procedure inc_month(YYMM) # 年月データ +1月 yy := numeric(YYMM[1:3]) ; mm := numeric(YYMM[3:0]) # 年月を数字に変換 if mm = 12 then { yy +:= 1 ; mm := 1 } # 計算 else { mm +:= 1 } return right(string(yy),2,"0") || right(string(mm),2,"0") end -----$ TITLE.ICN ( lines:57 words:216 ) --------------------<cut here (追記:ミス修正のため差し替え) 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 瞳水晶/遊佐未森 (icon_121.txt 1997/03/08 PCVAN PIG) ■ Icon > Icon日記(25) 5クイーン(1) 風つかい 目次 今日の日食は20世紀では最後だそうです。 今朝、久しぶりに眺めてみま した。 小学校の授業で眺めて以来かな。 その時は、ガラスの破片にろうそく のすすをつけて眺めました。 そう思って家中見渡しても、ガラスの破片なんかありませんので、透明な食品 ケースにろうそくですすをつけました。ケースは熱でべこべこになりましたが、 太陽を透かして見るのにはあまり問題はありませんでした。 透かして見ると太陽って小さいんですね〜。でも、下弦の形に月で影ができて いる太陽がハッキリ見えました。 次は、2002年だそうです。 では、今日はバックトラッキングで使う Reversible assignment(戻し可能な 代入)を取り上げます。 Iconではバックトラッキングのしかけがありますが、プログラム制御だけでな くデータの代入もバックが可能です。 8クイーンを例にとります。 8個のクイーンを、1個目から順に置いてくの ですが、あるクイーンを置こうとして置けなくなったら、1つ前のクイーンを置 く場面へ戻って、置き直します。 置けるか置けないかを判定するためには、それ迄に置いたクイーンの位置を覚 えておく必要があります。 すると、置き直しをする場合は、覚えていたそれ迄に置いたクイーンの位置を、 戻った場面で置く前の状態に戻す必要があります。 Iconでは代入の記号は、:= ですが、この戻し可能は代入を行いたいときは <- を使います。 交換 :=: も戻し可能な交換 <->が用意されています。 クイーンの数が多いと例題のコメントが面倒になりますので、5つに減らして 5クイーンでやります。 まず、<-を使わない5クイーンプログラムです。 5クイーンの解を書き出し ます。 大まかな考え方は前のお話ししていますので、コメントで動作はご理解 いただけるのではないかと思います。 クイーンの置き直しは、suspend ... do ...の構文を使っています。 suspend の後に do をつけると、上位 procedure呼ばれてあるデータを返して、再びその 上位 procedureから呼ばれて動作を行う前に、 do 以降の処理を行います。 この例では、do のところで、直前に置いたクイーンを戻して(置かない状態) います。 -----^ 5QUEEN1A.ICN ( date:97-03-09 time:15:15 ) -----------<cut here # 5クイーンの解の書き出し # 5x5のチェス盤に5個のクイーンを互い取られない位置に置く。 # Rev.01 1997/03/09 windy # This file is in the public domain. # Icon教典(The Icon Programming Language)の8クイーンプログラムに # 手を加えたもの。 # # 行・列の番号 右上がり対角線 右下がり対角線 # 列→(colum) 番号→ ←番号 # 1 2 3 4 5 1 2 3 4 5 5 4 3 2 1 # 行 1Q・・・・ Q//// 6 6 Q\\\\ # ↓ 2・・Q・・ //Q// 7 7 \\Q\\ # (row) 3・・・・Q ////Q 8 8 \\\\Q # 4・Q・・・ /Q/// 9 9 \Q\\\ # 5・・・Q・ ///Q/ \\\Q\ # # 上の図のように置き終わった状態では、 # 行 右上がり対角線 右下がり対角線 # row 12345 up 123456789 down 123456789 # col "13524" col "1..32.54." col "..53142.." # procedure main() # クイーンが1行から5行まで全て置けたら、列位置を順に書き出す。 # q(1),...,q(5)が全て成功しなければ writeは失敗する。 every write(q(1)," ",q(2)," ",q(3)," ",q(4)," ",q(5)) write() end procedure q(r) # r番目の行のクイーンを、1〜5列に置いて試すためのジェネレータ suspend place(r,1 to 5) end procedure place(r,c) # クイーンを置いてみる。置けないと失敗。置けると列位置を返す。 # 置き直しに suspend ... do を使用。 static up,down,col # 既に置かれたクイーンを記憶。 # 列位置と影響する対角線2方向の位置を記憶する。 initial{ # 初期値(クイーンを何処にも置いていない状態) up := repl(".",9) # 右上がり対角線管理 down := repl(".",9) # 右下がり対角線管理 col := repl(".",5) # 列番号管理 } if col[c] == up[r + c -1] == down[5 - c + r] == "." # ↑r行c列に置けるかのチェック(全部 "."ならあいている。) then { suspend col[c] := up[r + c -1] := down[5 - c + r] := c do # ↑ c番目の列にクイーンを置く。 ↑続行時の処理 # 置いた列・右上がり対角線・右下がり対角線 cを代入している。 ↓ # 置いたことを示すだけなら "."以外の文字ならなんでも良いが、 ↓ # 戻り値を列番号にするために cを代入。 ↓ col[c] := up[r + c -1] := down[5 - c + r] := "." # ← # ↑ c番目からクイーンを取り去る。 # do の後の式は、続行する際に実行される。 # 続行は、次のクイーンが置けなかった時、または全部のクイーンが置けた # 時に起こる。 } end -----$ 5QUEEN1A.ICN ( lines:60 words:240 ) -----------------<cut here 結果は、次の10通りです。1つの解が1行になっています。 各行は先頭か ら順に1行目のクイーンを置く列、2行目のクイーンを置く列、...となっ ています。 -----^ 5QUEEN1A.TXT ( date:97-03-09 time:15:18 ) -----------<cut here 1 3 5 2 4 1 4 2 5 3 2 4 1 3 5 2 5 3 1 4 3 1 4 2 5 3 5 2 4 1 4 1 3 5 2 4 2 5 3 1 5 2 4 1 3 5 3 1 4 2 -----$ 5QUEEN1A.TXT ( lines:11 words:50 ) ------------------<cut here だいぶ長くなりましたので、これ以降は別の書込みとします。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: そのままの君でいて/岡本真夜 (icon_122.txt 1997/03/09 PCVAN PIG) ■ Icon > Icon日記(26) 5クイーン(2) 風つかい 目次 Iconでは、upto,findの関数や generatorのように、条件に合ったデータを探 し出すしかけが設けられています。 条件に合わないデータは無視して、必要なデータだけを取り出すしかけが用意 されています。 Icon教典ではこのしかけを、"Goal-Directed Evaluation" と呼んでいます。 日本語に直訳すると、「ゴールを目指した評価」となるのでしょうが、長いので ここは短く、 「イケイケ評価」 と呼びたいところです。 では、5クーンのつづきです。 Reversible assignment <-を使った5クイーンプログラムです。 -----^ 5QUEEN1B.ICN ( date:97-03-09 time:15:17 ) -----------<cut here # 5クイーンの解の書き出し # Rev.01 1997/03/09 windy # 5queen1a.icn の置き直しに reversible assignment <-を使用したもの。 # This file is in the public domain. # procedure main() # クイーンが1行から5行まで全て置けたら、列位置を順に書き出す。 every write(q(1)," ",q(2)," ",q(3)," ",q(4)," ",q(5)) write() end procedure q(r) # r番目の行のクイーンを、1〜5列に置いて試すためのジェネレータ suspend place(r,1 to 5) end procedure place(r,c) # クイーンを置いてみる。置けないと失敗。置けると列位置を返す。 # 置き直しに reverseible assignment <-を使用。 static col,up,down # 既に置かれたクイーンを記憶。 initial{ # 初期値(クイーンを何処にも置いていない状態) up := repl(".",9) # 右上がり対角線管理 down := repl(".",9) # 右下がり対角線管理 col := repl(".",5) # 列番号管理 } if col[c] == up[r + c -1] == down[5 - c + r] == "." # ↑r行c列に置けるかのチェック(全部 "."ならあいている。) then { suspend col[c] <- up[r + c -1] <- down[5 - c + r] <- c # ↑ c番目の列にクイーンを置く。 # 置いた列・右上がり対角線・右下がり対角線 cを代入している。 # reversible assignment <- は、続行時に、前に置いたクイーンを # 取り去るため使う。 } end -----$ 5QUEEN1B.ICN ( lines:35 words:124 ) -----------------<cut here 数字で出すだけでは面白くないので、図を出してみます。 -----^ 5QUEEN1C.ICN ( date:97-03-09 time:14:59 ) -----------<cut here # 5クイーンの解の書き出し # Rev.01 1997/03/09 windy # Icon教典(The Icon Programming Language)の8クイーンを5クイーンにした # 5queen1b.icn に、チェス盤表示をつけたもの。 procedure main() L := [] # 解を格納するリスト # クイーンが1行から5行まで全て置けたら、リストに格納。 every put(L,q(1) || q(2) || q(3) || q(4) ||q(5)) show_board(L) # 解の書き出し end procedure show_board(L) # 5クイーンの解の書き出し n := 0 # 解番号初期値 -1 while s := get(L) do { # リストから解を取り出す。 write("解 ", n +:= 1) # 解番号 write(" 1 2 3 4 5") # 列番号目盛り every i := 1 to 5 do { # 行 writes(" ",i) # 行番号目盛り every j := 1 to 5 do { # 列 writes( if j = numeric(s[i]) then "Q" else "・") # ますの状態 } write() } write() } end procedure q(r) suspend place(r,1 to 5) end procedure place(r,c) static up,down,col # 既に置かれたクイーンを記憶。 initial{ # 初期値(クイーンを何処にも置いていない状態) up := repl(".",9) # 右上がり対角線管理 down := repl(".",9) # 右下がり対角線管理 col := repl(".",5) # 列番号管理 } if col[c] == up[r + c -1] == down[5 - c + r] == "." then suspend col[c] <- up[r + c -1] <- down[5 - c + r] <- c end -----$ 5QUEEN1C.ICN ( lines:42 words:174 ) -----------------<cut here こういう解がでてきます。 -----^ 5QUEEN1C.TXT ( date:97-03-09 time:15:19 ) -----------<cut here 解 1 1 2 3 4 5 1Q・・・・ 2・・Q・・ 3・・・・Q 4・Q・・・ 5・・・Q・ 解 2 1 2 3 4 5 1Q・・・・ 2・・・Q・ 3・Q・・・ 4・・・・Q 5・・Q・・ (中略) 解 10 1 2 3 4 5 1・・・・Q 2・・Q・・ 3Q・・・・ 4・・・Q・ 5・Q・・・ -----$ 5QUEEN1C.TXT ( lines:80 words:120 ) -----------------<cut here Iconのライブラリーには、nクイーン(nxnのチェス盤にn個置く)のプロ グラムが入っています。 BIPLにはテキスト表示版、GIPLにはグラフィック表示版が入っています。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: そのままの君でいて/岡本真夜 (icon_123.txt 1997/03/09 PCVAN PIG) ■ Icon > Icon日記(27) Wicon ベータ8 風つかい 目次 TVで日食とヘール・ボップ彗星の解説をしていました。乗りやすいたちですの で本屋で天文雑誌を買ってきまして、ヘール・ボップ彗星の記事を読んでみました。 今の時期(3月上・中旬)ですと、早朝4時〜5時頃に東の空に見えるとありま す。 下旬になると夕方の6時〜7時頃に見えるとあります。 という記事を読んだせいか、何故か今朝4時に目がさめました。 外へ出て見ると街あかりで星は殆ど見えないのですが、東の空にそれらしき星が 見えました。 他の星はくっきりしているのに、その星は縦長にぼやけて見えましたので、多分 ヘール・ボップ彗星だろうと思います。 そうだとしますと相当明るいですね〜。 記事では、推定サイズ 10〜20kmの氷とちりのかたまり 推定質量 5兆トン となっていました。 ひぇ〜。 莫大な大きさですね〜。 ふと、地球のサイズが気になりましたので調べましたら、 直径 12756km 質量 60億・兆トン(6x10^24kg) でしたので、約10億分の1の質量ですね。 少し安心しましたが、シューメーカ・レビ彗星が木星に激突した例もあります。 2年後にこんなものが地球にぶつかると、ノストラダムスの大予言が当たってし まうんですね。 さて、アリゾナ大にアクセスしてみましたら、Windows対応 Iconがβ8にバージ ョンアップされていました。 そのうちに getしてまた試してみたいと思います。 次のところにあります。 ご興味のある方はアクセスしてみて下さい。 ftp://ftp.cs.arizona.edu/icon/beta/windows/ READ.ME 3 Kb Thu Mar 06 20:21:00 1997 docs.zip 38 Kb Thu Mar 06 20:12:00 1997 Zip Compressed Data gprocs.zip 500 Kb Thu Mar 06 20:12:00 1997 Zip Compressed Data iconhelp.zip 144 Kb Thu Mar 06 20:13:00 1997 Zip Compressed Data keysyms.icn 3 Kb Thu Mar 06 20:23:00 1997 procs.zip 338 Kb Thu Mar 06 20:16:00 1997 Zip Compressed Data vib.zip 122 Kb Thu Mar 06 20:18:00 1997 Zip Compressed Data vibsrc.zip 260 Kb Thu Mar 06 20:18:00 1997 Zip Compressed Data wi.icn 14 Kb Thu Mar 06 20:23:00 1997 wi.zip 53 Kb Thu Mar 06 20:19:00 1997 Zip Compressed Data wicon.zip 338 Kb Thu Mar 06 20:20:00 1997 Zip Compressed Data 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 愛の言霊/サザン・オールスターズ (icon_124.txt 1997/03/11 PCVAN PIG) ■ Icon > Icon日記(28) idump2.icn 風つかい 目次 ヘール・ボップ彗星の情報で、書き落としがありました。 風つかい>今の時期(3月上・中旬)ですと、早朝4時〜5時頃に東の空に見え 風つかい>るとあります。下旬になると夕方の6時〜7時頃に見えるとあります。 中旬は、早朝は東の空に、夕方には西の空に、見えるのですが、みづらいそう です。 下旬は夕方に西の空に見えるそうです。 下旬になると見易いみたいですね。 ところで、以前、地球の重量は60億・兆トンと書きました。 理科年表に載っ ていたのですが、どうやって計るんでしょうね。 何をはかりにするんだろう。 さて、今回は、前に作ったヘキサダンプのプログラムに、印字可能なコードは 印字する機能を追加してみました。16バイト目で、2バイト文字が泣き別れに なるのはいやらしいので、その場合はもう1バイト出力するようにしました。 -----^ IDUMP2.ICN ( date:97-03-17 time:02:08 ) -------------<cut here # ファイルのヘキサダンプ/印字可能文字は印字 # 16バイト単位でダンプ。16バイト目が、2バイト文字の1バイト目の時は # 次の16バイトの先頭文字を、その後にくっつけて印字。 # This file is in the public domain. # Rev.02 1997/03/17 windy 先頭文字の印字文字が欠ける問題の修正 # Rev.01 1997/03/16 windy link hexcvt, sjis4 procedure main(args) Usage := "idump2 input_file > output_file" title1 := "offset +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f" title2 := " : " title3 := "0123456789abcdef0" title := title1 || title2 || title3 s := "" # ファイル一気読み込みバッファ c1 := "." # 印字不可文字を置換する文字 c2 := ">" # 2バイト文字の2バイト目が16バイト区切りの先頭に # 来たとき置換する文字 byte_count := 0 L := [] if *args[1] >1 then f_name := args[1] else stop(Usage) # ファイルオープン dir := open(f_name,"ru") | stop("cannot open ",f_name) # ↑読込・改行非変換モード #ファイル読み込み(ファイルはメモリーへ一気読み。) while s ||:= reads(dir,256) # ↑バイナリー読み込み関数。256byte単位指定。←いい加減な値 # ダンプ処理 write(title) # タイトル印字 every L := jcpos(s) do { # 文字列から取り出し if byte_count % 16 = 0 then { # 16バイト毎手当 if byte_count > 0 then { # 最初の文字でなければ if L[3] == "M" then { # 2バイト文字の2バイト目 s2 ||:= L[2] # 前の行へくっつける write(s1,title2,s2) # 出力 s2 := c2 # 印字文字バッファセット } else { # 2バイト文字の2バイト目以外 write(s1,title2,s2) # 出力 s2 := "" || # 印字文字バッファセット if L[3] == ("C" | "U") # 印字不可文字手当 then c1 else L[2] } } else { # 最初の文字なら s2 := "" || # 印字文字バッファセット if L[3] == ("C" | "U") # 印字不可文字手当(Rev.02) then c1 else L[2] # (Rev.02) } s1 := hexstring(byte_count,7,"") || " " # アドレス・ヘキサバッファ #↑バイト番号を7桁の16進数表記に変換。 writes(&errout,c2) # 動作モニター } else { # 16バイト区切り以外 s2 ||:= if L[3] == ("C" | "U") # 印字不可文字手当 then c1 else L[2] } s1 ||:= " " || hexstring(ord(L[2]),2,"") # ヘキサ変換→足し込み #↑文字を文字番号に変換し、2桁の16進数表記に変換。 byte_count +:= 1 } # 文字列の最後が16バイト区切りに不足の時の処理 if *s1 > 0 then write(left(s1,*title1),title2,s2) write(&errout) # CRTカーサを左端へ end # hexstring(i,n,lowercase) は、ライブラリーBIPLの hexcvt.icn に含まれる関数。 # 10進数 iを16進数表記に変換する。nは桁数。3番目のパラメータに何か入れる # と a-fは小文字(デフォルトは A-Fは大文字)。 -----$ IDUMP2.ICN ( lines:68 words:292 ) -------------------<cut here (追記:ミス修正のため差し替え) SJISコード文字列混じりのバイナリーファイル処理のための procedureです。 -----^ SJIS4.ICN ( date:97-03-16 time:18:54 ) --------------<cut here # SJIS関係 procedure その4 # Rev.01 1997/03/16 windy # This file is in the public domain. #link hexcvt # テスト用 # コントロールコード混じりのSJISコード文字列の 1byte毎の先頭位置、 # 文字、文字種別 を発生する generator # value: list [1]:先頭位置, [2]:文字, [3]:文字種別 # 文字種別 "C": コントロールコード "A": ASCII # "K": 1byteカナ "L": 2byte文字の 1byte目 # "M": 2byte文字の 2byte目 "U": 未定義文字 procedure jcpos(s) /s := &subject # デフォルト mode := 1 # 1バイト目(/2バイト目)モード every i := 1 to *s do { # 文字列 sから 1byteづつ取り出す。 case mode of { 1 : case sjis_zone(s[i]) of { # SJISコードの1バイト目チェック 1 : suspend [i,s[i],"C"] 2 | 3 : suspend [i,s[i],"A"] 7 : suspend [i,s[i],"K"] 6 | 8 | 9 : { if i = *s then suspend [i,s[i],"U"] # ←文字列末尾チェック # ↓2バイト文字の1バイト目なら、次の文字をチェック else { if sjis_zone(s[i +1]) = (3 | 5 | 6 | 7 | 8 | 9) then { # 2バイト目となれるコード mode := 2 # 2バイト目モードセット suspend [i,s[i],"L"] # 2バイト文字1バイト目 } else suspend [i,s[i],"U"] # 未定義文字 } } default : suspend [i,s[i],"U"] # 未定義文字 } 2 : { # 2バイト文字の2バイト目 mode := 1 # 1バイト目モードセット suspend [i,s[i],"M"] # 2バイト文字2バイト目 } } } end procedure sjis_zone(c) # SJISコード文字の分類のためコード範囲チェックを行う。 # ↓文字コード分類用定数 1byte文字 または # (16rは16進数を示す) 2byte文字の1byte目 2byte目 # ------------------ ------- # 16r00 # 1: 16r00 - 16r1F コントロールコード - L := [16r20, # 2: 16r20 - 16r3F ASCII - 16r40, # 3: 16r40 - 16r7E ASCII 2byte目 16r7F, # 4: 16r7F - - 16r80, # 5: 16r80 - 2byte目 16r81, # 6: 16r81 - 16r9F 2byte文字の1byte目 2byte目 16rA0, # 7: 16rA0 - 16rDF 1byteカナ文字 2byte目 16rE0, # 8: 16rE0 - 16rEF 2byte文字の1byte目 2byte目 16rF0, # 9: 16rF0 - 16rFC 2byte文字の1byte目 2byte目 16rFD] #10: 16rFD - 16rFF - - return zone_chk(ord(c),L) end procedure zone_chk(n,L) # 数字 nをリスト L内の数字によって示される範囲によってよって分類 # Lには、昇順の数字が範囲の区切りとして、入っていること。 # value : 例えば、リストに3個の数字がはいっているとすると # 1: n < L[1], 2: L[1] <= n < L[2], 3: L[2] <= n < L[3], 4: L[3] <= n every i := 1 to *L do { # リストから比較数を順次取り出し if n < L[i] then return i # 比較数より小さければ、比較数番号 } # を返す。 return i +1 # リストの末尾の数字より大きい end # jcpos test #procedure main() # s := "\x00\x01\x1f abアイウあいう\x7f\x80\xe0\xf0\xff\xfc" # write("jcpos test") # every L := jcpos(s) do { # # ↓16進表示へ変換 # write(L[1]," ",hexstring(ord(L[2]),2,"")," ",L[3]) # } #end -----$ SJIS4.ICN ( lines:81 words:369 ) --------------------<cut here idump2 idump2.icn > idump2.txt とした時の結果です。 -----^ IDUMP2.TXT ( date:97-03-21 time:00:23 ) -------------<cut here offset +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f : 0123456789abcdef0 0000000 23 20 83 74 83 40 83 43 83 8b 82 cc 83 77 83 4c : # ファイルのヘキ 0000010 83 54 83 5f 83 93 83 76 81 5e 88 f3 8e 9a 89 c2 : サダンプ/印字可 0000020 94 5c 95 b6 8e 9a 82 cd 88 f3 8e 9a 0d 0a 23 20 : 能文字は印字..# (中略) 0000c10 b6 8e 9a 81 69 83 66 83 74 83 48 83 8b 83 67 82 : >字(デフォルトは 0000c20 cd 20 41 2d 46 82 cd 91 e5 95 b6 8e 9a 81 6a 81 : > A-Fは大文字)。 0000c30 42 0d 0a 1a : >... -----$ IDUMP2.TXT ( lines:197 words:3937 ) -----------------<cut here (追記 データ差し替え) 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 海になりたい青/篠原美也子 (icon_125.txt 1997/03/16 PCVAN PIG) ■ Icon > Icon日記(29) Record 風つかい 目次 そろそろ、天気予報で桜前線の話がでる頃ですね。 前線と言えば、前線は暖かい空気と冷たい空気の境目で、目には見えないと 思っていたのですが、実際に見えることもありますね。 新幹線で大阪〜東京間を移動中に、ふと景色をみると、空が斜めに2つに分 かれているんですね。 晴れた空に小さな雲が斜めに並んでいるんです。 壁のようになっています。 うまく表わせないのですが、真横から見ますと、下の図みたいになっていま す。 %の所に小さい巻雲みたい雲が一面に発生していて、境目がくっきり分か りました。 % % % % % % なんだろう? と思ったんですが、あっ、これが前線か! と感動しました。 もう20年位前の事ですが、それ以来同じ現象はみたことはありません。 さて、今回は、Icon日記の(たぶん)最後の話題、Recordです。 使い道がよく分かっていないのですが、とりあえずサンプルを。 -----^ PLANET.ICN ( date:97-03-18 time:01:15 ) -------------<cut here # Record のテスト # 太陽系の惑星 record planet(jname,long,rad,math) # janame: 日本名 long:太陽からの距離(億km) # rad : 半径(千km) math: 質量(地球を 1として。 5.974 x 10^24 kg) procedure main() # 日本名 距離 半径 質量 # 億km 千km /Earth Mercury := planet("水星", 0.58, 2.44, 0.06) # Mercuryの定義 Venus := planet("金星", 1.08, 6.05, 0.82) Earth := planet("地球", 1.50, 6.38, 1.0 ) Mars := planet("火星", 2.28, 3.40, 0.11) Jupiter := planet("木星", 7.78, 71.49, 317.83) Saturn := planet("土星", 14.29, 60.27, 95.16) Uranus := planet("天王星", 28.75, 25.56, 14.54) Neptune := planet("海王星", 45.04, 24.76, 17.15) Plute := planet("冥王星", 59.15, 1.14, 0.01) write("Record の要素の指定法1") write(Mercury.jname," ",Mercury.long," ",Mercury.rad," ",Mercury.math) write("Record の要素の指定法2") write(Venus[1]," ",Venus[2]," ",Venus[3]," ",Venus[4]) # Earthの全要素の順次取り出し write("Record の全要素の順次取り出し") every writes(!Earth," ") ; write() write("サイズ") write(*Mars) end -----$ PLANET.ICN ( lines:29 words:113 ) -------------------<cut here planet > planet.txt とした時の結果です。 -----^ PLANET.TXT ( date:97-03-18 time:01:17 ) -------------<cut here Record の要素の指定法1 水星 0.58 2.44 0.06 Record の要素の指定法2 金星 1.08 6.05 0.82 Record の全要素の順次取り出し 地球 1.5 6.38 1.0 サイズ 4 -----$ PLANET.TXT ( lines:8 words:20 ) ---------------------<cut here プログラムのトップで、record宣言をします。 この例では、planetという タイプのレコード構造があると宣言しています。 そしてその要素は、jname,long,rad,mathであると宣言しています。 その上で、main()の procedureの中で、具体的に太陽系の惑星の定数を代入し ています。 例えば、Murcuryは、"水星",0.58,2.44,0.66 の要素を持つとして しています。 その後では、Murcuryの要素のアクセスに Mercury.jname とか Mercury.long とか の表記が可能となります。 なお、リストと同じように要素番号でもアクセスできます。 また要素の順次 取り出し、サイズ(要素数)指定もリストと同じようにできます。 リストとの違いは、要素の指定に名前が使えるという点くらいみたいですね。 そうそう、recordのスコープ(有効範囲)は、global(全域)です。 リストとあまり、変わらないということで、次のようなプログラムでも同じ結果を 得ることができます。 -----^ PLANET2.ICN ( date:97-03-18 time:01:43 ) ------------<cut here # Recordの代わりにリストを使ったもの # 太陽系の惑星 procedure main() jname := 1 ; long := 2 ; rad := 3 ; math :=4 # 日本名 距離 半径 質量 # 億km 千km /Earth Mercury := ["水星", 0.58, 2.44, 0.06] # Mercuryの定義 Venus := ["金星", 1.08, 6.05, 0.82] Earth := ["地球", 1.50, 6.38, 1.0 ] Mars := ["火星", 2.28, 3.40, 0.11] Jupiter := ["木星", 7.78, 71.49, 317.83] Saturn := ["土星", 14.29, 60.27, 95.16] Uranus := ["天王星", 28.75, 25.56, 14.54] Neptune := ["海王星", 45.04, 24.76, 17.15] Plute := ["冥王星", 59.15, 1.14, 0.01] write("要素の指定法1") write(Mercury[jname]," ",Mercury[long]," ",Mercury[rad]," ",Mercury[math]) write("要素の指定法2") write(Venus[1]," ",Venus[2]," ",Venus[3]," ",Venus[4]) # Earthの全要素の順次取り出し write("の全要素の順次取り出し") every writes(!Earth," ") ; write() write("サイズ") write(*Mars) end -----$ PLANET2.ICN ( lines:27 words:107 ) ------------------<cut here recordは、いまいち、メリットがわかりません。(汗) 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: 愛よりも激しく、誰よりも愛しく/Favorite Blue (icon_126.txt 1997/03/18 PCVAN PIG) ■ Icon > Icon日記(30) むすび 風つかい 目次 Iconのプログラム解説と雑記帳が混ざった Icon日記でしたが、generatorの解説が 一応できたところで、Icon日記を終わります。 generatorを使ってみると、Iconは確かにテキスト(文章)処理言語だという気が します。 Iconはテキストファイルを、1文字(=1バイト)づつ処理していきます。 その次に、1文字の集まりの 単語やデータ の処理という構成を取ります。 ですから、日本語のような複数バイトで1文字を構成する言語に対しても、ユーザ が、日本語対応の procedureを容易に構成できます。 この時 generatorが活躍しま す。 一方、AWKですと、行が基本処理単位で、行をFS(Field Separater)で分割して、 単語やデータを取り出して処理します。 そのため、行をデータのかたまりとして処理するときは非常に便利です。 表の 形式のデータ処理なんかは得意ですよね。 しかし、テキストデータを ・1文字づつ処理 しようとしたり、 ・文章を頭からなめて文字や単語の出現順に何かの処理 を加える というような処理では、逆に不便になります。 勿論、AWKでもやればできる訳で、 ・1文字づつの切り出しも substr関数で、 ・単語の出現順の処理も 単語をキーとして出現位置を連想配列に格納すれば、 できます。 でも結構、無理をしているという気がしていました。 こういう場合は Iconが向い ていると思います。 AWKでは、まず行ありき。 Iconでは、まず文字ありき。 と感じます。 ところで、Iconの道はまだまだ続いています。テキスト解析言語と紹介しておきな がら、テキスト解析という程のプログラムを未だ書いていないんですね〜。 コンパイラを書こうと迄は言いませんが、せめてアセンブラ位は書いてみたいです。 グラフィック機能もまだ手がついていません。 その辺は、次のシリーズで研究してみたいと思います。 というところで、ひとまず Icon日記を終わります。長文にお付き合い頂きまして、 ありがとうございました。 気がつけば、もう春。 風つかい (TRA11936@pcvan.or.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html > BGM: エロティカ・セブン/サザン・オールスターズ (icon_128.txt 1997/03/20 PCVAN PIG)