【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 入门


相关推荐
会编程的土豆5 小时前
GoWeb 处理请求详解:请求行、请求头、请求参数与给客户端响应
开发语言·http·golang
name好难取诶14 小时前
PHP 静态分析工具实战 PHPStan 和 Psalm 完全指南
android·开发语言·php
湿滑路面15 小时前
Rouyan:使用WPF/C#构建的基于LLM的快捷翻译小工具
开发语言·c#·wpf
Lee_jerome15 小时前
《C/C++编译全家桶:g++四阶段、.a与.so区别、CMake构建、ARM交叉编译,这篇全讲透了》
c语言·开发语言·arm开发·c++·编译·cmake·cmakelists
冰心孤城16 小时前
C++ 与 C#混合编程 示例 (基于VS)
java·c++·c#
软萌萌的116 小时前
C#中的多级缓存架构设计与实现深度解析
缓存·c#·wpf
kisloy16 小时前
【爬虫入门第5讲】Python爬虫文本解析详解
开发语言·爬虫·python
春生野草17 小时前
个人笔记——C语言字符串、树
c语言·开发语言·笔记
风中芦苇啊18 小时前
Java EasyExcel 导入通用工具类:自定义注解映射字段 + 反射机制
java·开发语言
PieroPc18 小时前
Python 写的 Windows凭据添加工具 第二版 解决Win11 23H2, 25H2,26H1,共享文件和打印 一部份问题,不是全部!
开发语言·windows·python