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


相关推荐
大圣编程11 小时前
Java 多维数组详解
java·开发语言
殳翰14 小时前
下服务器端开发流程及相关工具介绍(C++)
开发语言·c++
落寞的星星14 小时前
这个对象就包含了已经转换好的DFA和各种词法分析器运转所需要的参数。下一步,我们就可以用ScannerInfo对象创建出Scanner对象,请看下面的代码:
开发语言·c#
nothing&nowhere14 小时前
用 Python 做问卷数据清洗:无效样本检测与处理实战
开发语言·python·数据清洗·数据处理·问卷星·问卷星脚本·刷问卷
2601_9615934215 小时前
Rust 开发环境配置繁琐?RustRover 开箱即用搞定编码调试
开发语言·后端·macos·rust
HZZD_HZZD15 小时前
DL/T 645-2026新国标深度解读与智能电表协议适配实战:从帧结构变化到Java采集器升级的全链路改造方案
java·开发语言
冬奇Lab16 小时前
每日一个开源项目(第154篇):Warp - 从‘好看的终端‘到 Agentic 开发环境
人工智能·rust·llm
多加点辣也没关系17 小时前
JavaScript|第4章:类型转换
开发语言·javascript
聪慧的水蜜桃17 小时前
【YFIOs】用C#开发硬件之设备上云
开发语言·c#
yqcoder18 小时前
httpOnly 是什么,又有什么用?
开发语言·前端·javascript