プログラミングと私
暇さえあればプログラム書いてる私ですが、いろいろあって意識的にプログラミングから離れてみるということをやってみました。それが今まで悩んでいたことを解決してくれそうです。あんまり共感してくれる人がいないと思いますが、同じ悩みを持っている人の解決策になればなぁと思いました。
私は以前から以下のような悩みがありました
- 現実に生きてる心地がしない
- 人に興味が湧かない
プログラミングから離れてみるきっかけとなったのは、ある親しい人から言われた言葉でした。
「殻にこもらないで、もっといろんな経験を積んで」
言われたときは少しショックでした。自分が殻にこもっているという自覚が全くなかったからです。むしろ好きなプログラムを書いていて自分ではとても意欲的だと思っていたのです。(その人は僕がどんなプログラムを書いているのかは知らないと思いますが)周りから見るとそういう風に見えるのだなと、納得しました。
それで何のためにプログラムを書いているんだろうと、すこし自暴自棄になり、エディタを開くのを二週間ぐらい避けて生活してみました。まあ作りたいものが無かったというのもあります。
やってみると結構いろんなことが分かりました。
まず虚しさとか寂しさとかそういう感情がふつふつと湧いてきました。普段プログラムを書いている時期でもそういう感情はありますが、プログラム書き始めると気にならなくなってしまうのでそれほど問題視してませんでした。
寂しいので友達誘ってプール行ったりするとすごく現実に生きてる感じがしました。
また、人にあまり興味を持たない理由もわかりました。 人の興味の持ち方には二種類あるようで、「人」に興味を強く持つタイプと、「物」に興味を強く持つタイプに分かれるようです。調べた先で書いてあった例ですが、昔ライブドア事件というのがありました。ライブドアの社長が証券取引法違反で逮捕された事件です。ここで人に興味を持つタイプはホリエモンというのはどういう人物かに興味が湧くわけです。一方、物に興味を持つタイプは「有価証券とは何か」や「どういうことをやって捕まったのか」などの物や仕組みに興味が湧きます。
一般的な人はどちらも兼ね備えていると思います。ただ、この興味の割合はだいたい同じくらいに興味を持っている人もいればどちらかに極端に偏る人がいるようです。
私はもちろん「人」への興味もあるのですが、「物」への興味が強いようです。小学校の時は友達と遊ぶのより、図解の本を読むのが好きでした。
それからもプログラミングに興味を持ち始めて、「人付き合いしてる時間があればプログラムを書いてる方が有意義」という信念があったので、どんどん物への興味が強くなったのだと思います。
minecraft ramdisk化
家で立てているMinecraft サーバーがどうも重いらしいので、実行ファイル群を仮想的にメモリ上に配置するRamDisk化をしてみました。
RamDisk化するソフトはいくつかあるのですが、稼働しているサーバーは一つ前のモデルのMac Miniなので、TmpDiskというソフトを使いました。
ただ、このソフトは単に領域を確保してくれるだけなので、マウント*1して実際に動かすファイルは手動でコピーしなければいけません。
RamDisk化する点で問題なのが、「電源を切るとデータが飛んでしまう」のと「バックアップを正確に取っておかないとデータが飛んでしまう」という脅威があります。
手動でやるとミスをしてしまいそうなので、今回はシェルスクリプトを使って対処した話をします。
下準備
まずはTmpDisk用意します。
TmpDiskはドライブ名と容量を指定するだけで簡単にRamDiskを作れます。
チェックボックスを入れることによって起動時に自動でRamDiskを作る事もできます。
問題はここから。
作ったRamDiskはOS Xの/dev以下に配置されます。おそらくドライブ化された順番だと思うのですが、disk0 … disk1とあり、disk0はOS X入っているドライブを指しているのだと思われます。
マウントするには
Diskutil mount disk1
という風にコマンドを打つ事によってマウントすることが出来ます。
マウントされると/Volumes直下にRamDiskを生成するときに指定したドライブ名のボリュームが出来ます。
あとはシェルスクリプトを書いて動かすだけです。
シェルスクリプト芸
シェルスクリプトとはLinuxやOS Xなどで実行できるコマンドを一つのファイルにまとめて書くことが出来るスクリプト言語のことです。
実際にはWindowsの.batより強力で、パイプとかgrepとかの便利な機能が使えます。
シェルクスリプトにしてほしいこと
最後に同期を解除する必要があるのは、minecraftと同時に起動している必要があるためです。
シェルスクリプトはC言語のように上から下に命令(コマンド)を実行していきます。
そのため、Minecraftサーバーが起動している間は下の命令は実行しないまま止まってしまうわけです。
そこでコマンドの後ろに&をつけることでコマンドをバックグラウンドで実行することが出来ます。
しかしこれが厄介で、バックグラウンドで実行するということはminecraftサーバーが終了してもそのまま命令は実行され続けるということです。
ではどうするかというとバックグラウンドで実行される命令のPID(プロセスID)を取得しておいて、minecraft サーバーが終了した時に同時にkillコマンドを使って終了させる事ができます。
同期は、fswatchとrsyncを組み合わせます。
fswatchは指定したフォルダ内にアクセスがあった時に後ろのコマンドを実行するというコマンドです。
日本語の文献にはあまり記載がなく、うまく動かずに悩んていたのですが、fswatchはバージョンが新しくなってから書き方が変わっていたようです。
fswatch -o path | xargs -n1 -I{} program
参考
ちなみに今回はコマンドに引数を渡す必要はないので
fswatch -r -0 path | xargs -0 -I {} program
とすることで引数を渡さずに後ろのコマンドを実行してくれます。
実際にプレイしてみましたが、もともと無線使っても全然ラグ出なかったので、違いがわからないです(爆笑)
どっちかというと回線の問題のような気もします。
おまけ
pythonでスクリプト書いてブラウザからサーバーの状況確認出来るようにしてみました
*1:ドライブをディレクトリから参照出来るようにすること
AOJ1193 - Chain Disappearance Puzzle
ICPC 国内予選の問題が今の自分はどれぐらい解けるのか気になり、去年の問題を眺めていたら解けるのは解けるのだけど、あまり美しくない解き方しか思いつかない問題があったので考察してみました。
ICPC 2014 国内予選のProblem B「Chain Disappearance Puzzle」という問題です。
→Chain Disappearance Puzzle | Aizu Online Judge
問題概要
N×5のマス目があり、それぞれ1~9の数字が書かれている。
横向きに数字が3つ以上揃うとその数字は消え、消えたマスには上の数字が落ちてくる。
(パズドラとかぷよぷよとかイメージするといいかも
最終的に消えた数字の和を答えなさいという問題です
考察
この手の問題はシミュレーションと呼ばれます。
最初問題文読んでうわぁって思いました。
というのも、下に落ちるの考えるのって結構面倒臭いんですよね。
2行同時に消える列があると列全体を2つ下ろさなければいけないし、でも綺麗な解法が思い浮かばなかったので結局思いついたとおりに書きました。
形としては、
- 入力
- 3つ以上揃うところを足していって、0で上書きする
- 下からループしていって、0を見つけたら上に向かって0以外の数字を探して交換する
- 合計が変わるまで2と3をループする
- 合計の出力
実際に書いたコード
後の考察
他の人のソースコードを見ていると結構自分と同じやり方でやっている人がいて、意外でした。(冗長すぎると思っていた
ただ、自分の場合はこういうソースコード書いた時点でバグが多発して"オンラインプログラミングコンテスト"が"オンラインデバッギングコンテスト"になりかねないので、少なくとも落ちるところの処理を簡潔にしたいなぁと探していたらclimpetさんがいいソースコード書いていました。
書いたコードでは配列に数字を格納していましたが、C++にはvectorとかいうイケメン配列(個人的なイメージです)があり、それを使ってうまく解かれていました。
fill(remove(v[j].begin(), v[j].end(), 0), v[j].end(), 0);
どうもvectorの属しているSTLにはremoveという「指定した値を取り除いて、勝手に切り詰められる関数」があるようです。
切り詰められたあとの余った領域には余計な値が残っているので、fillで残った箇所に0を入れていかにも重力で落ちたようにシミュレーションをしているようです。
5 5 4 4 3 (4を取り除く)
5 5 3 ? ? (残ったところを0で埋める)
5 5 3 0 0
あと他にもあらかじめ消滅させる場所を記憶させておいて数え上げるなどを参考にして書き直しました。
repとか意気って使った。
NYC2015 - A問題
塾とAtCoderの定期開催の時間が絶妙に被っていてなかなか参加できなかったのですが、年末年始は塾がお休みだったのでNew Year Contestというのに参加しました。
AtCoderは順位表がリアルタイムで変わるので、競技している感が出ていいのですが、
早い人はA問題1分程度で解いていて、自分は30分ぐらいかかってしまうのでA問題ぐらいはなんとかしたいなぁと復習を書くことにしました。
A 2015
問題概要
2015というタイトルの問題です。いや~去年はいろいろありましたね。
この問題は、与えられた数字を二進数に変換してその数字列が回文*1であるかどうかを調べなさいという問題です。
考察
後で強そうな人のソースコードを見てみた限り、二進数に変換せずに回文かどうか判定する方法はなさそうなので
1.二進数に変換する
2.回文かどうかチェックする
というまあやるだけみたいな問題ですね。
(やるだけに30分もかかってしまってつらい
実際に書いたコード
後の考察
進数変換とかまともに勉強したことないので他の人を参考にしながら書いてみました。
これが自分の中で一番気持ちいいコードです。
ビット演算とか使ったことないので新年記念に
前のコードだと、どこからどこまでループを回すかというところを考えながらやる必要があったのでそれだけで時間が取られてしまうのですが、後のコードはループを出来るだけ使わずに関数に任せているのでその分デバッグがしやすいという利点があります。
普段からプログラムを書いていてもいかに早く書き上げられるかというのはあまり意識しないので、そういった意味で競技プログラミングはいい勉強になります。
*1:左から呼んでも右から呼んでも同じ文字列