Rename sheet folders to assure proper sorting

This commit is contained in:
Lukas Kalbertodt
2017-02-16 15:12:56 +01:00
parent aaf0332117
commit b3664c6ffd
74 changed files with 0 additions and 0 deletions

4
aufgaben/sheet07/README.md Executable file
View File

@ -0,0 +1,4 @@
Blatt 7
=======
Ok, langsam wird es tatsächlich langweilig, mich zu wiederholen: Ab jetzt für jedes Aufgabenblatt einen eigenen Branch anlegen... der vom `master` abzweigt. Wehe, ihr vergesst das beim nächsten mal! :worried:

31
aufgaben/sheet07/sol1/fib.rs Executable file
View File

@ -0,0 +1,31 @@
struct Fib {
curr: u64,
last: u64,
}
impl Fib {
fn new() -> Self {
Fib {
curr: 1,
last: 0,
}
}
}
impl Iterator for Fib {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
let new = self.last + self.curr;
self.last = self.curr;
self.curr = new;
Some(self.last)
}
}
fn main() {
for i in Fib::new().take(20) {
println!("{}", i);
}
}

93
aufgaben/sheet07/sol2/iters.rs Executable file
View File

@ -0,0 +1,93 @@
fn factorial(x: u64) -> u64 {
(1..x + 1).product()
}
#[test]
fn test_factorial() {
assert_eq!(factorial(1), 1);
assert_eq!(factorial(2), 2);
assert_eq!(factorial(3), 6);
assert_eq!(factorial(15), 1_307_674_368_000);
}
fn is_palindrome(word: &str) -> bool {
word.chars()
.zip(word.chars().rev())
// This is just an optional optimization
.take(word.len() / 2)
.all(|(a, b)| a == b)
}
#[test]
fn test_is_palindrome() {
assert!(is_palindrome("bob"));
assert!(is_palindrome("anna"));
assert!(is_palindrome("lagerregal"));
assert!(!is_palindrome("peter"));
}
fn greatest_subsequencial_sum(arr: &[i64]) -> &[i64] {
// all possible window lengths
(1..arr.len() + 1)
// iterate over all possible windows
.flat_map(|len| arr.windows(len))
// add the empty slice in case all numbers are negative
.chain(std::iter::once(&arr[0..0]))
// we want to select the window which sum is the greatest
.max_by_key(|win| win.iter().sum::<i64>())
// we know our iterator has at least one element
.unwrap()
}
#[test]
fn test_greatest_subsequencial_sum() {
let a = [1, 2, 39, 34, 20, -20, -16, 35, 0];
assert_eq!(greatest_subsequencial_sum(&a), &a[0..5]);
let b = [-3, -9, -8, -34];
assert_eq!(greatest_subsequencial_sum(&b), &[]);
}
fn rot13(s: &str) -> String {
s.chars().map(|c| {
match c {
'a' ... 'm' | 'A' ... 'M' => (c as u8 + 13) as char,
'n' ... 'z' | 'N' ... 'Z' => (c as u8 - 13) as char,
_ => c
}
}).collect()
}
#[test]
fn test_rot13() {
assert_eq!(rot13("hello"), "uryyb");
assert_eq!(rot13("uryyb"), "hello");
assert_eq!(
rot13("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
);
assert_eq!(rot13("peter"), "crgre");
}
fn used_chars_count<S: AsRef<str>>(words: &[S]) -> usize {
use std::collections::HashSet;
words.iter()
.flat_map(|w| w.as_ref().chars())
.filter(|c| !c.is_whitespace())
.collect::<HashSet<_>>()
.len()
}
#[test]
fn test_used_letters() {
assert_eq!(used_chars_count(&["hi", "ih gitt"]), 4);
assert_eq!(used_chars_count(&["peter"]), 4);
assert_eq!(used_chars_count(&["p e t e r", "barbara"]), 6);
}
fn main() {
}

19
aufgaben/sheet07/sol3/fold.rs Executable file
View File

@ -0,0 +1,19 @@
fn main() {
// product
let fac_5 = (1..5).fold(1, |acc, x| acc * x);
assert_eq!(fac_5, (1..5).product());
println!("5! = {}", fac_5);
// max
let max = vec![3, 1, 4, 1, 5, 9, 2, 6]
.into_iter()
.fold(0, |acc, x| std::cmp::max(acc, x));
assert_eq!(max, 9);
println!("max: {}", max);
// all
let all_even = (1..9)
.fold(true, |acc, x| acc && (x % 2 == 0));
assert!(!all_even);
println!("all_even: {}", all_even);
}

4
aufgaben/sheet07/sol4/Cargo.lock generated Executable file
View File

@ -0,0 +1,4 @@
[root]
name = "mycp"
version = "0.1.0"

View File

@ -0,0 +1,6 @@
[package]
name = "mycp"
version = "0.1.0"
authors = ["Lukas Kalbertodt <lukas.kalbertodt@gmail.com>"]
[dependencies]

106
aufgaben/sheet07/sol4/src/main.rs Executable file
View File

@ -0,0 +1,106 @@
use std::ffi::OsString;
use std::{fmt, io};
const USAGE: &'static str = "
Partial `cp` implementation in Rust. Copies files.
Usage:
mycp <source> <destination>
";
fn main() {
// First, try to parse the cmd args (we require exactly two args!)
let (from, to) = match parse_args() {
Err(e) => {
println!("{}", USAGE);
print_and_exit(e);
}
Ok(t) => t,
};
// Next, just copy from the first file to the second
if let Err(e) = copy(&from, &to) {
print_and_exit(e);
}
}
/// Prints the given error, the USAGE string and exits with a non-zero exit
/// status.
fn print_and_exit<E: fmt::Display>(e: E) -> ! {
println!("error: {}", e);
std::process::exit(1);
}
/// Tries to open file `from` for reading and file `to` for writing. Then
/// tries copy all contents from `from` to `to`. Returns first IO error.
fn copy(from: &str, to: &str) -> io::Result<()> {
use std::fs::File;
let mut from = match File::open(from) {
Ok(f) => f,
Err(e) => return Err(e),
};
let mut to = match File::create(to) {
Ok(f) => f,
Err(e) => return Err(e),
};
io::copy(&mut from, &mut to)
// we are not interested in the number of bytes written
.map(|_| ())
}
/// Tries to parse the command line args as two arguments.
fn parse_args() -> Result<(String, String), ArgsError> {
use std::env;
match env::args_os().count() {
n if n > 4 => return Err(ArgsError::TooManyArgs(n - 1)),
n if n < 3 => return Err(ArgsError::NotEnoughArgs),
_ => {}
}
env::args_os()
// only interested in the first two "real" arguments
.skip(1)
.take(2)
// try to convert each OsString into a proper Utf8 String
.map(|oss| oss.into_string())
// collect to get the Result on the outside
.collect::<Result<Vec<_>, _>>()
// convert vector into tuple of Strings
.map(|mut v| (v.remove(0), v.remove(0)))
// wrap conversion error into our error type
.map_err(|oss| ArgsError::NotUtf8(oss))
}
/// Stuff that can go wrong while parsing command line args.
enum ArgsError {
NotEnoughArgs,
TooManyArgs(usize),
NotUtf8(OsString),
}
impl fmt::Display for ArgsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ArgsError::NotEnoughArgs => {
write!(f, "not enough arguments given")
}
ArgsError::TooManyArgs(count) => {
write!(
f,
"too many arguments were given (expected 2, found {})",
count
)
}
ArgsError::NotUtf8(ref oss) => {
write!(
f,
"given argument '{}' is not valid UTF8",
oss.to_string_lossy()
)
}
}
}
}

View File

@ -0,0 +1,10 @@
Aufgabe 1: Fibonacci Iterator
=============================
Schreibt ein Programm, welches die ersten 20 Zahlen in der [Fibonacci-Folge][fib-wiki] ausgibt.
Entwerft dazu selber einen Typ, der das Trait `Iterator` implementiert und so *theoretisch* alle Zahlen aus der Fibonacci-Folge generieren kann.
In `main()` sollen dann die ersten 20 ausgegeben werden.
[fib-wiki]: https://de.wikipedia.org/wiki/Fibonacci-Folge

View File

@ -0,0 +1,24 @@
Aufgabe 2: Diverse Funktionen
=============================
In dieser Aufgabe sollen diverse kleinere Funktionen enstehen.
In der Musterlösung habe ich immer irgendwie Iteratoren und Iterator-Methoden genutzt, also liegt es nahe, dass ihr es auch tun solltet.
Wenn ihr natürlich meint, eine schönere Lösung ohne Iteratoren gefunden zu haben, könnt ihr sie eurem Tutor natürlich auch vorstellen ;-)
Versucht bei dieser Aufgabe alle Funktionen immer möglichst kurz (also mit wenigen Anweisungen) zu implementieren. Ihr müsst also auch nicht so sehr auf die Laufzeit eurer Algorithmen achten.
Euch ist ein Gerüst mit diversen Unittests gegeben. Die Testfälle erklären die Funktionen zusätzlich.
*Hinweis*: Es könnten für diese Aufgabe auch Funktionen direkt aus dem Modul `std::iter` sinnvoll sein.
### Funktionen
- `factorial()`: Berechnet `x!` für ein gegebenes `x`.
- `rot13()`: "Verschlüsselt" einen gegebenen String mit der derzeit besten [Verschlüsselungsmethode Rot13](https://de.wikipedia.org/wiki/ROT13). Die einzige noch bessere Verschlüsselung ist Rot26. Falls ihr meint, dass ihr es hinbekommt, könnt ihr zusätzlich auch gerne Rot26 implementieren...
- `is_palindrome()`: Testet ob ein gegebener String ein Palindrom ist.
- `used_chars_count()`: Bekommt eine Slice von String-Slices übergeben und gibt die Anzahl der unterschiedlichen Zeichen in allen Strings zurück. Whitespace-Zeichen sollen aber nicht mitgezählt werden. Schaut euch hier den Unittest für Beispiele an. Ihr könnt hier auch gerne eine passende collection aus `std` benutzen...
- `greatest_subsequencial_sum()`: Bekommt ein Array von ganzen Zahlen gegeben und sucht nun das Subarray (die Slice), bei dem die Summe aller Zahlen am größten unter allen möglichen Subarrays ist. *Tipp*: [Slices](https://doc.rust-lang.org/std/primitive.slice.html) definieren eine für diese Aufgabe *sehr* hilfreiche Methode.

47
aufgaben/sheet07/task2/iters.rs Executable file
View File

@ -0,0 +1,47 @@
#[test]
fn test_factorial() {
assert_eq!(factorial(1), 1);
assert_eq!(factorial(2), 2);
assert_eq!(factorial(3), 6);
assert_eq!(factorial(15), 1_307_674_368_000);
}
#[test]
fn test_is_palindrome() {
assert!(is_palindrome("bob"));
assert!(is_palindrome("anna"));
assert!(is_palindrome("lagerregal"));
assert!(!is_palindrome("peter"));
}
#[test]
fn test_greatest_subsequencial_sum() {
let a = [1, 2, 39, 34, 20, -20, -16, 35, 0];
assert_eq!(greatest_subsequencial_sum(&a), &a[0..5]);
let b = [-3, -9, -8, -34];
assert_eq!(greatest_subsequencial_sum(&b), &[]);
}
#[test]
fn test_rot13() {
assert_eq!(rot13("hello"), "uryyb");
assert_eq!(rot13("uryyb"), "hello");
assert_eq!(
rot13("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
);
assert_eq!(rot13("peter"), "crgre");
}
#[test]
fn test_used_letters() {
assert_eq!(used_chars_count(&["hi", "ih gitt"]), 4);
assert_eq!(used_chars_count(&["peter"]), 4);
assert_eq!(used_chars_count(&["p e t e r", "barbara"]), 6);
}
fn main() {}

View File

@ -0,0 +1,6 @@
Aufgabe 3: Fold
===============
Die Methode `Iterator::fold()` ist sehr mächtig, aber nicht trivial zu benutzen. In dieser Aufgabe sollt ihr `fold()` benutzen, um das Verhalten von `Iterator::{product(), max(), all()}` zu simulieren. Das heißt, dass euer `fold()` Aufruf genau zu dem gleichen Ergebnis wie `product()`, `max()` oder `all()` kommt.
Ihr könnt alle drei Aufrufe einfach mit einem kleinen Beispiel in `main()` programmieren. Es sollte also irgendetwas funktionieren und ihr solltet in der Lage sein, eurem Tutor zu erklären, warum es funktioniert.

View File

@ -0,0 +1,40 @@
Aufgabe 4: Kopierbefehl
=======================
(*In dieser Aufgabe geht es nicht mehr unbedingt nur um Iteratoren!*)
In dieser Aufgabe sollt ihr den `cp` Befehl nachprogrammieren ... Ok, nur einen Teil davon.
Euer Programm soll zwei Dateinamen als *command line parameter* erhalten und dann von der einen Datei in die andere kopieren:
```
$ mycp Cargo.toml Peter.toml
```
Euer Programm soll also `mycp` heißen!
Wenn ihr es richtig gemacht habt, könnt ihr mit dem Befehl `cargo install` euer Programm global auf eurem System installieren (die Executable wird in `~/.cargo/bin` kopiert, welches im `$PATH` ist). Damit ihr es aber nicht immer neu installieren müsst, um es auszuprobieren, könnt ihr es aber natürlich mit `cargo run` testen. Die Kommandozeilenparameter werden nach den `--` übergeben:
```
$ cargo run -- Cargo.toml Peter.toml
```
Die Hauptschritte zur Implementation sind folgende:
### a) Parsen der Kommandozeilenparameter
Diese müssen zunächst eingelesen werden und auf Gültigkeit überprüft werden (richtige Anzahl?).
Dies soll in einer eigenen Funktion geschehen, in der *keine* Ausgabe auf dem Terminal geschehen soll.
Alle Informationen müssen im Rückgabewert kodiert sein.
Hierzu ist sicherlich das [`std::env` Modul](https://doc.rust-lang.org/std/env/index.html) interessant.
### b) Kopieren des Dateiinhalts
Falls die Parameter korrekt waren, muss jetzt von einer Datei in die andere kopiert werden.
Das soll ebenfalls in einer eigenen Funktion passieren, welche *keine* Ausgaben auf dem Terminal macht.
Dabei sollten natürlich auch Fehler behandelt werden.
Das heißt aber nicht, dass ihr selber viel Code programmieren müsst; wahrscheinlich ist die Implementierung kürzer, als ihr anfangs vermuten würdet.
Wie man schon vermutet, wird hier das [`std::io` Modul](https://doc.rust-lang.org/std/io/index.html) eine Rolle spielen.
Nur die Funktion `std::fs::copy()` dürft ihr **nicht** nutzen! Das wäre ja zu einfach ;-)