NHK高校講座の世界史の「オリエント文明」を見て興味を持ったものをネットで検索した

www.nhk.or.jp

ホモ・サピエンス

ホモ・サピエンスは20万年前から10万年前にかけておもにアフリカで現生人類へ進化したのち、6万年前にアフリカを離れて長い歳月を経て世界各地へ広がった。

ホモ・サピエンス - Wikipedia

楔形文字

楔形文字(くさびがたもじ、せっけいもじ)とは、世界四大文明の一つであるメソポタミア文明で使用されていた古代文字である。

筆記には水で練った粘土板に、葦を削ったペンが使われた。最古の出土品は紀元前3400年にまで遡ることができる。文字としては人類史上最も古いものの一つであり、古さでは紀元前3200年前後から使われていた古代エジプト象形文字に匹敵すると言われている。

楔形文字 - Wikipedia

メソポタミア文明を支えたのは、高い農業生産力でした。
2つの川がもたらす豊富な水を灌漑によって畑に引き込んで、主に小麦が栽培されました。
小麦1粒から80粒、つまり80倍ほどの収穫量があったと考えられています。
中世のヨーロッパで4倍程度、現在のアメリカで20数倍といわれていますから、メソポタミアの農業技術が驚くほど高かったことがわかります。
収穫した小麦は、人々の主食となるほか、交易の商品となりました。
この大事な小麦を管理・記録するために、文字が使われるようになったと考えられています。

NHK高校講座 | 世界史 | 第2回 オリエント文明

メソポタミア

メソポタミアは、ティグリス川とユーフラテス川の間の沖積平野である。現在のイラクの一部にあたる。
土地が非常に肥沃で、数々の勢力の基盤となったが、長年の灌漑によって徐々に土地の塩害が深刻となり、収量は低下していった。

メソポタミア - Wikipedia

シュメール人

シュメール人は、楔形文字を生み出し、最古の神話「ギルガメシュ叙事詩」を残しており、最近では多数出土した粘土板でシュメール法典の存在が注目されている。彼らの文化は、メソポタミア文明の最初の段階であるシュメール文化と総称される。楔形文字はその後もオリエント世界の諸民族の言語を書き表す文字として共通の文字とされ、アケメネス朝ペルシアまで続いた。シュメール法典は古バビロニア王国ハンムラビ法典に継承された。またシュメール人の神話は、その後のオリエントの諸民族に影響を与え、ユダヤ教旧約聖書を通じてキリスト教にも引き継がれており、例えば、旧約聖書の「ノアの箱舟」(大洪水)の話の原型はギルガメッシュ神話に見ることができる。

シュメール人

ハンムラビ法典

「目には目を、歯には歯を」という言葉は「復讐してヨシ」ではなく、「復讐はしすぎるな」という抑止の意図だった!

そこで「目には目を、歯には歯を」という一説の真意ですが、「こちらがやられたこと以上の過剰な復讐をしてはならない」と、過剰な報復合戦を防ぐ目的で条文化されたのではないか?という学説が有力になっています。

つまり「やり返せ!」と煽るのではなく、むしろ「やられて悔しい人は、同じ程度の復讐をする程度でとどめなさい」という、抑止の意図でつくられた、と考えられるのです。

ハンムラビ法典』の後書きには、王の願いとして「強者が弱者を虐げないように、正義が孤児と寡婦とに授けられるように」との文言も記載されています。条文だけでも法典として成り立つものを、あえて後書きに王の願いとしてこうした内容を記載しているあたり、ハンムラビ王は良心ある賢帝だったのであろう、と推測できます。

もちろん、現代的な価値観で見ると残酷に感じる内容も多々ありますが、ハンムラビ王は、国民の最大公約数が納得できる『法』とは何か?という課題に、誠実に真摯に向き合ったうえで、法典を編纂したのではないでしょうか?

precious.jp

フェニキア

東地中海岸で前13世紀ごろから海上貿易に活躍したセム語族の一つ。アルファベットのもととなったフェニキア文字をつくった。地中海世界カルタゴなどの多くの植民市を建設した。

アルファベットの考案
 彼らは活発な交易活動に便利なように、後のアルファベットのもとになる線状文字であるフェニキア文字を作り出した。この文字体系はすでに、前2000年紀中ごろのカナーンおよびシナイ半島に始まったが、その段階では象形文字的要素が強く残る線状文字であった。この初期のアルファベットは文字数も27個から30個と多く、文字を書く方向も右から左、左から右、あるいは行ごとに交互に書く牛耕式とまちまちで一定せず、さらには縦書きさえあった。それをフェニキア人は、前11世紀の中ごろ、文字数22個の子音文字からなり、右から左への横書きという北西セム語の線状アルファベットとしてのフェニキアを文字完成させた。<佐藤育子『同上書』 p.41>
 フェニキア人の作ったアルファベットは、子音を表すだけであったので、後にギリシア人が母音を加えて、現在のようなアルファベットになった。この完成された形のアルファベットは、フェニキア人の交易活動の広がりと共に、地中海世界に広がっていった。(ただし、アルファベットの伝搬者ではあったが、彼ら自身が書き記した文献資料は発見されていない。)

フェニキア人

UNIXシステムコール 標準入力から読んでECHOせずに標準出力に表示する

ECHOするプログラム

#include <stdio.h>

int main(void) {
  int c;

  while ((c = getchar()) != EOF) {
    putchar(c);
  }
}

ECHOしないプログラム

#include <stdio.h>
#include <termios.h>
#include <unistd.h>

int main(void) {
  int c;
  struct termios new, old;

  tcgetattr(STDIN_FILENO, &old); /* 現在の端末設定を取得 */
  new = old;
  new.c_lflag &= ~ECHO; /* ECHOフラグをオフにする */
  tcsetattr(STDIN_FILENO, TCSANOW, &new); /* 設定を反映させる */
  while ((c = getchar()) != EOF) {
    putchar(c);
  }
  tcsetattr(STDIN_FILENO, TCSANOW, &old); /* 設定を元に戻す */
}

GDBによるデバッグ

9	  tcgetattr(STDIN_FILENO, &old); /* 現在の端末設定を取得 */
(gdb) n
10	  new = old;
(gdb) 
11	  new.c_lflag &= ~ECHO; /* ECHOフラグをオフにする */
(gdb) p new
$1 = {c_iflag = 17664, c_oflag = 5, c_cflag = 191, c_lflag = 35387, c_line = 0 '\000', 
  c_cc = "\003\034\177\025\004\000\001\000\021\023\032\000\022\017\027\026", '\000' <repeats 15 times>, c_ispeed = 15, c_ospeed = 15}
(gdb) p/t new->c_lflag 
$2 = 1000101000111011
(gdb) n
12	  tcsetattr(STDIN_FILENO, TCSANOW, &new); /* 設定を反映させる */
(gdb) p/t new->c_lflag 
$3 = 1000101000110011

Linuxターミナルのショートカットキー

ターミナルを起動する
Ctrl + Alt + T
ターミナルを終了する
(入力欄に何も入力されていない状態で) Ctrl + D

カーソルの移動
右に1つ移動 Ctrl + F
左に1つ移動 Ctrl + B
行頭に移動 Ctrl + A
行末に移動 Ctrl + E

カーソルの左側の1文字を削除する
Ctrl + H
カーソルより左側の入力されている文字列をすべて削除する
Ctrl + U
カーソルより右側の入力されている文字列をすべて削除する
Ctrl + K

何かを理解しているとはそれについて高い確率で正解を作り続けることができることだ

俳句を理解しているとは、高い確率でいい俳句を作り続けることができることだ。
数学を理解しているとは、高い確率で正解を作り続けることができることだ。

俳句を理解しているとはどういうことだろうか。
ランダムに17個のひらがなを並べるコンピュータのプログラムは、俳句を理解(作成)しているとは言えないだろう。
また、過去に作られた俳句と呼ばれているものをデータとして持ちその中からランダムに一つを表示するプログラムは、俳句を理解しているとは言えないだろう。

一つ思考実験をしてみる。
ある人が正岡子規の俳句をすべて暗記して、タイムマシンに乗って正岡子規が生まれる少し前の過去に移動し、暗記した正岡子規の俳句を自分が作ったものだとして発表すれば、彼は正岡子規とだいたい同じ評価を受けるだろう。
でも、彼は俳句を理解してなさそうである。
彼は俳句のデータを持っているプログラムと大きく変わらないだろう。

数学を理解している人と暗記している人の違いはなんだろう。彼らを見分けるにはどうすればいいだろう。

また思考実験をしてみる。
ある人が素数というものを理解しているか判定しようとする。

まず単純にある数が素数であるかを答えさせる試験で判定することを考える。
Aさんは素数を理解しているとする。
Bさんは素数を理解していないが100以下の素数を暗記しているとする。

そうすると、100以下の数について試験を行うと、AさんとBさんに違いは現れない。つまり、Bさんも素数を理解しているように見える。
しかし、100より大きい数で試験を行うと、Bさんが素数を理解していないことが分かる。
Aさんは高い確率で正解を答えることができ、Bさんは低い確率(狭い範囲)で正解を答えることができるということだ。

さらに素数についていろいろな観点で質問をして試験することによってその人の素数に関する理解度を判定できるだろう。
やはり、理解度が高い人は高い確率(広い範囲)で正解を出し続けることができると言えるだろう。
理解度が高いとは理解の抽象度が高く応用範囲が広いということなのだと思う。

すべてのものを暗記している人とすべてのものを理解している人に違いはないだろう。
彼らは同じ質問に対して同じ答えをするだろうから。
理解は暗記の圧縮だと思う。
暗記と理解の違いは、その点ではないか。

catコマンドでファイルに^C(アスキーコード3の文字)を書く方法

^CはCtrl + C を押したときに入力されるアスキーコード3の文字のこと

% cat > foo

を実行して、Ctrl + Cを押すとSIGINTが送信されてコマンドが終了してしまい、^Cをファイルに書くことができない。

% cat > foo

を実行して、Ctrl + Vを押し、Ctrl + Cを押し、Ctrl + Dを押すと^Cをファイルに書くことができる。

$ cat -v foo 
^C
$ od -tx1 foo
0000000 03 0a
0000002

UNIXシステムコール 高水準入出力(getc,putchar) ファイルから読んで画面に表示する

#include <stdio.h>
#include <stdlib.h>

#define INFILE "abc.txt"

int main(void) {
  FILE *fp;
  int c;

  if ((fp = fopen(INFILE, "r")) == NULL) {
    perror("fopen");
    exit(1);
  }

  while ((c = getc(fp)) != EOF) {
    putchar(c);
  }

  if ((fclose(fp)) == EOF) {
    perror("fclose");
    exit(1);
  }

  return 0;
}
$ cat abc.txt 
abc
$ od -tx1 abc.txt 
0000000 61 62 63 0a
0000004

GDBによるデバッグ

10	  if ((fp = fopen(INFILE, "r")) == NULL) {
(gdb) n
15	  while ((c = getc(fp)) != EOF) {
(gdb) p *fp
$44 = {_flags = -72539000, _IO_read_ptr = 0x0, _IO_read_end = 0x0, _IO_read_base = 0x0, 
  _IO_write_base = 0x0, _IO_write_ptr = 0x0, _IO_write_end = 0x0, _IO_buf_base = 0x0, 
  _IO_buf_end = 0x0, _IO_save_base = 0x0, _IO_backup_base = 0x0, _IO_save_end = 0x0, 
  _markers = 0x0, _chain = 0x7ffff7f9c680 <_IO_2_1_stderr_>, _fileno = 3, _flags2 = 0, 
  _old_offset = 0, _cur_column = 0, _vtable_offset = 0 '\000', _shortbuf = "", 
  _lock = 0x555555559340, _offset = -1, _codecvt = 0x0, _wide_data = 0x555555559350, 
  _freeres_list = 0x0, _freeres_buf = 0x0, __pad5 = 0, _mode = 0, 
  _unused2 = '\000' <repeats 19 times>}
(gdb) n
16	    putchar(c);
(gdb) p/c c
$45 = 97 'a'
(gdb) p fp->_IO_read_ptr
$46 = 0x555555559491 "bc\n"
(gdb) p fp->_IO_read_end
$47 = 0x555555559494 ""
(gdb) p fp->_IO_read_base
$48 = 0x555555559490 "abc\n"
(gdb) n
15	  while ((c = getc(fp)) != EOF) {
(gdb) 
16	    putchar(c);
(gdb) p/c c
$49 = 98 'b'
(gdb) p fp->_IO_read_ptr
$50 = 0x555555559492 "c\n"
(gdb) n
15	  while ((c = getc(fp)) != EOF) {
(gdb) 
16	    putchar(c);
(gdb) p/c c
$51 = 99 'c'
(gdb) p fp->_IO_read_ptr
$52 = 0x555555559493 "\n"
(gdb) n
15	  while ((c = getc(fp)) != EOF) {
(gdb) 
16	    putchar(c);
(gdb) p/c c
$53 = 10 '\n'
(gdb) p fp->_IO_read_ptr
$54 = 0x555555559494 ""
(gdb) n
abc
15	  while ((c = getc(fp)) != EOF) {
(gdb) 
19	  if ((fclose(fp)) == EOF) {
(gdb) p/c c
$55 = -1 '\377'
(gdb) p fp->_IO_read_ptr
$56 = 0x555555559490 "abc\n"

UNIXシステムコール 標準出力が行緩衝であることを確認する

標準出力は改行が書き込まれるまで出力しない。これを行緩衝という。
下記のプログラムを実行すると、「54321 go!」という文字列が同時に表示される。
改行が書き込まれるまで出力は行われず、バッファに蓄積されるからである。

#include <stdio.h>
#include <unistd.h>

int main(void) {
  int i;

  for (i = 5; i > 0; i--) {
    printf("%d", i);
    sleep(1);
  }
  printf(" go!\n");
  return 0;
}

下記のように、「fflush(stdout);」を追加するとその都度画面に表示される。

#include <stdio.h>
#include <unistd.h>

int main(void) {
  int i;

  for (i = 5; i > 0; i--) {
    printf("%d", i);
    fflush(stdout);
    sleep(1);
  }
  printf(" go!\n");
  return 0;
}

標準エラー出力はその都度出力する。

#include <stdio.h>
#include <unistd.h>

int main(void) {
  int i;

  for (i = 5; i > 0; i--) {
    fprintf(stderr, "%d", i);
    sleep(1);
  }
  printf(" go!\n");
  return 0;
}