10 進数を平衡三進数に変換する haskell ワンライナー: bt x = aux [] x where aux ts x = let (q, r, y, ts') = (div y 3, mod y 3, x + 1, r - 1 : ts) in if (0 == q) then ts' else aux ts' q

世の中に平衡三進数、あるいは対称三進数、英語で言えば balanced ternary というものがあると知ったのが昨日のこと。(「http://www.amazon.co.jp/gp/product/4622075482/ref=as_li_ss_tl?ie=UTF8&tag=ryohji-22&linkCode=as2&camp=247&creative=7399&creativeASIN=4622075482」にあった)
-1 と 0 と 1 を使った位取りをすることで、正と負の数をひとつの表記法で統一的にあらわすことができるというもの。
たとえば 13 は 1 * 3^2 + 1 * 3^1 + 1 * 3^0 なので 111 と書き、 -8 なら -1 * 3^2 + 0 * 3^1 + 1 * 3^0 なので -101 とあらわす、といった感じ。
各桁の符号を反転すれば正負が逆転するので、引き算は引く数を否定してから足し算と単純。

それはそれとして、この 10 進数から平衡三進数に変換できないかとこねくりまわしてみた。結果はこれ:

bt x = aux [] x  where
 aux ts x = let
   q = (x + 1) `div` 3
   r = (x + 1) `mod` 3
   ts' = r - 1 : ts
  in if (0 == q) then ts' else aux ts' q

ざっと -13 から 13 の範囲に適用してみる。

Prelude> let bt x = aux [] x where aux ts x = let (q, r, y, ts') = (div y 3, mod y 3, x + 1, r - 1 : ts) in if (0 == q) then ts' else aux ts' q
Prelude> map bt [-13..13]
[[-1,-1,-1],[-1,-1,0],[-1,-1,1],[-1,0,-1],[-1,0,0],[-1,0,1],[-1,1,-1],[-1,1,0],,1,1],[-1,-1],[-1,0],[-1,1],[-1],[0],[1],[1,-1],[1,0],[1,1],[1,-1,-1],[1,-1,0],[1,-1,1],[1,0,-1],[1,0,0],[1,0,1],[1,1,-1],[1,1,0],[1,1,1]]

うん、あってそう。

x + 2 に対して 5 で div や mod を取り r - 2 をリストに結合していけば平衡五進数に、 x + 3 に対して 7 で div や mod を取り r - 3 をリストに結合していけば平衡七進数に、という変換もできる。