Full Code of cis198-2016s/homework for AI

master 880f1833e3f6 cached
11 files
65.7 KB
17.1k tokens
7 symbols
1 requests
Download .txt
Repository: cis198-2016s/homework
Branch: master
Commit: 880f1833e3f6
Files: 11
Total size: 65.7 KB

Directory structure:
gitextract_0bxq24dp/

├── .gitmodules
├── final/
│   └── README.md
├── hw00/
│   └── README.md
├── hw01/
│   ├── README.md
│   └── tests_provided.rs
├── hw02/
│   └── README.md
├── hw03/
│   └── README.md
├── hw04/
│   └── README.md
├── hw05/
│   └── README.md
├── hw06/
│   └── README.md
└── hw07/
    └── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitmodules
================================================
[submodule "hw02/starter"]
	path = hw02/starter
	url = git@github.com:cis198-2016s/hw02.git
	branch = master
[submodule "hw03/starter"]
	path = hw03/starter
	url = git@github.com:cis198-2016s/hw03.git
	branch = master
[submodule "hw04/starter"]
	path = hw04/starter
	url = git@github.com:cis198-2016s/hw04.git
	branch = master
[submodule "hw05/starter"]
	path = hw05/starter
	url = git@github.com:cis198-2016s/hw05.git
	branch = master
[submodule "hw06/starter"]
	path = hw06/starter
	url = git@github.com:cis198-2016s/hw06.git
	branch = master
[submodule "hw07/starter"]
	path = hw07/starter
	url = git@github.com:cis198-2016s/hw07.git
	branch = master


================================================
FILE: final/README.md
================================================
# Final Project

This final project gives you the freedom to do whatever you've been dying to
do with this fancy new programming language you've just learned.

## Schedule

* Tue 3/29 - Ideas Due (on Piazza megathread) (for participation credit)
* Thu 3/31 - Proposal Draft Due (PDF via email)
* Fri 4/01 - Proposal Meeting (by appointment)
* Wed 4/06 - Proposal Presentation (in class) (4 min)
    * Please also send: final proposal, repository link, and documentation link.
* Wed 4/13 - Milestone 1 Presentation (in class) (2 min)
* Wed 4/20 - Milestone 2 Presentation (in class) (2 min)
* Wed 4/27 - Final Presentation (in class) (6 min)
* Wed 4/27 - Final Report (PDF via email)

**IMPORTANT:** After your proposal is submitted, we want to talk to you before
the proposal presentation to discuss and finalize. There will be a sign-up
sheet for meetings, probably on Friday, April 1.

## Grading

This project is worth 40% of the final course grade.

* 15%: Proposal and Presentation
* 20%: Milestone 1 Presentation and Status
* 20%: Milestone 2 Presentation and Status
* 45%: Final Presentation, Status, and Report

**Important:** "Status" grading will be based primarily on your documentation.
Spend time on this and write in-depth documentation!
You'll need to use rustdoc to generate documentation before each presentation
(see below: [Documentation](#documentation)).

## Project Guidelines

* Groups may be 1-3 people, 2 preferred. Collaborate via GitHub (obviously).
  Make your own repository if applicable.

* You can either make your own project or contribute to an existing open-source
  project. If you do the latter, make sure that the project owners are okay
  with this. They will expect very high-quality contributions - so don't drop a
  half-done pull request on them.

* If you make a new project, we _prefer_ (but don't require) things that
  haven't been done in Rust before.

* Your idea needs to be doable in 3 weeks. This will be all of your
  198 work during those weeks, so schedule accordingly.

* We expect you to do about (3 weeks * 0.5 credit) worth of work per person -
  but what that means is subjective. More work will mean a more impressive
  project - but it's much more important that you finish!

* If your idea is in danger of being too big, you need to have a plan for how
  to scale it back. Carve out a reasonable subset of the idea as your baseline,
  and have additional goals on top of that.

* We would really like your project to be open-source! You don't have to if you
  really don't want to, but contributing to the Rust ecosystem is ideal.
  You don't need to pick licensing immediately, but consider Apache and MIT.

* If you have no ideas you like, you might consider putting out a call for
  project ideas to the Rust community (e.g. via Reddit).
  (If you take a community idea, your project must be open-source.)

### Ideas

These are our ideas - none of them have been investigated and you don't
have to use any of them.

* http://www.ncameron.org/rust.html
* https://www.rust-lang.org/contribute.html
* https://www.reddit.com/r/rust/comments/3bjl53/rust_language_project_ideas/
* https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md
* https://github.com/servo/servo/blob/master/CONTRIBUTING.md
* https://github.com/rust-lang-nursery
* https://github.com/redox-os/redox#contributing

* Parallel computation (e.g. scientific computing or ray tracing)
* Other fast scientific computing
* Safe(!) bindings for a C API
* Rewriting slow parts of other programs (e.g. Python/Ruby)
* Some interesting distributed system
* Some kind of game

## Proposal Document

* Your proposal document should be about 1 page. A Google Doc is recommended.
  (But please submit as a PDF!)

* List your group members.

* Abstract: Your idea in a sentence or two. New project or contribution?

* Open-source or not. If not, why?
  You don't need to pick a license right now, but Apache and MIT are good.

* Project outline: Your minimal goals, expected goals, and stretch goals.
    * This should be detailed enough that we can judge the complexity and merit.
    * Include appropriate technical details of each goal.

* Tentative Schedule: Which goals do you want to finish each week? Milestone
  presentations will be at the beginning of class each week.

## Milestone Presentations

These will be very quick (~2 min). Just update us on your progress.
You may present documentation or markdown on GitHub. Send a link before
class so we can open it on the classroom computer.

All of your work must be in your repository by class time, including
rustdoc documentation for the work you're presenting (see below).
If you're contributing, this means it should be in your fork.

## Documentation

If you are working on a standalone project, you should have rustdocs
documenting all of the work you've done so far,
at each milestone and the final presentation. This doesn't mean documenting
every single function - but you need detailed documentation for the modules,
functionality, and all important structs/functions.

**Important:** Spend time on this and write in-depth documentation.
It will be a significant part of our grading!

For any general information, put it on your crate root module. You can use
this syntax for module documentation:

```
//! if you put this documentation comment style in a
//! module, it will apply to the module itself instead
//! of the thing after it
```

Please host docs somewhere online. You can use
[hosting on Eniac](http://www.seas.upenn.edu/cets/answers/webpage.html),
or you may use a [GitHub Pages](https://pages.github.com/) project site.

By default, `cargo doc --no-deps` will export documentation for everything
_public_ in your crate. However, for the project, you'll likely want to
export everything. To do this, use:

```sh
cargo rustdoc -- --no-defaults --passes collapse-docs --passes unindent-comments
```

Here is some [example rustdoc output](http://cis198-2016s.github.io/final-sample-rustdoc/webchat/).
This shows the output of the above command on our HW07 solution. Note that it
doesn't have any _module-level_ documentation - which will be most important
for you.

If you're contributing to another project, you should send us a compilation of
the documentation for everything **you** have written as part of your project.

If there is any additional extra information that you want
to send to us but think doesn't belong in
the documentation, email it to us before your presentation.

## Final Report

Write your report in markdown, and save it as `REPORT.md` in your repository
root, and we'll find it there. If you don't have a dedicated repository for
this project (e.g. you are forking another project) or you plan to immediately
publicize your project, put the report in a [Gist](https://gist.github.com/)
and email us the link. If you have screenshots or images, save them in the repo
and embed them in `REPORT.md`.

We'll expect about 2-3 printed-pages-worth of info. Include whatever is
appropriate or important for your project, such as:

* Summary
* Approximate time spent
* Accomplishments
* Components, structure, design decisions
* Testing approach and results
* Benchmarks
* Limitations
* Postmortem
    * What went well
    * What you would do differently
* etc.

If your project would benefit from having a video, that would be great. You
can, e.g., record using [OBS](https://obsproject.com/) and upload to YouTube.

**Your documentation is still a part of the final milestone grade.** Anything
you've written for documentation can be copied to your report if it's
important. Make sure you have an appropriate amount of documentation. If you
have a ton of code but haven't written much documentation for it, your rustdoc
output will look very sparse and it'll be harder for us to tell how much you
have done. Comments don't count, as they don't appear in the rustdoc output.

Keep in mind that if your repo is public, your report will be as well.
If you have any private feedback, email us.


================================================
FILE: hw00/README.md
================================================
# Homework 00: Hello Rust & Hello Cargo!

**Due 2016-01-25, 11:59pm.**

For questions, please post on Piazza (Penn students) or Google Groups (other).
Links on homepage.

#### Classroom for GitHub

We're using Classroom for GitHub, which manages private homework repositories
for students. To create your very own private homework repository (owned by
us), click the link on the course Piazza.

If there is no starter code, such as in this homework, you can use Cargo to
initialize the git repository for you. See below. But first, Rust!

## Installing Rust

For this homework, all you'll have to do is install the Rust compiler (rustc)
and the Rust package manager (Cargo). We'll be using Rust v1.6 for this class.
(Version 1.6 is set to be released next Thursday! This homework doesn't depend
on the version of Rust, so it's fine to get started early.)

We recommend using [multirust][multirust], a tool to manage multiple
installations of Rust on your system. Multirust supports Linux, OS X, and
Windows (via MSYS2). Unfortunately, there is no support for Windows if you are
not using MSYS2.

Multirust maintains a user default toolchain version (stable, beta, or
nightly). Run `multirust default stable` to set your user preference to stable.
This will also download the stable toolchain.

**On Linux, OS X, or Windows+MSYS2:**
Install multirust by following the [instructions on their README][multirust].
You can also use your local friendly package manager.

[multirust]: https://github.com/brson/multirust

**On Windows (without MSYS2):** 
You can either use the standard Rust installer from
[the website](https://www.rust-lang.org/downloads.html), or you can use
multirust on Eniac.

**On Eniac:**
If you don't want to install Rust,
multirust is also available on Eniac. Add this line to your `~/.bashrc` on
Eniac: `export PATH=$PATH:/home1/c/cis198/local/bin`

To check that Rust and Cargo are installed properly, run the following commands
and make sure the output matches below:

```
$ rustc --version
rustc 1.5.0 (3d7cd77e4 2015-12-04)
$ cargo --version
cargo 0.6.0-nightly (e1ed995 2015-10-22)
```

When version 1.6 is released next week, you should update your version of Rust,
using `multirust update stable`.

## Hello, Rust!

Now that Rust is ready to roll, let's write our first "hello world" program.
Create a file named `main.rs` and modify the code snippet below to print out
"Hello, \<your name\>!".

```rust
fn main() {
    let name = "Ferris"; // Ferris is the name of Rust's unofficial crustacean mascot
    println!("Hello, {}!", name);
}
```

Once you've created your program, compile it using `rustc main.rs` and run the
resulting `main` binary to test it. Boom! You did it! You're a Rust programmer
now! 🎊🎉👍

## Hello, Cargo!

Rust has a fantastic package and build manager, Cargo, which is modeled from
years of learning from other languages. Cargo handles all the gory build
automation and dependency management details for you, so that you don't have to
worry about it when creating (or building or updating) a project.

Using `rustc` directly is fine for small projects, but Cargo really helps to
remove a lot of the friction of manual project management. If you've ever used
`rake` or `pip` for dependency management, Cargo is like those, plus all of the
build power provided by a good `Makefile`.

To make a new project for homework 0, run the command
`cargo new --bin hw00` (which will *create* the folder `hw00`).

Why `--bin`? We want this project to create a standalone executable, rather than
a library that can be rolled into other projects.

If you are not already in a git repository when you create your project, Cargo
will create a git repository (and `.gitignore`) for you. Then, you can add this
your GitHub repository as a git remote as follows:


```
git remote add origin git@github.com:cis198-2016s/hw00-<username>.git
git push -u origin master
```

Cargo creates this directory structure for you:

```
hw00
├── Cargo.toml
└── src
    └── main.rs

1 directory, 2 files
```

You may notice that the `main.rs` file Cargo creates looks suspiciously
similar to the "Hello World" code above. Since you've already written your
"Hello World" program, move the file you created into `src`, and overwrite
the `main.rs` that Cargo generated.

To finish things off, let's build our project. Simply run `cargo build` from any
directory in the project tree! You can run your executable with `cargo run`.
Pretty magic, huh?

## Bonus: Configuration

Adding to your personal environment setup is one of the many joys of starting
a new programming language. Rust has a pretty decent amount of support for being
new to the game.

Take a look at [this list of editor configs][configs.md]. There are more
unofficial or less-supported ones out there, so it's worth looking around. If
you aren't sure what to use, all three of your instructors use vim :)

  [configs.md]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md

## Submission

Commit and push your work to the master branch of your Classroom for Github
repository for this HW. **Make sure it is visible on Github!** This is your
submission. (Work must be in the master branch at the due time.)

That's it! ok bye get outta here :point_right:


================================================
FILE: hw01/README.md
================================================
# Homework 01: Rust Finger Exercises

**Due ~~2016-01-27~~ 2016-01-28, 11:59pm.**

For questions, please post on Piazza (Penn students) or Google Groups (other).
Links on homepage.

## Overview ##

In this assignment, you'll get your first crack at writing some short functions
in a Rust library, building and testing using Cargo, and writing modules. This
assignment isn't intended to be especially difficult, but will make sure you're
set up properly in the Rust ecosystem, and will give you some good experience
using the Rust compiler.

#### Classroom for GitHub

We're using Classroom for GitHub, which manages private homework repositories
for students. To create your very own private homework repository (owned by
us), click this link:
* https://classroom.github.com/assignment-invitations/d7a2cbae7d57de44e29c302c8e353a43

## Provided Code ##

Just one file, `tests_provided.rs`, which contains several test cases. We're
asking you to write everything else from scratch, but we'll give you function
signatures below, as a starting point.

## Part 01: Cargo ##

Don't clone your GitHub repository just yet.
To start off, let's create a new Rust library: `cargo new hw01`.

If you are not already in a git repository when you create your project, Cargo
will create a git repository (and `.gitignore`) for you. Then, you can add this
your GitHub repository as a git remote, with something like:

```
git remote add origin git@github.com:cis198-2016s/hw01-<username>.git
git push -u origin master
```

(If you're not using SSH for GitHub, you need to use the HTTPS URL of your
repository.)

Cargo creates this directory structure for you:

```
hw01
├── .git/
├── .gitignore
├── Cargo.toml
└── src
    └── lib.rs
```

You can build this project from anywhere in the project tree with
`cargo build`. Remember to compile periodically as you work.

### Modules ###

Before you go any further, a word on modules and crates.

Crates are any Rust library or package. Modules are the inner logical sections
of a crate.

You will want to organize each section of your crate into a different module,
so consumers can only import the parts that they need. You could do this in
`lib.rs`:

```rust
pub mod problem1 {
}

pub mod problem2 {
}

pub mod problem3 {
}

pub mod problem4 {
}

// ...
```

But this gets unwieldy pretty fast. You can instead put these modules in
separate files:

```
hw01
├── Cargo.toml
└── src
    ├── problem1.rs
    ├── problem2.rs
    ├── problem3.rs
    ├── problem4.rs
    └── lib.rs
```

Every `.rs` file defines a module that is the same as its filename, so
`problem1.rs` implicitly defines the module `problem1`.

Crates are organized into trees of files, where one file is the root, typically
`src/lib.rs` (or `src/main.rs`). To include a module, you need to declare it in
the crate root. To add `problem1` as a module, add the line `pub mod problem1;`
to the top of `src/lib.rs`. (This is equivalent to defining a module in the
file itself, with `pub mod problem1 { ... }`.) Until you add this directive,
Cargo will not try to build `problem1` part of your crate. The `pub` keyword in
this directive exposes the module `problem1` to any other crate that imports
your library. You can omit `pub` to leave modules private; however, if a
function is not exported or used internally, it will emit a dead code warning.

Within a module, all members (functions, types, submodules) are private by
default. The `pub` keyword can also be used to make any of these available from
outside of the module.

```rust
// problem1.rs

/// Functions are private (only available to this module) by default.
/// Use the `pub` keyword to mark this function as public.
pub fn sum(slice: &[i32]) -> i32 {
    // ...
}
```

There are a few different ways to import items from a different module:

1. To add `sum` to the scope of a file, add the line `use problem1::sum` to the
   top of the file. You can call the function with `sum()`. Try to import only
   what you need to use.

2. To import multiple things from a module, use curly braces:
   `use problem1::{sum, dedup};`

3. To import all items from a module, write `use problem1::*`.

4. To import an entire module, write `use problem1;`. This form requires you to
   qualify members of the module with the module name (e.g. `problem1::sum()`).
   This is more verbose but does not pollute the namespace of your scope.

We provided a `tests_provided.rs` file with a few test cases to start you off
with. You should add this to your library as a separate module, as you did with
each `problemX` module (but the tests don't need to be `pub`).

You can read more about modules in the Rust book
[here](https://doc.rust-lang.org/book/crates-and-modules.html).

## Part 02: Basic Functions ##

### Preface ###

For consistency, we ask that you put each problem into its own file, and name
the file as `problem1.rs`, etc. Remember to declare each module at the top of
`lib.rs` as well!

### Problem 01: Vector & Slice Manipulation ###

*Vectors, iteration, pass-by-ref, mutability, function pointers.*

Create a new module in your library named `problem1` inside `problem1.rs`.

To get a first taste of basic Rust, complete the following three functions.
Note that all of these functions take their arguments by reference, rather than
by value.

Don't use any of the standard library methods on the `Vec` class which implement
the target behavior, since using them would defeat the point of this exercise
:). (However, basic functions such as `contains()` and `push()` are fine).

```rust
/// Computes the sum of all elements in the input i32 slice named `slice`
pub fn sum(slice: &[i32]) -> i32 {
    // TODO
    unimplemented!();
}

/// Deduplicates items in the input vector `vs`. Produces a vector containing
/// the first instance of each distinct element of `vs`, preserving the
/// original order.
pub fn dedup(vs: &Vec<i32>) -> Vec<i32> {
    // TODO
    unimplemented!();
}

/// Filters a vector `vs` using a predicate `pred` (a function from `i32` to
/// `bool`). Returns a new vector containing only elements that satisfy `pred`.
pub fn filter(vs: &Vec<i32>, pred: &Fn(i32) -> bool) -> Vec<i32> {
    // TODO
    unimplemented!();
}
```

#### Testing

Before you move on, take a look at `tests_provided.rs`.

At the top of this file, there's a `#![cfg(test)]` attribute. `cfg`, short for
"configuration", is part of how Rust handles conditional compilation. This is
similar to (but way better than) the use of `#ifdef`s and include guards in C.
In this case, `#![cfg(test)]` tells the compiler that this module is not to be
compiled unless the `--test` flag is used with `rustc` (`cargo test` adds this
flag under the hood). This is handy because it means that you don't have to
waste time recompiling your tests every time you build unless you're actually
going to run them.

All of the functions in `test.rs` are annotated with the `#[test]` attribute;
this tells the compiler that they're tests. Test functions must have the
signature `fn() -> ()`, or else they will not compile. Tests will be run when
you invoke `cargo test`.

Any test which doesn't cause a `panic!` is considered to pass. You should use
[`assert!`][assert] or [`assert_eq!`][assert_eq] to check guarantees and
equality (respectively).

[assert]: https://doc.rust-lang.org/std/macro.assert!.html
[assert_eq]: https://doc.rust-lang.org/std/macro.assert_eq!.html

As an aside, the `cfg` attribute has many other uses, like knowing
which OS or architecture you're compiling for.

We have provided a few tests to start you off with. You should add at least one
non-trivial test for each function that you implement. Write these in a new
module, `tests_student.rs`, and declare the module in `lib.rs`.

### Problem 02: Matrix Multiplication ###

*Vectors, iteration, pass-by-reference, structs.*

Create a new module in your library named `problem2` inside `problem2.rs`.

We define a `Matrix` as a type alias to `Vec<Vec<f32>>`. Write a function that
takes in two `Matrix`es by reference and returns the product `mat1 * mat2`. The
function signature is provided below.

You should make sure that the two input matrices are actually compatible.
Remember that you can't multiply two matrices if the number of columns in the
first matrix is not equal to the number of rows in the second matrix. Use
`assert!` or `assert_eq!` to `panic!` if this condition is not met.

(Of course, crashing is bad - we'll learn about fixing this later.)

```rust
/// Represents a matrix in row-major order
pub type Matrix = Vec<Vec<f32>>;

/// Computes the product of the inputs `mat1` and `mat2`.
pub fn mat_mult(mat1: &Matrix, mat2: &Matrix) -> Matrix {
    // TODO
    unimplemented!();
}
```

### Problem 03: Sieve of Eratosthenes ###

*Vectors, iteration, mutability...*

Create a new module in your library named `problem3` inside `problem3.rs`.

The [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)
is used to find all primes below some given number (`n`), and is an efficient
way to find small primes.

Iterate through the numbers from `2` to `n`. For each number `i`:

1. If `i` has been crossed-out from previous iterations, skip it.
2. If `i` isn't crossed-out yet, then it is prime.
   Cross-out all multiples of `i` from `i*i` to `n`. These are non-prime.

Head over to the Wikipedia page for a more detailed description and some zesty
examples.

Your function will take a number, `n`, and return a list of all prime numbers
less than `n`. (Notice that you can't use a Rust array in this case, since you
don't know the length at compile time.)

```rust
/// Find all prime numbers less than `n`.
/// For example, `sieve(7)` should return `[2, 3, 5]`
pub fn sieve(n: u32) -> Vec<u32> {
    // TODO
    unimplemented!();
}
```

### Problem 04: Towers of Hanoi ###

*Mutability, type aliases, vecs, tuples, enums.*

[The Towers of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi) is a
classical mathematics and computer science puzzle. Imagine you have three pegs,
one of which holds a stack of discs in increasing size from bottom to top. Your
goal is to move all of the discs from the first peg to the third peg, using the
second peg as an intermediate. Your only restrictions are that you may only
move one disc at a time, and a disc may only be placed on a disc larger than it
(or on an empty peg). Check out the Wikipedia page for more details and snazzy
animations.

In this instance, we've provided you with an enum type containing the possible
names of `Peg`s and a type alias defining a move between two pegs.

This function will take in a number of discs, and the names of the three
pegs, and return a vector of `Move`s.

```rust
/// #[derive(...)] statements define certain properties on the enum for you for
/// free (printing, equality testing, the ability to copy values). More on this
/// when we cover Enums in detail.

/// You can use any of the variants of the `Peg` enum by writing `Peg::B`, etc.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Peg {
    A,
    B,
    C,
}

/// A move between two pegs: (source, destination).
pub type Move = (Peg, Peg);

/// Solves for the sequence of moves required to move all discs from `src` to
/// `dst`.
pub fn hanoi(num_discs: u32, src: Peg, aux: Peg, dst: Peg) -> Vec<Move> {
    // TODO
    unimplemented!();
}
```

## Submission

Commit and push your work to the master branch of your Classroom for Github
repository for this HW. **Make sure it is visible on Github!** This is your
submission. (Work must be in the master branch at the due time.)

Your repository should look like this:

```
[git root]
├── Cargo.toml
└── src
    ├── lib.rs
    ├── problem1.rs
    ├── problem2.rs
    ├── problem3.rs
    ├── problem4.rs
    ├── tests_provided.rs [same as given]
    └── tests_student.rs [your tests]
```

`cargo test` should run all of the tests in your homework. Make sure you have
written at least one test for each function you have written.


================================================
FILE: hw01/tests_provided.rs
================================================
#![cfg(test)]

use problem1::{sum, dedup, filter};
use problem2::mat_mult;
use problem3::sieve;
use problem4::{hanoi, Peg};

//
// Problem 1
//

// Part 1

#[test]
fn test_sum_small() {
    let array = [1,2,3,4,5];
    assert_eq!(sum(&array), 15);
}

// Part 2

#[test]
fn test_dedup_small() {
    let vs = vec![1,2,2,3,4,1];
    assert_eq!(dedup(&vs), vec![1,2,3,4]);
}

// Part 3

fn even_predicate(x: i32) -> bool {
    (x % 2) == 0
}

#[test]
fn test_filter_small() {
    let vs = vec![1,2,3,4,5];
    assert_eq!(filter(&vs, &even_predicate), vec![2,4]);
}

//
// Problem 2
//

#[test]
fn test_mat_mult_identity() {
    let mut mat1 = vec![vec![0.;3]; 3];
    for i in 0..mat1.len() {
        mat1[i][i] = 1.;
    }
    let mat2 = vec![vec![5.;3]; 3];
    let result = mat_mult(&mat1, &mat2);
    for i in 0..result.len() {
        for j in 0..result[i].len() {
            assert_eq!(result[i][j], mat2[i][j]);
        }
    }
}

//
// Problem 3
//

#[test]
fn test_sieve_basic() {
    assert_eq!(vec![2,3,5,7,11], sieve(12));
}

//
// Problem 4
//

#[test]
fn test_hanoi_1_disks() {
    let result = hanoi(1, Peg::A, Peg::B, Peg::C);
    assert_eq!(vec![(Peg::A, Peg::C)], result);
    assert_eq!(1, result.len());
}


================================================
FILE: hw02/README.md
================================================
# Homework 2: A Mediocre Binary Search Tree

**Due 2016-02-03, 11:59pm.**

For questions, please post on Piazza (Penn students) or Google Groups (other).
Links on homepage.

## Overview
This assignment is modeled after Alexis Beingessner (Gankro)'s [_Learning Rust
With Entirely Too Many Linked Lists_][TMLL] (herein referred to
as TMLL, because that's much easier to pronounce, right?)

[TMLL]: http://cglab.ca/~abeinges/blah/too-many-lists/book/

Even though we're implementing a [BST][], you should read Chapters 1-2
(introduction and first linked list); they're a great place to start.
Gankro's writing is really fun to read and the content is enlightening.

[BST]: https://en.wikipedia.org/wiki/Binary_search_tree

#### Classroom for GitHub

We're using Classroom for GitHub, which manages private homework repositories
for students. To create your very own private homework repository (owned by
us), click this link:
* https://classroom.github.com/assignment-invitations/9f6544879f4d5995f8a23cf35caf2133

## Instructions

Write your implementation in the `src/first.rs` file. You'll also write tests
in this file. The main file, `lib.rs`, is rather boring and done for you.

Your code doesn't have to follow any exact interface, just the guidelines
below. You'll write the data structure, `insert`, `search`, and tests.

Unlike in HW1, if you create your repository using Classroom for GitHub (link
on Piazza), your Git repository will be pre-populated (you won't need to use
`cargo new`). Just clone it to get going. (See the `starter` subrepo for the
starter repository contents.) You should edit `Cargo.toml` to add yourself as
the author.

#### Aside: Clippy

[Clippy][] is a compiler plugin which runs [lints][] on your code. It only
works in nightly Rust, however, so it's not enabled by default here. If you
feel like trying it out, switch to the nightly channel
(e.g. `multirust override nightly` while inside the project directory),
then build with the `clippy` feature:

```
cargo build --features clippy
cargo test --features clippy
```

This is recommended as it will help catch some stylistic errors as you learn
the language. (But, for ease of grading, please be sure to submit code which
works on Rust stable.)

[Clippy]: https://github.com/Manishearth/rust-clippy
[lints]: https://en.wikipedia.org/wiki/Lint_%28software%29

(If for some reason Clippy causes problems for your stable Rust build, just
remove the `[dependencies]` and `[features]` sections from `Cargo.toml` and
the Clippy-related lines at the top of `lib.rs`.)

### Implementation

This _roughly_ corresponds to
[TMLL 2](http://cglab.ca/~abeinges/blah/too-many-lists/book/first.html).
For more details, refer there.

As in TMLL 2:

* Write a `BST` type similar to the one in TMLL 2: a `pub struct` with a `root`
  element of type `Link`. Implement `BST::new()` which creates an empty BST.
    * This will be the only `pub struct`. The others are implementation
      details.
* Define `Link` as an `enum` with two instances: `Empty` and `More`, where
  `More` contains a boxed `Node`.
* Define `Node` as a `struct` containing an `i32` element. Instead of a single
  `next` element, it should also contain two child `Link`s: `left` and `right`.
* Add `#[derive(Debug)]` before each of the three types. This allows you to
  debug-print a value, e.g.: `println!("{:?}", bst);`
    * Use `println!("{:#?}", bst);` for multi-line, indented debug prints!
    * To be able to see printed output of successful tests, use
      `cargo test -- --nocapture`.

Now, instead of TMLL's `push` and `pop`, we'll implement:

* (`pub`) `bst.insert(i32) -> bool`: Insert an element into the BST. Return
  true if successful, or false if the element was already in the BST.
* (`pub`) `bst.search(i32) -> bool`: Search for an element in the BST. Return
  true iff the element was found.

#### Hints from our reference implementation

You should need: `struct`, `enum`, `impl`, `match`/`ref`/`ref mut`, `Box`,
`&`/`&mut`, dereferencing (`*`).

You should not need: named lifetimes, `Option`, `Vec`, `use`.

In our reference implementation, `BST::insert` and `BST::search` are short
functions which just call longer, recursive member functions of `Link`:

* `link.insert(i32) -> bool` (~25 lines)
  * If inserting into an empty link, place the element in this link (making it
    no longer empty).
  * If inserting into a non-empty link:
    * return `false` if the element is in this node; otherwise,
    * recurse to the left if the new value is less than the node's value
    * recurse to the right if the new value is greater than the node's value
  * You may not end up needing `mem::replace` like in TMLL.

* `link.search(i32) -> bool` (~15 lines)
  * If searching an empty link, return `false`; the element can't be found.
  * If searching a non-empty link:
    * return `true` if the element is in this node; otherwise,
    * recurse to the left if the target value is less than the node's value
    * recurse to the right if the target value is greater than the node's value

### Tests

You can run tests with `cargo test`. To show any printed output of successful
tests, use `cargo test -- --nocapture`.

Tests should be defined in the way specified in
[TMLL 2.6](http://cglab.ca/~abeinges/blah/too-many-lists/book/first-test.html).
This keeps unit tests close to the code that they test.

```rust
#[cfg(test)]
mod test {
    use super::List;

    #[test]
    fn test_push_pop() {
        // ...
    }
}
```

You should test `search` and `insert` in various orders, for both true and
false results. Use `assert!()` and/or `assert_eq!()`. They don't have
to be any more complex than the tests in TMLL 2.6.

### Submission

Just like in homework 01, commit and push your work to the master branch of
your Classroom for Github repository for this HW. Make sure it is visible on
Github! This is your submission. (Work must be in the master branch at the due
time.)

`cargo test` should work to run all of the tests in your homework on stable
Rust. Make sure you have written tests which cover every one of your functions.


================================================
FILE: hw03/README.md
================================================
# Homework 3: "Iterating" On Your Binary Search Tree

**Due 2016-02-10, 11:59pm.**

For questions, please post on Piazza (Penn students) or Google Groups (other).
Links on homepage.

## Overview

This assignment is modeled after Alexis Beingessner (Gankro)'s [_Learning Rust
With Entirely Too Many Linked Lists_][TMLL] (TMLL).

[TMLL]: http://cglab.ca/~abeinges/blah/too-many-lists/book/

This time, you should look at Chapter 3. We won't do everything in there, but
the content is similar.

#### Classroom for GitHub

We're using Classroom for GitHub, which manages private homework repositories
for students. To create your very own private homework repository (owned by
us), click this link:
* https://classroom.github.com/assignment-invitations/678e4f3868daaec525ce8f75f23fc53c 

## Instructions

Write your implementation and tests in `src/second.rs`. `lib.rs` is provided.

As before, your code doesn't have to follow an exact interface, but the
function signatures provided will probably work best.

You'll likely want to start off with your solution for HW2 - a lot will carry
over. You'll modify the data structure, `insert`, `search`, and the tests, and
write the code necessary to turn your BST into various iterator types:
`IntoIter`, `Iter`, and `IterMut`.

Like in HW2, your GitHub repository will be pre-populated with a skeleton Cargo
project. You should edit `Cargo.toml` to add yourself as the author.

### Implementation

This _roughly_ corresponds to
[TMLL 3](http://cglab.ca/~abeinges/blah/too-many-lists/book/second.html).
For more details, refer there.

We will use:

* `Option` and `take` (but *not* `map`).
* Type aliases.
* Generic type parameters (`BST<T>`) with trait bounds (`Ord`).
* Named lifetimes and lifetime bounds on type parameters.
* Traits, trait implementations, and associated types.
* Iterators.

We'll essentially be modifying HW2, so you should copy `first.rs` over as
`second.rs` in HW3.

**NOTE:**

[TMLL 3.1][] introduces `map` and anonymous functions and closures. Since we
haven't covered this in class, you can  use `match`es instead of closures
everywhere in this assignment. However, you're welcome to use `map`/closures if
you want the extra practice - simple closures aren't hard.

> Second, `match option { None => None, Some(x) => Some(y) }` is such an
> incredibly common idiom that it was called `map`. `map` takes a function to
> execute on `x` in the `Some(x)` to produce the `y` in `Some(y)`. We could
> write a proper `fn` and pass it to `map`, but we'd much rather write what to
> do *inline*.

#### Details

As in TMLL 3:

* Convert `BST` and `Link` to take a generic element `T` instead of `i32`.

* Replace the `Link` type with a type alias for `Option<Box<Node<T>>>`, because
  your life has felt strangely lacking in angle brackets recently. Then, update
  all of the code which uses `Link`. You may not have used `mem::replace` in
  HW2, in which case you won't need `take` yet.

  * If you want, take a look through the [`Option` documentation][optdoc] to
    find useful methods.

[optdoc]: https://doc.rust-lang.org/std/option/enum.Option.html

* Now that `Link` is a type alias and not a struct, you cannot directly `impl`
  methods for it, because you don't own the type `Option`. However, you do not
  feel constrained by the ~~silly~~ very serious and important rules that Rust
  imposes on your life, so you can work around this by defining a generic trait
  `InsertSearch<T>` which provides your two functions `insert(&mut self, e: T)
  -> bool` and `search(&self, e: T) -> bool`.

  * Proceed to exercise your unbounded power by implementing `InsertSearch`
    for `Link<T>`, by adapting the functions you wrote for HW02 to be generic
    over `T`. Make sure your old tests still pass.

* Now you will transform your ordinary BST into an extraordinary BST iterator!
  We're going to use the [`Iterator`] trait.

  * Build yourself an `IntoIter` struct like the one in [TMLL 3.4][].

    * Since this is a BST, and not a list, we're going to cheat a bit and
      just iterate over the rightmost edge of the tree, since that's less
      annoying. (If you feel like it, you can try doing an in-order
      traversal of the tree instead. We can't guarantee that you can do it
      with the material we have covered so far, so try the cheaty version
      first!)

    * Implement the [`Iterator`][] trait for `IntoIter`. This requires an
      associated type, `type Item`, and an implementation of
      `next(&mut self) -> Option<Self::Item>`.

  * Instead of implementing `BST::into_iter` as a plain member function,
    we're going to do something _way_ cooler:

    * [`IntoIterator`][] is a trait with one method, `into_iter`. This is the
      sugar that fuels Rust's `for` loops. Go ahead and `impl IntoIterator for
      BST`. Don't forget: this trait requires you to declare associated types!
      Read the [docs][`IntoIterator`] for the deets.

[`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
[`IntoIterator`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html

  * BAM! Now your BST can harness the power of `for` loops. Try this:

```rust
let mut bst = BST::new();
bst.insert(1);
bst.insert(2);
bst.insert(3);

for elt in bst { // calls bst.into_iter()
    println!("{}", elt);
}
```

  * But your power is yet incomplete. What about borrowed iteration? Implement
    an `Iter` struct, as described in [TMLL 3.5][] (similar to `IntoIter`).

    * Again, instead of implementing `BST::iter`, we're going to lord our
      superiority over Gankro's tutorial and use `IntoIterator`. But you can't
      just implement a trait _twice_ for the same struct; that would be absurd.
      And confusing. It would break so many rules. Instead, we'll implement this
      for `&BST`.
      
    * Again, iterate over the rightmost edge of the tree.

    * You're going to need named lifetimes here! To start, you have to
      implement `impl<'a, T> IntoIterator for &'a BST<T>`.

    * This is what allows:

```rust
for elt in &bst { // calls (&bst).into_iter()
    println!("{}", elt);
}
```

  * Finally, we'll move on to [TMLL 3.6][], `IterMut`. You know what you need
    to do.

```rust
for elt in &mut bst { // calls (&mut bst).into_iter()
    println!("{}", elt);
}
```

[TMLL 3.1]: http://cglab.ca/~abeinges/blah/too-many-lists/book/second-option.html
[TMLL 3.4]: http://cglab.ca/~abeinges/blah/too-many-lists/book/second-into-iter.html
[TMLL 3.5]: http://cglab.ca/~abeinges/blah/too-many-lists/book/second-iter.html
[TMLL 3.6]: http://cglab.ca/~abeinges/blah/too-many-lists/book/second-iter-mut.html

### Tests

Test all three of your iterators. To do this, you should check two things:

* For a BST `bst`, you should be able to compile a for loop over
  `bst`, `&bst`, or `&mut bst`.

* The values returned by the iterator should be correct. You can explictly
  get an iterator (with, for example, `(&mut bst).into_iter()`), then
  `assert_eq!` the values returned by `next()`.

### Submission

Commit and push your work to the master branch of your Classroom for Github
repository for this HW. Make sure it is visible on Github! This is your
submission. (Work must be in the master branch at the due time.)

`cargo test` should work to run all of the tests in your homework on stable
Rust. Make sure you have written tests which cover every one of your functions.

If you have any comments or feedback on this assignment, include them in the
README of your submission.


================================================
FILE: hw04/README.md
================================================
# Homework 4: Reverse Polish ~~Sausage~~ Notation Calculator

**Due 2016-02-17, 11:59pm.**

For questions, please post on Piazza (Penn students) or Google Groups (other).
Links on course homepage.

## Overview

Reverse Polish notation, which is [not exactly][rpn] the reverse of Polish
notation, is a convention for mathematical expressions for ~~nerds~~
~~hipsters~~ ~~enterprising young computer scientists~~ ~~bored students~~ you!
Implementing an RPN calculator in Rust will cover several standard library
modules and common patterns.

[rpn]: https://en.wikipedia.org/wiki/Reverse_Polish_notation#Explanation

Reverse Polish notation defines expressions with _postfix_ operators (`1 2 +`),
rather than the typical _infix_ expression form (`1 + 2`). Postfix form is very
easy to evaluate using a state machine with a stack data structure. When
the calculator encounters a numeric literal (`1`), it pushes the number onto the
stack. When an operator (`+`) is encountered, the machine pops one or more
numbers off the stack, evaluates the expression, then pushes the result back
onto the stack.

#### Classroom for GitHub

We're using Classroom for GitHub, which manages private homework repositories
for students. To create your very own private homework repository (owned by
us), click this link:
* https://classroom.github.com/assignment-invitations/4247c727a1c77eb1982e03bc4083a574

## Instructions

Write your calculator implementation in `rpn.rs`, and your parser
implementation in `parser.rs`. `main.rs` is provided. Hooray! You're finally
writing an executable program!

Like in HW3, your GitHub repository will be pre-populated with a skeleton Cargo
project. You should edit `Cargo.toml` to add yourself as the author.

##### Stack Element Types

Your stack will support two types: `i32` and `bool`. We're starting you off with
a convenient enum to store these, `Elt`, in `rpn.rs`.

##### Operators

You're only required to implement the following operations because ~~they're the
ones that won out in a fight~~ implementing all operations would be tedious:

_Addition_ adds the top two elements of the stack, or type-errors on booleans.

_Negation_ computes logical-not of booleans, and inverts the sign of integers.

_Equality_ compares the top two elements and pushes a boolean onto the stack.

_Swap_ reverses the order of the top two elements on the list.

_Random_ pops a value off of the stack; if that value is an integer `x`, it will
use the `rand` library to generate a random number between `0` and `x` and push
it onto the stack. Otherwise, it type-errors.

_Quit_ exits the program.

We're providing an `Op` type to represent the various operators you may
encounter in the wild, located in `rpn.rs`.

##### Result Aliases

When your calculator hits an error, it should exit. Conveniently, there's also a
handy-dandy provided `Error` enum which defines a few different types of
possible errors: undeflow, type mismatch, syntax, IO, and quit (which is not an
error, but represents an exit value).

Because you're a good software engineer, you're going to create your own
`Result` alias for use in your calculator. Use the provided `Error` enum in
`rpn.rs` to define an alias over `std::result::Result` - a similar aliasing
can be seen in `std::io::Result`.

##### External Crates: `rand`

`rand` is a Rust library which is part of the `rust-nursery` project. (It had
previously been part of `std`, but was moved when Rust decided to downsize its
standard library.) Good thing Cargo makes it so easy to add dependencies!

To use `rand`, you'll need to add it as a dependency to your `Cargo.toml` file.
[The guide][crates-guide] on crates.io (which hosts crates) explains how Cargo
adds and manages project dependencies.
You can find name and version information on [the page for `rand` on
crates.io](https://crates.io/crates/rand)

[crates-guide]: http://doc.crates.io/guide.html#adding-dependencies

You also need to declare it (`extern crate rand`) in your crate's
top-level file (`main.rs`) in order to import and use modules from `rand` in
your project.

##### Stack API

You should define a `Stack` struct, which should define at least the following
public methods:

```rust
/// Creates a new Stack
pub fn new() -> Stack {
    unimplemented!()
}

/// Pushes a value onto the stack.
pub fn push(&mut self, val: Elt) -> Result<()> {
    unimplemented!()
}

/// Tries to pop a value off of the stack.
pub fn pop(&mut self) -> Result<Elt> {
    unimplemented!()
}

/// Tries to evaluate an operator using values on the stack.
pub fn eval(&mut self, op: Op) -> Result<()> {
    unimplemented!()
}
```

You may implement the internals of your stack however you like, but we'd suggest
using a `Vec`.

##### Calculator API

The tokens your parser should recognize and their corresponding interpretations
are as follows:

| Input token | Action                 |
| ----------- | ---------------------- |
| any integer | push Elt::Int(integer) |
| "true"      | push Elt::Bool(true)   |
| "false"     | push Elt::Bool(false)  |
| "+"         | eval Op::Add           |
| "~"         | eval Op::Neg           |
| "<->"       | eval Op::Swap          |
| "="         | eval Op::Eq            |
| "#"         | eval Op::Rand          |
| "quit"      | eval Op::Quit          |

Any other input is considered an error. Your calculator can read multiple tokens
on a single line, and will evaluate them in order. You can parse strings into
integers by using `i32::from_str()`.

We started two functions in `parser.rs` for reading and manipulating input:

`read_eval_print_loop` will do just what it says on the tin: reads from `stdin`,
evaluates some tokens, and then prints out a result. This tin comes with some
~~cookies~~ 🍰 stub code, which prints a prompt and then (`try!`s to) flush
`stdout` so you can read input.

`evaluate_line` is a helper function to `read_eval_print_loop`. It takes the
input `String` and your calculator's `stack` and evaluates the tokens in that
line. Currently, it takes the input string, trims off whitespace from the ends,
and creates a `SplitWhitespace` iterator over the string.

## Tests

Tests have been provided in the starter code. You can add as many tests as you
want (but you don't need to write any). Obviously, you should test your
calculator by using it.

## Submission

Commit and push your work to the master branch of your Classroom for Github
repository for this HW. Make sure it is visible on Github! This is your
submission. (Work must be in the master branch at the due time.)

`cargo test` should work to run all of the tests in your homework on stable
Rust. Make sure you have written tests which cover every one of your functions.

If you have any comments or feedback on this assignment, include them in the
README of your submission.


================================================
FILE: hw05/README.md
================================================
# Homework 05: The ~~Fun-Time Reference Sharing~~ _Darkest_ Dungeon
### It's not just a phase, _Mom_!

**Due Friday, 2016-02-26, 11:59pm.**

For questions, please post on Piazza (Penn students) or Google Groups (other).
Links on course homepage.

## Overview

You have found yourself standing at the entrace of a large, mysterious,
~~smelly~~ castle. You must have taken a wrong turn when you were wandering
through that dark, imposing, werewolfy forest. Why were you doing that?
Nevermind, it's not relevant. Just go on inside. There's treasure. I think.
There's definitely at least gold. This wouldn't be an adventure game if you
couldn't even find gold!

Ahem. Let me try this again:

> _Wander forth for promises of grand treasures hidden in glamorous bejeweled
chests and decrepit iron maidens, dangerous traps filled with poisonous spikes.
Climb over the forgotten corpses of the fallen adventurers who have come before
you yet were not as blessed with luck._

Wait, seriously, _where_ is that smell coming from?

#### Classroom for GitHub

We're using Classroom for GitHub, which manages private homework repositories
for students. To create your very own private homework repository (owned by
us), click this link:

* https://classroom.github.com/assignment-invitations/d7fc86f713d77fa96deed930a9e75244

## Instructions

- In this assignment we are going to build a text adventure game!

Okay, we lied. The castle doesn't exist yet. All you have is some poorly
written down map that someone shoved into your hand earlier. They didn't even
draw it out properly! It's written in some weird... "JSON" format.

- Finish the JSON parser. The provided code parses a JSON file to create a
  series of rooms connected by hallways. See below for more detail.

[*Look around you*][]. What can you see? Nothing! You haven't implemented eyes
yet. That doesn't make any sense. What are you doing. Nevermind, nevermind. Stop
asking questions.

[*Look around you*]: https://www.youtube.com/watch?v=gaI6kBVyu00

- Print out a description of a room when you enter it, containing  adjacent
  rooms accessable from your current location.

We promised you gold, and so there shall be gold! Some of these rooms contain
treasure and glory! Chests contain gold; food provides nourishment and restores
health. Be sure to look closely: some curios, such as iron maidens and fallen
adventurers, contain yet more items within them.

But beware! There is danger afoot. When you encounter a spike trap or iron
maiden, it will deal damage to your person.

- Use all items in a room when you enter it, and output to the player
  ~~a tale of their misery~~ a description of what happened to them. All items are
  handled immediately but death visits at the end of the turn, so it is possible
  to take fatal damage from a spike trap but immediately cure yourself with a
  fistful of food to avoid death. Gold is added to your inventory. Items can
  only be used once, so they should be removed from a room once used.

It wouldn't be an adventure if you were stuck in the entrance. You'd probably
die of boredom before you even died of thirst.

- Implement `go [destination]` to move from your current location to any
  room connected by a hallway.

Now that you have the freedom of movement, you've finally come to a great,
terrible, disgusting realization. You've remembered the legend of *the Wumpus*.

The Wumpus is a large, repulsive, oozing monster from which that putrid smell
emanates. The Wumpus will consume your being if you happen upon the room where
it makes its lair. However, you are no defenseless peasant; you have prepared
with your mighty bow and arrow. If you shoot an arrow toward the room a Wumpus
lies in, it will surely kill the Wumpus, because you are a mighty warrior and
all of your arrows fly true. Or maybe because the Wumpus is so big you can't
possibly miss.

- Implement `shoot [destination]` to shoot an arrow into a room and kill the
  Wumpus if it's there.

When you've killed the Wumpus, congratulations! You have freed this castle from
its terrible and malodorous curse. All the land rejoices in your honor. You are
crowned as the exalted ruler for the people whose lives you have saved. There is
no end of riches and luxury for you. Or something. Maybe you just go home and
smell the roses.

## Demo

If this doesn't make any sense, or you aren't familiar with text adventures, you
can play this game on Eniac:

```rust
~cis198/local/bin/hw05 ~cis198/local/share/hw05/castle.json
```

### How To Play

After building your project, you can run it with `cargo run
[castle_description.json]`. A sample castle is provided in `data/castle.json`.

The available commands are `go [room]`, `shoot [room]`, and `quit`. Quit prints
your score, whether or not you've won, and exits the game. Dying, when your
health falls below 0, also results in exiting the game.

Players have a location (`Rc<RefCell<Room>>`, health (`i32`), gold (`i32`), and
an account of whether they won (`bool`). Players can `Go` or `Shoot` a room.

Movement between rooms should be implemented by replacing the stored
`Rc<RefCell<Room>>` owned by the player.

### Castle Structure

A room in this castle contains a name (`String`), a list of contents
(`Vec<Curio>`), a list of halls (`Vec<Rc<Hall>>`), and the possibility of a
Wumpus (`bool`). Halls each connect two rooms (two
`Option<Rc<RefCell<Room>>>`s).

See the provided JSON file (`data/castle.json)`: Rooms are defined by name, the
number of randomly-generated curios, and whether the wumpus is in that room.
Halls are defined as tuples (in as much as JSON allows tuples) between room
numbers. Rooms are numbered in the order they are defined. Room names should be
unique.

Each room contains a set of Curios. The generation of Curios for a given room is
provided. The JSON parsing is provided; you will start by finishing room and
hallway generation.


## Testing

No tests! Yay!

We're not providing any tests nor expecting that you write any. We'll grade your
game by simply playing it.

## Writeup

Edit the README in your project with a (brief!) explanation of how `Rc` and
`RefCell` are used and why they are necessary in this game.

## Make your game more game

Apply as much creativity as you want to your game. Add your own maps,
flavortext, additional curios, miscellaneous player effects. Extremely arbitrary
numbers of brownie points (which can be redeemed for real brownies!) will be
distributed for making your game more fun.

Please do not edit the structure of Rooms and Halls. Otherwise, you're missing
the point of this assignment!

Highlight any interesting additions that you've made in your README.

## Submission

Commit and push your work to the master branch of your Classroom for Github
repository for this HW. Make sure it is visible on Github! This is your
submission. (Work must be in the master branch at the due time.)

If you have any comments or feedback on this assignment, include them in the
README of your submission.


================================================
FILE: hw06/README.md
================================================
# Homework 6: BB-198 - A Bulletin Board System (BBS)

**Due Sunday, 2016-03-06, 11:59pm.**

The internet is the beginning of the hyper-connected future. Isn't it great?
We're working to create a new _wireless_ social network, where people can
communicate with their friends over the internet! We think the next big product
in this space will be bulletin board systems, where people in all different
places can gather and share information throughout the world.

You've recently been hired as an engineer. Welcome to the team! Since we've
heard that you have a lot of experience using Rust, you've been given
responsibility for this BBS project that we've just started. Good luck!

#### Classroom for GitHub

We're using Classroom for GitHub, which manages private homework repositories
for students. To create your very own private homework repository (owned by
us), click this link:

* https://classroom.github.com/assignment-invitations/c674a59f072e68a140e54599fcf35e8f

## Background

### [`hyper.rs`][]

[`hyper.rs`]: http://hyper.rs

> Hyper is a fast, modern HTTP implementation written in and for Rust. It is a
low-level typesafe abstraction over raw HTTP, providing an elegant layer over
"stringly-typed" HTTP.

Hyper is the beginning of the future. Hyper contains both a server, which
manually handles requests that it receives, and a client, which can build HTTP
requests and parse HTTP responses. You will use both in this assignment.

Hyper uses OpenSSL, which means OpenSSL needs to be installed.

On OS X, you need to set environment variables telling Cargo where to find
OpenSSL headers on your computer. Read
[this StackOverflow post][osx_ssl_instructions] and follow the instructions.

[osx_ssl_instructions]: http://stackoverflow.com/questions/34612395/openssl-crate-fails-compilation-on-mac-os-x-10-11

On Linux, you may need to install a development package for OpenSSL (this
provides OpenSSL's header files, so Hyper can link against them). On Ubuntu, you
can install this with `apt-get install libssl-dev`.

## Instructions

### lib

We're going to build this BBS in a library crate, so it can be easily deployed
to others who want to use it. This crate will contain `lib.rs` as before, which
defines common functions and types used in the rest of your project.
Additionally, the crate contains several binaries (located in `src/bin`). Each binary
is a standalone Rust file, which uses the library as if it were an external
crate.

Here's what's defined in `lib.rs`:

- `Message`: a struct representing a post on the bulletin board, containing the
  username and their message.
- `UserClient`: a struct storing a username, the server address they make posts
  to, and a `hyper::Client`, which can be used to make multiple requests to a
  server.
  - `get_content`: a method which builds a GET request to the stored server
  address.
- Some constants which are shared between binaries.
  - `SERVER_ADDR`, `BOT_ADDR`: the addresses that the server and bot will listen
    on.
  - `HTML_ADDR`: the addresses the BBS is visible at (i.e. the
    address you'd visit with browser)
  - `HTML_HEADER`, `HTML_DATA`, `HTML_FOOTER`: the local files which the server
    uses to generate the page.

### `bin/server`

Provided: A basic web server which can respond to GET requests at
http://127.0.0.1:1980 and serves a static web page. It generates this static web
page by concatenating two files (the header, and footer).

* You may need to change the port numbers from 1980 to others if you are working
  on Eniac, to avoid colliding with other servers.

This is the _future_, though. Static webpages are so _nineties_. Add to the
existing request handler (`req_handler`) the ability to receive posts through
POST requests. The body of a POST request will contain a JSON-encoded `Message`
(defined in `lib.rs`). You should append each post to the bulletin board's data
page (`HTML_DATA`) when it's received. You should also update the GET request
handler to include the posted messages when it generates a page.

* For more context on RESTful APIs and the difference between GET and POST
  requests, you can read this [StackOverflow page][restful].

[restful]: https://stackoverflow.com/questions/671118/what-exactly-is-restful-programming

Notice that, since the `bbs` library is external to this server, you need to
declare it with `extern crate bbs` at the top of your file, and import parts as
needed.

### `bin/client`

Provided: A client which initializes a user and makes a GET request to read the
current bulletin board.

_Boring._ The user of this software should be able to post a message to the
bulletin board. Otherwise, this wouldn't be an innovation at all!

We'd like to provide our users with a clean, modern command-line interface for
making posts to our bulletin board. It's up to you to design this. For example,
you may retain the current command line interface (where the user specifies
their username), and allow the user to post messages to the BBS by reading from
standard input.

### `bin/bot`

Oh no! You've put all of this hard work in, and your bulletin board still
doesn't have any users. ~~Because you have no friends,~~ To help build activity
and user interest, you decide to build a bot service which will automatically
respond to certain types of messages on the board. This is exactly the sort of
fun, exciting feature that people are looking for on the Web.

Add a new binary to your BBS crate which contains a bot.

This bot listens for TCP connections on port 1981 (as defined in `lib.rs`).
Whenever the server receives a new post, it will make new connection to this bot,
relaying the contents of the post. The bot will read the post and determine if
it should respond.

This is the future, so of course your bot will have to be connected to the
internet. When the bot receives a message of the form "choose x y z", it will
make a query to random.org's [HTTP API][random-api], asking for a value between
1 and the length of the options. You can use `hyper::client` to receive and
parse these queries. Then, the bot should post a message back to the server with
the appropriate choice (e.g. for a value of 2, your bot would post the message
"y"). Bam. Random.org. _The future_.

* You can easily build these query URLs with a format string. A simple example
  (as given [here][random-api]) will generate ten integers in base 10, between 1
  and 6, returned as a plaintext page:
  https://www.random.org/integers/?num=10&min=1&max=6&col=1&base=10&format=plain&rnd=new

You are the head engineer on this project, so you are free to build any sort of
bot functionality you want. If you want to do something different, just explain
what you've done in your README.

[random-api]: https://www.random.org/clients/http/

### Feature List

To recap, here are all the features you should implement:

- In `server.rs`:
  - Handle `POST` requests in `req_handler`
  - Update the `GET` handler in `req_handler` to generate a page containing the
      post data
- In `client.rs`:
  - Create a command-line interface to allow users to easily send data to the
      server
- In `bot.rs`:
  - Listen on port 1981 for incoming TCP connections to determine if new posts
      have been made to the BBS
  - Create a function to randomly choose "x", "y", or "z" from posts of the form
      "choose x y z" using random.org's HTTP API

## Submission

Commit and push your work to the master branch of your Classroom for Github
repository for this HW. Make sure it is visible on Github! This is your
submission. (Work must be in the master branch at the deadline.)

If you have any comments or feedback on this assignment, include them in the
README of your submission.


================================================
FILE: hw07/README.md
================================================
# Homework 7: A Multithreaded Chat System

**Due Wednesday, 2016-03-23, 11:59pm.**

Okay, you admit it - a BBS isn't exactly the most modern web technology of all
time. Inspired by the rising success of this newfangled "AOL Instant Messenger"
thing all the kids are using, you've decided to make your own chat service!

In this homework, you'll write your own multithreaded, multi-user, IRC-esque
chat service! And as a bonus, it'll run in the browser using WebSockets!

#### Classroom for GitHub

We're using Classroom for GitHub, which manages private homework repositories
for students. To create your very own private homework repository (owned by
us), click this link:

* https://classroom.github.com/assignment-invitations/8380d7698ae30e972cf46d5c80daa2a8

## Background

**This assignment should work on [any modern browser](http://caniuse.com/#feat=websockets); tested on Firefox and Chrome.**

### WebSockets

WebSockets are a web technology for allowing JavaScript in webpages to connect 
back to servers using a bidirectional data stream. WebSockets behave very
similarly to TCP streams (but are message-based).

We will be using the `rust-websocket` library. You'll definitely need to take
a look at some of the documentation and examples:

* [GitHub repo](https://github.com/cyderize/rust-websocket)
* [Documentation](http://cyderize.github.io/rust-websocket/doc/websocket/)
* [Example server](https://github.com/cyderize/rust-websocket/blob/master/examples/server.rs)

### Multithreaded Networking

In this assignment, we'll be using threads to easily handle several network
clients at once. One way to do this is to create one thread for each client.
As clients connect, a thread is spawned to manage that particular connection:

```rust
// fn listen
for connection in server {
    // Spawn a client_thread.
}
```

In this paradigm, each _client thread_ will _block_ as it waits for data to
come in from its respective client. This can be expressed very elegantly using
iterators: every time a message comes in, the loop runs once. When the channel
closes, the loop terminates.

```rust
// fn client_thread
for message in client_recv.incoming_messages() {
    // Handle message; relay via MPSC channel.
}
```

In the _relay thread_, each message received via the MPSC channel should be
sent to all of the clients (including the originator). Once again, iterators
allow us to use the MPSC receiver very nicely:

```rust
// fn relay_thread
for action in relay_mpsc_recv {
    // Send message to all clients.
}
```

**Aside:** For many applications, the one-thread-per-client model does not work
well. For systems which will have many (thousands or more) clients, spawning
thousands of threads is very inefficient. In these cases, a more complex system
will typically be used; for example, several threads (usually about one per
core) might run in a thread pool, where each _asynchronously_ handles many
clients. That is, each thread will periodically poll for incoming data from
each client (_non-blocking_), rather than waiting for incoming data from a
single client (_blocking_). For `rust-websocket`, there is a discussion
[here](https://github.com/cyderize/rust-websocket/issues/6).

### IRC Principals

IRC (Internet Relay Chat) operates on very simple principals:

* Maintain a list of all of the currently connected clients.
* For each message that comes in, relay it back out to all of the clients.

We won't be implementing IRC precisely, but we will use the "relay" idea.

## Instructions

`main.rs` and `webpage.rs` are provided for you; they just serve a static HTML
webpage over **port 1980**. To access this, just run the server (`cargo run`)
and open [localhost:1980](http://localhost:1980/) in a web browser.
The static webpage is also written for you.

Your job is to write `chatserver.rs`. In `chatserver::start`, you should spawn
a thread to listen for incoming WebSockets connections on **port 1981**.
We've also given you a (de)serializable `enum ChatAction` - don't modify this;
the JavaScript code depends on it!

**Note:** The messages received-from and sent-to the client should be JSON
object strings with the same form as `rustc_serialize`'s serialization of the
`ChatAction` type. This means you can `json::encode` `ChatAction`s to create
text to send to the web browser, and `json::decode` to turn the web browser's
messages into `ChatAction`s.

The [example server](https://github.com/cyderize/rust-websocket/blob/master/examples/server.rs)
will be an important resource - you'll use a lot of the same boilerplate code.
(Note: we aren't using a protocol; the protocol response isn't necessary.)

Now, go check out the comments left in `chatserver.rs`!

## Submission

Commit and push your work to the master branch of your Classroom for Github
repository for this HW. Make sure it is visible on Github! This is your
submission. (Work must be in the master branch at the deadline.)

If you have any comments or feedback on this assignment, include them in the
README of your submission or post on Piazza or the Google Group.
Download .txt
gitextract_0bxq24dp/

├── .gitmodules
├── final/
│   └── README.md
├── hw00/
│   └── README.md
├── hw01/
│   ├── README.md
│   └── tests_provided.rs
├── hw02/
│   └── README.md
├── hw03/
│   └── README.md
├── hw04/
│   └── README.md
├── hw05/
│   └── README.md
├── hw06/
│   └── README.md
└── hw07/
    └── README.md
Download .txt
SYMBOL INDEX (7 symbols across 1 files)

FILE: hw01/tests_provided.rs
  function test_sum_small (line 15) | fn test_sum_small() {
  function test_dedup_small (line 23) | fn test_dedup_small() {
  function even_predicate (line 30) | fn even_predicate(x: i32) -> bool {
  function test_filter_small (line 35) | fn test_filter_small() {
  function test_mat_mult_identity (line 45) | fn test_mat_mult_identity() {
  function test_sieve_basic (line 64) | fn test_sieve_basic() {
  function test_hanoi_1_disks (line 73) | fn test_hanoi_1_disks() {
Condensed preview — 11 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (70K chars).
[
  {
    "path": ".gitmodules",
    "chars": 654,
    "preview": "[submodule \"hw02/starter\"]\n\tpath = hw02/starter\n\turl = git@github.com:cis198-2016s/hw02.git\n\tbranch = master\n[submodule "
  },
  {
    "path": "final/README.md",
    "chars": 8012,
    "preview": "# Final Project\n\nThis final project gives you the freedom to do whatever you've been dying to\ndo with this fancy new pro"
  },
  {
    "path": "hw00/README.md",
    "chars": 5248,
    "preview": "# Homework 00: Hello Rust & Hello Cargo!\n\n**Due 2016-01-25, 11:59pm.**\n\nFor questions, please post on Piazza (Penn stude"
  },
  {
    "path": "hw01/README.md",
    "chars": 11969,
    "preview": "# Homework 01: Rust Finger Exercises\n\n**Due ~~2016-01-27~~ 2016-01-28, 11:59pm.**\n\nFor questions, please post on Piazza "
  },
  {
    "path": "hw01/tests_provided.rs",
    "chars": 1223,
    "preview": "#![cfg(test)]\n\nuse problem1::{sum, dedup, filter};\nuse problem2::mat_mult;\nuse problem3::sieve;\nuse problem4::{hanoi, Pe"
  },
  {
    "path": "hw02/README.md",
    "chars": 6092,
    "preview": "# Homework 2: A Mediocre Binary Search Tree\n\n**Due 2016-02-03, 11:59pm.**\n\nFor questions, please post on Piazza (Penn st"
  },
  {
    "path": "hw03/README.md",
    "chars": 7492,
    "preview": "# Homework 3: \"Iterating\" On Your Binary Search Tree\n\n**Due 2016-02-10, 11:59pm.**\n\nFor questions, please post on Piazza"
  },
  {
    "path": "hw04/README.md",
    "chars": 6801,
    "preview": "# Homework 4: Reverse Polish ~~Sausage~~ Notation Calculator\n\n**Due 2016-02-17, 11:59pm.**\n\nFor questions, please post o"
  },
  {
    "path": "hw05/README.md",
    "chars": 6989,
    "preview": "# Homework 05: The ~~Fun-Time Reference Sharing~~ _Darkest_ Dungeon\n### It's not just a phase, _Mom_!\n\n**Due Friday, 201"
  },
  {
    "path": "hw06/README.md",
    "chars": 7696,
    "preview": "# Homework 6: BB-198 - A Bulletin Board System (BBS)\n\n**Due Sunday, 2016-03-06, 11:59pm.**\n\nThe internet is the beginnin"
  },
  {
    "path": "hw07/README.md",
    "chars": 5067,
    "preview": "# Homework 7: A Multithreaded Chat System\n\n**Due Wednesday, 2016-03-23, 11:59pm.**\n\nOkay, you admit it - a BBS isn't exa"
  }
]

About this extraction

This page contains the full source code of the cis198-2016s/homework GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 11 files (65.7 KB), approximately 17.1k tokens, and a symbol index with 7 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!