1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use crate::constants::*;
use std::convert::TryInto;

fn encode_unit(index: usize, buffer: &mut String) {
  let tens = index / SYLLABLES.len();
  if tens > 0 {
    encode_unit(tens, buffer);
  }

  let units = index % SYLLABLES.len();
  buffer.push_str(SYLLABLES[units]);
}

pub fn encode(value: i64) -> String {
  let mut buffer = String::new();
  let index: usize = if value < 0 {
    buffer.push_str(NEGATIVE_SYLLABLE);
    -1 * value
  } else {
    value
  }
  .try_into()
  .unwrap();

  encode_unit(index, &mut buffer);
  buffer
}

#[cfg(test)]
mod tests {
  use super::*;
  use rand::Rng;

  #[test]
  fn single_syllable() {
    let units = rand::thread_rng().gen_range(0, SYLLABLES.len());
    let value = units as i64;

    assert_eq!(encode(value), SYLLABLES[units]);
  }

  #[test]
  fn one_tens() {
    let tens = 1;
    let units = rand::thread_rng().gen_range(0, SYLLABLES.len());
    let value = (tens * SYLLABLES.len() + units) as i64;

    assert_eq!(encode(value), [SYLLABLES[tens], SYLLABLES[units]].concat());
  }

  #[test]
  fn many_tens() {
    let tens = rand::thread_rng().gen_range(2, SYLLABLES.len());
    let units = rand::thread_rng().gen_range(0, SYLLABLES.len());
    let value = (tens * SYLLABLES.len() + units) as i64;

    assert_eq!(encode(value), [SYLLABLES[tens], SYLLABLES[units]].concat());
  }

  #[test]
  fn many_hundreds() {
    let hundreds = rand::thread_rng().gen_range(1, SYLLABLES.len());
    let tens = rand::thread_rng().gen_range(0, SYLLABLES.len());
    let units = rand::thread_rng().gen_range(0, SYLLABLES.len());
    let value =
      (hundreds * SYLLABLES.len() * SYLLABLES.len() + tens * SYLLABLES.len() + units) as i64;

    assert_eq!(
      encode(value),
      [SYLLABLES[hundreds], SYLLABLES[tens], SYLLABLES[units]].concat()
    );
  }

  #[test]
  fn negative() {
    let units = rand::thread_rng().gen_range(1, SYLLABLES.len());
    let value = (units as i64) * -1;

    assert_eq!(
      encode(value),
      [NEGATIVE_SYLLABLE, SYLLABLES[units]].concat()
    );
  }
}