balanced_direction/
lib.rs

1//! This module provides an enum `Balance` that models a position within a 3x3 grid,
2//! along with several utility methods to manipulate these positions.
3//!
4//! The `Balance` enum is intended for scenarios where balanced ternary logic or
5//! grid-based movement is required. It represents nine possible positions in a
6//! 3x3 grid, with the central point being `(0, 0)` and other points positioned
7//! as offsets relative to this center.
8//!
9//! ## Main Features
10//!
11//! - `Balance` enum variants represent specific positions in the grid, such as
12//!   `TopLeft`, `Center`, or `BottomRight`.
13//! - Methods to convert between `Balance` variants and their 2D vector representations.
14//! - Utility methods to move a position in the grid (e.g., `up`, `down`, `left`, `right`).
15//!
16//! ## Usage Examples
17//!
18//! Basic usage of `Balance` to convert between variants and vectors:
19//!
20//! ```rust
21//! use balanced_direction::Balance;
22//!
23//! let position = Balance::TopLeft;
24//! assert_eq!(position.to_vector(), (-1, -1));
25//!
26//! let center = Balance::Center;
27//! assert_eq!(center.to_vector(), (0, 0));
28//!
29//! let balance = Balance::from_vector(-1, -1);
30//! assert_eq!(balance, Balance::TopLeft);
31//! ```
32//!
33//! Moving positions in the grid:
34//!
35//! ```rust
36//! use balanced_direction::Balance;
37//!
38//! let balance = Balance::Center;
39//! assert_eq!(balance.up(), Balance::Top);
40//! assert_eq!(balance.down(), Balance::Bottom);
41//! assert_eq!(balance.left(), Balance::Left);
42//! assert_eq!(balance.right(), Balance::Right);
43//! ```
44#![cfg_attr(not(test), no_std)]
45extern crate alloc;
46
47mod balance;
48mod conversions;
49mod operations;
50
51#[cfg(feature = "ternary")]
52mod ternary;
53
54mod path;
55
56pub use balance::Balance;
57pub use path::Path;
58
59#[cfg(test)]
60mod tests {
61    use core::fmt::Debug;
62    
63    pub fn assert_eq_array<T: PartialEq + Debug>(a: [T; 9], b: [T; 9]) {
64        for i in 0..9 {
65            assert_eq!(a[i], b[i]);
66        }
67    }
68
69    mod readme_examples {
70        use alloc::vec;
71        use crate::{Balance, Path};
72        use balanced_ternary::Digit;
73
74        #[test]
75        fn example_usage() {
76            let position = Balance::TopLeft;
77            assert_eq!(position.to_vector(), (-1, -1));
78
79            let moved = position.right();
80            assert_eq!(moved, Balance::Top);
81
82            let rotated = moved.rotate_left();
83            assert_eq!(rotated, Balance::Left);
84            assert_eq!(rotated.to_angle(), Balance::WEST);
85        }
86
87        #[test]
88        fn path_example() {
89            let movements = vec![Balance::Top, Balance::Right, Balance::Bottom];
90            let path = Path::new(movements);
91
92            assert_eq!(path.len(), 3);
93            assert_eq!(path.to_vector(), (1, 0)); // Cumulative movement: right by 1
94
95            let movements = vec![Balance::Top, Balance::Top, Balance::Top, Balance::Bottom];
96            let path = Path::new(movements);
97            assert_eq!(path.to_vector(), (0, -2)); // Cumulative movement: top by 2
98            let normalized_path = path.normalized();
99            assert_eq!(normalized_path.to_vector(), (0, -2));
100            assert_eq!(normalized_path.len(), 2);
101        }
102
103        #[test]
104        fn ternary_example() {
105            let position = Balance::Top;
106            let ternary_pair = position.to_ternary_pair();
107            assert_eq!(ternary_pair, (Digit::Zero, Digit::Neg)); // Top is represented as (0, -1)
108
109            let recreated_position = Balance::from_ternary_pair(Digit::Zero, Digit::Neg);
110            assert_eq!(recreated_position, Balance::Top);
111            let possibly = recreated_position.possibly();
112            assert_eq!(possibly, Balance::TopRight);
113        }
114
115    }
116}