LINQで組み合わせを列挙する
先週から話題のこちらのプログラミング課題
アプローチの仕方はいろいろあると思うのですが、新宿Scala座主宰のid:numanuma08氏は「Scalaだったらリストからすべての組み合わせを生成するのもcombinationsメソッドで一発だよ」といつも通りScala全力押しです*1。
ところがその紹介の最後で
#新宿Scala座 で新入女子社員を救ってきた
今煽られました。
完全に煽られました。
LINQとやらで組み合わせ列挙書いてみろよほら張り子の虎とか笑わないからさと煽られました。
書いてやろーじゃねーの。
*1:組み合わせ全列挙は商品数に対してO(n^2)の時間とメモリを使うので冒頭の問題の解き方としては不利です。片割れをまず列挙してそれぞれに最適な相手を二分探索するのならO(n log(n) )でいけます。だからこの記事では新人女子プログラマ問題からは離れて組み合わせ列挙のことだけ考えています。
CodeIQ×はてなの賞品をいただきました
「CodeIQの問題・パズルを考えよう」
http://partner.hatena.ne.jp/codeiq_matsuri2013_2
に調子に乗って3問ほどパズルを出したところ、佳作にあたるんですかね、CodeIQ賞に選んでいただけました。
http://codeiq.hatenablog.com/entry/2013/09/06/150247
で、このたび賞品の葉っぱが届きました。
ペアですね。
組み立ててみました。でかい。
でかい葉っぱはいまベッドの頭に鎮座しております。
で、これがペアで届いちゃうあたりがまたいじり方はんぱないっすねはてなさん。
もう1枚の葉っぱは、先着でご希望の方にお裾分けします。コメントかtwitterでご連絡ください。
Play2.0 - secureクッキーは設定でオンにしておきたいけど開発機ではオフにしたい場合
secureクッキーは、HTTPSを使っていない場合にはブラウザからサーバに送り返されないフラグを付けたクッキーのことです。
秘密情報をクッキーに乗せて覚えさせたのに、うっかりさんユーザーがHTTPでアクセスしてきてクッキー内容がパケット盗聴で漏れるとかもうダメダメパターンですからね。
Play! frameworkでHTTPSを使うサイトなら、application.confに
session.secure=true
の一行を加えて、セッション情報を格納するクッキーには必ずsecureフラグが付くようにしてあげましょう。
ところが問題が。
この設定があると、HTTPではログインとかまったくできなくなります。開発機の開発サーバでも。デバッグできないじゃない。
SQLプログラミング課題・表示順変更の実現
CodeIQの問題・パズルを考えよう!(by CodeIQ×はてな)
タイトル見ただけで苦労の記憶がよみがえってきた方はその時点で合格ってことでいいかもしれません。
INT型の主キーを持ったテーブルがあり、1行を1アイテムとして表示できます。
CREATE TABLE items ( id INT PRIMARY KEY, name VARCHAR(20) NOT NULL);
このアイテムリストの表示順を、ユーザが自由に変更できるようにしてほしいのです。
もちろん、業務アプリならば「表示優先度」なんていう整数値をユーザが設定できるようにすれば要件は達成ですが、コンシューマ向けWebアプリではそうはいきません。
ケース1
UIでは、各アイテムに「上げる」「下げる」ボタンをつけました。
「上げる」「下げる」それぞれの操作を実現するためのテーブル変更と、操作時に発行するSQL文を書き下ろしてください。
操作のパラメータとして無効なIDが渡された場合や、一番上にいるのに「上げる」を指示された場合の動作は、エラーになるか何も起こらないかなど妥当なものを定義してください。
ケース2
UIでは各アイテムのドラッグ&ドロップを可能にしました。
ドロップ時の操作を実現するためのテーブル変更、ドロップ先領域にどんな識別値を与えておくか、操作時に発行するSQL文を書き下ろしてください。
無効な指示に対してはケース1と同様、妥当な動作を定義してください。
ポイント
表示優先度にあたるカラムを作ることになりますが、それはユニーク値を格納することになると思います。
それを変更するにあたって、UPDATE文が複数行を変更するときすべて変更し終わるまでUNIQUE制約はチェックされないという点がコツになります。だから例えば値の入れ替えも一文で書けば制約に引っかかることなく実行可能です。
コーディング課題・貸しボート屋の問題
CodeIQの問題・パズルを考えよう!(by CodeIQ×はてな)
ある湖の貸しボート屋が古いボートを処分しようとしましたが何艘残せばいいかわかりません。
貸し出しリストから、ピークのときに何艘が貸し出されていたかを求めたいです。
貸し出しリストは
貸出日時, 返却日時, ボート番号
の組になっており、貸出日時の順に並んでいます。
このリストを一回だけスキャンして(ランダムアクセスすることなく)ピーク貸出数を算出してください。(2013-08-25 制約が曖昧だったので書き直しました)
このリストからピーク貸出数を算出してください。
リストは膨大なサイズなのでメモリに収まることは期待できません。1回のシーケンシャルアクセスで解決してください(ボートの数はたかが知れているので、ボートの数に比例する程度のメモリを使うことは問題ありません)。
ただし、同一時刻に返却と貸出があった場合、それらの貸出期間は重なっていないものとします。
例えば
('2013-08-22 08:00', '2013-08-22 09:00', 5) ('2013-08-22 08:30', '2013-08-22 09:30', 6) ('2013-08-22 09:00', '2013-08-22 09:30', 7)
という貸出記録だったら2が回答です。
応用問題
貸出リストは
CREATE TABLE rental ( rental_id INT NOT NULL PRIMARY KEY, starts DATETIME NOT NULL, ends DATETIME NOT NULL, boat_id INT NOT NULL );
というRDBテーブルになっています。
ピーク数をSELECT文一本で算出してください。