課題10: 構造体の実践
マンダトリー要件
問題1: 基本的な構造体(20点)
様々な構造体を定義し、基本的なメソッドを実装しなさい。
// 座標を表す構造体
#[derive(Debug, PartialEq)]
struct Point {
x: f64,
y: f64,
}
impl Point {
fn new(x: f64, y: f64) -> Self {
// TODO: 実装
}
fn origin() -> Self {
// TODO: 原点(0, 0)を返す
}
fn distance_from_origin(&self) -> f64 {
// TODO: 原点からの距離
}
fn distance_to(&self, other: &Point) -> f64 {
// TODO: 他の点との距離
}
fn translate(&mut self, dx: f64, dy: f64) {
// TODO: 平行移動
}
}
// 長方形を表す構造体
#[derive(Debug)]
struct Rectangle {
top_left: Point,
bottom_right: Point,
}
impl Rectangle {
fn new(top_left: Point, bottom_right: Point) -> Self {
// TODO: 実装
}
fn width(&self) -> f64 {
// TODO: 幅を計算
}
fn height(&self) -> f64 {
// TODO: 高さを計算
}
fn area(&self) -> f64 {
// TODO: 面積を計算
}
fn contains(&self, point: &Point) -> bool {
// TODO: 点が長方形内にあるか
}
}
// 円を表す構造体
#[derive(Debug)]
struct Circle {
center: Point,
radius: f64,
}
impl Circle {
fn new(center: Point, radius: f64) -> Self {
// TODO: 実装
}
fn area(&self) -> f64 {
// TODO: 面積を計算
}
fn circumference(&self) -> f64 {
// TODO: 円周を計算
}
fn contains(&self, point: &Point) -> bool {
// TODO: 点が円内にあるか
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_point() {
let p1 = Point::new(3.0, 4.0);
assert_eq!(p1.distance_from_origin(), 5.0);
let p2 = Point::new(0.0, 0.0);
assert_eq!(p1.distance_to(&p2), 5.0);
let mut p3 = Point::new(1.0, 1.0);
p3.translate(2.0, 3.0);
assert_eq!(p3, Point::new(3.0, 4.0));
}
#[test]
fn test_rectangle() {
let rect = Rectangle::new(
Point::new(0.0, 10.0),
Point::new(10.0, 0.0),
);
assert_eq!(rect.width(), 10.0);
assert_eq!(rect.height(), 10.0);
assert_eq!(rect.area(), 100.0);
assert!(rect.contains(&Point::new(5.0, 5.0)));
assert!(!rect.contains(&Point::new(15.0, 5.0)));
}
#[test]
fn test_circle() {
let circle = Circle::new(Point::new(0.0, 0.0), 5.0);
assert!((circle.area() - 78.54).abs() < 0.1);
assert!(circle.contains(&Point::new(3.0, 4.0)));
assert!(!circle.contains(&Point::new(10.0, 10.0)));
}
}
提出物:problem1_basic_structs.rs
問題2: ユーザー管理システム(20点)
ユーザー管理システムを実装しなさい。
use std::collections::HashMap;
#[derive(Debug, Clone)]
struct User {
id: u64,
username: String,
email: String,
age: u32,
is_active: bool,
}
impl User {
fn new(id: u64, username: String, email: String, age: u32) -> Self {
// TODO: 実装(is_activeはtrue)
}
fn deactivate(&mut self) {
// TODO: 実装
}
fn activate(&mut self) {
// TODO: 実装
}
fn update_email(&mut self, new_email: String) {
// TODO: 実装
}
}
struct UserDatabase {
users: HashMap<u64, User>,
next_id: u64,
}
impl UserDatabase {
fn new() -> Self {
// TODO: 実装
}
fn add_user(&mut self, username: String, email: String, age: u32) -> u64 {
// TODO: 実装
// ユーザーを追加し、IDを返す
}
fn get_user(&self, id: u64) -> Option<&User> {
// TODO: 実装
}
fn get_user_mut(&mut self, id: u64) -> Option<&mut User> {
// TODO: 実装
}
fn remove_user(&mut self, id: u64) -> Option<User> {
// TODO: 実装
}
fn find_by_username(&self, username: &str) -> Option<&User> {
// TODO: 実装
}
fn active_users(&self) -> Vec<&User> {
// TODO: アクティブなユーザーのリスト
}
fn user_count(&self) -> usize {
// TODO: ユーザー数
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_user_database() {
let mut db = UserDatabase::new();
let id1 = db.add_user("alice".to_string(), "alice@example.com".to_string(), 30);
let id2 = db.add_user("bob".to_string(), "bob@example.com".to_string(), 25);
assert_eq!(db.user_count(), 2);
let user = db.get_user(id1).unwrap();
assert_eq!(user.username, "alice");
db.get_user_mut(id1).unwrap().deactivate();
assert_eq!(db.active_users().len(), 1);
db.remove_user(id2);
assert_eq!(db.user_count(), 1);
}
}
提出物:problem2_user_management.rs
問題3: 銀行口座システム(20点)
銀行口座の管理システムを実装しなさい。
#[derive(Debug)]
struct Transaction {
amount: f64,
description: String,
timestamp: String, // 簡易版:文字列で時刻を保存
}
impl Transaction {
fn new(amount: f64, description: String) -> Self {
// TODO: 実装
// timestampは現在時刻の文字列表現
}
}
#[derive(Debug)]
struct BankAccount {
account_number: String,
owner: String,
balance: f64,
transactions: Vec<Transaction>,
}
impl BankAccount {
fn new(account_number: String, owner: String) -> Self {
// TODO: 実装
}
fn deposit(&mut self, amount: f64, description: String) -> Result<(), String> {
// TODO: 実装
// 金額チェック、残高更新、取引記録
}
fn withdraw(&mut self, amount: f64, description: String) -> Result<(), String> {
// TODO: 実装
// 金額チェック、残高チェック、残高更新、取引記録
}
fn balance(&self) -> f64 {
// TODO: 実装
}
fn transaction_history(&self) -> &[Transaction] {
// TODO: 実装
}
fn total_deposits(&self) -> f64 {
// TODO: 全ての入金額の合計
}
fn total_withdrawals(&self) -> f64 {
// TODO: 全ての出金額の合計
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bank_account() {
let mut account = BankAccount::new(
"123-456".to_string(),
"Alice".to_string(),
);
assert!(account.deposit(1000.0, "初期入金".to_string()).is_ok());
assert_eq!(account.balance(), 1000.0);
assert!(account.withdraw(300.0, "ATM出金".to_string()).is_ok());
assert_eq!(account.balance(), 700.0);
assert!(account.withdraw(1000.0, "残高不足".to_string()).is_err());
assert_eq!(account.transaction_history().len(), 2);
}
}
提出物:problem3_bank_account.rs
問題4: タスク管理システム(20点)
タスク管理システムを実装しなさい。
#[derive(Debug, PartialEq, Clone, Copy)]
enum Priority {
Low,
Medium,
High,
}
#[derive(Debug, PartialEq, Clone, Copy)]
enum Status {
Todo,
InProgress,
Done,
}
#[derive(Debug, Clone)]
struct Task {
id: u32,
title: String,
description: String,
priority: Priority,
status: Status,
}
impl Task {
fn new(id: u32, title: String, description: String, priority: Priority) -> Self {
// TODO: 実装(statusはTodo)
}
fn start(&mut self) {
// TODO: statusをInProgressに
}
fn complete(&mut self) {
// TODO: statusをDoneに
}
fn is_done(&self) -> bool {
// TODO: 実装
}
}
struct TaskManager {
tasks: Vec<Task>,
next_id: u32,
}
impl TaskManager {
fn new() -> Self {
// TODO: 実装
}
fn add_task(&mut self, title: String, description: String, priority: Priority) -> u32 {
// TODO: 実装
}
fn get_task(&self, id: u32) -> Option<&Task> {
// TODO: 実装
}
fn get_task_mut(&mut self, id: u32) -> Option<&mut Task> {
// TODO: 実装
}
fn remove_task(&mut self, id: u32) -> Option<Task> {
// TODO: 実装
}
fn tasks_by_status(&self, status: Status) -> Vec<&Task> {
// TODO: 実装
}
fn tasks_by_priority(&self, priority: Priority) -> Vec<&Task> {
// TODO: 実装
}
fn high_priority_incomplete(&self) -> Vec<&Task> {
// TODO: 高優先度で未完了のタスク
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_task_manager() {
let mut manager = TaskManager::new();
let id1 = manager.add_task(
"タスク1".to_string(),
"説明1".to_string(),
Priority::High,
);
let id2 = manager.add_task(
"タスク2".to_string(),
"説明2".to_string(),
Priority::Low,
);
manager.get_task_mut(id1).unwrap().start();
manager.get_task_mut(id1).unwrap().complete();
assert_eq!(manager.tasks_by_status(Status::Done).len(), 1);
assert_eq!(manager.tasks_by_priority(Priority::High).len(), 1);
}
}
提出物:problem4_task_manager.rs
---
ボーナス課題
> ボーナス: 以下はオプションです。マンダトリー要件を完了してから挑戦してください。
ボーナス1: 図書館管理システム(5点)
図書館の本と貸出を管理するシステムを実装しなさい。
#[derive(Debug, Clone)]
struct Book {
id: u32,
title: String,
author: String,
isbn: String,
is_available: bool,
}
struct Loan {
book_id: u32,
user_id: u32,
loan_date: String,
return_date: Option<String>,
}
struct Library {
books: Vec<Book>,
loans: Vec<Loan>,
next_book_id: u32,
}
impl Library {
fn new() -> Self {
// TODO: 実装
}
fn add_book(&mut self, title: String, author: String, isbn: String) -> u32 {
// TODO: 実装
}
fn borrow_book(&mut self, book_id: u32, user_id: u32) -> Result<(), String> {
// TODO: 実装
}
fn return_book(&mut self, book_id: u32) -> Result<(), String> {
// TODO: 実装
}
fn available_books(&self) -> Vec<&Book> {
// TODO: 実装
}
fn books_on_loan(&self) -> Vec<&Book> {
// TODO: 実装
}
}
提出物:bonus1_library/プロジェクト
ボーナス2: ショッピングカート(5点)
ECサイトのショッピングカートを実装しなさい。
#[derive(Debug, Clone)]
struct Product {
id: u32,
name: String,
price: f64,
}
struct CartItem {
product: Product,
quantity: u32,
}
struct ShoppingCart {
items: Vec<CartItem>,
}
impl ShoppingCart {
fn new() -> Self {
// TODO: 実装
}
fn add_item(&mut self, product: Product, quantity: u32) {
// TODO: 同じ商品があれば数量を増やす
}
fn remove_item(&mut self, product_id: u32) -> Option<CartItem> {
// TODO: 実装
}
fn update_quantity(&mut self, product_id: u32, quantity: u32) -> Result<(), String> {
// TODO: 実装
}
fn total(&self) -> f64 {
// TODO: 合計金額
}
fn item_count(&self) -> u32 {
// TODO: 商品の総数
}
fn clear(&mut self) {
// TODO: カートを空にする
}
}
提出物:bonus2_shopping_cart/プロジェクト
ボーナス3: ゲームキャラクター(5点)
RPGのキャラクターシステムを実装しなさい。
#[derive(Debug, Clone, Copy)]
enum Class {
Warrior,
Mage,
Archer,
}
#[derive(Debug)]
struct Stats {
hp: u32,
max_hp: u32,
mp: u32,
max_mp: u32,
attack: u32,
defense: u32,
}
struct Character {
name: String,
class: Class,
level: u32,
stats: Stats,
experience: u32,
}
impl Character {
fn new(name: String, class: Class) -> Self {
// TODO: クラスに応じた初期ステータス
}
fn take_damage(&mut self, damage: u32) {
// TODO: ダメージを受ける
}
fn heal(&mut self, amount: u32) {
// TODO: 回復
}
fn is_alive(&self) -> bool {
// TODO: 実装
}
fn gain_experience(&mut self, exp: u32) {
// TODO: 経験値獲得、レベルアップ処理
}
fn level_up(&mut self) {
// TODO: レベルアップ
}
}
提出物:bonus3_game_character/プロジェクト
ボーナス4: 在庫管理システム(5点)
商品の在庫を管理するシステムを実装しなさい。
#[derive(Debug, Clone)]
struct Item {
sku: String,
name: String,
quantity: u32,
price: f64,
reorder_level: u32,
}
struct Inventory {
items: HashMap<String, Item>,
}
impl Inventory {
fn new() -> Self {
// TODO: 実装
}
fn add_item(&mut self, item: Item) {
// TODO: 実装
}
fn update_quantity(&mut self, sku: &str, quantity: i32) -> Result<(), String> {
// TODO: 在庫数を更新(正負両方対応)
}
fn get_item(&self, sku: &str) -> Option<&Item> {
// TODO: 実装
}
fn low_stock_items(&self) -> Vec<&Item> {
// TODO: reorder_level以下の商品
}
fn total_value(&self) -> f64 {
// TODO: 在庫の総額
}
fn inventory_report(&self) -> String {
// TODO: レポート生成
}
}
提出物:bonus4_inventory/プロジェクト
ボーナス5: SNS風投稿システム(5点)
SNSの投稿とコメント機能を実装しなさい。
#[derive(Debug, Clone)]
struct Comment {
id: u32,
user_id: u32,
content: String,
timestamp: String,
}
#[derive(Debug, Clone)]
struct Post {
id: u32,
user_id: u32,
content: String,
likes: u32,
comments: Vec<Comment>,
timestamp: String,
}
impl Post {
fn new(id: u32, user_id: u32, content: String) -> Self {
// TODO: 実装
}
fn like(&mut self) {
// TODO: いいね数を増やす
}
fn add_comment(&mut self, user_id: u32, content: String) {
// TODO: コメントを追加
}
fn comment_count(&self) -> usize {
// TODO: 実装
}
}
struct Feed {
posts: Vec<Post>,
next_post_id: u32,
next_comment_id: u32,
}
impl Feed {
fn new() -> Self {
// TODO: 実装
}
fn create_post(&mut self, user_id: u32, content: String) -> u32 {
// TODO: 実装
}
fn get_post(&self, id: u32) -> Option<&Post> {
// TODO: 実装
}
fn get_post_mut(&mut self, id: u32) -> Option<&mut Post> {
// TODO: 実装
}
fn posts_by_user(&self, user_id: u32) -> Vec<&Post> {
// TODO: 実装
}
fn popular_posts(&self, min_likes: u32) -> Vec<&Post> {
// TODO: 指定いいね数以上の投稿
}
}
提出物:bonus5_social_media/プロジェクト
---
評価基準
マンダトリー部分(80点)
| 項目 | 配点 | 評価ポイント |
|---|---|---|
| 問題1:基本構造体 | 20点 | メソッド実装の正確性 |
| 問題2:ユーザー管理 | 20点 | データ管理の設計 |
| 問題3:銀行口座 | 20点 | エラーハンドリング |
| 問題4:タスク管理 | 20点 | フィルタリングロジック |
ボーナス部分(20点)
| 項目 | 配点 | 評価ポイント |
|---|---|---|
| ボーナス1:図書館 | 5点 | 貸出管理 |
| ボーナス2:カート | 5点 | 商品管理 |
| ボーナス3:キャラクター | 5点 | ステータス管理 |
| ボーナス4:在庫 | 5点 | レポート機能 |
| ボーナス5:SNS | 5点 | コメント機能 |
注: ボーナスは最大20点まで加算されます。
---
提出方法
ファイル構成
rust-foundations-10/
├── problem1_basic_structs.rs
├── problem2_user_management.rs
├── problem3_bank_account.rs
├── problem4_task_manager.rs
└── bonus/
├── bonus1_library/
├── bonus2_shopping_cart/
├── bonus3_game_character/
├── bonus4_inventory/
└── bonus5_social_media/
提出期限
- マンダトリー:第10章学習後、1週間以内
- ボーナス:コース修了時まで
---
ヒント
問題1のヒント
distance_to実装:
fn distance_to(&self, other: &Point) -> f64 {
let dx = self.x - other.x;
let dy = self.y - other.y;
(dx * dx + dy * dy).sqrt()
}
問題2のヒント
find_by_username実装:
fn find_by_username(&self, username: &str) -> Option<&User> {
self.users.values().find(|u| u.username == username)
}
問題3のヒント
deposit実装:
fn deposit(&mut self, amount: f64, description: String) -> Result<(), String> {
if amount <= 0.0 {
return Err("金額は正の数である必要があります".to_string());
}
self.balance += amount;
self.transactions.push(Transaction::new(amount, description));
Ok(())
}
---
学習の確認
この課題を通じて、以下を理解できたか確認してください:
- [ ] 構造体の定義と初期化
- [ ] メソッドの実装(&self、&mut self、self)
- [ ] 関連関数(new、コンストラクタ)
- [ ] implブロックの使い方
- [ ] タプル構造体とnewtype パターン
- [ ] Debugトレイトの自動導出
- [ ] 構造体を使ったデータ管理
おめでとうございます!Rust Foundations コースの基礎編を完了しました。次のステップとして、より高度なトピックに進みましょう。