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


相关推荐
xier_ran9 小时前
【C++】“内部”、“外部”、“派生类”、“友元“类
java·开发语言·c++
im_AMBER9 小时前
从面试题看JS变量提升
开发语言·前端·javascript·前端框架
故事和你919 小时前
洛谷-数据结构1-2-二叉树1
开发语言·数据结构·c++·算法·leetcode·动态规划·图论
大橘9 小时前
【qml-5.1】qml与c++交互(QML_ELEMENT/QML_SINGLETON)
开发语言·c++·qt·交互·qml
凭君语未可9 小时前
从静态代理走向动态代理:理解 JDK 动态代理的本质
java·开发语言
小碗羊肉9 小时前
【从零开始学Java | 第三十八篇】序列化流(Object Stream)
java·开发语言
百锦再9 小时前
使用JavaScript获取和解析页面内容的完整指南
开发语言·前端·javascript·python·flask·fastapi
iCxhust9 小时前
C#如何实现textbox文本多行输出 且自动换行输出
开发语言·c#
想带你从多云到转晴9 小时前
02、JAVAEE--多线程(二)
java·开发语言·javaee
实在智能RPA9 小时前
Agent 如何处理流程中的异常情况?——2026企业级智能体稳定性架构深度拆解
开发语言·人工智能·ai·架构·php