1use std::fmt;
2use std::fmt::{Error, Formatter};
3
4pub trait Printable {
5 fn to_print_units(&self) -> PrintUnits;
6}
7
8#[derive(Clone, Debug)]
9pub struct PrintUnits(Vec<PrintUnit>);
10
11impl PrintUnits {
12 pub fn new(units: Vec<PrintUnit>) -> PrintUnits {
13 PrintUnits(units)
14 }
15
16 pub fn right_of(&mut self, others: &PrintUnits) {
18 let offset = others.max_x() - self.min_x() + 1;
19 self.shift_right(offset);
20 }
21
22 pub fn on_top_of(&mut self, others: &PrintUnits) {
24 let offset = self.max_y() - others.min_y() + 1;
25 self.shift_down(-offset);
26 }
27
28 pub fn below(&mut self, others: &PrintUnits) {
30 let offset = others.max_y() - self.min_y() + 1;
31 self.shift_down(offset);
32 }
33
34 pub fn width(&self) -> usize {
35 (self.max_x() - self.min_x() + 1) as usize
36 }
37
38 pub fn height(&self) -> usize {
39 (self.max_y() - self.min_y() + 1) as usize
40 }
41
42 pub fn append(&mut self, others: &PrintUnits) {
43 let mut others_copy = others.0.clone();
44 self.0.append(&mut others_copy);
45 }
46
47 fn min_x(&self) -> i64 {
48 self.0
49 .iter()
50 .map(|print_unit| print_unit.x)
51 .min()
52 .unwrap_or(0)
53 }
54
55 fn max_x(&self) -> i64 {
56 self.0
57 .iter()
58 .map(|print_unit| print_unit.x + print_unit.s.len() as i64 - 1)
59 .max()
60 .unwrap_or(0)
61 }
62
63 fn min_y(&self) -> i64 {
64 self.0
65 .iter()
66 .map(|print_unit| print_unit.y)
67 .min()
68 .unwrap_or(0)
69 }
70
71 fn max_y(&self) -> i64 {
72 self.0
73 .iter()
74 .map(|print_unit| print_unit.y)
75 .max()
76 .unwrap_or(0)
77 }
78
79 pub fn shift_right(&mut self, amount: i64) {
81 for print_unit in self.0.iter_mut() {
82 print_unit.x += amount
83 }
84 }
85
86 pub fn shift_down(&mut self, amount: i64) {
88 for print_unit in self.0.iter_mut() {
89 print_unit.y += amount
90 }
91 }
92}
93
94impl From<PrintUnit> for PrintUnits {
95 fn from(print_unit: PrintUnit) -> Self {
96 PrintUnits(vec![print_unit])
97 }
98}
99
100impl fmt::Display for PrintUnits {
101 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
102 let mut sorted = self.0.clone();
103 sorted.sort_by_key(|print_unit| (print_unit.y, print_unit.x));
104
105 if sorted.is_empty() {
106 return Ok(());
107 }
108
109 let mut sorted = PrintUnits(sorted);
110
111 sorted.shift_right(-sorted.min_x());
113 sorted.shift_down(-sorted.min_y());
114 let mut cur_x = 0;
115 let mut cur_y = 0;
116 for print_unit in sorted.0 {
117 if cur_y > print_unit.y {
120 panic!();
121 }
122
123 if cur_y < print_unit.y {
124 cur_x = 0;
125 }
126
127 if cur_x > print_unit.x {
128 panic!();
129 }
130
131 while cur_y < print_unit.y {
132 writeln!(f)?;
133 cur_y += 1;
134 }
135
136 while cur_x < print_unit.x {
137 write!(f, " ")?;
138 cur_x += 1;
139 }
140
141 f.write_str(&print_unit.s)?;
142
143 cur_x += print_unit.s.len() as i64;
144 }
145
146 Ok(())
147 }
148}
149
150#[derive(Clone, Debug)]
151pub struct PrintUnit {
152 x: i64,
153 y: i64,
154 s: String,
155}
156
157impl PrintUnit {
158 pub fn new(s: &str) -> PrintUnit {
159 PrintUnit {
160 x: 0,
161 y: 0,
162 s: s.to_owned(),
163 }
164 }
165}