一些rustlings题目

First Post:

Last Update:

iterator

iterators2

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
// iterators2.rs
//
// In this exercise, you'll learn some of the unique advantages that iterators
// can offer. Follow the steps to complete the exercise.
//
// Execute `rustlings hint iterators2` or use the `hint` watch subcommand for a
// hint.

// I AM NOT DONE

// Step 1.
// Complete the `capitalize_first` function.
// "hello" -> "Hello"
pub fn capitalize_first(input: &str) -> String {
let mut c = input.chars();
match c.next() {
None => String::new(),
Some(first) => first.to_uppercase().to_string()+c.as_str(),
}
}

// Step 2.
// Apply the `capitalize_first` function to a slice of string slices.
// Return a vector of strings.
// ["hello", "world"] -> ["Hello", "World"]
pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
let mut c =vec![];
words.iter().for_each(|x| c.push(capitalize_first(x)));
c
}
//

// Step 3.
// Apply the `capitalize_first` function again to a slice of string slices.
// Return a single string.
// ["hello", " ", "world"] -> "Hello World"
pub fn capitalize_words_string(words: &[&str]) -> String {
let mut s = String::new();
words.iter().for_each(|x| s+=capitalize_first(x).as_str());
s
}
//另一种方法
pub fn capitalize_words_string(words: &[&str]) -> String {
// let mut s = String::new();
// words.iter().for_each(|x| s+=capitalize_first(x).as_str());
let s =words.iter().map(|x| capitalize_first(x)).collect::<String>();
s
}

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

#[test]
fn test_success() {
assert_eq!(capitalize_first("hello"), "Hello");
}

#[test]
fn test_empty() {
assert_eq!(capitalize_first(""), "");
}

#[test]
fn test_iterate_string_vec() {
let words = vec!["hello", "world"];
assert_eq!(capitalize_words_vector(&words), ["Hello", "World"]);
}

#[test]
fn test_iterate_into_string() {
let words = vec!["hello", " ", "world"];
assert_eq!(capitalize_words_string(&words), "Hello World");
}
}

image.png
image.png

奇怪的报错

iterators5

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
fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize {
// map is a hashmap with String keys and Progress values.
// map = { "variables1": Complete, "from_str": None, ... }
// 要使用迭代器来重现计数功能,可以使用filter方法过滤出具有指定进度值的元素,
// 并使用count方法计算满足条件的元素数量。
map.values().filter(|&progress| *progress == value).count()

}

//我的写法
fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize {
// map is a hashmap with String keys and Progress values.
// map = { "variables1": Complete, "from_str": None, ... }
// todo!();
let count:usize=map.iter().filter(|(_,v)| **v==value).count();
count
}

fn count_collection_for(collection: &[HashMap<String, Progress>], value: Progress) -> usize {
let mut count = 0;
for map in collection {
for val in map.values() {
if val == &value {
count += 1;
}
}
}
count
}

fn count_collection_iterator(collection: &[HashMap<String, Progress>], value: Progress) -> usize {
// collection is a slice of hashmaps.
// collection = [{ "variables1": Complete, "from_str": None, ... },
// { "variables2": Complete, ... }, ... ]
// todo!();
// 需要先展平这个切片,然后再进行过滤和计数。
// 可以使用flat_map方法将切片中的每个HashMap转换为一个迭代器,
// 然后使用filter方法过滤出具有指定进度值的元素,
// 最后使用count方法计算满足条件的元素数量。
collection.into_iter()
.flat_map(|x| x.values())
.filter(|&progress| *progress == value)
.count()
}

conversions

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
// Your task is to complete this implementation in order for the line `let p =
// Person::from("Mark,20")` to compile Please note that you'll need to parse the
// age component into a `usize` with something like `"4".parse::<usize>()`. The
// outcome of this needs to be handled appropriately.
//
// Steps:
// 1. If the length of the provided string is 0, then return the default of
// Person.
// 2. Split the given string on the commas present in it.
// 3. Extract the first element from the split operation and use it as the name.
// 4. If the name is empty, then return the default of Person.
// 5. Extract the other element from the split operation and parse it into a
// `usize` as the age.
// If while parsing the age, something goes wrong, then return the default of
// Person Otherwise, then return an instantiated Person object with the results

// I AM NOT DONE

impl From<&str> for Person {
fn from(s: &str) -> Person {
if s.len()==0{
return Person::default();
}
let mut x:Vec<&str> = s.split(",").collect();
if x.len() != 2 {
return Person::default();
}
let name = x[0].trim();
if name.is_empty(){
return Person::default();
}

match x[1].parse::<usize>(){
Ok(age)=>Person{
name:name.to_string(),
age
},
Err(_) => Person::default()
}
}
}

heap(作为对heap的复习)

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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
heap
This question requires you to implement a binary heap function
*/
// I AM NOT DONE

use std::cmp::Ord;
use std::default::Default;

pub struct Heap<T>
where
T: Default,
{
count: usize,
items: Vec<T>,
comparator: fn(&T, &T) -> bool,
}

impl<T> Heap<T>
where
T: Default,
{
pub fn new(comparator: fn(&T, &T) -> bool) -> Self {
Self {
count: 0,
items: vec![T::default()],
comparator,
}
}

pub fn len(&self) -> usize {
self.count
}

pub fn is_empty(&self) -> bool {
self.len() == 0
}

pub fn add(&mut self, value: T) {
//TODO
self.items.push(value);
self.count += 1;
let mut idx = self.count;

while idx > 1 && (self.comparator)(&self.items[idx], &self.items[idx / 2]) == true {
self.items.swap(idx, idx / 2);
idx /= 2;
};//加入后不断上浮对父节点进行比较直到到达顶点或小/大于父节点
}

fn parent_idx(&self, idx: usize) -> usize {
idx / 2
}

fn children_present(&self, idx: usize) -> bool {
self.left_child_idx(idx) <= self.count
}

fn left_child_idx(&self, idx: usize) -> usize {
idx * 2
}

fn right_child_idx(&self, idx: usize) -> usize {
self.left_child_idx(idx) + 1
}

fn smallest_child_idx(&self, idx: usize) -> usize {
//TODO
let left_child = self.left_child_idx(idx);
let right_child = self.right_child_idx(idx);
if right_child > self.count || (self.comparator)(&self.items[left_child], &self.items[right_child]) == true {
left_child
} else {
right_child
}//right_child不存在或左节点比右节点大/小
}
}

impl<T> Heap<T>
where
T: Default + Ord,
{
/// Create a new MinHeap
pub fn new_min() -> Self {
Self::new(|a, b| a < b)
}

/// Create a new MaxHeap
pub fn new_max() -> Self {
Self::new(|a, b| a > b)
}
}

impl<T> Iterator for Heap<T>
where
T: Default+Copy,
{
type Item = T;

fn next(&mut self) -> Option<T> {
//TODO
if !self.is_empty() {
self.items.swap(1, self.count);
let res = self.items.swap_remove(self.count);
self.count -= 1;

// SWIM
let mut idx: usize = 1;
let mut smallest_child_idx = self.smallest_child_idx(idx);
while smallest_child_idx <= self.count && (self.comparator)(&self.items[smallest_child_idx], &self.items[idx]) {
self.items.swap(smallest_child_idx, idx);
idx = smallest_child_idx;
smallest_child_idx = self.smallest_child_idx(smallest_child_idx);
};
Some(res)
} else {
None
}
}//如果堆不为空,交换顶点和最小节点,然后检测下沉,如果顶点小/大于子节点,则不断下沉交换。
//因为add的上浮操作导致堆的顶点的下方是无序的,需要不断下沉保证堆的性质

}

pub struct MinHeap;

impl MinHeap {
#[allow(clippy::new_ret_no_self)]
pub fn new<T>() -> Heap<T>
where
T: Default + Ord,
{
Heap::new(|a, b| a < b)
}
}

pub struct MaxHeap;

impl MaxHeap {
#[allow(clippy::new_ret_no_self)]
pub fn new<T>() -> Heap<T>
where
T: Default + Ord,
{
Heap::new(|a, b| a > b)
}
}

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty_heap() {
let mut heap = MaxHeap::new::<i32>();
assert_eq!(heap.next(), None);
}

#[test]
fn test_min_heap() {
let mut heap = MinHeap::new();
heap.add(4);
heap.add(2);
heap.add(9);
heap.add(11);
assert_eq!(heap.len(), 4);
assert_eq!(heap.next(), Some(2));
assert_eq!(heap.next(), Some(4));
assert_eq!(heap.next(), Some(9));
heap.add(1);
assert_eq!(heap.next(), Some(1));
}

#[test]
fn test_max_heap() {
let mut heap = MaxHeap::new();
heap.add(4);
heap.add(2);
heap.add(9);
heap.add(11);
assert_eq!(heap.len(), 4);
assert_eq!(heap.next(), Some(11));
assert_eq!(heap.next(), Some(9));
assert_eq!(heap.next(), Some(4));
heap.add(1);
assert_eq!(heap.next(), Some(2));
}
}