Add exercise 372, 378

This commit is contained in:
Emelie Graven 2022-04-02 19:40:33 +02:00
parent 84e4493060
commit c5aa3d4abf
Signed by: emelie
GPG key ID: C11123726DBB55A1
4 changed files with 254 additions and 0 deletions

9
e_372/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "e_372"
version = "0.1.0"
authors = ["Emelie Graven <emelie@graven.dev>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

48
e_372/src/main.rs Normal file
View file

@ -0,0 +1,48 @@
/*!
# Description
Given a string containing only the characters `x` and `y`, find whether there are the same number of `x`s and `y`s.
balanced("xxxyyy") => true
balanced("yyyxxx") => true
balanced("xxxyyyy") => false
balanced("yyxyxxyxxyyyyxxxyxyx") => true
balanced("xyxxxxyyyxyxxyxxyy") => false
balanced("") => true
balanced("x") => false
## Optional bonus
Given a string containing only lowercase letters, find whether every letter that appears in the string appears the same number of times. Don't forget to handle the empty string (`""`) correctly!
balanced_bonus("xxxyyyzzz") => true
balanced_bonus("abccbaabccba") => true
balanced_bonus("xxxyyyzzzz") => false
balanced_bonus("abcdefghijklmnopqrstuvwxyz") => true
balanced_bonus("pqq") => false
balanced_bonus("fdedfdeffeddefeeeefddf") => false
balanced_bonus("www") => true
balanced_bonus("x") => true
balanced_bonus("") => true
Note that `balanced_bonus` behaves differently than `balanced` for a few inputs, e.g. `"x"`.
*/
use std::collections::HashMap;
fn main() {
println!("{}", balanced(String::from("jbsssssh")));
}
fn balanced(input: String) -> bool {
let count: HashMap<char, i32> = input.chars().fold(HashMap::new(), |mut map, ch| {
map.entry(ch).and_modify(|n| *n += 1).or_insert(1);
map
});
println!("{:?}", count);
let mut values = count.values();
if let Some(first) = values.next() {
values.all(|x| x == first)
} else {
true
}
}

9
e_378/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "e_378"
version = "0.1.0"
authors = ["Emelie Graven <emelie@graven.dev>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

188
e_378/src/main.rs Normal file
View file

@ -0,0 +1,188 @@
/*!
It was a dark and stormy night. Detective Havel and Detective Hakimi arrived at the scene of the crime.
Other than the detectives, there were 10 people present. They asked the first person, "out of the 9 other people here, how many had you already met before tonight?" The person answered "5". They asked the same question of the second person, who answered "3". And so on. The 10 answers they got from the 10 people were:
5 3 0 2 6 2 0 7 2 5
The detectives looked at the answers carefully and deduced that there was an inconsistency, and that somebody must be lying. (For the purpose of this challenge, assume that nobody makes mistakes or forgets, and if X has met Y, that means Y has also met X.)
Your challenge for today is, given a sequence of answers to the question "how many of the others had you met before tonight?", apply the Havel-Hakimi algorithm to determine whether or not it's possible that everyone was telling the truth.
If you're feeling up to it, skip ahead to the Challenge section below. Otherwise, try as many of the optional warmup questions as you want first, before attempting the full challenge.
# Optional Warmup 1: eliminating 0's.
Given a sequence of answers, return the same set of answers with all the 0's removed.
warmup1([5, 3, 0, 2, 6, 2, 0, 7, 2, 5]) => [5, 3, 2, 6, 2, 7, 2, 5]
warmup1([4, 0, 0, 1, 3]) => [4, 1, 3]
warmup1([1, 2, 3]) => [1, 2, 3]
warmup1([0, 0, 0]) => []
warmup1([]) => []
If you want to reorder the sequence as you do this, that's fine. For instance, given `[4, 0, 0, 1, 3]`, then you may return `[4, 1, 3]` or `[1, 3, 4]` or `[4, 3, 1]` or any other ordering of these numbers.
# Optional Warmup 2: descending sort
Given a sequence of answers, return the sequence sorted in descending order, so that the first number is the largest and the last number is the smallest.
warmup2([5, 1, 3, 4, 2]) => [5, 4, 3, 2, 1]
warmup2([0, 0, 0, 4, 0]) => [4, 0, 0, 0, 0]
warmup2([1]) => [1]
warmup2([]) => []
# Optional Warmup 3: length check
Given a number `N` and a sequence of answers, return true if `N` is greater than the number of answers (i.e. the length of the sequence), and false if `N` is less than or equal to the number of answers. For instance, given 7 and [6, 5, 5, 3, 2, 2, 2], you would return false, because 7 is less than or equal to 7.
warmup3(7, [6, 5, 5, 3, 2, 2, 2]) => false
warmup3(5, [5, 5, 5, 5, 5]) => false
warmup3(5, [5, 5, 5, 5]) => true
warmup3(3, [1, 1]) => true
warmup3(1, []) => true
warmup3(0, []) => false
# Optional Warmup 4: front elimination
Given a number `N` and a sequence in descending order, subtract 1 from each of the first `N` answers in the sequence, and return the result. For instance, given `N = 4` and the sequence `[5, 4, 3, 2, 1]`, you would subtract 1 from each of the first 4 answers (5, 4, 3, and 2) to get 4, 3, 2, and 1. The rest of the sequence (1) would not be affected:
warmup4(4, [5, 4, 3, 2, 1]) => [4, 3, 2, 1, 1]
warmup4(11, [14, 13, 13, 13, 12, 10, 8, 8, 7, 7, 6, 6, 4, 4, 2]) => [13, 12, 12, 12, 11, 9, 7, 7, 6, 6, 5, 6, 4, 4, 2]
warmup4(1, [10, 10, 10]) => [9, 10, 10]
warmup4(3, [10, 10, 10]) => [9, 9, 9]
warmup4(1, [1]) => [0]
You may assume that `N` is greater than 0, and no greater than the length of the sequence. Like in warmup 1, it's okay if you want to reorder the answers in your result.
# Challenge: the Havel-Hakimi algorithm
Perform the Havel-Hakimi algorithm on a given sequence of answers. This algorithm will return true if the answers are consistent (i.e. it's possible that everyone is telling the truth) and false if the answers are inconsistent (i.e. someone must be lying):
1. Remove all 0's from the sequence (i.e. `warmup1`).
2. If the sequence is now empty (no elements left), stop and return true.
3. Sort the sequence in descending order (i.e. `warmup2`).
4. Remove the first answer (which is also the largest answer, or tied for the largest) from the sequence and call it `N`. The sequence is now 1 shorter than it was after the previous step.
5. If `N` is greater than the length of this new sequence (i.e. `warmup3`), stop and return false.
6. Subtract 1 from each of the first `N` elements of the new sequence (i.e. `warmup4`).
7. Continue from step 1 using the sequence from the previous step.
Eventually you'll either return true in step 2, or false in step 5.
You don't have to follow these steps exactly: as long as you return the right answer, that's fine. Also, if you answered the warmup questions, you may use your warmup solutions to build your challenge solution, but you don't have to.
hh([5, 3, 0, 2, 6, 2, 0, 7, 2, 5]) => false
hh([4, 2, 0, 1, 5, 0]) => false
hh([3, 1, 2, 3, 1, 0]) => true
hh([16, 9, 9, 15, 9, 7, 9, 11, 17, 11, 4, 9, 12, 14, 14, 12, 17, 0, 3, 16]) => true
hh([14, 10, 17, 13, 4, 8, 6, 7, 13, 13, 17, 18, 8, 17, 2, 14, 6, 4, 7, 12]) => true
hh([15, 18, 6, 13, 12, 4, 4, 14, 1, 6, 18, 2, 6, 16, 0, 9, 10, 7, 12, 3]) => false
hh([6, 0, 10, 10, 10, 5, 8, 3, 0, 14, 16, 2, 13, 1, 2, 13, 6, 15, 5, 1]) => false
hh([2, 2, 0]) => false
hh([3, 2, 1]) => false
hh([1, 1]) => true
hh([1]) => false
hh([]) => true
# Detailed example
Here's the first pass through the algorithm using the original example:
* `[5, 3, 0, 2, 6, 2, 0, 7, 2, 5]` - Starting sequence
* `[5, 3, 2, 6, 2, 7, 2, 5]` - After step 1, removing 0's.
* Step 2: This sequence is not empty, so go on to step 3.
* `[7, 6, 5, 5, 3, 2, 2, 2]` - After step 3, sorting in descending order.
* `[6, 5, 5, 3, 2, 2, 2]` - After step 4, removing the first answer `N = 7`.
* Step 5: N (7) is less than or equal to the number of answers remaining in the sequence (7), so go on to step 6.
* `[5, 4, 4, 2, 1, 1, 1]` - After step 6, subtracting 1 from each of the first 7 answers (which is all of them in this case).
At this point you would start over at step 1 with the sequence `[5, 4, 4, 2, 1, 1, 1]`. After your second pass through the algorithm, your sequence will be `[3, 3, 1, 0, 0, 1]`, so start back at step 1 with this sequence. After your third pass you'll have `[2, 0, 0]`. On your fourth pass, you'll stop at step 5, because you'll have `N = 2` and an empty sequence (`[]`), and 2 > 0, so you will return false.
*/
fn main() {}
fn warmup_1(set: Vec<i32>) -> Vec<i32> {
set.into_iter().filter(|x| *x != 0).collect()
}
fn warmup_2(mut set: Vec<i32>) -> Vec<i32> {
set.sort_by(|a, b| b.cmp(a));
set
}
fn warmup_3(i: i32, set: Vec<i32>) -> bool {
(i as usize) > set.len()
}
fn warmup_4(i: i32, mut set: Vec<i32>) -> Vec<i32> {
set.iter_mut().take(i as usize).for_each(|x| *x -= 1);
set
}
fn e_378(mut set: Vec<i32>) -> bool {
loop {
set = warmup_1(set);
if set.len() == 0 {
break true;
}
set = warmup_2(set);
let largest = set.remove(0);
if warmup_3(largest, set.clone()) {
break false;
}
set = warmup_4(largest, set);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn does_warmup_1_remove_zero() {
assert_eq!(warmup_1(vec![12, 0, 5, 7, 0, 2]), vec![12, 5, 7, 2]);
assert_ne!(warmup_1(vec![0, 1, 2, 0, 17]), vec![0, 1, 2, 0, 17]);
}
#[test]
fn does_warmup_2_sort() {
assert_eq!(warmup_2(vec![16, 2, 9, 1, 0, -5]), vec![16, 9, 2, 1, 0, -5]);
assert_ne!(warmup_2(vec![1, 2, 3, 4, 5]), vec![1, 2, 3, 4, 5]);
}
#[test]
fn is_warmup_3() {
assert!(warmup_3(8, vec![5, 3, 1, 7, 8, 4, 2]));
assert!(!warmup_3(3, vec![5, 2, 3]));
assert!(!warmup_3(3, vec![6, 5, 1, 3, 7]));
}
#[test]
fn t_warmup_4() {
assert_eq!(warmup_4(2, vec![5, 4, 3, 2, 1]), vec![4, 3, 3, 2, 1]);
assert_ne!(warmup_4(4, vec![5, 4, 3, 2, 1]), vec![5, 4, 3, 2, 1]);
}
#[test]
fn does_e_378_havel_hakimi() {
assert!(!e_378(vec![5, 3, 0, 2, 6, 2, 0, 7, 2, 5]));
assert!(!e_378(vec![4, 2, 0, 1, 5, 0]));
assert!(e_378(vec![3, 1, 2, 3, 1, 0]));
assert!(e_378(vec![
16, 9, 9, 15, 9, 7, 9, 11, 17, 11, 4, 9, 12, 14, 14, 12, 17, 0, 3, 16
]));
assert!(e_378(vec![
14, 10, 17, 13, 4, 8, 6, 7, 13, 13, 17, 18, 8, 17, 2, 14, 6, 4, 7, 12
]));
assert!(!e_378(vec![
15, 18, 6, 13, 12, 4, 4, 14, 1, 6, 18, 2, 6, 16, 0, 9, 10, 7, 12, 3
]));
assert!(!e_378(vec![
6, 0, 10, 10, 10, 5, 8, 3, 0, 14, 16, 2, 13, 1, 2, 13, 6, 15, 5, 1
]));
assert!(!e_378(vec![2, 2, 0]));
assert!(!e_378(vec![3, 2, 1]));
assert!(e_378(vec![1, 1]));
assert!(!e_378(vec![1]));
assert!(e_378(vec![]));
}
}