私は今日、仕事のためにこれと同じ問題を解決しなければなりませんでした。私の解決策はElixirで書かれており、再帰を使用していますが、その考え方を平易な英語で説明しています。
変換の例を次に示します。
0-> "A"、1-> "B"、2-> "C"、3-> "D"、.. 25-> "Z"、26-> "AA"、27-> "AB" 、..。
一見、通常の26ベースのカウントシステムのように見えるかもしれませんが、残念ながらそれほど単純ではありません。「問題」は、次のことに気付くと明らかになります。
A = 0
AA = 26
これは、通常のカウントシステムとは相容れません。通常のカウントシステムでは、「0」は、その単位以外の小数点以下の桁にある場合、「1」として動作しません。
アルゴリズムを理解するために、より単純ですが同等の2進数システムを考えてみましょう。
A = 0
B = 1
AA = 2
AB = 3
BA = 4
BB = 5
AAA = 6
通常の2進数カウントシステムでは、2の累乗(1、2、4、8、16)をとることで小数点以下の桁数の「値」を決定でき、2進数の値は、各桁にその桁の桁数を掛けて計算されます。価値。例:10101 = 1 *(2 ^ 4)+ 0 *(2 ^ 3)+ 1 *(2 ^ 2)+ 0 *(2 ^ 1)+ 1 *(2 ^ 0)= 21
より複雑なABシステムでは、小数点以下の値が次のようになっていることがわかります。
1, 2, 6, 14, 30, 62
パターンは、それ自体がであることを示しています(previous_unit_place_value + 1) * 2
。そのため、次に低い単位の場所の値を取得するには、2で除算して1を減算します。
これは、ベース26システムに拡張できます。単純に26で割り、1を引きます。
これで、通常の基数10の数値を特殊な基数26に変換する式が明らかになりました。入力がであるとしましょうx
。
- アキュムレータリストを作成します
l
。
- xが26未満の場合は、設定
l = [x | l]
して手順5に進みます。それ以外の場合は続行します。
- xを2で割ります。床の結果は
d
で、余りはr
です。
- アキュムレータリストの先頭として残りをプッシュします。すなわち
l = [r | l]
- (d-1)を入力としてステップ2に進みます。例:
x = d - 1
- """のすべての要素を
l
対応する文字に変換します。0->Aなど。
それで、最後に、これがエリクサーで書かれた私の答えです:
defmodule BijectiveHexavigesimal do
def to_az_string(number, base \\ 26) do
number
|> to_list(base)
|> Enum.map(&to_char/1)
|> to_string()
end
def to_09_integer(string, base \\ 26) do
string
|> String.to_charlist()
|> Enum.reverse()
|> Enum.reduce({0, nil}, fn
char, {_total, nil} ->
{to_integer(char), 1}
char, {total, previous_place_value} ->
char_value = to_integer(char + 1)
place_value = previous_place_value * base
new_total = total + char_value * place_value
{new_total, place_value}
end)
|> elem(0)
end
def to_list(number, base, acc \\ []) do
if number < base do
[number | acc]
else
to_list(div(number, base) - 1, base, [rem(number, base) | acc])
end
end
defp to_char(x), do: x + 65
end
単にとして使用しますBijectiveHexavigesimal.to_az_string(420)
。オプションの「ベース」引数も受け入れます。
OPがJavascriptについて質問したことは知っていますが、後世のためにElixirソリューションを提供したいと思いました。