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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
extern crate svg;
use std::process;
use std::collections::HashSet;
use svg::node::element::path::Data;
use svg::node::element::Path;
use svg::Document;
pub fn recaman_sequence(n: u32) -> Vec<u32> {
if n == 0 {
return vec![];
}
let mut used_numbers = HashSet::new();
let mut seq: Vec<u32> = vec![0];
while seq.len() < n as usize {
let seq_len = seq.len() as i32;
let last = *seq.last().unwrap() as i32;
let subtract_result = last - seq_len;
let a: i32;
if subtract_result > 0 && !used_numbers.contains(&(subtract_result as u32)) {
a = subtract_result;
} else {
a = last + seq_len;
}
seq.push(a as u32);
used_numbers.insert(a as u32);
}
seq
}
fn get_line_height(recaman_sequence: &Vec<u32>) -> f32 {
0.5 * recaman_sequence.len() as f32
}
pub fn generate_svg_document(recaman_sequence: &Vec<u32>, stroke_width: f32) -> svg::Document {
const ARC_LARGE_FLAG: u32 = 0;
const ARC_ANGLE: u32 = 0;
const ARC_RX: u32 = 1;
const ARC_RY: u32 = 1;
const X_SCALE: u32 = 2;
let scale = |x: f32| x * X_SCALE as f32;
let line_height = scale(get_line_height(recaman_sequence));
let mut data = Data::new().move_to((0, line_height));
let mut should_go_up = false;
let mut last_x = 0;
let mut max_x = u32::min_value();
for x in recaman_sequence {
let x = *x;
let sweep_flag = if x > last_x {
!should_go_up
} else {
should_go_up
};
data = data.elliptical_arc_to((
ARC_RX,
ARC_RY,
ARC_ANGLE,
ARC_LARGE_FLAG,
sweep_flag as u32,
scale(x as f32),
line_height,
));
last_x = x;
should_go_up = !should_go_up;
max_x = max_x.max(x);
}
const MARGIN: f32 = 2.0;
let document = Document::new().set(
"viewBox",
(
scale(0.0 - MARGIN),
scale(0.0 - MARGIN),
scale(max_x as f32 + MARGIN * 2.0),
line_height * 2.0 + scale(MARGIN * 2.0),
),
);
let path = Path::new()
.set("fill", "none")
.set("stroke", "black")
.set("stroke-width", stroke_width)
.set("d", data);
document.add(path)
}
pub fn write_svg_document(document: svg::Document, filename: &str) {
svg::save(filename, &document).unwrap_or_else(|err| {
eprintln!("Couldn't write file: {}", err.to_string().to_lowercase());
process::exit(1);
});
}