変換には、いくつかの巧妙な省略形を使用できます。次のコードは「間違った」方向です。これは、2 進加算のみを使用して 3^2 = 2^3 + 1 という事実に基づいて、3 進から 2 進に変換したものです。基本的には、3 桁の 2 桁を 2 進数の 3 桁に変換しています。2 進数から 3 進数への変換は、3 進数の加算 (およびおそらく減算) が必要になるため、少し複雑になります (それに取り組んでいます)。リストの先頭にある最下位桁を想定しているため (これが唯一の意味のある方法です)、数字を「逆方向」に読む必要があります。
addB :: BNumber → BNumber → BNumber
addB a [] = a
addB [] b = b
addB (B0:as) (B0:bs) = B0 : (addB as bs)
addB (B0:as) (B1:bs) = B1 : (addB as bs)
addB (B1:as) (B0:bs) = B1 : (addB as bs)
addB (B1:as) (B1:bs) = B0 : (addB (addB as bs) [B1])
t2b :: TNumber → BNumber
t2b [] = []
t2b [T0] = [B0]
t2b [T1] = [B1]
t2b [T2] = [B0,B1]
t2b (T2:T2:ts) = let bs = t2b ts in addB bs (B0:B0:B0:(addB bs [B1]))
t2b (t0:t1:ts) =
let bs = t2b ts
(b0,b1,b2) = conv t0 t1
in addB bs (b0:b1:b2:bs)
where conv T0 T0 = (B0,B0,B0)
conv T1 T0 = (B1,B0,B0)
conv T2 T0 = (B0,B1,B0)
conv T0 T1 = (B1,B1,B0)
conv T1 T1 = (B0,B0,B1)
conv T2 T1 = (B1,B0,B1)
conv T0 T2 = (B0,B1,B1)
conv T1 T2 = (B1,B1,B1)
[編集] これはバイナリからターナリへの方向です。予想通り、もう少し長くなります。
addT :: TNumber → TNumber → TNumber
addT a [] = a
addT [] b = b
addT (T0:as) (T0:bs) = T0 : (addT as bs)
addT (T1:as) (T0:bs) = T1 : (addT as bs)
addT (T2:as) (T0:bs) = T2 : (addT as bs)
addT (T0:as) (T1:bs) = T1 : (addT as bs)
addT (T1:as) (T1:bs) = T2 : (addT as bs)
addT (T2:as) (T1:bs) = T0 : (addT (addT as bs) [T1])
addT (T0:as) (T2:bs) = T2 : (addT as bs)
addT (T1:as) (T2:bs) = T0 : (addT (addT as bs) [T1])
addT (T2:as) (T2:bs) = T1 : (addT (addT as bs) [T1])
subT :: TNumber → TNumber → TNumber
subT a [] = a
subT [] b = error "negative numbers supported"
subT (T0:as) (T0:bs) = T0 : (subT as bs)
subT (T1:as) (T0:bs) = T1 : (subT as bs)
subT (T2:as) (T0:bs) = T2 : (subT as bs)
subT (T0:as) (T1:bs) = T2 : (subT as (addT bs [T1]))
subT (T1:as) (T1:bs) = T0 : (subT as bs)
subT (T2:as) (T1:bs) = T1 : (subT as bs)
subT (T0:as) (T2:bs) = T1 : (subT as (addT bs [T1]))
subT (T1:as) (T2:bs) = T2 : (subT as (addT bs [T1]))
subT (T2:as) (T2:bs) = T0 : (subT as bs)
b2t :: BNumber → TNumber
b2t [] = []
b2t [B0] = [T0]
b2t [B1] = [T1]
b2t [B0,B1] = [T2]
b2t [B1,B1] = [T0,T1]
b2t (b0:b1:b2:bs) =
let ts = b2t bs
(t0,t1) = conv b0 b1 b2
in subT (t0:t1:ts) ts
where conv B0 B0 B0 = (T0,T0)
conv B1 B0 B0 = (T1,T0)
conv B0 B1 B0 = (T2,T0)
conv B1 B1 B0 = (T0,T1)
conv B0 B0 B1 = (T1,T1)
conv B1 B0 B1 = (T2,T1)
conv B0 B1 B1 = (T0,T2)
conv B1 B1 B1 = (T1,T2)
[Edit2] addT を必要としない、subT のわずかに改良されたバージョン
subT :: TNumber → TNumber → TNumber
subT a [] = a
subT [] b = error "negative numbers supported"
subT (a:as) (b:bs)
| b ≡ T0 = a : (subT as bs)
| a ≡ b = T0 : (subT as bs)
| a ≡ T2 ∧ b ≡ T1 = T1 : (subT as bs)
| otherwise = let td = if a ≡ T0 ∧ b ≡ T2 then T1 else T2
in td : (subT as $ addTDigit bs T1)
where addTDigit [] d = [d]
addTDigit ts T0 = ts
addTDigit (T0:ts) d = d:ts
addTDigit (T1:ts) T1 = T2:ts
addTDigit (t:ts) d = let td = if t ≡ T2 ∧ d ≡ T2 then T1 else T0
in td : (addTDigit ts T1)