鍋あり谷あり

テーマを決めずに適当に書いています。

主要なプログラミング言語8種をぐったり解説

主要なプログラミング言語8種をぐったり解説するよ。

C言語

「はじめてのC」( https://www.amazon.co.jp/dp/4774133345 )という本で有名になった*1この言語は、「_Generic」という魔術が使えるためか、常人には理解不能なプログラムを書きたい人に、perl の次に愛されています。
C言語で書かれたプログラムは、大抵メモリリークしています。

C++

C言語と異なり、「C++言語」と呼ばれることは稀です。
テンプレートという魔界の扉を開いてしまったために人類には早過ぎる言語とも言われていますが、愛嬌のある文法とキュートでコンパクトなバイナリで、多くの人に愛されています。
C言語と違って、ちゃんと書けばメモリリークはかなり回避できますが、ちゃんと書ける人は稀だと言われています。

Java

Java Tea ストレート よりやや遅れてリリースされたこの言語は、Java Tea とも Java島 ともあまり関係がありません。読み方は「ジャワ」ではなく「ジャヴァ」です。
実行時最適化という必殺技でスピード狂の C/C++ 愛好家を唸らせています。
GCがあるのでメモリリークしないと信じている人がいますが、そんなことはないことに気付かされるのにそれほど長い時間は必要ありません。

J++ / J#

嘘です。C#です。

JavaScript

ブラウザ戦争という戦果の中で内部的には異常とも言える進化を遂げた言語ですが、表面的にはどうかと思う文法で、多くの人々を悲しませ続けています。
ちなみに、ケツカンマは英語で「hip-comma」ではありません。

Ruby

文字列型が文字コードを自分で持つという珍しい選択をした言語です。
「ブロック」の中で return するとブロックではなくメソッドから return するという珍しい選択をした言語です。
有理数リテラル多倍長整数虚数リテラルなどがそろっているため、ライトな数値計算好きユーザーに愛されているかもしれません。

PHP

四捨五入の計算を間違える*2唯一の言語として畏れられていましたが、そのバグは治っているかもしれません(治ってないかもしれません)*3

Python

C/Java/Ruby などを見慣れた人がPython を見ると、ズボンを履きなれた人がスカートを履いた時のような気分になるかもしれません。
for 文に else がある、世界で唯一(鍋谷の脳内調べ)の言語です。

その他の言語

TIOBE ランキングを見ると、ruby を外して perlVB.NET を入れるべきかもしれません。

余談

以前、某春日部系の人材紹介会社の人が「すごいエンジニア紹介しますよ。20代です。」
というので、どんなふうにすごいのか聞いてみると

「今日紹介する10人は、APL 使いなんですよ」
「それはすごい」
「全員 APL キーボード持ってます」
「」

...という話は嘘です。すいません。

最後に

この記事は http://d.hatena.ne.jp/shi3z/20160701/1467330446 にインスパイアされて書きました。

用もないのに原ノ町駅近辺に行ってきた

常磐線の果てに行ってみたかった。
切符を買ってから気づいたんだけど、私が行きたかった場所はどちらかと言うと 竜田駅 の方で、原ノ町駅は反対側だった。そんな日もある。

気にせず原ノ町駅 https://goo.gl/maps/Qmxyfd4fvMn

へ。新幹線で福島→バス。

何かがあることを期待していたわけでもなく、そこで人が普通に暮らしていることを自分の目で見たかったという感じ。

案の定、そこは普通の田舎町だった。

震災から5年もたっているので当たり前かもしれないけど、まだ普通の田舎町になっていない地域もあるので実は当たり前ではない。

海に向かって歩いた。

バスで行きたかったんだけど、バスはなかった。

途中までは普通の田舎町なんだけど、ある地点を超えると様子が変わった。

右は田んぼなのかもしれないけど、左は整地中という感じ。

海まであと一歩のところまで歩いたけど、堤防工事中とのことで、

海までは辿りつけなかった。残念。

駅に戻る途中、tonbo というケーキ屋さんでレアチーズケーキを頂いた。おいしかった。

通りすがりの雀。

マイルの話

ふとマイルという長さについて知ろうと思い、 wikipedia( http://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%A4%E3%83%AB ) を見てみた。
すると。

イタリアマイル(ミリオ miglio)
古代は2.226キロメートル、伝統的には1.489キロメートル、現在は1キロメートル。

という驚くべき記載が。
潔い。
アメリカ・イギリスもこれぐらいの荒療治をしてくれたらいいのにと思ったり。

じゃあその、1マイル=1キロメートル の世界での ヤード フィート インチ はどうなってるんだろうと思い、イタリア語版の wikipedia( http://it.wikipedia.org/wiki/Miglio_(unit%C3%A0_di_misura) )を見てみた。

ら。

現在のイタリアマイルについての記載は一切ない。
代わりに

Miglio nuovo nederlandese = 1 000 m

拙訳「新オランダマイル = 1000メートル」

という記載がある。
なんだこれ。と思い、オランダ語wikipedia( http://nl.wikipedia.org/wiki/Mijl )に行ってみると、1000m であるマイルについての記載は一切ない。

どうなってんだこれ。

英語・スペイン語・フランス語 の wikipedia も見てみたけど、情報はなかった。

なんだろうなぁ。

遅いソート

http://bugrammer.hateblo.jp/entry/2014/08/16/014212 ( バブルソートよりも非効率なソートアルゴリズムを探して ―― ストゥージソートとスローソート ) を読んで。

ちゃんと終わるけどもっと遅いソートがあるので書いてみた。

たぶん名前がついていると思うんだけど、調べてないので名称不明。
こういう奴。

def try_all_sort(s)
  s.permutation(s.size){ |x|
    return x if x.each_cons(2).all?{ |a,b| a<=b }
  }
end

typical case では bogo sort と同じオーダー。
bogo sort と違って、worst case は有限。O((N+1)!)だと思う。

で。ベンチマーク
100要素を1000回なんて宇宙が消滅するまでに終わらないので、試したのはシャッフル済み10要素を10回。

手元で測って、30秒ぐらい。
一方、slowsort だと速すぎて測定不能
bogo sort だと 54秒だった。まあ運次第だけど。

10要素で30秒なので、15要素なら4ヶ月、20要素なら60万年ぐらいかかる。
コンピュータがやる計算なのに、人間が紙に書いてソートするよりずっと遅い。

■ 8/17 追記

メモリ消費は、上記のソースでは O(N)。だと思う。
100要素1000回に要する時間は、普通の人がパッと読んで分かるような表現ができないぐらい長い。
10の148乗年ぐらい。
概ね、千無量大数倍高速化すると、千無量大数年かかるぐらい。百万倍ぐらいサバ読んでるけどいいでしょ?
メモリ消費は、数キロバイト〜数十キロバイト だと思う。

無量大数倍高速化というと無理難題のように思うかもしれないけど、普通の sort に書き換えれば、それ以上の高速化を実現できる。

どう書くの問題を作るときに考えること

虎塚さんの記事
http://d.hatena.ne.jp/torazuka/20140512/doukaku
を受けて。

正確なテストデータ / データの数

深く考えずに、40個ぐらいにしていることが多いんだけど、
コーナーケースが多そうなら多めに、コーナーケースが少なそうなら少なめにしてる。
仕様を網羅したいという希望はありつつも、べつに網羅できなくてもいいよね、とも思っている。

正確なテストデータ / データの作成方法

だいたい以下の順序で

  1. 典型的なケース。問題文中に例として挙げます。
  2. 典型的な例外ケース。該当するものがなかったらとかそういうの。
  3. 典型的なケースをいくつか。
  4. コーナーケースを思いつく限り。
  5. 乱数

「乱数」と、さらっと書いたけど、一様乱数でうまくいくわけではない。
たとえば「ポーカーの残り+」( http://nabetani.sakura.ne.jp/hena/ord10pokarest/ )。
この問題の場合は(あんまりおぼえてないけど)全部の手についてのデータをまあまあ均等に出している。

解き方が複数ある問題にする

この要件が大問題で、ここに注力するとすぐに難易度が上がってしまう。
で。
『「自分では思いつかないけれど、誰かが別の方法で解いてくれるかもしれない」などと勝手に期待』することは結構あって、解き方がひとつしか思いついていない場合でも、いやこれはこの経路以外にありそうだという感触があればそれでよしとする場合もある。
もちろん複数の経路を実装しておきたいとは思うんだけど。

特定のプログラミング言語に配慮する

だいたい ruby に対する嫌がらせをしたいんだけど、いくら考えても他の言語に対する嫌がらせにしかならない。
C と Java、特に C を優遇したいと考えていて、入力データを固定長にしたりしている。

視覚的な演出になる図表を入れる

どちらかというと、できれば図を入れたくないと思ってる。
図を書くコードを書くのが面倒なので。
図が入っているのは、図を入れないと仕様が明確にならないと思ったときだと思う。

過去に出した図で一番気に入ってるのはやっぱり
折って切る( http://nabetani.sakura.ne.jp/hena/ord17foldcut/ )のアニメーション。
問題としてもすごく気に入ってる。
未見の方は是非解くことをおすすめする。

それ以外

どれ以外だと

  • 数学的になりすぎないようにする。
  • 参加者を想像して問題を作る。
  • コンピュータがなくても解ける問題の方が良い。

あたりのことを考えてるって、前にどっかに書いたような。

参加者を想像して問題を作る

これはあんまり具体的にどう問題を作るかという話ではなく。
文字通り、参加者を想像する。
☓☓さんはこの問題を見たらどういう表情をするだろうか。
◯◯さんはこの問題にどう取り組むだろうか。
とか、そういうこと。
CodeIQ と違って、問題を解く人々の集う場があるので(問題だけではなく)その場を面白くしたいと思ってる。
どうしたら面白くなるのか全然わからないんだけど、たぶん面白くするための手段として、想像しながら問題を作っている。

久々に 剰余なしで FizzBuzz

はるか昔に書いた
http://d.hatena.ne.jp/Nabetani/20070510/p1
が、ruby 2.1.0 では動かないようなので、書きなおした。

def f(name,n)
  Fiber.new do
    loop do
      (n-1).times{ Fiber.yield "" }
      Fiber.yield name
    end
  end
end

def fb(sup, *x)
  s=x.map{|name,n| f(name,n)}
  1.upto(sup) do |n|
    yield( (r=s.map{|x|x.resume}.join).empty? ? n : r )
  end
end

fb( 100, [ 'Fizz', 3], [ 'Buzz', 5 ] ) do |s|
  puts s
end

Generator がなくなって Fiber になったらしいので、それに関する対応。
ほかにも多少変更したけど。

記号の読み方

記号の読み方は本を読んでも書いてなかったりするし、会社や文化圏によっても違ったりするので結構困るんだけど、私はこう読んでるよ、という話は書くことができる。

!文脈がなければ「ビックリ」。単項演算子なら「ノット」とか
#「シャープ」か「ハッシュ」
&「アンド」
~チルダ
^文脈がなければ「ハット」。二項演算子なら「エックスオア」とか
|文脈がなければ「縦棒」。二項演算子なら「オア」とか
<「右が大きい」あるいは「不等号」。不等号の意味で「>」はほとんど使わないので「不等号」で誤解がないことが多い。
>「左が大きい」または「右が小さい」。template なんかで閉じ括弧に使う時も「右が小さい」と読んだりする。
{ }「波括弧」
[ ]「配列括弧」か「角括弧」
( )「括弧」か「丸括弧」
_「下線」か「アンダースコア」
\「バックスラッシュ」
`「バッククオート」

こんぐらいかな。

正規表現の中にある ^ は、「ハット」と呼んでいる。
「アクサンシルコンフレクス」とか「サーカムフレックス」だと、は â や ê にくっついている場合の「 ̂ 」のことで、単体で意味を成す「^」のことではないような気分。
まあその割に「~」のことを「チルダ」と呼んでるけどね。