Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit aaf0332

Browse files
Add forgotten solutions
1 parent c81400e commit aaf0332

File tree

8 files changed

+378
-0
lines changed

8 files changed

+378
-0
lines changed

‎aufgaben/sheet10/sol1/magic.s‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; This is the assembly of:
2+
;
3+
; fn is_prime(n: u64) -> bool {
4+
; (2..n).all(|d| n % d != 0)
5+
; }
6+
;
7+
; Of course, it was compiled in release mode. Thus, this is a primality test
8+
; which works for numbers >= 2.
9+
10+
magic:
11+
pushrbp ; standard function prologue:
12+
movrbp,rsp ; storing old rbp and setting new one
13+
14+
movrcx,rdi ; copy function argument to rcx
15+
movesi,2 ; rsi = 2 (this will be our counter)
16+
17+
.LBB0_1:
18+
moval,1 ; out = true (rax contains the return value)
19+
20+
cmprsi,rcx ; if our counter is equal to our function argument
21+
jae .LBB0_4 ; (rsi == rcx) we will jump to the end (return)
22+
23+
xoredx,edx ; set rdx to 0 (just for the upcoming div instruction)
24+
movrax,rcx ; copy the function argument into rax temporarily
25+
; (this is just for the next instruction)
26+
27+
divrsi ; divide rdx:rax by rsi (counter). The result is stored
28+
; in rax and more importantly: the remainder is stored
29+
; in rdx!
30+
31+
incrsi ; increment our counter
32+
33+
testrdx,rdx ; if the remainder is NOT 0, we will jump up
34+
jne .LBB0_1 ; again (keep going). Else we will just continue...
35+
36+
xoreax,eax ; out = false
37+
.LBB0_4:
38+
poprbp ; standard function epilogue
39+
ret

‎aufgaben/sheet10/sol2/Cargo.lock‎

Lines changed: 109 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎aufgaben/sheet10/sol2/Cargo.toml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "flip"
3+
version = "0.1.0"
4+
authors = ["Lukas Kalbertodt <lukas.kalbertodt@gmail.com>"]
5+
6+
[dependencies]
7+
clap = "~2.20"
8+
rand = "0.3.15"
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//! This subcommand chooses items from a list.
2+
//!
3+
4+
use clap::{Arg, ArgMatches, App, SubCommand};
5+
use rand::{self, Rng};
6+
use std::error::Error;
7+
8+
pub fn clap() -> App<'static, 'static> {
9+
SubCommand::with_name("choose")
10+
.about("Chooses one or more values from a list")
11+
.arg(
12+
Arg::with_name("count")
13+
.long("count")
14+
.short("c")
15+
.help("How many elements to choose")
16+
.takes_value(true)
17+
.validator(|s| {
18+
s.parse::<u64>()
19+
.map_err(|e| e.to_string())
20+
.and_then(|n| {
21+
if n == 1 {
22+
Err("number is smaller than 2".into())
23+
} else {
24+
Ok(())
25+
}
26+
})
27+
})
28+
)
29+
.arg(
30+
Arg::with_name("ELEMENTS")
31+
.help("The list to choose one item from (comma separated)")
32+
.required(true)
33+
.multiple(true)
34+
)
35+
}
36+
37+
pub fn exec(matches: &ArgMatches) -> Result<String, Box<Error>> {
38+
// Retrieve arguments
39+
let count = value_t!(matches, "count", u64).unwrap_or(1);
40+
let mut elements = values_t!(matches, "ELEMENTS", String).unwrap();
41+
42+
// Sanity check arguments
43+
if count > elements.len() as u64 {
44+
return Err("'count' argument is greater than the number of given elements".into());
45+
}
46+
47+
let mut rng = rand::thread_rng();
48+
49+
// Choose a random valid index, remove the respective element from the
50+
// input vector and insert it into the out vector. Repeat specified number
51+
// of times.
52+
let mut out = Vec::with_capacity(count as usize);
53+
for _ in 0..count {
54+
let idx = rng.gen_range(0, elements.len());
55+
out.push(elements.swap_remove(idx));
56+
}
57+
58+
if count == 1 {
59+
Ok(out[0].to_string())
60+
} else {
61+
Ok(format!("{:?}", out))
62+
}
63+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//! This subcommand flips a coin, returning either 'heads' or 'tails'
2+
//!
3+
4+
use clap::{ArgMatches, App, SubCommand};
5+
use rand::{self, Rng};
6+
use std::error::Error;
7+
8+
9+
pub fn clap() -> App<'static, 'static> {
10+
SubCommand::with_name("coin")
11+
.about("Flips a coin, returning either 'heads' or 'tails'")
12+
13+
}
14+
15+
pub fn exec(_: &ArgMatches) -> Result<String, Box<Error>> {
16+
let out = if rand::thread_rng().gen() {
17+
"heads"
18+
} else {
19+
"tails"
20+
};
21+
22+
Ok(out.into())
23+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//! This subcommand rolls a dice with a configurable number of sides, returning
2+
//! the number of the rolled dice.
3+
//!
4+
5+
use clap::{Arg, ArgMatches, App, SubCommand};
6+
use rand::{self, Rng};
7+
use std::error::Error;
8+
9+
pub fn clap() -> App<'static, 'static> {
10+
SubCommand::with_name("dice")
11+
.about("Rolls a dice")
12+
.arg(
13+
Arg::with_name("sides")
14+
.long("sides")
15+
.help("The number of sides of the dice")
16+
.takes_value(true)
17+
.validator(|s| {
18+
s.parse::<u64>()
19+
.map_err(|e| e.to_string())
20+
.and_then(|n| {
21+
if n <= 1 {
22+
Err("number is smaller than 2".into())
23+
} else {
24+
Ok(())
25+
}
26+
})
27+
})
28+
)
29+
}
30+
31+
pub fn exec(matches: &ArgMatches) -> Result<String, Box<Error>> {
32+
let sides = value_t!(matches, "sides", u64).unwrap_or(6);
33+
34+
let num = rand::thread_rng().gen_range(1, sides);
35+
Ok(num.to_string())
36+
}

‎aufgaben/sheet10/sol2/src/cmd/mod.rs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//! Contains all subcommands.
2+
//!
3+
//! Each subcommand's module has a `clap()` function which returns the clap
4+
//! structure describing the subcommand's command line use. The `exec()`
5+
//! function of each module executes the actual algorithm.
6+
//!
7+
8+
pub mod dice;
9+
pub mod coin;
10+
pub mod choose;

‎aufgaben/sheet10/sol2/src/main.rs‎

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//! Flip -- command line utility for randomness tools
2+
//!
3+
//! This is a simple application which offers several small tools related to
4+
//! randomness. It uses the crates `clap` and `rand` for argument parsing and
5+
//! random number generation, respectively. Example usage:
6+
//!
7+
//! ```
8+
//! $ flip coin
9+
//! heads
10+
//! $ flip dice --sides=10
11+
//! 7
12+
//! $ flip choose --count=2 Peter Ursula Jürgen
13+
//! ["Peter", "Jürgen"]
14+
//! $ flip --times=3 coin
15+
//! heads
16+
//! heads
17+
//! tails
18+
//! ```
19+
20+
#[macro_use]
21+
extern crate clap;
22+
extern crate rand;
23+
24+
mod cmd;
25+
26+
use clap::{Arg, App, AppSettings};
27+
use std::str::FromStr;
28+
use std::error::Error;
29+
30+
31+
/// Does most of the work: parses the command line args and executes the
32+
/// subcommand.
33+
fn parse_and_exec() -> Result<(), Box<Error>> {
34+
let matches = App::new("Flip")
35+
.version(crate_version!())
36+
.author(crate_authors!())
37+
.about("Offers several tools related to randomness")
38+
.setting(AppSettings::SubcommandRequired)
39+
.arg(
40+
Arg::with_name("times")
41+
.short("t")
42+
.long("times")
43+
.takes_value(true)
44+
.validator(validate_parse::<u64>)
45+
.help("Executes the specified subcommand the given number of times")
46+
)
47+
.subcommand(cmd::coin::clap())
48+
.subcommand(cmd::dice::clap())
49+
.subcommand(cmd::choose::clap())
50+
.get_matches();
51+
52+
// Check what subcommand has been executed and fetch the matching
53+
// function and sub-matches.
54+
let (cmd_fn, sub_matches): (fn(_) -> _, _) = match matches.subcommand() {
55+
("coin", sub_matches) => (cmd::coin::exec, sub_matches.unwrap()),
56+
("dice", sub_matches) => (cmd::dice::exec, sub_matches.unwrap()),
57+
("choose", sub_matches) => (cmd::choose::exec, sub_matches.unwrap()),
58+
_ => unreachable!("We enabled 'SubcommandRequired' for clap!"),
59+
};
60+
61+
// We validate the string above. Thus, this will be an `Err` iff the
62+
// argument wasn't specified. In this case it defaults to 1.
63+
let times = value_t!(matches, "times", u64).unwrap_or(1);
64+
65+
// Execute the sub command the specified number of times, printing
66+
// every result
67+
for _ in 0..times {
68+
let s = cmd_fn(sub_matches)?;
69+
println!("{}", s);
70+
}
71+
72+
Ok(())
73+
}
74+
75+
fn main() {
76+
let res = parse_and_exec();
77+
if let Err(e) = res {
78+
println!("{}", e);
79+
}
80+
}
81+
82+
/// Validator shorthand to check if a string is parsable as given type.
83+
fn validate_parse<T>(s: String) -> Result<(), String>
84+
where T: FromStr,
85+
T::Err: ToString,
86+
{
87+
s.parse::<T>()
88+
.map(|_| ())
89+
.map_err(|e| e.to_string())
90+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /