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}