私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「異世界のブラウザの判定」(CodeIQ)を参照してください。
【概要】
あなたの知らない遠い世界。
そこにもブラウザがあり、そこにもブラウザ依存コードが必要だった。
で。
user-agent 文字列を与えるのでブラウザの判定をしてください。
【詳細】
この世界には、5種類のブラウザがあります。
各ブラウザの対応すべきバージョンと user-agent 文字列は下表の通り:
※ 【】内の文字列は、OS やマイナーバージョンによって変わります。
※ ★ は、よく意味の分からない謎の番号です。正の整数をピリオド区切りでならべたものになっています。
<Mamella Firedog>
ブラウザの老舗。
以前は Mamella というブラウザを作っていたが、プロジェクトが上手く行かずバージョン6をリリースできず破綻。
サブプロジェクトだった Firedog がメジャーになった。
【リリース日】は、10進数8桁の数字。
バージョン user-agent 文字列 1.0〜50.0 Mamella/5.0 (【OS名】) Lizard/【リリース日】 Firedog/【バージョン】
<Orange Voyage>
NavOS が搭載された Navel というパソコンを売っている会社が出しているブラウザ。
バージョン user-agent 文字列 1.0〜10.0 Mamella/5.0 (【OS名】) OrangeKit/【OrangeKitのバージョン】 (like Lizard) Version/【バージョン】 Voyage/★
<AnachroSoft Internet Traveller>
PCシェア9割を超えるOS、Fenetre を出している会社のブラウザ。
一時はブラウザシェア95%を誇っていたが、今では1割弱になっている。
ASIT12 でシェアを取り戻すことを狙っている。
バージョン user-agent 文字列 2.0〜7.0 Mamella/4.0 (compatible; ASIT 【バージョン】; 【OS名】) 8.0〜10.0 Mamella/5.0 (compatible; ASIT 【バージョン】; 【OS名】) 11.0 Mamella/5.0 (【OS名】; Quadent/7.0; .KNOT SLR; rv:4.0) like Lizard 12.0 Mamella/5.0 (【OS名】; Quadent/7.0) OrangeKit/12.0 Firedog/3.0 (like Lizard) Voyage/4.0 ASIT/12.0
<Kabuki Browser>
シェアは少ないものの、一定のファンを獲得し続けているブラウザ。
バージョン 14 までは Lento という独自エンジンを使っていたが、 バージョン 15 からは後述の Monochrome と同じ Twinkle というエンジンを使うようになった。
バージョン user-agent 文字列 1.0〜6.0 Mamella/4.0 (【OS名】) Kabuki 【バージョン】 7.0〜8.0 Mamella/4.0 (compatible; ASIT 6.0; ASIT 5.5; 【OS名】) Kabuki 【バージョン】 9.0〜14.0 Kabuki/【バージョン】 (【OS名】) Lento/【Lentoのバージョン】 15.0〜40.0 Mamella/5.0 (【OS名】) OrangeKit/★ (like Lizard) Monochrome/★ Voyage/★ KBK/【バージョン】
<Gluege Monochrome>
検索エンジンで世界を制した会社が突然出してきたブラウザ。
当初は Voyage と同じエンジンを使っていたが、途中でフォークし、今は Twinkle というエンジンを使っている。
バージョン user-agent 文字列 1.0〜27.0 Mamella/5.0 (【OS名】) OrangeKit/【OrangeKitのバージョン】 (like Lizard) Monochrome/【バージョン】 Voyage/★ 28.0〜53.0 Mamella/5.0 (【OS名】) OrangeKit/★ (like Lizard) Monochrome/【バージョン】 Voyage/★
OSについて
OSは、以下のいずれかです。
名称 user-agent 内での表記 Anachrosoft Fenetre 88 Fenetre, Fenetre 88, Fen32 Anachrosoft Fenetre Testament Fenetre, Fenetre Testament, Fen32, Fen64 Anachrosoft Fenetre ichtus Fenetre, Fenetre ichtus, Fen32, Fen64 Anachrosoft Fenetre 9 Fenetre, Fenetre 9, Fen32, Fen64 NavOS W NavOS, NavOS W Tovax Tovax
【入出力】
入力は
Mamella/5.0 (Fen32) Lizard/20050919 Firedog/1.0.0こんな感じで標準入力から来ます。
出力は、ブラウザ名の略称です。
ブラウザのバージョンは不要です。
ブラウザの略称は下表のとおりです:
ブラウザ名 略称 Mamella Firedog MFD Orange Voyage VYG AnachroSoft Internet Traveller ASIT Kabuki Browser KBK Gluegle Monochrome GMC
さきほどの入力は Firedog 1.0 なので
MFDを出力すると正解です。
【例】
入力 出力 Mamella/5.0 (Fen32) Lizard/20050919 Firedog/1.0.0 MFD Mamella/4.0 (compatible; ASIT 5.5; Fenetre Testament) ASIT
【補足】
不正な入力に対処する必要はありません。
問題文中にある5つのブラウザ / 6つの OS 以外の user-agent は入力に含まれません。
現実世界の user-agent 文字列は、もっと複雑で混沌としています。
Rubyで解答しています。
#!/usr/bin/ruby def isKabuki(line) if line.index("Kabuki") != nil then return "KBK" end if line.index("KBK") != nil then return "KBK" end return nil end def isMonochrome(line) if line.index("Monochrome") != nil then if line.index("KBK") != nil then return nil else return "GMC" end end return nil end def isOrangeVoyage(line) if (line.index("Voyage") != nil) && (line.index("Monochrome") == nil) && (line.index("ASIT") == nil) then return "VYG" end return nil end def isASIT(line) if (line.index("ASIT") != nil) && (line.index("Kabuki") == nil) then return "ASIT" elsif line.index(".KNOT SLR") != nil then return "ASIT" end return nil end def check(line) funcs = ["isKabuki", "isMonochrome", "isOrangeVoyage", "isASIT"] for f in funcs ret = send(f, line) if ret != nil then return ret end end return "MFD" end # main while line = gets line.strip! if line.empty? then next end puts check(line) end
この出題者の問題で私がやった中では一番簡単と思います。
が、面倒くさいです。
ただ、(多分0私のコードはあんまりよろしくありません。
私の方法はuser agetn文字列から特徴のある部分をひっかっけて、特徴の多いものから判断して行くという方法をとっています。
そして、どれにも引っかからなかったらMFDと答えます。
入力値を文字をcheck()に渡し、結果を印字します。
ユーザエージェント判別関数を順次呼び出し、結果が得られたらその文字列を返します(30〜34行目)。どのチェックにも引っかからなかったらデフォルトの"MFD"を返します(35行目)。
チェック順はKabuki、Monochrome、OrangeVoyage、ASITで、ループで処理するためsend()を使った動的呼び出しを利用しています。呼び出し順は重要で、より少ない判定条件で判断できるものを先に判断することによってふるい分けしています。
各チェック関数のインターフェースは当該ブラウザなら略称文字列、当該ブラウザでなければnilを返すとしています。
Kabukiブラウザかどうかをチェックします。
入力値に"Kabuki"が含まれているか、"KBK"が含まれるのはKabukiブラウザなので"KBK"を返します。
Monochromeブラウザかどうかをチェックします。
入力値に"Monochrome"が含まれているもので、"KBK"が含まれないものを"GMC"と判断します。
OrangeVoyageブラウザかどうかをチェックします。
入力値に"Voyage"が含まれているもので、"Monochrome"と"ASIT"が含まれないものを"VYG"と判断します。
ASITブラウザかどうかをチェックします。
入力値に"ASIT"が含まれているもので、"Kabuki"が含まれないもの、入力値に".KNOT SLR"が含まれるものを"ASIT"と判断します。
問題の仕様だとこれで十分ですが、このプログラムがよろしくない理由を説明します。
最大の問題はuser agent文字列が追加された場合、影響が全体に及ぶことです。もう一つは不明なブラウザを判断しなければいけなくなった時、うまくできないことです。
この辺りをきちんとするとuser agent文字列に対してチェックするための正規表現と略称の組を作って判断する、というのが模範解答かなぁ、と思います。問題にOSや★の仕様について言及があるのもこの辺りを考慮してのことだと思います。