2022-04-02 19:40:33 +02:00
/*!
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 .
* /
2022-04-03 12:28:12 +02:00
#![ allow(dead_code) ]
#![ allow(unused) ]
2022-04-02 19:40:33 +02:00
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 ) ;
2022-04-03 12:28:12 +02:00
if set . is_empty ( ) {
2022-04-02 19:40:33 +02:00
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! [ ] ) ) ;
}
}