mirror of
https://github.com/LukasKalbertodt/programmieren-in-rust.git
synced 2024-11-18 02:48:58 +01:00
Add solution sheet7
This commit is contained in:
parent
9f2347a0be
commit
5167f21bca
31
aufgaben/sheet7/sol1/fib.rs
Executable file
31
aufgaben/sheet7/sol1/fib.rs
Executable 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/sheet7/sol2/iters.rs
Executable file
93
aufgaben/sheet7/sol2/iters.rs
Executable 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/sheet7/sol3/fold.rs
Executable file
19
aufgaben/sheet7/sol3/fold.rs
Executable 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/sheet7/sol4/Cargo.lock
generated
Executable file
4
aufgaben/sheet7/sol4/Cargo.lock
generated
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
[root]
|
||||||
|
name = "mycp"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
6
aufgaben/sheet7/sol4/Cargo.toml
Executable file
6
aufgaben/sheet7/sol4/Cargo.toml
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "mycp"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Lukas Kalbertodt <lukas.kalbertodt@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
106
aufgaben/sheet7/sol4/src/main.rs
Executable file
106
aufgaben/sheet7/sol4/src/main.rs
Executable 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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user