Skip to main content

bct/
translate.rs

1// This is not be the most efficient way to do it
2// TODO: Come up with an algorithm and implement it
3// Resource: http://homepage.divms.uiowa.edu/~jones/ternary/bct.shtml
4
5use std::iter;
6
7/// Translate a single BCT trybble (3 trits) into an integer
8///
9/// ```
10/// # use bct::translate::*;
11/// let result = bct_trybble_to_i8(0b010001);
12/// assert_eq!(result, 10);
13/// ```
14pub fn bct_trybble_to_i8(bct: u8) -> i8 {
15  match bct {
16    0b101010 => -13,  // TTT
17    0b101000 => -12,  // TT0
18    0b101001 => -11,  // TT1
19    0b100010 => -10,  // T0T
20    0b100000 => -9,   // T00
21    0b100001 => -8,   // T01
22    0b100110 => -7,   // T1T
23    0b100100 => -6,   // T10
24    0b100101 => -5,   // T11
25    0b001010 => -4,   // 0TT
26    0b001000 => -3,   // 0T0
27    0b001001 => -2,   // 0T1
28    0b000010 => -1,   // 00T
29    0b000000 => 0,    // 000
30    0b000001 => 1,    // 001
31    0b000110 => 2,    // 01T
32    0b000100 => 3,    // 010
33    0b000101 => 4,    // 011
34    0b011010 => 5,    // 1TT
35    0b011000 => 6,    // 1T0
36    0b011001 => 7,    // 1T1
37    0b010010 => 8,    // 10T
38    0b010000 => 9,    // 100
39    0b010001 => 10,   // 101
40    0b010110 => 11,   // 11T
41    0b010100 => 12,   // 110
42    0b010101 => 13,   // 111
43    _ => 0,
44  }
45}
46
47/// Translate an integer (-13 through 13) to a BCT trybble (3 trits)
48///
49/// ```
50/// # use bct::translate::*;
51/// let result = i8_trybble_to_bct(10);
52/// assert_eq!(result, 0b010001);
53/// ```
54pub fn i8_trybble_to_bct(number: i8) -> u8 {
55  match number {
56    -13 => 0b101010,  // TTT
57    -12 => 0b101000,  // TT0
58    -11 => 0b101001,  // TT1
59    -10 => 0b100010,  // T0T
60    -9 => 0b100000,   // T00
61    -8 => 0b100001,   // T01
62    -7 => 0b100110,   // T1T
63    -6 => 0b100100,   // T10
64    -5 => 0b100101,   // T11
65    -4 => 0b001010,   // 0TT
66    -3 => 0b001000,   // 0T0
67    -2 => 0b001001,   // 0T1
68    -1 => 0b000010,   // 00T
69    0 => 0b000000,    // 000
70    1 => 0b000001,    // 001
71    2 => 0b000110,    // 01T
72    3 => 0b000100,    // 010
73    4 => 0b000101,    // 011
74    5 => 0b011010,    // 1TT
75    6 => 0b011000,    // 1T0
76    7 => 0b011001,    // 1T1
77    8 => 0b010010,    // 10T
78    9 => 0b010000,    // 100
79    10 => 0b010001,   // 101
80    11 => 0b010110,   // 11T
81    12 => 0b010100,   // 110
82    13 => 0b010101,   // 111
83   _ => 0,
84  }
85}
86
87pub fn bct_trybble_to_ternary_string(bct: u8) -> Option<String> {
88  let res = match bct {
89    0b101010 => Some("TTT"),
90    0b101000 => Some("TT0"),
91    0b101001 => Some("TT1"),
92    0b100010 => Some("T0T"),
93    0b100000 => Some("T00"),
94    0b100001 => Some("T01"),
95    0b100110 => Some("T1T"),
96    0b100100 => Some("T10"),
97    0b100101 => Some("T11"),
98    0b001010 => Some("0TT"),
99    0b001000 => Some("0T0"),
100    0b001001 => Some("0T1"),
101    0b000010 => Some("00T"),
102    0b000000 => Some("000"),
103    0b000001 => Some("001"),
104    0b000110 => Some("01T"),
105    0b000100 => Some("010"),
106    0b000101 => Some("011"),
107    0b011010 => Some("1TT"),
108    0b011000 => Some("1T0"),
109    0b011001 => Some("1T1"),
110    0b010010 => Some("10T"),
111    0b010000 => Some("100"),
112    0b010001 => Some("101"),
113    0b010110 => Some("11T"),
114    0b010100 => Some("110"),
115    0b010101 => Some("111"),
116    _ => None,
117  };
118  match res {
119    Some(s) => Some(s.to_string()),
120    None => None,
121  }
122}
123
124fn negate_nonary(ns: &str) -> String {
125  ns.chars().map(|c| {
126    match c {
127      'D' => '4',
128      'C' => '3',
129      'B' => '2',
130      'A' => '1',
131      '1' => 'A',
132      '2' => 'B',
133      '3' => 'C',
134      '4' => 'D',
135      _ => '0',
136    }
137  }).collect()
138}
139
140pub fn i16_tryte_to_nonary_string(number: i16) -> Option<String> {
141  if number > 364 { return None }
142  if number < -364 { return None }
143
144  let is_negative = number < 0;
145  let mut v = Vec::new();
146  let mut n = if is_negative { -number } else { number };
147
148  while n > 0 {
149    let rem = n % 9;
150    n = n / 9;
151    if rem > 4 {
152      n += 1;
153    }
154
155    let out = match rem {
156      1 => "1",
157      2 => "2",
158      3 => "3",
159      4 => "4",
160      5 => "D",
161      6 => "C",
162      7 => "B",
163      8 => "A",
164      _ => "0",
165    };
166    v.push(out);
167  }
168
169  if v.len() < 3 {
170    let diff = 3 - v.len();
171    v.extend(iter::repeat("0").take(diff));
172  }
173
174  v.reverse();
175  let result = v.join("");
176
177  let nonary = if is_negative { negate_nonary(&result) } else { result };
178  Some(nonary)
179}