これは、比較的些細な問題に対して最も洗練されたJavaScript、Ruby、またはその他のソリューションを考え出すための課題です。
この問題は、最長の一般的な部分文字列問題のより具体的なケースです。配列内で最も長い共通の開始部分文字列を見つけるだけで済みます。これにより、問題が大幅に簡素化されます。
たとえば、の最長の部分文字列[interspecies, interstelar, interstate]
は「inters」です。ただし、で「ific」を見つける必要はありません[specifics, terrific]
。
シェルのようなタブ補完に関する回答の一部として、JavaScriptでソリューションをすばやくコーディングすることで、問題を解決しました(テストページはこちら)。これがその解決策ですが、少し調整されています。
function common_substring(data) {
var i, ch, memo, idx = 0
do {
memo = null
for (i=0; i < data.length; i++) {
ch = data[i].charAt(idx)
if (!ch) break
if (!memo) memo = ch
else if (ch != memo) break
}
} while (i == data.length && idx < data.length && ++idx)
return (data[0] || '').slice(0, idx)
}
このコードは、Rubyの同様のソリューションとともにこのGistで利用できます。要旨をgitリポジトリとして複製して試してみることができます。
$ git clone git://gist.github.com/257891.git substring-challenge
私はそれらの解決策にあまり満足していません。よりエレガントで実行の複雑さを軽減することで解決できるかもしれないと感じています。そのため、このチャレンジを投稿しています。
私は答えとして、私が最もエレガントまたは簡潔だと思う解決策を受け入れるつもりです。たとえば、私が思いついたクレイジーなRubyハックは&
、Stringで演算子を定義することです。
# works with Ruby 1.8.7 and above
class String
def &(other)
difference = other.to_str.each_char.with_index.find { |ch, idx|
self[idx].nil? or ch != self[idx].chr
}
difference ? self[0, difference.last] : self
end
end
class Array
def common_substring
self.inject(nil) { |memo, str| memo.nil? ? str : memo & str }.to_s
end
end
JavaScriptまたはRubyのソリューションが推奨されますが、何が起こっているのかを説明する限り、他の言語で巧妙なソリューションを披露することができます。標準ライブラリのコードのみを使用してください。
更新:私のお気に入りのソリューション
kennebecによるJavaScriptの並べ替えソリューションを「答え」として選択したのは、それが予想外で天才的であると感じたからです。実際の並べ替えの複雑さを無視すると(言語の実装によって無限に最適化されると想像してみてください)、ソリューションの複雑さは2つの文字列を比較するだけです。
その他の優れたソリューション:
- FMによる「regexgreed」は、把握するのに1、2分かかりますが、その優雅さがあなたを襲います。イェフダカッツも正規表現ソリューションを作成しましたが、より複雑です
commonprefix
Pythonの場合— Roberto Bonvalletは、この問題を解決するためにファイルシステムパスを処理するために作成された機能を使用しました- Haskellのワンライナーは圧縮されているかのように短く、美しい
- 簡単なRubyワンライナー
参加していただきありがとうございます!コメントからわかるように、私は多くのことを学びました(Rubyについてさえ)。