6

次のことを行うコードを作成しようとしています。

0 から 9 までの数字を取り、この数字に 1 つ以上の文字を割り当てます。例えば:

0 = N,
1 = L,
2 = T,
3 = D,
4 = R,
5 = V or F,
6 = B or P,
7 = Z,
8 = H or CH or J,
9 = G

0123 のようなコードがある場合、それをエンコードするのは簡単です。それは明らかにコード NLTD を構成します。5、6、8 などの数字が導入されると、状況が異なります。051 のような数値は、複数の可能性をもたらします。

NVLとNFL

これは、5、6、8 などの数桁を含む長い数字ではさらに「悪化」することは明らかです。

私は数学がかなり苦手なので、プログラムに大量の数字を入力して、可能なすべての文字の組み合わせを吐き出すことができる適切な解決策をまだ考え出すことができませんでした。わからないので、少しでも参考になれば幸いです。順列と組み合わせに関する情報を掘り起こしましたが、うまくいきませんでした。

提案/手がかりをありがとう。コードを書くために必要な言語は PHP ですが、一般的なヒントをいただければ幸いです。

アップデート:

もう少し背景: (素早い回答に感謝します!)

私の質問の背後にあるアイデアは、人々が覚えたい数字をはるかに覚えやすい単語に簡単に変換できるようにするスクリプトを作成することです。これは、「疑似数秘術」と呼ばれることもあります。

可能なすべての組み合わせをスクリプトから取得し、それを削除された単語のデータベースに対して保持するようにしたいと考えています。これらの削除された単語は、辞書から取得したもので、質問で言及したすべての文字が削除されています。そうすれば、通常、エンコードする数値を 1 つ以上のデータベース レコードに簡単に関連付けることができます。そして、それが起こると、覚えたかった数字を覚えるために使用できる単語のリストができあがります。

4

9 に答える 9

8

再帰的に簡単に実行できます。

サイズ n のコード全体を処理するには、最初に n - 1 桁を処理する必要があります。n-1 桁のすべての回答が得られると、最後の数字の正しい文字を追加することで、全体の回答が推定されます。

于 2008-09-19T14:55:24.967 に答える
3

実際には、数値の可能な翻訳をすべて列挙して調べるよりもはるかに優れた解決策があります。辞書内のすべての単語に対して逆の計算を行い、数字の文字列を別のフィールドに格納するだけです。したがって、マッピングが次の場合:

0 = N,
1 = L,
2 = T,
3 = D,
4 = R,
5 = V or F,
6 = B or P,
7 = Z,
8 = H or CH or J,
9 = G

逆マッピングは次のとおりです。

N = 0,
L = 1,
T = 2,
D = 3,
R = 4,
V = 5,
F = 5,
B = 6,
P = 6,
Z = 7,
H = 8,
J = 8,
G = 9

「c」は削除され、「h」はとにかく 8 に変換されるため、「ch」のマッピングがないことに注意してください。

次に、辞書の単語の各文字を繰り返し処理し、一致する場合は適切な数字を出力し、一致しない場合は何もしません。

生成されたすべての数字文字列を別のフィールドとしてデータベースに保存します。何かを調べたいときは、入力された数に対して単純なクエリを実行するだけで済みます。数十回 (または数百回、数千回) 潜在的な単語を検索する必要はありません。

于 2008-09-19T17:00:56.273 に答える
2

数字を保持する一般的な構造 -> 文字の割り当ては、次のような配列または配列です。

// 0 = N, 1 = L, 2 = T, 3 = D, 4 = R, 5 = V or F, 6 = B or P, 7 = Z, 
// 8 = H or CH or J, 9 = G
$numberMap = new Array (
    0 => new Array("N"),
    1 => new Array("L"),
    2 => new Array("T"),
    3 => new Array("D"),
    4 => new Array("R"),
    5 => new Array("V", "F"),
    6 => new Array("B", "P"),
    7 => new Array("Z"),
    8 => new Array("H", "CH", "J"),
    9 => new Array("G"),
);

次に、少し再帰的なロジックにより、次のような関数が得られます。

function GetEncoding($number) {
    $ret = new Array();
    for ($i = 0; $i < strlen($number); $i++) {
        // We're just translating here, nothing special.
        // $var + 0 is a cheap way of forcing a variable to be numeric
        $ret[] = $numberMap[$number[$i]+0];
    }
}

function PrintEncoding($enc, $string = "") {
    // If we're at the end of the line, then print!
    if (count($enc) === 0) {
        print $string."\n";
        return;
    }

    // Otherwise, soldier on through the possible values.
    // Grab the next 'letter' and cycle through the possibilities for it.
    foreach ($enc[0] as $letter) {
        // And call this function again with it!
        PrintEncoding(array_slice($enc, 1), $string.$letter);
    }
}

再帰のための3つの乾杯!これは次の方法で使用されます。

PrintEncoding(GetEncoding("052384"));

本当に配列として欲しい場合は、出力バッファリングで遊んで、分割文字列として "\n" を使用して分解してください。

于 2008-09-19T15:14:28.697 に答える
2

この種の問題は通常、再帰によって解決されます。Rubyでは、1つの(迅速で汚い)解決策は

@values = Hash.new([])


@values["0"] = ["N"] 
@values["1"] = ["L"] 
@values["2"] = ["T"] 
@values["3"] = ["D"] 
@values["4"] = ["R"] 
@values["5"] = ["V","F"] 
@values["6"] = ["B","P"] 
@values["7"] = ["Z"] 
@values["8"] = ["H","CH","J"] 
@values["9"] = ["G"]

def find_valid_combinations(buffer,number)
 first_char = number.shift
 @values[first_char].each do |key|
  if(number.length == 0) then
     puts buffer + key
  else
     find_valid_combinations(buffer + key,number.dup)
    end
 end
end

find_valid_combinations("",ARGV[0].split(""))

コマンドラインからこれを実行すると、次のようになります。

$ ruby r.rb 051
NVL
NFL

これは総当たり検索バックトラッキングに関連しています

于 2008-09-19T15:35:28.273 に答える
1

Python での再帰的なソリューションを次に示します。

#!/usr/bin/env/python

import sys

ENCODING = {'0':['N'],
            '1':['L'],
            '2':['T'],
            '3':['D'],
            '4':['R'],
            '5':['V', 'F'],
            '6':['B', 'P'],
            '7':['Z'],
            '8':['H', 'CH', 'J'],
            '9':['G']
            }

def decode(str):
   if len(str) == 0:
       return ''
   elif len(str) == 1:
       return ENCODING[str]
   else:
       result = []
       for prefix in ENCODING[str[0]]:
           result.extend([prefix + suffix for suffix in decode(str[1:])])
       return result

if __name__ == '__main__':
   print decode(sys.argv[1])

出力例:

$ ./demo 1
['L']
$ ./demo 051
['NVL', 'NFL']
$ ./demo 0518
['NVLH', 'NVLCH', 'NVLJ', 'NFLH', 'NFLCH', 'NFLJ']
于 2008-09-19T15:30:09.690 に答える
0

秘訣は、特定の数字に一致するすべての可能な文字の組み合わせを生成するだけでなく、最も覚えやすい文字列を選択することです。各シーケンスに対してsoundexアルゴリズムを実行し、 Wordnetなどの英語の辞書と照合して、最も「実際の単語に聞こえる」シーケンスを見つけることをお勧めします。

于 2008-09-19T15:22:12.313 に答える
0

指定された数値文字列の可能なすべての文字の組み合わせのリストを数字までとします。pnsnth

次に、次のアルゴリズムが生成されます。pn+1

digit = s[n+1];
foreach(letter l that digit maps to)
{
    foreach(entry e in p(n))
    {
        newEntry = append l to e;
        add newEntry to p(n+1);
    }
}

p -1が定義されていないため、最初の反復はやや特殊なケースです。最初の文字のすべての可能な文字のリストとしてp 0を単純に初期化できます。

したがって、051 の例:

反復 0:

p(0) = {N}

反復 1:

digit = 5
foreach({V, F})
{
    foreach(p(0) = {N})
    {
        newEntry = N + V  or  N + F
        p(1) = {NV, NF}
    }
}

反復 2:

digit = 1
foreach({L})
{
    foreach(p(1) = {NV, NF})
    {
        newEntry = NV + L  or  NF + L
        p(2) = {NVL, NFL}
    }
}
于 2008-09-19T15:13:00.370 に答える
0

必要なフォームはおそらく次のようなものです。

function combinations( $str ){
$l = len( $str );
$results = array( );
if ($l == 0) { return $results; }
if ($l == 1)
{  
   foreach( $codes[ $str[0] ] as $code )
   {
    $results[] = $code;
   }
   return $results;
}
$cur = $str[0];
$combs = combinations( substr( $str, 1, $l ) );
foreach ($codes[ $cur ] as $code)
{
    foreach ($combs as $comb)
    {
        $results[] = $code.$comb;
    }
}
return $results;}

これは醜い pidgin-php ですので、まず確認してください。基本的な考え方は、[1..n] から文字列のすべての組み合わせを生成し、それらすべての組み合わせの先頭に、str[0] の可能な各コードを追加することです。最悪の場合、これは文字列の長さで指数関数的にパフォーマンスが向上することに注意してください。これは、コード化スキームに実際に多くのあいまいさが存在するためです。

于 2008-09-19T15:17:11.233 に答える
0

次のことができますか: 結果配列を作成します。配列内に値 "" を持つ項目を作成します

番号をループして、たとえば 051 を個別に分析します。

数値間の 1 対 1 の一致が見つかるたびに、結果配列のすべての項目に正しい値を追加します。したがって、"" は N になります。

1 対多の一致が見つかるたびに、1 つのオプションを使用して結果配列に新しい行を追加し、もう 1 つのオプションを使用して既存の結果を更新します。したがって、N は NV になり、新しいアイテムが作成されます NF

最後の数字は 1 対 1 の一致であるため、結果配列の項目は NVL と NFL になります。

結果を生成するには、結果配列をループして、それらを印刷するなどします。

于 2008-09-19T15:04:58.813 に答える