「語族」を含む日記 RSS

はてなキーワード: 語族とは

2019-06-19

日本英語教育に足りないもの

日本英語教育を語る上で、知っておかなければならない数字があります

中学高校で、英語の授業が週4時間あるとして総時間数:800時間

CIA職員日本語を習得するのに必要時間数:2000~2500時間

 英語ネイティブスピーカーにとって習得簡単なのは文化的文法的に近似する

オランダ語フランス語スペイン語などです。これらは600時間習得できます

 では『オランダ語フランス語簡単なのか』と日本人が学んでも苦労します。結局のところ、

『同じインドヨーロッパ語族なら習得が楽になる』というだけの話です。

 一方、 ”英語ネイティブスピーカーにとって極めて困難な言語”としては日本語・中国語アラビア語などがあり、

これらの習得には2500時間くらいを要し、これは、英検1級合格に要する時間に相当します。

 逆の日本ネイティブ英語も同じくらい時間がかかるとすると、答えは一つです。

日本人が学校勉強する程度の時間では、英語は出来るようになりません』

もう一つ、データを出しましょう。

中学英語教科書単語数:1000

高校英語教科書単語数:3000~5000

英検準二級合格必要単語数:3000

マーチ大学合格必要単語数:3000

英検二級合格必要単語数:5000

早慶上智合格必要単語数:5000

大学入試において、2つ以上の大学で長文問題に出てきた単語の数 8000

========壁========

アメリカ人労働者が知っている単語数:10000

アメリカ人インテリが知ってる単語数:40000

さて、上のデータを踏まえた上で質問します。日本英語教育には、何が足りないと思いますか?

anond:20181223184149

2019-01-29

Land of Lisp読み終わった

一周目は軽く読み流し、二周目にコードを書きながらしっかり読んだ。2週間かかった。

これに手を付ける前のLisp歴は1週間。ネットLisp入門読んだ程度。

オライリーの本にあるまじきファンキーな表紙なだけでなく、中身もジワる漫画イラストがちょくちょくある。

にもかかわらず内容は恐ろしく難しかった。

読んでいて素晴らしい技術書だと絶賛されているのがわかったし私もそう思うが

Lispを学ぶのに一冊目の本としては適さないと思った。

一冊目の本は機能解説に特化すべきだ。

ソケット通信ゲーム木、ミニマックス法によるAI実装など出てきて

それを今学習中の未知のプログラミング言語解説されるので二重の複雑さ・苦しみになっていた。

とは言っても他にLispの本なんてないし、これをやるしかないのだろう。

2019-01-17

ハッカー画家に影響され2週間ほどLisp語族にいろいろ触れてみた。

「なんかいまいちだな…他のLisp言語はどうだろう」「こっちもなんかアレだな…」と

調べてるうちに4つくらい試すことになってしまった。

結局、これ、というものがなく、どれもツラいという感想をもった。

・「〇〇 入門」で検索してQiitaしかない

・「〇〇 入門」で検索すると講座サイトが見つかるが、一つしかない。それも20年前に作られたサイト

日本語の本がない。あっても一冊しかなくて評判が悪い。

IDEがない。Emacsコマンドラインでやるしかない。

・5chのスレシリーズ番号が一桁。1スレ消化に何年もかかっている。

ライブラリがない。あっても手作り感あるの個人制作のしかない。何年も前に更新が止まっている。

それでもLispが素晴らしい力を私に授けてくれるなら我慢してやってみようとおもったが、

そもそも、今となっては大してすごくないんじゃないか?と不安になった。

すごいすごい言われてたの何十年も前だし。

2018-03-09

anond:20180309113631

EU無意味な脱欧州語族中心主義だよね、英語を使っていないのだから差別ではないみたいな

2018-01-27

タイ・カダイ語族

2016-04-22

プログラミング。好きだけど、さようなら

追記(2015 5/20)

洋食屋ジョブチェンジを果たしました。

---

1年の間、プログラマとして働いていたが、続けていくことが無理だと思い、さようならする話。

プログラマになる前は、コーヒー屋で働いていた。しかし、色々とあり辞め、職業訓練校に通ってプログラミング(php)を学び、60人ほどのソフトウェア開発会社就職した。

会社に入ると、まずC#研修があった。研修と言っても、C#で内製ツールを独りで作るという研修だった。この研修中に「あれ、オレ、プログラム書けねー」と思ったりしたが、研修は終えることができたし、社内の人にも「なかなか良く出来ている」と言ってもらえ、大丈夫だろうと思っていた。

研修が終わり、C#の社内で実際に使われているツールに、機能をいくつか追加する仕事を振られた。前任者にどんな設計になっているのか大雑把に聞き、なんとなくイメージができ、コードを読み始めたのだが、これが全く意味不明で、何のために有るかがわからないクラスが大量にあった。名詞王国だと思った。前任者に、何故このクラスは、この単位で分割されているのか聞くと、「単一責任原則だよ」とか「hogeパターン使うと、後から機能追加しやすいじゃん」というような回答をもらった。納得は出来なかったが、プルリクも承認されて、このツールデプロイされていたので、社内的にも、このコードは、クソコードと言われる物では無いはずだと思ったので、自分プログラムを書き続けていれば、こんな感じの設計に慣れてくるんだろうと思った。モヤモヤは残っていたものの、仕事はしなければいけないので、前任者のコードに習うように、クラスを追加したりして、機能を追加した。プルリクを出すと、設計には何も言われずに、タイポや、テストコードを注意されただけだった。指摘された点を修正すると承認された。振られた仕事は完遂した。が、結局最後まで、モヤモヤは消えなかった。むしろモヤモヤモヤモヤになった。

次に振られた仕事は、内製ツール設計から自分で行い作成する仕事だった。言語Goだった。Goで書いてと言われた時は、以前から自分モヤモヤオブジェクト指向のせいで、モヤモヤしているんじゃないかとも思っていたので、喜んで!という感じであった。が、Goを触ってみると、結局、Go継承の無いオブジェクト指向言語やないかと思った。Goの標準ライブラリinterface名もHogerみたいな感じに接尾辞に-erを持ってくることが慣習らしく、この命名だと、interfaceを満たす構造自身が-erになるので、正にオブジェクトだなぁと思った。巷での「Goオブジェクト指向ではない」というのに期待していたのだが、自分にとっては、とてもオブジェクトしていました。

Goに対する印象は良くなくなったが、ツール設計をしないといけなかったので、Go構造体をC#クラス見立て、前回の前任者のコードのように、単一責任も持つ構造体に(無駄に)分けて、プログラムを書いて、プルリクを出した。自分でクソなコードだと思いながら。だけれどもレビューでは、「errorのチェック忘れ」「標準ライブラリにこの機能ある」「こんな風に書ける」といった感じだった。こんなコードで良いんかよと思ったが、良いらしい。ワケワカメだった。

ここらで、プログラムを書く仕事は、無理だと悟った。現実世界は、自分自然だと思う方法と違う方法で、プログラミングをすることを強要してくる。

ちなみに、仕事ではC#Goを書いていましたが、オブジェクト指向と仲良くなるためにSqueak(Smalltalk)で、オレオレ言語作ってみたりもしましたが、何が嬉しくて、オブジェクト同士のメッセージパッシングプログラムを作るのかわかりませんでした。

Lisp語族言語も触りました。

Clojureは、気持ち良くプログラムを書いていても、Javaが顔を出すところでフラストレーションが溜まってしまって、つらくなりました。

Common Lispは、自分が触った言語の中でも、秀でて良いと思いました。プログラマを辞めても、プログラム書く必要に迫られたらCommon Lispで書こうと思うくらいにです。Land of Lisp楽しいです。あと、CLOS総称関数の考え方が大好きです。

最後に、この投稿は、一種の決別の表明です。いつまでも自分に向いていなかったことに、時間を掛けてしまっている自分との決別です。

最後まで読んでいただきありがとうございました。

自分共感をもった参考リンク

2015-04-14

http://anond.hatelabo.jp/20150413225831

>以上のように、Dvorak配列実用である上、学習過程面白い体験をすることができる。

語族語派の異なる新しい外国語学習するときも似たような面白さを体験することが出来るよ。

2011-01-13

単純に言語同士の遠い近いはあると思うけど。日本人英語を習得するのとインドヨーロッパ語族母語とする人が英語を習得するのとでは前者の方が圧倒的に難しいよ。

2010-08-02

http://anond.hatelabo.jp/20100731111129

http://anond.hatelabo.jp/20100731075251 を書いた者です。


http://anond.hatelabo.jp/20100731111129

実を言うと、あれを書いたのは、グローバル信者英語ブログを見つけてものすごく腹が立ったからなんだよね。自分グローバル活躍する勝ち組みたいなことを言っておいてその英語日本人の俺でもまともに読む気をなくすレベルだった。お前、それでネイティブと戦おうなんて竹槍突撃もいいところじゃないかと。それで気になって調べてみると、「英語ができるだけで収入が2倍になる」とか言ってる某自己啓発教祖英語だってブロークンもブロークン、俺の方がマシじゃないかってレベルだった。もう腹が立って腹が立って。要するにこいつらの「英語」は、日本ガラパゴス猿共のコンプを煽るためのものでしかないわけよ。ネイティブから「天才チンパンジーアイちゃん」程度に扱われればそれでボクチャン名誉白人、満足ですぅってことなんだろとしか思えなかった。




日本においては、英語コンプレックス産業だからね。アメリカのように、移民たちにどう英語を習得してもらうか、という現実の必要性もないわけで、そうなると耳障りのよい宣伝文句のほうがウケてしまうんだろう。日本で発売されてる英語教材には「今日は良い天気でした。」というのんびりしたものが多いが、英米圏の教材では仕事に関する生々しいシチュエーションがたくさん出てくるしね。


元増田エントリーにさまざまなコメントが寄せられてたけども、それらを見ていても似たようなことを感じたよ。以下のような視点からのコメントが多かったね。


1.「英語は国際語だ。」

地球人口の3割近くが英語を話すとも言われてるけども、それでもたったの3割だよ。また、傲慢なアメリカ人が同じことを言うならばまだしも、日本人にとって英語外国語でしかないのに、このような意見に易々と同調するのは実に不思議だね。


2.「簡単な英語でいいんだ。」

シングリッシュを引き合いに出してた人がいたね。シンガポールである程度の教育を受けた人たちがシングリッシュフォーマルな場で使うことなんてあり得ないよ。そういった人たちはやはりイギリス英語をお手本にして英語を学んでいる。そして、元増田が指摘してたように英米圏においては簡易英語ネタ的に扱われている。それは最近、話題になっているGlobishなども同じこと。

「簡単な英語でいいんだ」と主張する人たちのうち、どれくらいの割合が実際にその「簡単な英語」について書かれた英米圏の記事を読んだのだろう。「簡単な英語」なんてものは英米圏において「英語が危ない」というネタとして消費されてるだけだよ。

そして、そういった英米圏の抵抗を現実的に打ち負かすほどの力が、それらの簡易英語に備わっているとは思えない。それは政治的にも、言語の仕組みとしても。


ともあれ、こういった「英語は国際語で、しかも、簡単な英語でいいのだ」という発想は、実に日本人的なものだと思うよ。日本人日本国内においては日本語だけを使っていればいいけども、それと同じように「簡単な英語」で「世界のどこでも」乗り切れればいいな、という願望があるのかもしれない。


http://d.hatena.ne.jp/atq/20100801

元増田 2010/08/02 00:34

もしかして、あなたやその他の私に反論されている方は、言語とは「英語」と「その他大勢」しかないという見方をされているのでしょうか。




ここらへんがキモじゃないかと思うね。元増田に反発する人たちは、日本語のモノリンガ環境(=日本)を英語に置き換えて考えてるだけなんだろう。「「英語」と「その他大勢」しかないという見方」とは、まさにそのことじゃないかという気がした。

しかしながら、シングリッシュのようなクレオール言語で「世界のどこでも」乗り切っていくのは不可能だ。多少ブロークンな英語でノンネイティブ同士がやりとりすることはあるけども、それはクレオール言語ピジン言語ではない。minor errorを含んでるだけであって、あくまでもモデルは英米圏の英語だ。

そういった前提に立てば、同一語族に属していない日本語の話者がいかに不利か、気付かされるし、元増田が主張していたような「絶望」という感情も生まれてくるのだろう。そして、「簡単な英語でいい」などと無責任に煽ったりするブロガーを見れば、「所詮、こいつら「言語」ってものを舐めすぎだと思うんだよ。」という感想を抱くのも自然なことだろう。


思うに、「言語」を「舐めすぎ」るというのは、ある意味で居心地のよい日本語に甘えているということなのかもしれないね。そして、日本語と同じように「苦労せずに習得できるレベル」の英語を用いて、海外コミュニケーションを取りたい、という違う甘えも生み出しているのかもしれない。もっとも、日本語を習得するのだって、ほんとうは大変だったはずなんだけどね。子供の頃から漢字の書き取りを行い、長いあいだテレビなどで標準語言い回しを見聞きして、いろんな人と話すことでようやく習得できたはず。

本来であれば、安易に「英語英語」と喧伝するまえに、外国人向けの「簡単な日本語」を策定して国際機関公用語に押し上げる、くらいの発想も必要じゃないかな。もし、そこで「日本語外国人には理解できない」という日本特殊論に落ち込むとしたら、それもある意味では日本語に甘えているということなんだろう。


元増田の人は煽りをふんだんに詰め込んであの増田を書いたけども、細部をきちんと見ていけば、実に丁寧に言語と付き合ってる人だとわかる。なので、反発していた人たちも英語勉強が進んだら、もう一度読み返してみれば少なからず得るものがあるだろう。もしかしたら、元増田と似たような思いを抱くかもしれない。学歴コンプ日本特殊論などの仕掛けを用いなくとも、そういった言語についてのお話が読まれるようになり、日本人がもっと積極的に自らの意見を発信できるようになれればいいね。

2010-04-26

ポッポ

1・系統

ポッポ語とは、日本語から派生した言語であり、日本語派に分類される言語である。

しかし、話者が極めて少数であり、まったく異なる語族ではないか、という慎重論を唱える識者も根強い。

2・分布

主として日本国内に極めて狭く分布される。しかしながら、ごくまれに海外でも見れるので「トンネル効果ではないか」という識者もいる。

3・現状

ポッポ語は研究者も少なく、またサンプル数の極めて少ない絶滅の危機にある言語であるため、言語体系の解決には早期の決着が望まれる。日本語との類似の指摘が多いが、それでは日本語話者との解釈に隔たりがあることの説明にはなっておらず、研究のさらなる進展の必要がある。

言語学に詳しい野武千代美(65・日本学術大教授)は、「日本語も話せる、近親関係のある人に詳しい解説を求めるべきです。日本語と音韻が似ているからと日本語と同じ枠組みにしてしまうのは尚早です」と今の言語学の流れに警鐘を鳴らす。

また、未釜吉良(50・東京ニュータウンこくさい女子大教授)は、「日本語親和性が強いが、『思い』と勘違いしやすい『おモイ』や、『友愛』と誤解しやすい『ユウアい』など、日本語と明らかに意味が異なるものがある。今後の進展には注意しなければならない」として時間をかけて考えるべきという考えを明らかにしている。

2007-09-07

ようこそ、℃-uteLisp の世界へ

発祥: http://ex23.2ch.net/test/read.cgi/morningcoffee/1188654905/

はじめに

Scheme という Lisp 語族言語を用いて ℃-ute相関関係プログラムし、様々な角度から関係性を分析する手法を紹介していきます(ソースコードは最後に張ります)。

まずは、メンバー間の関係を「リスト」というデータ型で表現します。例えば「栞菜->愛理」という関係

(kanna . airi)

という形で表すことができます。これに、「大好き」という情報を付加し、ついでにその関係の性質を数値化したものを加えると

((kanna . airi) (desc "大好き") (score . 1))

のようになり、関係図における一つの矢印の情報データ化できたことになります(暫定的に、好意は 1、良好・中立は 0、険悪は -1 の3段階で表すことにします)。

メンバー間の全ての関係性をこのデータ単位で定義し、データベース化しておくことで、色んな条件に基づいた検索やスコア計算などが可能となります。

例 1: リンク状況の調査

ここで相関関係図における矢印を「リンク」と呼ぶことにして、あるメンバーから他のメンバーへどのようにリンクし、またリンクされているかを調べることができます。

関係の中からリンクの起点を抽出してソートしてみると

(sort-nodes (number-list (from-links)))

結果:

((kanna . 6) (saki . 5) (maimi . 4) (erika . 3) (mai . 3) (chisato . 3) (airi . 2))

栞菜ちゃんがメンバー全員にリンクを張っていることが分かり、℃-ute ラブっぷりが伺えます。なっきーにも同様の事が言えます。例の「女の子が好き」発言を数値的に裏付ける結果と言えるかもしれません。

ただ、データ不足でリンク件数がまだ少ないのと、リンクの性質(好意/反感など)までは分からない点を考慮する必要があるでしょう。

例 2: 被リンク状況の調査

同様に、リンクの終点の件数を調べてみます。

(sort-nodes (number-list (to-links)))
((chisato . 5) (erika . 5) (kanna . 4) (maimi . 4) (airi . 4) (mai . 3) (saki . 1))

えりかちゃんと千聖ちゃんが高ポイントです。メンバーからの人気や注目度の高さを示すデータですが、千聖ちゃんの場合敵対的なリンクが2件含まれている点に注意してください。

なっきーの被リンク数が極端に少ないですが、単純にデータ不足のためだと思われます。はぶら(ryとか言わないようにお願いします。

例 3: 愛情度の評価

リンクに付随するスコアを計算することで、愛情の度合いを測ることができるのではないか、という考えに基づく研究です。

まず、全ての関係性を対象として、スコアマイナス関係を抽出してみます。

(filter-nodes (lambda (n)
		(< (score-relation n) 0)))

結果:

(((kanna . chisato) (desc "愛理に手出すんじゃねぇよ") (score . -1))
 ((saki . chisato) (desc "愛理に手出すんじゃねぇよ") (score . -1)))

件数だけを得ると

(length (filter-nodes (lambda (n)
			(< (score-relation n) 0))))
2

僅か2件です。

良好・中立的な関係

(length (filter-nodes (lambda (n)
			(= (score-relation n) 0))))
8

愛に満ちた関係

(length (filter-nodes (lambda (n)
			(> (score-relation n) 0))))
16

非常に多いです。舞美ちゃんの「℃-ute同士でラブラブなんですよ」発言(例のラジオ)を数値的に裏付ける結果と言えるんじゃないでしょうか。

次に、メンバーごとのスコアを算出してみます。Lisp 的には以下のようにフィルタリングと畳み込み (fold) で計算することができます。例えば

(foldr (lambda (n acc)
	 (+ (get-score n) acc))
       0
       (filter-nodes (cut to? <> 'kanna)))

栞菜ちゃんに対するリンクスコアが得られます。結果:

3

上式を一般化して一挙にメンバー全員に適用してみると

(sort-nodes (map (lambda (x)
		   (cons x (score-loved x)))
		 (all-members)))

結果:

((airi . 4) (kanna . 3) (mai . 2) (erika . 2) (maimi . 2) (saki . 1) (chisato . 0))

愛理ちゃんが好意を寄せられやすい傾向が伺えます。

今度は逆方向のスコアを計算してみると

(sort-nodes (map (lambda (x)
		   (cons x (score-loving x)))
		 (all-members)))
((kanna . 3) (maimi . 3) (chisato . 2) (airi . 2) (saki . 2) (mai . 1) (erika . 1))

まいまいえりかちゃんが特に堅い・一途だという傾向を読み取ることができます。

例 4: 相性の調査

今度は組み合わせ(カップリング)の評価です。

2点間相互のリンクスコアを加算したものを「相性」と考えられるものとします。最大値 (互いに好意を寄せている場合の数値) は現在スコアリング方式では 2 です。例えば

(score-between 'kanna 'airi)

の値は

2

となります。1 であれば一方通行と考えます。

関係性が未定義の場合もあるので 0 のものを除外して算出すると

(sort-nodes (filter (lambda (n)
		      (not (= (cdr n) 0)))
		    (map (lambda (n)
			   (cons n (apply score-between n)))
			 (all-combinations))))
(((chisato mai) . 2)
 ((chisato airi) . 2)
 ((airi kanna) . 2)
 ((saki kanna) . 2)
 ((kanna maimi) . 2)
 ((erika maimi) . 2)
 ((saki airi) . 1)
 ((saki erika) . 1)
 ((kanna mai) . 1)
 ((maimi airi) . 1)
 ((saki chisato) . -1)
 ((kanna chisato) . -1))

となります。若干ピンとこない部分もあるかも知れませんが、計算上は矛盾無くデータの内容を表しています。

参考までに、スコア 1 の相互関係の中身を見てみると

(map (lambda (p)
       (find-relation (cons (caar p) (cadar p))
		      identity))
     (filter (lambda (n)
	       (= (cdr n) 1))
	     (map (lambda (n)
		    (cons n (apply score-between n)))
		  (all-combinations))))
(((kanna . mai) (desc "喰ってやるよ") (score . 1))
 ((saki . airi) (desc "好き") (score . 1))
 ((maimi . airi) (desc "良き妹") (score . 1))
 ((saki . erika) (desc "彼氏にしたい") (score . 1)))

のようになります。

まとめ

以上の調査を経て気になった問題点を列挙してみます。

特に最初の点に関して、「百合的」なるものの質的評価がなかなか難しいと感じました。例えば「大好き」も「良き妹」も同じ 1 と評価してしまっているのが妥当かどうか、といったことです。

また、スレにて与えられた情報を評価・分析する方法としては有効だとしても、逆方向のフィードバックの手段がなかなか見つからないというのが三つ目の問題です(技術力不足とも言います)。(注:画像化の方法が分かりました。追記参照)

最後に、プログラムソースを示します。実行には PLT Scheme が必要です。文字コードUTF-8 で保存した上で、(load "c-ute.ss") としてください。文字化けする場合はターミナルUTF-8 を表示できるよう設定する必要があります。がんばってください。

プログラム

c-ute.ss:

(require (lib "etc.ss")
         (lib "list.ss")
         (lib "26.ss" "srfi")
         (lib "delete.ss" "srfi" "1"))

;;; Utilities

(define true? (compose not not))

(define (ignore _) #f)

(define fif
  (case-lambda
    ((predicate consequent)
     (fif predicate consequent ignore))
    ((predicate consequent alternative)
     (lambda (x)
       (if (predicate x)
           (consequent x)
           (alternative x))))))

(define (concat! xs) (apply append! xs))

(define (mapconcat f lst sep)
  (let lp ((str (f (car lst)))
           (lst (cdr lst)))
    (if (null? lst)
        str
        (lp (string-append str sep (f (car lst)))
            (cdr lst)))))

(define (slice-string str len)
  (let lp ((res '())
           (str str))
    (if (<= (string-length str) len)
        (reverse! (cons str res))
        (lp (cons (substring str 0 len) res)
            (substring str len)))))

(define (break-string str len)
  (mapconcat identity (slice-string str len) "\\n"))

;; NOTE: input and output ports have to be either file-stream or #f
;; (i.e., cannot be a string port)
(define (run exe opt in out)
  (let-values (((p p-i p-o p-e)
                (subprocess out in #f exe opt)))
    (subprocess-wait p)
    (close-input-port p-e)))

;;; Database

;; http://ja.wikipedia.org/wiki/%E2%84%83-ute

(define names
  '((erika . "えりか") (maimi . "舞美") (saki . "早貴") (airi . "愛理")
    (chisato . "千聖") (mai . "舞") (kanna . "栞菜")))

(define (symbol->name sym)
  ((fif true?
        cdr)
   (assq sym names)))

(define nodes '())
(define edges '())

(define (relate from to desc score)
  (let ((n (cons from to)))
    (or (find-relation n
                       (lambda (r)
                         (let ((d (assq 'desc r))
                               (s (assq 'score r)))
                           (set-cdr! d (cons desc (cdr d)))
                           (set-cdr! s (+ score (cdr s))))))
        (begin
          (set! nodes (cons n nodes))
          (set! edges (cons (cons n `((desc ,desc)
                                      (score . ,score)))
                            edges))))))

(define (find-relation n k)
  ((fif true? k)
   (assoc n edges)))

(define (related? x y)
  (find-relation (cons x y) (lambda (_) #t)))

(define (from? n x)
  (eq? (car n) x))

(define (to? n x)
  (eq? (cdr n) x))

(define flip-relation
  (case-lambda
    ((n)
     (and (related? (cdr n) (car n))
          (cons (cdr n) (car n))))
    ((n k)
     ((fif true? k)
      (flip-relation n)))))

(define (get-score n)
  (cdr (assq 'score n)))

(define (get-description n)
  (cdr (assq 'desc n)))

(define (describe-relation n)
  (find-relation n get-description))

(define (score-relation n)
  (or (find-relation n get-score) 0))

(define (print-node . ns)
  (for-each (cute find-relation <>
                  (lambda (r)
                    (display
                     (format "| ~a => ~a  (~a)~%"
                             (caar r) (cdar r)
                             (mapconcat (lambda (s)
                                          (string-append "\"" s "\""))
                                        (cdr (assq 'desc r))
                                        ", ")))))
            ns))

(define (iter-nodes k)
  (let lp ((nodes nodes))
    (unless (null? nodes)
      (k (car nodes))
      (lp (cdr nodes)))))

(define (filter-nodes p)
  (let ((ns '()))
    (iter-nodes (fif p
                     (cut find-relation <> (lambda (n)
                                             (set! ns (cons n ns))))))
    ns))

(define (from-links)
  (map car nodes))

(define (to-links)
  (map cdr nodes))

(define (all-members)
  (delete-duplicates! (from-links)))

(define (all-pairs) nodes)

(define (ordered-pairs)
  (concat! (map (lambda (x)
                  (map car
                       (sort (filter-nodes (cute to? <> (car x)))
                             (lambda (x y)
                               (> (get-score x) (get-score y))))))
                (sort-nodes (map (lambda (x)
                                   (cons x (score-loved x)))
                                 (all-members))))))

(define (all-combinations)
  (let lp ((cs '()) (ns nodes))
    (if (null? ns)
        cs
        (let ((n (car ns)))
          (lp (if (member (list (cdr n) (car n))
                          cs)
                  cs
                  (cons (list (car n) (cdr n)) cs))
              (cdr ns))))))

;; number-list :: [a] -> [(a . Int)]
(define (number-list ls)
  (let lp ((ns '()) (ls ls))
    (if (null? ls)
        ns
        (let ((x (car ls)))
          (lp ((fif not
                    (lambda (_) (cons (cons x 1) ns))
                    (lambda (n)
                      (set-cdr! n (add1 (cdr n)))
                      ns))
               (assq x ns))
              (cdr ls))))))

;; sort-nodes :: [(a . Int)] -> [(a . Int)]
(define (sort-nodes ns)
  (sort ns (lambda (x y)
             (> (cdr x) (cdr y)))))

(define (diff-nodes ms ns)
  (let lp ((ds '()) (ns ns))
    (if (null? ns)
        (sort-nodes ds)
        (lp (let* ((n (car ns))
                   (m (assq (car n) ms)))
              (cons (cons (car n)
                          (- (cdr m) (cdr n)))
                    ds))
            (cdr ns)))))

(define (get-total-score x p)
  (foldr (lambda (n acc)
           (+ (get-score n) acc))
         0
         (filter-nodes (cut p <> x))))

(define (score-loved x)
  (get-total-score x to?))

(define (score-loving x)
  (get-total-score x from?))

(define (score-between x y)
  (+ (score-relation (cons x y))
     (score-relation (cons y x))))

(define (-> x)
  (display (format "~%Links from [~a]~%" x))
  (iter-nodes (fif (cut from? <> x)
                   print-node)))

(define (<- x)
  (display (format "~%Links towards [~a]~%" x))
  (iter-nodes (fif (cut to? <> x)
                   print-node)))

(define (<-> x)
  (display (format "~%Reciprocal links for [~a]~%" x))
  (iter-nodes (fif (cut to? <> x)
                   (lambda (n)
                     (flip-relation n
                                    (lambda (m)
                                      (print-node m n)))))))

(define (<=> x)
  (display (format "~%Reciprocal matches for [~a]~%" x))
  (iter-nodes
   (fif (cut to? <> x)
        (lambda (n)
          (flip-relation n
                         (lambda (m)
                           (if (ormap (lambda (x)
                                        (ormap (lambda (y)
                                                 (equal? x y))
                                               (describe-relation m)))
                                      (describe-relation n))
                               (print-node m n))))))))

(define (<?> x)
  (let ((to (assq x (number-list (from-links))))
        (from (assq x (number-list (to-links)))))
    (display (string-append
              (format "~%Link statistics for [~a]~%"
                      x)
              (format "| ~a => ~a (love ~a)~%"
                      x
                      (cdr to)
                      (score-loving x))
              (format "| ~a => ~a (love ~a)~%"
                      (cdr from)
                      x
                      (score-loved x))))))

(define (info x)
  (for-each (cut <> x)
            (list <- <-> <=> -> <?>)))

;;; GraphViz (http://www.graphviz.org/) support

(define graphviz "C:/Program Files/ATT/Graphviz/bin/dot.exe")

(define (nodes->dot ns)
  (string-append "digraph cute {\n"
                 ;;"\tordering=out;\n"
                 ;;"\trankdir=LR;\n"
                 "\toverlap=true;\n"
                 "\tnode[fontname=\"msgothic.ttc\"];\n"
                 "\tedge[fontname=\"msgothic.ttc\",fontsize=9];\n"
                 (let lp ((str "") (ns ns))
                   (if (null? ns)
                       str
                       (let* ((n (car ns))
                              (s (score-relation n)))
                         (lp (string-append
                              str
                              (format "\t\"~a\" -> \"~a\""
                                      (symbol->name (car n))
                                      (symbol->name (cdr n)))
                              (format "[label=\"~a\",color=\"~a\","
                                      (break-string
                                       (car (describe-relation n))
                                       7)
                                      (cond ((> s 0) "red")
                                            ((= s 0) "green")
                                            (else "blue")))
                              (format "style=\"bold~a\"];\n"
                                      (if (and (not (= s 0)) (< s 1) (> s -1))
                                          ",dashed"
                                          "")))
                             (cdr ns)))))
                 "}"))

(define (write-dotfile dot file)
  (and (file-exists? file) (delete-file file))
  (with-output-to-file file
    (lambda ()
      (display dot)))
  file)

(define (dot->png dot png)
  (call-with-input-file (write-dotfile dot "c-ute.dot")
    (lambda (in)
      (and (file-exists? png) (delete-file png))
      (call-with-output-file png
        (lambda (out)
          (run graphviz "-Tpng" in out)))))
  'done)

;;; Setup database

;; Based on:
;; http://ex23.2ch.net/test/read.cgi/morningcoffee/1188654905/116-142
(begin
  (relate 'maimi 'erika "大好き" 1)
  (relate 'maimi 'kanna "良き妹" 1)
  (relate 'maimi 'airi "良き妹" 1)
  (relate 'maimi 'mai "姉妹" 0)
  (relate 'erika 'maimi "一番可愛いよ" 1)
  (relate 'erika 'kanna "仲間" 0)
  (relate 'erika 'chisato "おソロパジャマ" 0)
  (relate 'kanna 'erika "仲間" 0)
  (relate 'kanna 'maimi "好き" 1)
  (relate 'kanna 'saki "喰ってやるよ" 1)
  (relate 'kanna 'mai "喰ってやるよ" 1)
  (relate 'kanna 'airi "大好き" 1)
  (relate 'kanna 'chisato "愛理に手出すんじゃねぇよ" -1)
  (relate 'saki 'maimi "荷物整理" 0)
  (relate 'saki 'erika "彼氏にしたい" 1)
  (relate 'saki 'kanna "興味がある" 0.5)
  (relate 'saki 'chisato "愛理に手出すんじゃねぇよ" -1)
  (relate 'saki 'airi "好き" 1)
  (relate 'airi 'kanna "受け入れる" 1)
  (relate 'airi 'chisato "最近親密" 1)
  (relate 'mai 'erika "保護者" 0)
  (relate 'mai 'maimi "姉妹" 0)
  (relate 'mai 'chisato "恋人" 1)
  (relate 'chisato 'erika "おソロパジャマ" 0)
  (relate 'chisato 'mai "恋人" 1)
  (relate 'chisato 'airi "最近親密" 1))

;; query relations / draw graphs

(if (file-exists? graphviz)
    (dot->png (nodes->dot (ordered-pairs))
              "c-ute.png")
    (for-each info (all-members)))

追記(グラフ描画について)

Graphviz というソフトによって関係図を可視化できる、ということを教えていただきました(既に上プログラムを実行すると自動的に関係画像を作成するようにしてあります)。ここでは技術的な観点から幾つか注意点を挙げておきます。

まず、Scheme プログラムから Graphviz を動かす方法について。コマンドラインからの起動のように、プログラムへのオプション文字列で入出力ファイルを指定する方法ではどうも上手く行きませんでした。調査の結果、入出力ファイルポートScheme 側で用意しておく必要があるようです。処理系によって異なりますが、PLT Scheme の場合 subprocess という関数を次のように呼び出します。

(subprocess output-port input-port #f "/path/to/dot.exe" "-Tpng")

ここで output-port は png画像ファイルへの出力ポート。input-port は dot ファイルグラフの定義ファイル)の入力ポートです。エラーポートは必要無いでしょう (#f)。

dot という名前の実行ファイルが、関係図のような有向グラフを描画するプログラムです。最後にオプション文字列として出力形式を指定します(png, jpeg, gif, etc.)。

次に dot ファイルScheme で書く方法ですが、以下の基本的な有向グラフの書式

digraph g {
  A -> B;
  B -> C;
  C -> A;
}

を理解すれば、後は実直に Schemeデータを当てはめて format 関数等で変換するだけです。

(string-append
 "digraph g {"
 (format "~a -> ~a;" (car node) (cdr node))
 "}")

問題は、ノードを配置する順番によって出来上がる画像が変わってくる、ということです。

より見た目に分かりやすくするための工夫としては、相互にリンクするノード同士が dot ファイル上でも近接して出力されるようにすると良いでしょう。関連の強いものが画像の上でも近くに表示されるようになります。

また上述(特に例3)のスコア概念を応用し、スコアの低いものが後に出力されるようにすることで、重力感覚に一致するような関係図を得ることができるでしょう。

 
アーカイブ ヘルプ
ログイン ユーザー登録
ようこそ ゲスト さん