Language detail: Emacs Lisp
Coverage: 31.54%
|
number of '+' ratings |
contribution for coverage |
Unsolved challenges
- LL Golf Hole 4 - 文章から単語の索引を作る (Nested Flatten)
- LL Golf Hole 3 - 13日の金曜日を数え上げる (Nested Flatten)
- tailの実装 (Nested Flatten)
- lessの実装 (Nested Flatten)
- 2次元ランダムウォーク (Nested Flatten)
codes
LL Golf Hole 2 - 文字列に含まれる単語の最初の文字を大文字にする
(Nested
Flatten)
バッファに文字列を書いた状態で。
1 | (mark-whole-buffer)(upcase-initials-region)
|
コード圧縮
(Nested
Flatten)
昔ゴルフ用に書いたものを書き直しました。Emacs のバッファを書き換えます。対象言語は Common Lisp で、バッファのモードは lisp-mode と仮定しています。
- 出力例:
- (defun mylib-compress-need-space-p()(cond((or(bobp)(eobp))nil)((string-match"["'(),`]"(string(following-char)))nil)((looking-back"#[0-9]+#")nil)((looking-back"#\\.")t)((string-match"["()]"(string(preceding-char)))nil)(t)))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | (defun mylib-compress-region (&optional start end)
(interactive "r")
(save-restriction
(when (and start end)
(narrow-to-region start end)
(goto-char (point-min)))
(loop
do (delete-region (point)
(progn (while (forward-comment 1)) (point)))
until (or (eobp) (= (following-char) ?\)))
if (mylib-compress-need-space-p)
do (insert " ")
if (looking-at "\\(#'?\\|['`]\\|,@?\\)?(")
do
(down-list 1)
(mylib-compress-region)
(up-list 1)
else do (forward-sexp 1))))
(defun mylib-compress-need-space-p ()
(cond ((or (bobp) (eobp))
nil)
((string-match "[\"'(),`]" (string (following-char)))
nil)
((looking-back "#[0-9]+#")
nil)
((looking-back "#\\\\.")
t)
((string-match "[\"()]" (string (preceding-char)))
nil)
(t)))
|
設定ファイルから値を取得
(Nested
Flatten)
設定ファイルのフォーマットは S式の連想リストです。 ファイルの内容を一時バッファに格納し、そのバッファを read で読み込んでいます。 ファイル:ShowPrice.ini ((item-name . りんご) (item-cost . 200)) > (show-price) => "「りんご」は210円(税込み)"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | (defun show-price ()
(let ((call-with-input-file #'(lambda (filename proc)
(with-temp-buffer
(progn (insert-file-contents filename)
(funcall proc (current-buffer))))))
(call-with-name&cost #'(lambda (alist proc)
(funcall proc
(cdr (assq 'item-name alist))
(cdr (assq 'item-cost alist)))))
(call-with-add-tax #'(lambda (rate base proc)
(funcall proc (/ (* base (+ rate 100)) 100)))))
(funcall call-with-input-file (expand-file-name "ShowPrice.ini")
#'(lambda (in)
(funcall call-with-name&cost (read in)
#'(lambda (name cost)
(funcall call-with-add-tax 5 cost
#'(lambda (cost)
(format "「%s」は%d円(税込み)" name cost)))))))))
|
コメントの削除
(Nested
Flatten)
comment-kill がやるようです。
1 2 3 4 5 6 7 | (defun decomment (buffer)
"バッファ内のコメント文を削除します"
(interactive "bdecomment ")
(with-current-buffer buffer
(save-excursion
(goto-char (point-min))
(comment-kill (point-max)))))
|
スタックの操作
(Nested
Flatten)
本当のスタックオーバーフローではありませんが、すぐ書ける Emacs Lisp の場合でも。
関数呼び出しのネスト数が max-lisp-eval-depth の値を超えるとエラーになります。初期値は 300 ぐらいが普通みたいです。
普通の変数なので setq で大きい数に設定すれば増やせますが、documentation に「大きくしすぎるとクラッシュするかも」とか書いてあります。
1 2 | (defun f () (f))
(f) ;; => Debugger entered--Lisp error: (error "Lisp nesting exceeds `max-lisp-eval-depth'")
|
自然数の分割
(Nested
Flatten)
comprehensionって便利ですね。 List Comprehension - defmacro によるリストの内包表記 http://lambda.s55.xrea.com/Emacs.html のlist-of を利用してemacs-lispで書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | (defun partitionNum (a b)
(if (= b 1)
(list (list a))
(let ((x 0) (l '()))
(while (<= x a)
(progn
(setq l
(append
l
(list-of (append (list (- a x)) y)
(y in (partitionNum x (- b 1))))))
(setq x (+ x 1))))
l)))
(print (partitionNum 5 3))
|
文字列のセンタリング
(Nested
Flatten)
Emacs Lisp 実行結果: (string-centering "abc" 0) "" (string-centering "abc" 1) "b" (string-centering "abc" 2) "ab" (string-centering "abc" 3) "abc" (string-centering "abc" 4) "abc " (string-centering "abc" 5) " abc " (string-centering "abc" 6) " abc " (string-centering "abc" 7) " abc "
1 2 3 4 5 6 7 8 | (defun string-centering (s c)
(let ((p (lambda (k) (make-string k ? )))
(d (- c (length s))))
(let ((n (/ d 2))
(m (% d 2)))
(if (>= d 0)
(concat (funcall p n) s (funcall p (+ n m)))
(substring s (abs n) (- (length s) (abs (+ n m))))))))
|
文字列リストをTRIE Optimizeされた正規表現に
(Nested
Flatten)
Emacs Lisp だと regexp-opt が要求通り(+α)のことをやってくれるようです。 ただ、backslash だらけな elisp の正規表現が返ります。 実行結果は以下。 "program\\(?:ist\\(?:ic\\)?\\|m\\(?:a\\(?:r\\|ti\\(?:c\\(?:ally\\)?\\|st\\)\\)?\ \\|er\\)\\)?"
1 2 3 4 5 6 7 8 9 | (regexp-opt '("program"
"programist"
"programistic"
"programma"
"programmar"
"programmatic"
"programmatically"
"programmatist"
"programmer"))
|
水の移し替えパズル
(Nested
Flatten)
解くプロセスを Emacs で表示してみました。 もっときれいに書けるかも……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | (eval-when-compile (require 'cl))
(defun water-puzzle (a b c)
(let ((cups (list a b c)))
(destructuring-bind ((i p) (j q) (k r))
(sort `((0 ,a) (1 ,b) (2 ,c))
(lambda (x y) (< (cadr x) (cadr y))))
(cond ((zerop (mod (- p q) 3)) (show-strategy cups i j k))
((zerop (mod (- p r) 3)) (show-strategy cups i k j))
((zerop (mod (- q r) 3)) (show-strategy cups j k i))
(t (message "Cannot solve!"))))))
(defun show-strategy (cups i j k)
(let ((buf (get-buffer-create "*water puzzle*"))
(mover (lambda (di dj dk)
(incf (nth i cups) di) (redraw-cup i di)
(incf (nth j cups) dj) (redraw-cup j dj)
(incf (nth k cups) dk) (redraw-cup k dk)))
(counter 0))
(switch-to-buffer buf)
(show-init-state cups)
(while (> (nth j cups) 0)
(sit-for 1)
(apply mover (if (zerop (nth i cups)) '(2 -1 -1) '(-1 -1 2)))
(incf counter))
(message "Solved in %d step%s."
counter (if (= counter 1) "" "s"))))
(defun show-init-state (cups)
(delete-region (point-min) (point-max))
(redraw-cup 0 (car cups)) (insert ?\n)
(redraw-cup 1 (cadr cups)) (insert ?\n)
(redraw-cup 2 (caddr cups)) (insert ?\n))
(defun redraw-cup (i d)
(goto-line (1+ i))
(if (plusp d) (dotimes (x d) (insert ?|)) (delete-char (- d))))
;;; test
(water-puzzle 4 2 10)
|
制限時間内のキー入力検査
(Nested
Flatten)
Emacs のミニバッファから。
1 2 3 4 5 6 7 | (defun input-checker (n s)
(interactive "nTime(second): \nsString: ")
(let ((c (read-char (concat "input(" s ")=>"))))
(push c unread-command-events))
(with-timeout (n (message "TIME OUT"))
(let ((input (read-string (concat "input(" s ")=>"))))
(message (if (string= input s) "OK" "NG")))))
|
文字列の反転
(Nested
Flatten)
Emacs Lispにはそれ用の関数はないです。
1 2 | (defun reverse-string (str)
(concat (nreverse (append str nil))))
|
与えられた文字列でピラミッド
(Nested
Flatten)
あまり長くない文字列なら再帰でも行けます。
(Emacsは再帰の深さが変数max-lisp-eval-depthで制限されるので事実上使えない)
(pyramid "abracadabra")
a
r a
b r a
a b r a
d a b r a
a d a b r a
c a d a b r a
a c a d a b r a
r a c a d a b r a
b r a c a d a b r a
a b r a c a d a b r a
1 2 3 4 | (defun pyramid (s &optional p)
(unless (string= s "")
(pyramid (substring s 1) (cons ? p))
(insert (concat p) (mapconcat #'string s " ") "\n")))
|
1 2 3 4 5 6 7 8 | (require 'cl)
(defun pyramid (str)
(interactive "sPyramid string: ")
(with-output-to-temp-buffer "*Pyramid*"
(loop for i from (1- (length str)) downto 0 do
(princ (make-string i ? ))
(princ (mapconcat 'identity (split-string (substring str i) "") " "))
(terpri))))
|
重複無し乱数
(Nested
Flatten)
;; random-permutation (random t) (bingo 10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | (defun iota (n &optional a step)
(setq step (or step 1))
(do ((n n (- n 1))
(ret '() (cons a ret))
(a (or a 0) (+ a step)))
((<= n 0) (nreverse ret))))
(defun bingo (a &optional b)
(let* ((ret (vconcat (mapcar '1+ (iota a b))))
(num (length ret))
val rnd)
(dotimes (x num ret)
(setq rnd (random num)
val (aref ret x))
(aset ret x (aref ret rnd))
(aset ret rnd val))))
|
文字列からの情報抽出
(Nested
Flatten)
カレントバッファを入力としてM-x print-image-spec-on-bufferすると*image-spec*バッファに出力されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | (require 'cl)
(defun print-image-spec-on-buffer ()
(interactive)
(save-excursion
(goto-char (point-min))
(with-output-to-temp-buffer "*image-spec*"
(while (re-search-forward "\\([A-Za-z]+\\)\\(-hidden\\)?\\(-\\(small\\|big\\)\\)?\\.\\([A-Za-z]+\\)" nil t)
(destructuring-bind (s0 e0 sname ename shidden ehidden _ _ ssize esize sext eext)
(match-data)
(princ (format "name:'%s', ext:'%s', size: %s hidden: %s\n"
(buffer-substring sname ename)
(buffer-substring sext eext)
(if ssize (buffer-substring ssize esize) "normal")
(if shidden "True" "False"))))))))
|
隣り合う二項の差
(Nested
Flatten)
elispのmapcarは劣化版。
1 2 3 | (defun diffseq (list)
(mapcar* #'- (cdr list) list))
(diffseq '(3 1 4 1 5 9 2 6 5)) ; => (-2 3 -3 4 4 -7 4 -1)
|
複数行のコメントアウト
(Nested
Flatten)
ソースコード中で使われることは意図してなさそうですが #@n で n 文字読み飛ばすことができます。
1 2 | #@18
this is a comment
|
与えられた数字のケタ数
(Nested
Flatten)
今度は数値計算でやってみた。そのままCommon Lispでも通る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | (require 'cl)
(defun keta (n)
(cond ((zerop n) (values 1 1))
((< n 0) (keta (- n)))
(t (loop
with d = 1
with len = 0
while (>= (/ n d) 1) do
(incf len)
(setf d (* d 10))
finally (return (values len (/ d 10)))))))
(keta 2469) ; => (4 1000)
(keta 600) ; => (3 100)
(keta 1) ; => (1 1)
(keta 0) ; => (1 1)
(keta -2469) ; => (4 1000)
|
複数行のコメントアウト
(Nested
Flatten)
next >>
elispは #| ~ |# をサポートしていないため、言語仕様上複数行コメントはできない。
しかし、式をquoteすることでお手軽コメントアウトもどきはできる。
言うまでもないが、評価結果はlistである。どうせGCされる運命なんだけどね。
某所で見かけて以来、自分も使うようになった。
1 2 3 4 | '(progn
;; 式をquoteすることで事実上コメントアウトになる
(switch-to-buffer "*scratch*")
(goto-char (point-max)))
|






匿名
#7087()
[
Emacs Lisp
]
Rating0/0=0.00
コマンドラインから
Rating0/0=0.00-0+
[ reply ]