[Mew-dist 05605] Re: b47

Shun-ichi GOTO gotoh at example.com
1998年 7月 19日 (日) 02:45:50 JST


後藤@太陽計測です

>>>>> From: Kazu Yamamoto (山本和彦) <kazu at example.com>
kazu> さっきは時間がなかったので答えられませんでした。確かにちょっと分りにく
kazu> いですね。では解説を兼ねて、眠くなるための呪文を唱えてあげましょう。

なんだか面白そうなので、挑戦しました。

#え、マジにやるなって?
#眠くなるどころか、今日1日が充実してしまいました。


kazu> 100 点を取れる修士学生はどれくらい日本にいるか?

どんなもんスかねぇ (-_-;


P.S.
個人的にはSubject:は可能な限り可読であって欲しい。。。かな


--- Regards,
 Shun-ichi Goto  <gotoh at example.com>
   R&D Group, TAIYO Corp., Tokyo, JAPAN

-------------- next part --------------
kazu> (問1) 下記の Subject: に対する最適な符号化を示し、その理由を述べよ。
kazu> ただし、"<o>" はウムラウト文字を表す。[10 点]

理由は省略 :-)
またFoldingは考慮していない

kazu> 	m<o>tley crue が好き

=?iso-8859-1?Q?m=F6tley?= crue =?iso-2022-jp?B?GyRCJCw5JSQtGyhC?=

kazu> 	m<o>tley crueが好き

=?iso-8859-1?Q?m=F6tley_crue?= =?iso-2022-jp?B?GyRCJCw5JSQtGyhC?=
or
=?iso-2022-jp-2?B?bRsuQRtOdnRsZXkgY3J1ZRskQiQsOSUkLRsoQg==?=


kazu> 	m<o>tley crue "が好き"

=?iso-8859-1?Q?m=F6tley?= crue =?iso-2022-jp?B?IhskQiQsOSUkLRsoQiI=?=

kazu> 	m<o>tley crue"が好き"

=?iso-8859-1?Q?m=F6tley_crue"?= =?iso-2022-jp?B?GyRCJCw5JSQtGyhCIg==?=
or
=?iso-2022-jp-2?B?bRsuQRtOdnRsZXkgY3J1ZSIbJEIkLDklJC0bKEIi?=

kazu> 	m<o>tley "crue が好き"

=?iso-8859-1?Q?m=F6tley?= "crue =?iso-2022-jp?B?GyRCJCw5JSQtGyhCIg==?=



-------------- next part --------------
kazu> (問2) 問1 で答えた符号化パターンを選択する評価アルゴリズムを示せ。[20点]

まず、field-bodyを「エンコード不要」な部分と「要エンコード」な部分に分割
することを考える。
これにあたり、RFC2047での空白の保存問題に着目する必要があるため、
まず、field-bodyの構成要素を、LWSPのみで構成される文字列SPACEと
それ以外の文字列で構成されるWORDで分割するものとする。WORDには
エンコード不要なAWORDとそれ以外のもの(エンコードが必要)EWORDとが
存在する。

以下のルール(yacc風)を順次適用しSPACE、AWORD、EWORDの並びを
APARTおよびEPARTの並びに変換する(ただし、BOLは行頭、EOLは行末を
あらわすものとする)。
この結果、EPARTとAPARTが単一か、あるいは交互に現れ、EPARTとAPARTの
隣接においては隣接部には必ずLWSPが保証される。


EPART : EWORD                   /* r.1 */
      | AWORD EPART             /* r.2 */
      | EPART EPART             /* r.3 */
      | EPART SPACE EPART       /* r.4 */
      | BOL SPACE EPART         /* r.5 */
      | EPART SPACE EOL         /* r.6 */
      ;

APART : BOL AWORD EOL           /* r.7 */
      | SPACE AWORD SPACE       /* r.8 */
      | APART SPACE AWORD SPACE /* r.9 */
      | BOL SPACE APART         /* r.10 */
      | APART SPACE EOL         /* r.11 */
      ;


field-bodyをEPARTとAPARTへ分割した後、EPARTのエンコードを行う。
エンコードには2つのルールがあり、iso-2022-jpとiso-8859-1を
単一のiso-2022-jp-2としてエンコードする方法と、個々にエンコードする
方法である。1つのEPARTを複数のencoded-wordに分割する際は
LWSPで区切る。

以上//


問1の例を元にこの操作を行った例を以下に示す。


(1) m<o>tley crue が好き

   "m<o>tley" " " "crue" " " "が好き"
   == EWORD SPACE AWORD SPACE EWORD
   => EPART SPACE AWORD SPACE EWORD   /* r.1 */
   => EPART SPACE AWORD SPACE EPART   /* r.1 */
   => EPART APART EPART               /* r.8 */
   == "m<o>tley" " crue " "が好き"
   => iso-8859-1  "m<o>tley"
      ascii       " crue "
      iso-2022-jp "が好き"
   => "=?iso-8859-1?Q?m=F6tley?= crue =?iso-2022-jp?B?GyRCJCw5JSQtGyhC?="


(2) m<o>tley crueが好き

   "m<o>tley crueが好き"
   => "m<o>tley" " " "crue" "が好き"
   == EWORD SPACE AWORD EWORD        
   => EPART SPACE AWORD EWORD         /* r.1 */
   => EPART SPACE AWORD EPART         /* r.1 */
   => EPART SPACE EPART               /* r.2 */
   => EPART                           /* r.4 */
   == "m<o>tley crueが好き"
     => iso-8859-1  "m<o>tley crue"   /* charsetで分割 */
        iso-2022-jp "が好き"
     => "=?iso-8859-1?Q?m=F6tley_crue?= =?iso-2022-jp?B?GyRCJCw5JSQtGyhC?="
   or
     => iso-2022-jp-2 "m<o>tley cureが好き"  /* 包含charset */
     => "=?iso-2022-jp-2?B?bRsuQRtOdnRsZXkgY3J1ZRskQiQsOSUkLRsoQg==?="



(3) m<o>tley crue "が好き"

   "m<o>tley crue \"が好き\""
   => "m<o>tley" " " "crue" " " "\"が好き\""
   == EWORD SPACE AWORD SPACE EWORD
   => EPART AWORD EWORD               /* r.1 */
   => EPART AWORD EPART               /* r.1 */
   => EPART APART EPART               /* r.8 */
   == "m<o>tley" " crue " "\"が好き\""
   => iso-8859-1  "m<o>tley"
      ascii       " crue "
      iso-2022-jp "\"が好き\""
   => "=?iso-8859-1?Q?m=F6tley?= crue =?iso-2022-jp?B?IhskQiQsOSUkLRsoQiI=?="


(4) m<o>tley crue"が好き"

   "m<o>tley crue\"が好き\""
   => "m<o>tley" " " "crue\"が好き\""
   == EWORD SPACE EWORD
   => EPART SPACE EWORD               /* r.1 */
   => EPART SPACE EPART               /* r.1 */
   => EPART                           /* r.4 */
   == "m<o>tley crue\"が好き\""
     => iso-8859-1  "m<o>tley crue\""   /* charsetで分割 */
        iso-2022-jp "が好き\""
     => "=?iso-8859-1?Q?m=F6tley_crue"?= =?iso-2022-jp?B?GyRCJCw5JSQtGyhCIg==?="
   or
     => iso-2022-jp-2 "m<o>tley crue\"が好き\""  /* 包含charset */
     => "=?iso-2022-jp-2?B?bRsuQRtOdnRsZXkgY3J1ZSIbJEIkLDklJC0bKEIi?="


(5) m<o>tley "crue が好き"

   "m<o>tley \"crue が好き\""
   => "m<o>tley" " " "\"crue" " " "が好き\""
   == EWORD SPACE AWORD SPACE EWORD
   => EPART SPACE AWORD SPACE EWORD   /* r.1 */
   => EPART SPACE AWORD SPACE EPART   /* r.1 */
   => EPART APART EPART               /* r.8 */
   == "m<o>tley" " \"crue " "が好き\""
   => iso-8859-1  "m<o>tley" 
      ascii       " \"crue "
      iso-2022-jp "が好き\""
   => "=?iso-8859-1?Q?m=F6tley?= \"crue =?iso-2022-jp?B?GyRCJCw5JSQtGyhCIg==?="

-------------- next part --------------
kazu> (問3) 問2 で答えたアルゴリズムが、いかなるパターンでも最適解を選択/生
kazu> 成することの正当性を証明せよ。[30点]

#証明はパス

text部でRFC-2047を実践するに当たっての注意点はエンコードを行う部分
(encoded-word)とそうでない部分とに分ける方法である。このとき空白文字
(列)の保存の問題があり、以下のルールに注意する

1. encoded-wordとascii文字列の間には空白が必要
2. encoded-word 同士間の空白は保存されない。

問2のアルゴリズムにおいて、APARTは両端に常に空白、あるいはBOL,EOLを
維持する。またEPARTとAWORDの間に空白がない場合は上記1の問題を回避する
ために単一のEPARTとする。
これによりAPARTに隣接するEWORDのエンコードにおける上記1の問題はクリア
される。

-------------- next part --------------
kazu> (問3) 問1、問2 の答えを元に Subject: を符号化するアルゴリズムを Elisp 
kazu> で記述せよ。ただし、Mew がサポートしている Emacs/XEmacs/Mule で問題な
kazu> く動く必要がある。さらに、プログラムは 1 パスで終了しなければならない。
kazu> [40点]

ちょっと長いですがこんなのでどうでしょうか。
#関数の命名はテキトーです。
#foldingはとりあえず考慮していません。
#string から stringを生成します。

最初mew-1.93b37環境で作り、後になってmew-1.93b48で動作するように
修正しましたので、ちょいと冗長なところもありますが御愛嬌。
mew-1.93b48がロードされている状態で添付したコードをロードし、
(rfc2047-encode ".....") を評価してください。
#先の回答はこの結果によるものです。


また、「1パス」意味が不明瞭なのでその辺はパス :-)


;; -*- Emacs-Lisp -*-
;;
;; my-mew-enc.el -- no desc
;; $Revision$

;; Author: Shun-ichi GOTO <gotoh at example.com>
;; Create: Sat Jul 18 20:51:31 1998

;;; Commentary:

;;

;;; Code:


;; sample:  (See [Mew-dist 05595] Re: b47)
;; m<o>tley crue が好き
;;   => "=?iso-8859-1?Q?m=F6tley?= crue =?iso-2022-jp?B?GyRCJCw5JSQtGyhC?="
;; m<o>tley crueが好き
;;   => "=?iso-2022-jp-2?B?bRsuQRtOdnRsZXkgY3J1ZRskQiQsOSUkLRsoQg==?="
;; m<o>tley crue "が好き"
;;   => "=?iso-8859-1?Q?m=F6tley?= crue =?iso-2022-jp?B?IhskQiQsOSUkLRsoQiI=?="
;; m<o>tley crue"が好き"
;;   => "=?iso-2022-jp-2?B?bRsuQRtOdnRsZXkgY3J1ZSIbJEIkLDklJC0bKEIi?="
;; m<o>tley "crue が好き"
;;   => "=?iso-8859-1?Q?m=F6tley?= \"crue =?iso-2022-jp?B?GyRCJCw5JSQtGyhCIg==?="

(defconst rfc2047-text-ascii-regexp 
  "\\(\\(^\\|[ \t]+\\)[\040-\177][ \t\040-\177]*\\([ \t]+\\|$\\)\\)")

(defvar rfc2047-encode-as-minimum-charset nil
  "If this value is t, word which contains both iso-2022-jp and
iso-8859-1 is encoded not single encoded-word of iso-2022-jp-2
but two encoded-word of iso-2022-jp and iso-8859-1")


(defun mew-rfc2047-text-split (str)
  (let ((slist nil)
	estr astr
	ebeg eend
	abeg aend)
    ;; "eeee aaaa ... " => ("eee" "aaaa") and "...."
    (while (< 0 (length str))
      (if (string-match rfc2047-text-ascii-regexp str)
	  ;; found cut out
	  (setq slist (cons (cons (substring str 0 (match-beginning 1))
				  (substring str
					     (match-beginning 1)
					     (match-end 1)))
			    slist)
		str (substring str (match-end 1))) ; update
	;; not found ... all for encoded
	(setq slist (cons (cons str "") slist)
	      str "") ;; no more
	))
    (nreverse slist)))

(defun mew-find-charset-info (tcsl)
  "Give list of coding system symbols, return encode information if acceptable"
  (let ((alst mew-cs-database)
	(N (length tcsl))
	tmpl a acsl aret acs aenc csl ret)
    (setq tcsl (delq 'ascii tcsl))
    (while (and (null ret) alst)
      (setq a (car alst))
      (setq acsl (nth 1 a))
      (setq aret (nth 0 a))
      (setq acs  (nth 4 a))
      (setq aenc (nth 5 a))
      (setq alst (cdr alst))
      (catch 'loop
	(setq tmpl tcsl)
	(while tmpl
	  (if (mew-member (car tmpl) acsl)
	      ()
	    (setq aret nil)
	    (setq acsl nil)
	    (throw 'loop nil))
	  (setq tmpl (cdr tmpl)))
	;; all in single charset
	(setq ret (list aret acs aenc ))))
    ret))


(defun mew-split-string-by-charset (str)
  "Separete given STR by coding system.
ascii only or ascii and other one may be included for each list of result.
"
  (let ((sub "")
	(pos 0)
	(len (length str))
	(wlist nil)			; result
	charset cs ch csl beg info cst)
    (while (< pos len)
      (setq cat nil
	    beg pos
	    csl (list 'ascii)		; accepted coding system except ascii
	    charset nil)		; result charset
      (while (and (< pos len)
		  (progn
		    (setq ch (mew-aref str pos)
			  cs (char-charset ch))
		    (if (memq cs csl)
			t		; already accepted coding-system
		      ;; check this cs is allowable as single charset
		      (setq cst (mew-find-charset-info (cons cs csl)))
		      (if (null cst)
			  nil		; deny
			(if (and rfc2047-encode-as-minimum-charset
				 charset
				 (not (string= charset (car cst))))
			    nil		; deny
			  (setq csl (cons cs csl)
				charset (car cst))))
		      )))
	;; accepted
	(setq pos (+ pos (mew-charlen ch))))
      (setq info (mew-find-charset-info csl))
      (setq wlist (cons (list (nth 0 info)
			      (nth 2 info)
			      (substring str beg pos)
			      (nth 1 info))
			wlist)))
    (nreverse wlist)))



(defun rfc2047-encode (str)
  ""
  (let ((slist (mew-rfc2047-text-split str))
	(result "")
	elist estr astr)
    (while slist
      (setq estr (car (car slist))
	    astr (cdr (car slist)))
      ;; string to be encode
      (if (or (null estr)
	      (= 0 (length estr)))
	  ()
	(setq result 
	      (concat result
		      (mapconcat
		       '(lambda (x)
			  (let* ((charset (nth 0 x))
				 (bq (nth 1 x))
				 (str (nth 2 x))
				 (cs (nth 3 x))
				 (func (cdr (mew-assoc-case-equal 
					     bq mew-header-encode-switch 0))))
			    (concat "=?" charset "?" bq "?"
				  (funcall func str) "?=")))
		       (mew-split-string-by-charset estr) " "))))
      ;; string to be as-is (ASCII)
      (if (and astr
	       (< 0 (length astr)))
	  (setq result (concat result astr)))
      (setq slist (cdr slist)))
    result))


;; my-mew-enc.el ends here
-------------- next part --------------
添付メールを保管しました...
送信者: Shun-ichi GOTO <gotoh at example.com>
件名:   #1   =?iso-8859-1?Q?m=F6tley?= crue =?iso-2022-jp?B?GyRCJCw5JSQtGyhC?=
日付:   Sun, 19 Jul 1998 02:06:55 +0900
サイズ: 815 バイト
URL:    <http://www.mew.org/pipermail/mew-dist/attachments/19980719/46d497c9/attachment.mht>


Mew-dist メーリングリストの案内