【Rust Exercism 练习详解:Anagram + Space Age + Sublist(附完整代码与深度解读)】

Rust Exercism 练习系列详解(Anagram、Space Age、Sublist)

大家好,我是 小杍随笔 。最近在刷 Exercism Rust Track 时,遇到了几个经典练习:Anagram(变位词)Space Age(行星年龄)Sublist(子列表判断) 。这些练习分别考察了 生命周期(lifetimes)trait 默认实现 + 宏枚举 + 模式匹配 + windows API 等 Rust 核心特性。

下面我把我们讨论的过程、代码实现和详细解读整理成一篇,供大家参考。


1. Anagram(变位词判断)

练习要求:给定一个目标词和若干候选词,找出所有是目标词变位词(anagram)的候选词。忽略大小写,不把单词自身视为变位词,支持 Unicode。

关键点

  • 需要调整函数签名中的生命周期
  • 使用小写 + 排序判断字母组成是否相同

完整实现

rust 复制代码
use std::collections::HashSet;

fn normalize(s: &str) -> Vec<char> {
    let mut chars: Vec<char> = s.to_lowercase().collect();
    chars.sort_unstable();
    chars
}

pub fn anagrams_for<'a>(word: &str, possible_anagrams: &[&'a str]) -> HashSet<&'a str> {
    let word_norm = normalize(word);

    possible_anagrams
        .iter()
        .filter(|&&candidate| {
            // 排除自身(忽略大小写)
            if candidate.to_lowercase() == word.to_lowercase() {
                return false;
            }
            normalize(candidate) == word_norm
        })
        .copied()
        .collect()
}

解读normalize 函数把字符串转为小写字符并排序,是判断变位词最简洁高效的方式。生命周期 'a 确保返回的引用与输入候选词生命周期一致。


2. Space Age(行星年龄计算)

练习要求:给定秒数,计算在不同行星上相当于多少年(每个行星轨道周期不同)。

关键点

  • From<u64> 实现
  • Planet trait 为每个行星实现 years_during

推荐实现(清晰版):

rust 复制代码
#[derive(Debug)]
pub struct Duration {
    seconds: u64,
}

const SECONDS_PER_EARTH_YEAR: u64 = 31_557_600;

const MERCURY: f64 = 0.2408467;
const VENUS: f64 = 0.61519726;
const EARTH: f64 = 1.0;
const MARS: f64 = 1.8808158;
const JUPITER: f64 = 11.862615;
const SATURN: f64 = 29.447498;
const URANUS: f64 = 84.016846;
const NEPTUNE: f64 = 164.79132;

impl From<u64> for Duration {
    fn from(s: u64) -> Self {
        Duration { seconds: s }
    }
}

pub trait Planet {
    fn years_during(d: &Duration) -> f64;
}

pub struct Mercury;

impl Planet for Mercury {
    fn years_during(d: &Duration) -> f64 {
        d.seconds as f64 / SECONDS_PER_EARTH_YEAR as f64 / MERCURY
    }
}

// Venus、Earth、Mars、Jupiter、Saturn、Uranus、Neptune 同理实现...

计算公式

行星年数 = (秒数 ÷ 地球年秒数) ÷ 该行星轨道周期(地球年)

优化建议 :可以使用 macro_rules! 消除重复代码,或者用关联常量 + 默认实现让代码更 DRY。


3. Sublist(子列表 / 超列表判断)

练习要求:判断两个列表的关系:

  • Equal(完全相等)
  • Sublist(第一个是第二个的子列表)
  • Superlist(第一个是第二个的超列表)
  • Unequal(以上均不成立)

核心函数解读

rust 复制代码
fn is_sublist(needle: &[i32], haystack: &[i32]) -> bool {
    if needle.len() > haystack.len() {
        return false;
    }
    haystack.windows(needle.len()).any(|w| w == needle)
}

详细解读

  • haystack.windows(needle.len())滑动窗口 API,返回大列表中所有长度等于 needle连续子切片
    • 例如 haystack = [1,2,3,4],needle.len()=2 时,会产生 [1,2][2,3][3,4]
  • .any(|w| w == needle):只要有一个窗口与 needle 完全相等,就返回 true

这是 Rust 中判断连续子列表的最优雅写法,零成本、高性能。

完整 sublist 函数(推荐现代写法):

rust 复制代码
#[derive(Debug, PartialEq, Eq)]
pub enum Comparison {
    Equal,
    Sublist,
    Superlist,
    Unequal,
}

pub fn sublist(first_list: &[i32], second_list: &[i32]) -> Comparison {
    if first_list.is_empty() && second_list.is_empty() {
        return Comparison::Equal;
    }
    if first_list.is_empty() {
        return Comparison::Sublist;
    }
    if second_list.is_empty() {
        return Comparison::Superlist;
    }

    match first_list.len().cmp(&second_list.len()) {
        std::cmp::Ordering::Equal => {
            if first_list == second_list {
                Comparison::Equal
            } else {
                Comparison::Unequal
            }
        }
        std::cmp::Ordering::Less => {
            if is_sublist(first_list, second_list) {
                Comparison::Sublist
            } else {
                Comparison::Unequal
            }
        }
        std::cmp::Ordering::Greater => {
            if is_sublist(second_list, first_list) {
                Comparison::Superlist
            } else {
                Comparison::Unequal
            }
        }
    }
}

match 表达式解读
first_list.len().cmp(&second_list.len()) 返回 Ordering::Equal / Less / Greater,用于快速分流逻辑,避免不必要的检查。


总结与建议

  1. Anagram 重点掌握生命周期和字符串规范化。
  2. Space Age 练习 trait 默认实现、常量提取和代码去重(宏或关联常量)。
  3. Sublist 是 Rust 迭代器和模式匹配的经典案例,windows() + any() 是必学技巧。

这些练习难度适中,但覆盖了 Rust 很多重要概念。建议多读官方文档中关于 lifetimestraitsiterators 的章节。


文章标签

Rust、Exercism、Rust 练习、生命周期、Trait、Sublist、Anagram、Space Age、Rust 入门


相关推荐
第二只羽毛2 小时前
IO代码解释3
java·大数据·开发语言
是娇娇公主~2 小时前
C++迭代器详解
开发语言·c++·stl
qq_148115372 小时前
C++网络编程(Boost.Asio)
开发语言·c++·算法
weisian1512 小时前
Java并发编程--24-死锁排查与性能调优:线上并发问题诊断指南(死锁,CPU飙升,内存溢出)
java·开发语言·arthas·死锁·火焰图·cpu飙升
CSCN新手听安2 小时前
【Qt】Qt概述(三)Qt初识,HelloWorld的创建,对象树
开发语言·qt
2301_804215412 小时前
内存映射文件高级用法
开发语言·c++·算法
luanma1509802 小时前
PHP vs C#:30字秒懂两大语言核心差异
android·开发语言·python·php·laravel
Channing Lewis2 小时前
Python 全局变量调用了一个函数,如何实现每次使用时都运行一次函数获取最新的结果
开发语言·python
CoderCodingNo2 小时前
【GESP】C++八级考试大纲知识点梳理 (5) 代数与平面几何
开发语言·c++