Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >回撸Rust China Conf 2020 之《浅谈Rust在算法题和竞赛中的应用》

回撸Rust China Conf 2020 之《浅谈Rust在算法题和竞赛中的应用》

作者头像
袁承兴
发布于 2021-01-04 02:35:52
发布于 2021-01-04 02:35:52
77500
代码可运行
举报
运行总次数:0
代码可运行

Review

很难通过某种单一的方式,就能get到所有Rust技能,学习的方式方法要多样化:

  • 循序渐进的系统性学习(内存管理->类型系统->所有权)
  • 主题学习(异步、宏)
  • 交流学习(开发者大会、社区)
  • 刻意练习(LeetCode)

刚刚结束的首届Rust China Conf 2020就是一种交流学习的方式。Rust中文社区采用直播并提供视频回放,为所有Rustacean提供了绝佳的、宝贵的学习资料。

本篇回撸一把《浅谈Rust在算法题和竞赛中的应用》,琳琅满目的特性和应用,让人爱不释手。

Speaker: Wu Aoxiang (吴翱翔)

视频:Day2 ,03:54:00~04:20:00

1 std::iter::Iterator::peekable

很实用的迭代器能力,标准库的注释如下:

Creates an iterator which can use [peek](https://doc.rust-lang.org/std/iter/struct.Peekable.html%23method.peek) to look at the next element of the iterator without consuming it.

fn peekable(self) -> Peekable<Self>

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let xs = [1, 2, 3];let mut iter = xs.iter().peekable();// peek() lets us see into the future
assert_eq!(iter.peek(), Some(&&1));
assert_eq!(iter.next(), Some(&1));

2 ?的Option解包能力的应用:LeetCode 7 整数反转。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
impl Solution {
    pub fn reverse(mut x: i32) -> i32 {
        || -> Option<i32> {
            let mut ret = 0i32;
            while x.abs() != 0 {
                ret = ret.checked_mul(10)?.checked_add(x%10)?;
                x /= 10;
            }
            Some(ret)
        }().unwrap_or(0)
    }
}

3 std::iter::Iterator::fold的应用:LeetCode 1486 数组异或操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
impl Solution {
    pub fn xor_operation(n: i32, start: i32) -> i32 {
        (1..n).fold(start, |acc, i| { acc ^ start + 2*i as i32 })
    }
}

4 std::net::IpAddr的应用:LeetCode 468 验证IP地址

IpAddr是个枚举类型,能通过String::parse直接进行解析。以下PPT上的代码并不能通过,所以我猜讲者只想给出一个算法框架方便做演示。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use std::net::IpAddr;
​
impl Solution {
    pub fn valid_ip_address(ip: String) -> String {
        match ip.parse::<IpAddr>() {
            Ok(IpAddr::V4(_)) => String::from("IPv4"),
            Ok(IpAddr::V6(_)) => String::from("IPv6"),
            _ => String::from("Neither"),
        }
    }
}

添加检查后可以通过测试,代码如下。可见标准库对IP地址的合法性还是比较宽容的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use std::net::IpAddr;
​
impl Solution {
    pub fn valid_ip_address(ip: String) -> String {
        match ip.parse::<IpAddr>() {
            Ok(IpAddr::V4(x)) => {
                let array: Vec<Vec<char>> = ip.split('.').map(|x| x.chars().collect()).collect();
                for i in 0..array.len() {
                    if (array[i][0] == '0' && array[i].len() > 1) { return String::from("Neither"); }
                }
                String::from("IPv4")
            },
            Ok(IpAddr::V6(_)) => {
                let array: Vec<Vec<char>> = ip.split(':').map(|x| x.chars().collect()).collect();
                for i in 0..array.len() {
                    if array[i].len() == 0  { return String::from("Neither"); }
                }
                String::from("IPv6")
            },
            _ => String::from("Neither"),
        }
    }
}

5 Rust调用C函数

调用C函数的能力,使得Rust的能力范围又扩展了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
extern "C" {
    fn rand() -> i32;
}
​
fn main() {
    let rand = unsafe { rand() };
    println!("{}", rand);
}

6 String零开销提供数组访问:std::string::String::into_bytes

从源码来看,String提供字节数组访问,简直不费吹灰之力。在ASCII范围的场景(大多数LeetCode字符串题目),每个字节通常对应一个拉丁字符,CRUD都非常方便。

源码如下:

This consumes the String, so we do not need to copy its contents.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_bytes(self) -> Vec<u8> {
    self.vec
}

需要注意的是,如果字符串涉及到国际化的时候,一个字节可能已经不再能映射一个字符了(比如中文字需要多字节存储),此时直接在字节层面进行CRUD都是非常危险的。

7 饱和运算(防溢出)

各类型的整数和浮点数都有saturating运算系列,以u8减法为例:

pub const fn saturating_sub(self, rhs: u8) -> u8

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
assert_eq!(100u8.saturating_sub(27), 73);
assert_eq!(13u8.saturating_sub(127), 0);

讲者在分析LeetCode 《1512 好数对的数目》一题中应用了该方法。但是就该题目来说,本文给出一种更加简单的解法,一次迭代即可。

同时讲者还使用了cargo bench,来得到该方法纳秒级的运行时间,比LeetCode的毫秒级要精确1000倍了。

这里需要注意的是,尽管Rust 2018已经放弃了extern crate,还是需要使用extern crate test来引入test "sysroot" crates。这是例外

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#![feature(test)]
extern crate test;
​
pub fn num_identical_pairs(nums: Vec<i32>) -> i32 {
    let mut map: [i32;101] = [0;101];
    nums.into_iter().fold(0, |mut acc, x| { 
        acc += map[x as usize];
        map[x as usize] += 1;
        acc })
}
​
#[cfg(test)]
mod tests {
    use test::Bencher;
    use super::*;
    #[bench]
    fn bench_func(b: &mut Bencher) {
        b.iter(|| {
            num_identical_pairs(vec![1,2,3,1,1,3,1]);
        });
    }
}

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PS D:\Project\rust_II\Language\r10_64_benchmark> cargo bench
    Finished bench [optimized] target(s) in 0.02s
     Running target\release\deps\r10_64_benchmark-8eb89c8ab9ad043d.exe
​
running 1 test
test tests::bench_func ... bench:          81 ns/iter (+/- 74)
​
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

8 善用cargo clippy

使用clippy,多多益善。cargo clippy是CI友好的,如果你是眼睛里容不下warning的人,可以设置使任何warning导致编译失败:

cargo clippy -- -D warnings

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【Rust日报】2020-11-21 使用 const 泛型的物理单位
const_unit_poc crate 链接,https://docs.rs/const_unit_poc/1.0.0/const_unit_poc/
MikeLoveRust
2020/12/07
3570
一起学Rust-理解所有权
原问题是这样的: &str 类型通过mem::size_of::<&str>()进行打印内存,始终为16字节。(这里不严谨了,应该是在64位机器上是16字节)
MikeLoveRust
2019/09/29
7670
一起学Rust-理解所有权
Rust的Vec优化
但当100个enum类型的数据中,有80%都是8字节数据,如f64,剩下的20%才是24字节的Vec,那占得比例:
fliter
2023/12/04
2890
Rust的Vec优化
Rust入坑指南:智能指针
在了解了Rust中的所有权、所有权借用、生命周期这些概念后,相信各位坑友对Rust已经有了比较深刻的认识了,今天又是一个连环坑,我们一起来把智能指针刨出来,一探究竟。
Jackeyzhe
2020/03/12
9240
Rust FFI 编程 - 手动绑定 C 库入门 02
本篇是《手动绑定 C 库入门》的第二篇。了解第一篇后,我们知道在调用 C 库时,需要重新在 Rust 中对该 C 库中的数据类型和函数签名进行封装。这篇我们将实践涉及到诸如数组,结构体等类型时,如何进行手动绑定。
MikeLoveRust
2020/05/24
1.3K0
【Rust日报】 2019-07-28:Rust Unsafe:把它们看作公理和定理
Seed(https://seed-rs.org/) 也是一个前端 Web 开发框架。这是用 Seed 写的一个前端网站(https://seed-rs-realworld.netlify.com/),这里是一些相关的资源(https://github.com/MartinKavik/awesome-seed-rs)。
MikeLoveRust
2019/07/30
6580
【Rust日报】 2020-1-16 用 Rust 来诠释 Epoll, Kqueue 和 IOCP
这其实是一本书,旨在说明 Epoll,Kqueue 和 IOCP 的工作原理,我们可以将其用于高效率、高性能的 I/O。其中一些实现将会使用 rust,原文地址:https://cfsamsonbooks.gitbook.io/epoll-kqueue-iocp-explained/
MikeLoveRust
2020/02/20
1.1K0
Rustilings 练习笔记
Rust有类型检查,执行运算或者赋值时候要遵循类型的规律,但是Rust可以重新定义同名变量,变量的类型可以发生改变
用户7267083
2023/03/20
1.5K0
Rust语法入门
Rust 是一种系统级编程语言,它的设计目标是提供高性能、安全性和并发性。Rust 的主要优势包括:
码客说
2023/04/17
1.3K0
一网打尽 Rust 语法
大家好,我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder
前端柒八九
2024/04/30
1830
一网打尽 Rust 语法
Rust Web 生态观察| SeaORM :要做 Rust 版本的 ActiveRecord
有些人说用 Rust 进行 Web 开发 是杀鸡用牛刀,这种观点其实是对「系统级语言」的刻板印象造成的。无论从性能、工程架构还是开发效率,Rust 其实都很出色,目前就是需要一套比较成熟的框架。无论如何,Rust 在 Web 开发领域的生态在逐步成型。
张汉东
2021/10/13
10.7K0
【翻译】Rust生命周期常见误区
我曾经有过的所有这些对生命周期的误解,现在有很多初学者也深陷于此。我用到的术语可能不是标准的,所以下面列了一个表格来解释它们的用意。
MikeLoveRust
2020/07/28
1.7K0
rust的单测和文档
测试的目的: 发现问题 保证项目长期的健壮性和可维护性 单元测试是重构的保证,编写无状态函数 rust的单元测试 内置测试框架:属性和宏 断言宏assert!, assert_eq!,assert_ne!,debug_assert! 运行测试 #[test] fn basic_test() { assert!(true); } //RUST_TEST_THREADS = 1 //rustc --test xxx.rs 隔离测试单独构建测试的文件夹和src同级 cargo test 故障测试 #s
李子健
2022/05/04
5680
简述:Rust-1.38.0 RELEASE NOTE
mac OS更新,如果使用brew安装的,那么恭喜你,现在brew上面只能更新到1.37.0:
江湖安得便相忘
2019/10/08
3860
从 RUST 库中公开 FFI
Wikipedia 将 FFI 定义为一种机制,通过这种机制,用一种编程语言编写的程序可以调用或使用用另一种编程语言编写的服务。
MikeLoveRust
2019/07/09
1.9K0
Rust FFI 编程 - 手动绑定 C 库入门 03
所有权是Rust中最核心的关注点之一。在Rust中,变量有严格的所有权关系,并于此之上建立了一整套上层建筑。
MikeLoveRust
2020/06/09
1.7K0
【Rust日报】 2019-05-19:Nokia 用 Rust 写了一个 Linux 内存调优工具
基于 crossterm 实现跨平台的终端输出。现在也可以输出成js,显示在web上。来看看效果。下图是可以转的。公众号里面图片大小有限制,发不上来,请看下面 demo 和 repo.
MikeLoveRust
2019/07/09
7030
【Rust日报】 2019-05-19:Nokia 用 Rust 写了一个 Linux 内存调优工具
Node.js 开发者的 Rust 入门指南
随着WebAssembly的进步,如果你想在JavaScript和Node.js的基础上,提高浏览器、服务器和边缘计算的性能,那么可以了解一下Rust。
五月君
2021/07/15
2K0
Node.js 开发者的 Rust 入门指南
Rust 中的枚举和控制流运算
枚举类型对于 Java 程序员来说不会陌生,它是列举常量成员的非常好用的工具。在 rust 中也同样如此,并且在 rust 中,枚举类型比其他语言中更为常用,尤其是 Option、Result 等语言自身定义的枚举类型,为 rust 本身添加了非常强大而独特的语法特性。
用户3147702
2022/06/27
9800
Rust 中的枚举和控制流运算
Rust 性能评估与调优实践
本文将围绕 Rust 性能评估和调优主题,比较系统地介绍 Rust 代码的性能优化经验。先从大的总原则出发,介绍在编写 Rust 过程中应该遵循哪些原则对后续优化有帮助。接下来会分享一些代码优化的方法和技巧,然后介绍可以用于 Rust 代码性能评估的工具,也会包括 Rust专用的一些异步并发测试工具介绍。
张汉东
2022/01/04
2.6K0
Rust 性能评估与调优实践
相关推荐
【Rust日报】2020-11-21 使用 const 泛型的物理单位
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验