すべてのローカライズと文字列タイプで機能する一般化された文字列逆関数を書くことは可能ですか?


16

Dev-DaysJon Skeet(Tony the Ponyと一緒に)のプレゼンテーションを見ていました

「文字列の逆関数を書く」はインタビュー101をコーディングしていますが、すべてのローカリゼーションとすべての文字列タイプで機能するものではなく、一般的な文字列の逆関数を書くことが実際に可能かどうかはわかりません。

入力文字列がASCII、UTF8、UTF16(固定長および可変長)などであるかどうかを検出することとは別に、
Jonが強調表示した「次の文字にアクセントを適用する」(U + 0301)コードがあります。次に、表示される場合とされない場合、または二重文字としてエンコードされる場合があります。

「文字列を逆にする」ことは、実際には難しいコンピューターサイエンスのタスクの1つであるようです。


いや、難易度を1段階上げるが、人々に説明するのが簡単な何かのために停止する問題を試してください。
JBキング

非主観的で技術的な質問なので、これはStackOverflowに適していると言いたいと思います(ただし、ここに再投稿しないでください。十分な人がここで閉じることに投票したら自動移行されます)。
ペテルトレック

1
プログラミング言語に依存します。たとえば、Rubyでは"stressed".reverse:p
Marcelo

偉大な哲学的質問。FWIW、JavaのStringBuilderはサロゲートを取得しますが、コンバイナは取得しません
-kdgregory

2
「Javaを使用してこの文字列を元に戻す」というのは、いい質問です。:)
スコットCウィルソン

回答:


5

はい。文字列を取得した場合、各文字を確実に反転できます。

Jonが指摘している問題は、反転が意味をなし、言語と文化のルール、文字、およびエンコードに準拠していることです。水は深く行くほど濁ります。

C#で任意の種類の文字列操作を行っている場合、書き込みおよび読み取り時にインバリアントカルチャを使用すると、安全に操作できます。それ以外の場合は、トルコ語のサポートコールの失敗に備えてください。

ToUpper()は非常に無害に見えますが、それは起こるのを待っている壮大な失敗です。


2
もう1つの質問は、(インタビューQ以外の)誰もが文字列リバースを使用することです 文字列でさえ、ほとんどない実際と-私は今までI / Oポートの低レベルのバッファ操作のためにそれを必要としてきました
マーティンベケット

@マーティン-同意しました。たぶん、パリドロームを見つけるための英語プログラムですか?クイズの問題を解く以外に使ったことはないと思います。
ジョンレイナー

@Martin true。皮肉なことだと思う。:)
スコットCウィルソン

2

一般的に、この質問が尋ねられるとき、それはUS-ASCIIを仮定しています。ポインターがどのように機能するかを理解しているかどうかを確認するために、ポイントはユニコードの個人の知識をテストすることではありません(これは興味深い続編ですが)。驚くほど多くの人々は、この種のポインター演算を行うことができません。


2
「ユニコードでこれはどのように失敗しますか?」フォローアップの良い質問です
マーティンベケット

良いですが、おそらくある程度高度です-結局のところ、「この文字列を元に戻す」ことは、エントリーレベルのインタビューの質問です。おそらく非常に恥ずかしがり屋であり、あなたがそれらを暖めようとしているのでない限り、あなたはおそらく経験豊かな人にこれほど簡単なことを尋ねないでしょう。
スコットCウィルソン

1

インタビューの質問として、通常、8ビット項目のインプレーススワップを実行してその順序を逆にする技術的な部分について尋ねられます(実際にどの文字が表されるかは関係ありません)。

同時に、特に比較的年配の人にインタビューしている場合は、少なくとも仕様と入力の正確な形式についてのいくつかの質問を聞くことを期待できます。単に8ビットのアイテムを交換するという単純なケースに戻して、それよりも広い意味で考えるかどうかを知ることは価値があるかもしれません。

幅広い入力を処理する必要がある場合、ネットワークスタックのような「スタック」の観点から考える必要があります。いくつかのレイヤーでソフトウェアを構築する必要があり、各レイヤーは特定の順序でかなり特定の変換セットを適用します。これにより、変換の各部分を十分にシンプルに保つことができ、制御下に置くことができ、要件を満たす十分な機会が得られます。

少なくともある程度実行可能であるとわかった可能性の1つを説明します。しかし、より良いアイデアを持つ他の人がいる可能性があることを認めたのは私が最初です。少なくとも私にとっては、これはブルートフォースエンジニアリングに少し似ているように見えますが、実際のエレガンスはほとんどありません。

通常、他の表現をUCS-4(別名UTF-32)に変換することから始めます。このため、一般的には、ユーザーが自分でそれを理解しようとするよりも、ユーザーからの入力に依存することを好みます。場合によっては、オクテットの特定のシーケンスが特定のエンコーディングスキームのルールに従っていないことを確認できますが、特定のエンコーディングスキームに従っていることはほとんどありません。

次のステップはオプションです。4つのUnicode正規化形式のいずれかに入力を正規化できます。この場合、おそらく「NFKC」変換を適用する必要があります。つまり、互換性分解とそれに続く標準的な構成です。これは(可能であれば)ダイアクリティカルマーク形式(ジョンが言及したU + 301など)を単一のコードポイントに変換します(たとえば、「A +」と「A + 301」は「ラテン語大文字Aと鋭角」に変換されます) 、U + 00C1)。

次に、すべての文字を最初から最後までウォークスルーし、文字列を実際の文字に分割します。発音区別符号を結合する(まだ)場合は、変更する文字でそれらを保持します。この結果は、通常、それぞれの位置や長さなど、文字列内の実際の文字のインデックスになります。

通常、前の手順で作成したインデックスを使用して、これらの完全な文字の順序を逆にします。

次に(再度、オプションで)NFD(標準分解)などの別のUnicode正規化プロセスを適用します。これにより、前述の「ラテン語Aの鋭角」が2つのコードポイント「ラテン語の大文字A」と「結合急性」に戻ります。あなたの入力はで開始するU + 00C1が含まれているために起こった場合は、しかし、それはまた、変換しますことを、同様の2つのコード・ポイントに。

次に、UCS-4コードポイントのシーケンスを目的のエンコード(UTF-8、UTF-16など)にエンコードします。

Unicodeの正規化手順により、文字列を格納するために必要なコードポイントの数が変わる可能性があるため、それらを含めると、元のストレージに適合する結果文字列を計画できなくなります。明らかに、結果のコードポイントも入力コードポイントに直接対応しない場合があります。


ジョンが立ち上げる前に、私はU + 301に出くわしていませんでした。私はそれは後方互換性だと想像-それは、すべてのアクセント付き文字のグリフをUnicodeで必要なのなぜ私が見ることができない
マーティンベケット

@Martin:実際にはかなりの数の発音区別記号があります(U + 0363からU + 036Fまでの範囲はせいぜい時代遅れですが)。事前に構成された文字は、最も一般的な可能性のいくつかに提供され、必要に応じて発音区別符を組み合わせます。
ジェリーコフィン

ストレージ、正規化、変換が多すぎます。文字を繰り返し、インプレースの構成コード単位の順序を逆にします。次に、すべてのコード単位のインプレースの順序を逆にします。
デデュプリケーター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.