Subtask

Struct Subtask 

Source
pub struct Subtask { /* private fields */ }
Expand description

This struct represents a subtask. You can add tests, test generators and set a checker function. Once you are done, you can add the subtask to a task.

Implementations§

Source§

impl Subtask

Source

pub fn new() -> Self

This function creates a new subtask with points.

Examples found in repository?
examples/example2.rs (line 40)
32fn main() {
33    // In this task you have n coins with values a1, a2, ..., an. You need to find the smallest sum, you cannot get using these coins.
34    // For example, if you have coins with values 1, 2 and 4, you can get any sum from 1 to 7, but you cannot get 8.
35
36    let mut task = ezcp::Task::new("Coins", &PathBuf::from("task2"));
37    task.solution_source = SOLUTION.to_owned();
38
39    // Constraint: n = 1
40    let mut subtask1 = ezcp::Subtask::new();
41
42    subtask1.set_checker(|mut input| {
43        let array = input.get_array()?;
44        input.expect_end()?;
45        let n = array.len();
46        if n != 1 {
47            ezcp::bail!("n should be 1");
48        }
49        let x = array[0];
50        if !(1..=1_000_000_000).contains(&x) {
51            ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
52        }
53        Ok(())
54    });
55
56    subtask1.add_test(5, ezcp::array_generator(1, 1, 1, 1000));
57    subtask1.add_test_str("1\n 1\n".to_owned());
58
59    // Constraint: elements in the array are powers of 2 and n <= 30
60    let mut subtask2 = ezcp::Subtask::new();
61
62    subtask2.set_checker(|mut input| {
63        let array = input.get_array()?;
64        input.expect_end()?;
65        let n = array.len();
66        if !(1..=30).contains(&n) {
67            ezcp::bail!("n should be in range [1, 30]");
68        }
69        for (i, x) in array.iter().enumerate() {
70            if *x != 1 << i {
71                ezcp::bail!("all array values should be powers of 2");
72            }
73        }
74        Ok(())
75    });
76
77    subtask2.add_test(5, || {
78        let mut rng = rand::rng();
79        let n = rng.random_range(1..=30);
80        let mut array = Vec::new();
81        for i in 0..n {
82            array.push(1 << i);
83        }
84        ezcp::array_to_string(&array, true)
85    });
86
87    // Constraint: n <= 1000
88    let mut subtask3 = ezcp::Subtask::new();
89
90    subtask3.set_checker(|mut input| {
91        let array = input.get_array()?;
92        input.expect_end()?;
93        let n = array.len();
94        if !(1..=1000).contains(&n) {
95            ezcp::bail!("n should be in range [1, 1000]");
96        }
97        for x in array {
98            if !(1..=1_000_000_000).contains(&x) {
99                ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
100            }
101        }
102        Ok(())
103    });
104
105    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1000));
106    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1_000_000_000));
107    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1));
108    subtask3.add_test(5, ezcp::array_generator(1000, 1000, 1, 1000));
109    subtask3.add_test(5, ezcp::array_generator(1000, 1000, 1, 1_000_000_000));
110    subtask3.add_test(1, ezcp::array_generator(1000, 1000, 1, 1));
111
112    // Constraint: n <= 200_000
113    let mut subtask4 = ezcp::Subtask::new();
114
115    subtask4.set_checker(|mut input| {
116        let array = input.get_array()?;
117        input.expect_end()?;
118        let n = array.len();
119        if !(1..=200_000).contains(&n) {
120            ezcp::bail!("n should be in range [1, 200_000]");
121        }
122        for x in array {
123            if !(1..=1_000_000_000).contains(&x) {
124                ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
125            }
126        }
127        Ok(())
128    });
129
130    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1000));
131    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1_000_000_000));
132    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1));
133    subtask4.add_test(5, ezcp::array_generator(200_000, 200_000, 1, 1000));
134    subtask4.add_test(5, ezcp::array_generator(200_000, 200_000, 1, 1_000_000_000));
135    subtask4.add_test(1, ezcp::array_generator(200_000, 200_000, 1, 1));
136
137    // add subtasks to task
138    let subtask1 = task.add_subtask(subtask1);
139    let subtask2 = task.add_subtask(subtask2);
140    let subtask3 = task.add_subtask(subtask3);
141    let subtask4 = task.add_subtask(subtask4);
142
143    // add dependencies
144    task.add_subtask_dependency(subtask3, subtask1);
145    task.add_subtask_dependency(subtask3, subtask2);
146    task.add_subtask_dependency(subtask4, subtask3);
147
148    task.create_tests().ok();
149}
More examples
Hide additional examples
examples/example1.rs (line 46)
36fn main() {
37    // The first task you get an array of integers. You need to find the sum of all elements in the array minus the half of the maximum element.
38    // Also all elements in the array are even.
39
40    let mut task = ezcp::Task::new("Coupon", &PathBuf::from("task1"));
41    //task.debug_level = LevelFilter::Trace;
42
43    task.solution_source = SOLUTION.to_owned();
44
45    // Constraint: n = 1
46    let mut subtask1 = ezcp::Subtask::new();
47
48    // This checker is optional and can be omitted.
49    subtask1.set_checker(|mut input| {
50        // read an array from input
51        let array = input.get_array()?;
52        // expect end of input
53        input.expect_end()?;
54        let n = array.len();
55        if n != 1 {
56            ezcp::bail!("n should be 1");
57        }
58        // check if the only value is even
59        if array[0] % 2 != 0 {
60            ezcp::bail!("all array values should be even");
61        }
62        // check if the only value is in range
63        if !(0..=1_000_000_000).contains(&array[0]) {
64            ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
65        }
66        Ok(())
67    });
68
69    // add 5 tests where an array is generated with length 1 and even values between 0 and 1_000_000_000 (inclusive)
70    subtask1.add_test(5, ezcp::array_generator_custom(1, 1, |rng| rng.random_range(0..=500_000_000) * 2));
71    // this is a faulty test for testing the checker
72    //subtask1.add_test_str("1\n 0 0\n".to_owned());
73
74    // Constraint: all values are the same
75    let mut subtask2 = ezcp::Subtask::new();
76
77    subtask2.set_checker(|mut input| {
78        let array = input.get_array()?;
79        input.expect_end()?;
80        let n = array.len();
81        if !(1..=200_000).contains(&n) {
82            ezcp::bail!("n should be in range [1, 200_000]");
83        }
84        let x = array[0];
85        for i in array {
86            if i != x {
87                ezcp::bail!("all array values should be the same");
88            }
89            if i % 2 != 0 {
90                ezcp::bail!("all array values should be even");
91            }
92            if !(0..=1_000_000_000).contains(&i) {
93                ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
94            }
95        }
96        Ok(())
97    });
98
99    // add 5 random tests where each test is an array of length between 1 and 200_000 (inclusive) and all values are the same even value between 0 and 1_000_000_000 (inclusive)
100    subtask2.add_test(5, || {
101        let mut rng = rand::rng();
102        let n = rng.random_range(1..=200_000);
103        let x = rng.random_range(0..=500_000_000) * 2;
104        ezcp::array_to_string(&vec![x; n as usize], true)
105    });
106
107    // add an edge case where n is maximal
108    let mut rng = rand::rng();
109    let x = rng.random_range(0..=500_000_000) * 2;
110    subtask2.add_test_str(ezcp::array_to_string(&vec![x; 200_000], true));
111
112    // add 3 edge cases where all values are maximal
113    subtask2.add_test(3, ezcp::array_generator(1, 200_000, 1_000_000_000, 1_000_000_000));
114
115    // add an edge case where all values and n are maximal
116    subtask2.add_test_str(ezcp::array_to_string(&vec![1_000_000_000; 200_000], true));
117
118    // No additional constraints
119    let mut subtask3 = ezcp::Subtask::new();
120
121    subtask3.set_checker(|mut input| {
122        let array = input.get_array()?;
123        input.expect_end()?;
124        let n = array.len();
125        if !(1..=200_000).contains(&n) {
126            ezcp::bail!("n should be in range [1, 200_000]");
127        }
128        for i in array {
129            if i % 2 != 0 {
130                ezcp::bail!("all array values should be even");
131            }
132            if !(0..=1_000_000_000).contains(&i) {
133                ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
134            }
135        }
136        Ok(())
137    });
138
139    // add some random tests
140    subtask3.add_test(5, ezcp::array_generator_custom(1, 200_000, |rng| rng.random_range(0..=500_000_000) * 2));
141
142    // add 5 edge cases where n is maximal (other edge cases are handled by subtask2)
143    subtask3.add_test(5, ezcp::array_generator_custom(200_000, 200_000, |rng| rng.random_range(0..=500_000_000) * 2));
144
145    // add subtasks to task
146    let subtask1 = task.add_subtask(subtask1);
147    let subtask2 = task.add_subtask(subtask2);
148    let subtask3 = task.add_subtask(subtask3);
149
150    // add dependencies (dependencies are only if constraints of a dependency are a subset of constraints of a subtask)
151    task.add_subtask_dependency(subtask3, subtask1);
152    task.add_subtask_dependency(subtask3, subtask2);
153
154    // there is a partial solution that only reads 2 integers: n, x and prints x / 2 which is correct for subtask1 but should fail for subtask2 and subtask3
155    task.add_partial_solution(PARTIAL_SOLUTION.to_owned(), &[subtask1]);
156
157    // finally create the tests
158    task.create_tests().ok();
159}
Source

pub fn add_test<F: Fn() -> String + 'static>( &mut self, number: i32, function: F, )

This function adds a test generator to the subtask with the provided count. Test generator is a function that returns a string.

Examples found in repository?
examples/example2.rs (line 56)
32fn main() {
33    // In this task you have n coins with values a1, a2, ..., an. You need to find the smallest sum, you cannot get using these coins.
34    // For example, if you have coins with values 1, 2 and 4, you can get any sum from 1 to 7, but you cannot get 8.
35
36    let mut task = ezcp::Task::new("Coins", &PathBuf::from("task2"));
37    task.solution_source = SOLUTION.to_owned();
38
39    // Constraint: n = 1
40    let mut subtask1 = ezcp::Subtask::new();
41
42    subtask1.set_checker(|mut input| {
43        let array = input.get_array()?;
44        input.expect_end()?;
45        let n = array.len();
46        if n != 1 {
47            ezcp::bail!("n should be 1");
48        }
49        let x = array[0];
50        if !(1..=1_000_000_000).contains(&x) {
51            ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
52        }
53        Ok(())
54    });
55
56    subtask1.add_test(5, ezcp::array_generator(1, 1, 1, 1000));
57    subtask1.add_test_str("1\n 1\n".to_owned());
58
59    // Constraint: elements in the array are powers of 2 and n <= 30
60    let mut subtask2 = ezcp::Subtask::new();
61
62    subtask2.set_checker(|mut input| {
63        let array = input.get_array()?;
64        input.expect_end()?;
65        let n = array.len();
66        if !(1..=30).contains(&n) {
67            ezcp::bail!("n should be in range [1, 30]");
68        }
69        for (i, x) in array.iter().enumerate() {
70            if *x != 1 << i {
71                ezcp::bail!("all array values should be powers of 2");
72            }
73        }
74        Ok(())
75    });
76
77    subtask2.add_test(5, || {
78        let mut rng = rand::rng();
79        let n = rng.random_range(1..=30);
80        let mut array = Vec::new();
81        for i in 0..n {
82            array.push(1 << i);
83        }
84        ezcp::array_to_string(&array, true)
85    });
86
87    // Constraint: n <= 1000
88    let mut subtask3 = ezcp::Subtask::new();
89
90    subtask3.set_checker(|mut input| {
91        let array = input.get_array()?;
92        input.expect_end()?;
93        let n = array.len();
94        if !(1..=1000).contains(&n) {
95            ezcp::bail!("n should be in range [1, 1000]");
96        }
97        for x in array {
98            if !(1..=1_000_000_000).contains(&x) {
99                ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
100            }
101        }
102        Ok(())
103    });
104
105    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1000));
106    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1_000_000_000));
107    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1));
108    subtask3.add_test(5, ezcp::array_generator(1000, 1000, 1, 1000));
109    subtask3.add_test(5, ezcp::array_generator(1000, 1000, 1, 1_000_000_000));
110    subtask3.add_test(1, ezcp::array_generator(1000, 1000, 1, 1));
111
112    // Constraint: n <= 200_000
113    let mut subtask4 = ezcp::Subtask::new();
114
115    subtask4.set_checker(|mut input| {
116        let array = input.get_array()?;
117        input.expect_end()?;
118        let n = array.len();
119        if !(1..=200_000).contains(&n) {
120            ezcp::bail!("n should be in range [1, 200_000]");
121        }
122        for x in array {
123            if !(1..=1_000_000_000).contains(&x) {
124                ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
125            }
126        }
127        Ok(())
128    });
129
130    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1000));
131    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1_000_000_000));
132    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1));
133    subtask4.add_test(5, ezcp::array_generator(200_000, 200_000, 1, 1000));
134    subtask4.add_test(5, ezcp::array_generator(200_000, 200_000, 1, 1_000_000_000));
135    subtask4.add_test(1, ezcp::array_generator(200_000, 200_000, 1, 1));
136
137    // add subtasks to task
138    let subtask1 = task.add_subtask(subtask1);
139    let subtask2 = task.add_subtask(subtask2);
140    let subtask3 = task.add_subtask(subtask3);
141    let subtask4 = task.add_subtask(subtask4);
142
143    // add dependencies
144    task.add_subtask_dependency(subtask3, subtask1);
145    task.add_subtask_dependency(subtask3, subtask2);
146    task.add_subtask_dependency(subtask4, subtask3);
147
148    task.create_tests().ok();
149}
More examples
Hide additional examples
examples/example1.rs (line 70)
36fn main() {
37    // The first task you get an array of integers. You need to find the sum of all elements in the array minus the half of the maximum element.
38    // Also all elements in the array are even.
39
40    let mut task = ezcp::Task::new("Coupon", &PathBuf::from("task1"));
41    //task.debug_level = LevelFilter::Trace;
42
43    task.solution_source = SOLUTION.to_owned();
44
45    // Constraint: n = 1
46    let mut subtask1 = ezcp::Subtask::new();
47
48    // This checker is optional and can be omitted.
49    subtask1.set_checker(|mut input| {
50        // read an array from input
51        let array = input.get_array()?;
52        // expect end of input
53        input.expect_end()?;
54        let n = array.len();
55        if n != 1 {
56            ezcp::bail!("n should be 1");
57        }
58        // check if the only value is even
59        if array[0] % 2 != 0 {
60            ezcp::bail!("all array values should be even");
61        }
62        // check if the only value is in range
63        if !(0..=1_000_000_000).contains(&array[0]) {
64            ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
65        }
66        Ok(())
67    });
68
69    // add 5 tests where an array is generated with length 1 and even values between 0 and 1_000_000_000 (inclusive)
70    subtask1.add_test(5, ezcp::array_generator_custom(1, 1, |rng| rng.random_range(0..=500_000_000) * 2));
71    // this is a faulty test for testing the checker
72    //subtask1.add_test_str("1\n 0 0\n".to_owned());
73
74    // Constraint: all values are the same
75    let mut subtask2 = ezcp::Subtask::new();
76
77    subtask2.set_checker(|mut input| {
78        let array = input.get_array()?;
79        input.expect_end()?;
80        let n = array.len();
81        if !(1..=200_000).contains(&n) {
82            ezcp::bail!("n should be in range [1, 200_000]");
83        }
84        let x = array[0];
85        for i in array {
86            if i != x {
87                ezcp::bail!("all array values should be the same");
88            }
89            if i % 2 != 0 {
90                ezcp::bail!("all array values should be even");
91            }
92            if !(0..=1_000_000_000).contains(&i) {
93                ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
94            }
95        }
96        Ok(())
97    });
98
99    // add 5 random tests where each test is an array of length between 1 and 200_000 (inclusive) and all values are the same even value between 0 and 1_000_000_000 (inclusive)
100    subtask2.add_test(5, || {
101        let mut rng = rand::rng();
102        let n = rng.random_range(1..=200_000);
103        let x = rng.random_range(0..=500_000_000) * 2;
104        ezcp::array_to_string(&vec![x; n as usize], true)
105    });
106
107    // add an edge case where n is maximal
108    let mut rng = rand::rng();
109    let x = rng.random_range(0..=500_000_000) * 2;
110    subtask2.add_test_str(ezcp::array_to_string(&vec![x; 200_000], true));
111
112    // add 3 edge cases where all values are maximal
113    subtask2.add_test(3, ezcp::array_generator(1, 200_000, 1_000_000_000, 1_000_000_000));
114
115    // add an edge case where all values and n are maximal
116    subtask2.add_test_str(ezcp::array_to_string(&vec![1_000_000_000; 200_000], true));
117
118    // No additional constraints
119    let mut subtask3 = ezcp::Subtask::new();
120
121    subtask3.set_checker(|mut input| {
122        let array = input.get_array()?;
123        input.expect_end()?;
124        let n = array.len();
125        if !(1..=200_000).contains(&n) {
126            ezcp::bail!("n should be in range [1, 200_000]");
127        }
128        for i in array {
129            if i % 2 != 0 {
130                ezcp::bail!("all array values should be even");
131            }
132            if !(0..=1_000_000_000).contains(&i) {
133                ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
134            }
135        }
136        Ok(())
137    });
138
139    // add some random tests
140    subtask3.add_test(5, ezcp::array_generator_custom(1, 200_000, |rng| rng.random_range(0..=500_000_000) * 2));
141
142    // add 5 edge cases where n is maximal (other edge cases are handled by subtask2)
143    subtask3.add_test(5, ezcp::array_generator_custom(200_000, 200_000, |rng| rng.random_range(0..=500_000_000) * 2));
144
145    // add subtasks to task
146    let subtask1 = task.add_subtask(subtask1);
147    let subtask2 = task.add_subtask(subtask2);
148    let subtask3 = task.add_subtask(subtask3);
149
150    // add dependencies (dependencies are only if constraints of a dependency are a subset of constraints of a subtask)
151    task.add_subtask_dependency(subtask3, subtask1);
152    task.add_subtask_dependency(subtask3, subtask2);
153
154    // there is a partial solution that only reads 2 integers: n, x and prints x / 2 which is correct for subtask1 but should fail for subtask2 and subtask3
155    task.add_partial_solution(PARTIAL_SOLUTION.to_owned(), &[subtask1]);
156
157    // finally create the tests
158    task.create_tests().ok();
159}
Source

pub fn add_test_str<S: Into<String>>(&mut self, input: S)

This function adds a single test from a string.

Examples found in repository?
examples/example2.rs (line 57)
32fn main() {
33    // In this task you have n coins with values a1, a2, ..., an. You need to find the smallest sum, you cannot get using these coins.
34    // For example, if you have coins with values 1, 2 and 4, you can get any sum from 1 to 7, but you cannot get 8.
35
36    let mut task = ezcp::Task::new("Coins", &PathBuf::from("task2"));
37    task.solution_source = SOLUTION.to_owned();
38
39    // Constraint: n = 1
40    let mut subtask1 = ezcp::Subtask::new();
41
42    subtask1.set_checker(|mut input| {
43        let array = input.get_array()?;
44        input.expect_end()?;
45        let n = array.len();
46        if n != 1 {
47            ezcp::bail!("n should be 1");
48        }
49        let x = array[0];
50        if !(1..=1_000_000_000).contains(&x) {
51            ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
52        }
53        Ok(())
54    });
55
56    subtask1.add_test(5, ezcp::array_generator(1, 1, 1, 1000));
57    subtask1.add_test_str("1\n 1\n".to_owned());
58
59    // Constraint: elements in the array are powers of 2 and n <= 30
60    let mut subtask2 = ezcp::Subtask::new();
61
62    subtask2.set_checker(|mut input| {
63        let array = input.get_array()?;
64        input.expect_end()?;
65        let n = array.len();
66        if !(1..=30).contains(&n) {
67            ezcp::bail!("n should be in range [1, 30]");
68        }
69        for (i, x) in array.iter().enumerate() {
70            if *x != 1 << i {
71                ezcp::bail!("all array values should be powers of 2");
72            }
73        }
74        Ok(())
75    });
76
77    subtask2.add_test(5, || {
78        let mut rng = rand::rng();
79        let n = rng.random_range(1..=30);
80        let mut array = Vec::new();
81        for i in 0..n {
82            array.push(1 << i);
83        }
84        ezcp::array_to_string(&array, true)
85    });
86
87    // Constraint: n <= 1000
88    let mut subtask3 = ezcp::Subtask::new();
89
90    subtask3.set_checker(|mut input| {
91        let array = input.get_array()?;
92        input.expect_end()?;
93        let n = array.len();
94        if !(1..=1000).contains(&n) {
95            ezcp::bail!("n should be in range [1, 1000]");
96        }
97        for x in array {
98            if !(1..=1_000_000_000).contains(&x) {
99                ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
100            }
101        }
102        Ok(())
103    });
104
105    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1000));
106    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1_000_000_000));
107    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1));
108    subtask3.add_test(5, ezcp::array_generator(1000, 1000, 1, 1000));
109    subtask3.add_test(5, ezcp::array_generator(1000, 1000, 1, 1_000_000_000));
110    subtask3.add_test(1, ezcp::array_generator(1000, 1000, 1, 1));
111
112    // Constraint: n <= 200_000
113    let mut subtask4 = ezcp::Subtask::new();
114
115    subtask4.set_checker(|mut input| {
116        let array = input.get_array()?;
117        input.expect_end()?;
118        let n = array.len();
119        if !(1..=200_000).contains(&n) {
120            ezcp::bail!("n should be in range [1, 200_000]");
121        }
122        for x in array {
123            if !(1..=1_000_000_000).contains(&x) {
124                ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
125            }
126        }
127        Ok(())
128    });
129
130    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1000));
131    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1_000_000_000));
132    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1));
133    subtask4.add_test(5, ezcp::array_generator(200_000, 200_000, 1, 1000));
134    subtask4.add_test(5, ezcp::array_generator(200_000, 200_000, 1, 1_000_000_000));
135    subtask4.add_test(1, ezcp::array_generator(200_000, 200_000, 1, 1));
136
137    // add subtasks to task
138    let subtask1 = task.add_subtask(subtask1);
139    let subtask2 = task.add_subtask(subtask2);
140    let subtask3 = task.add_subtask(subtask3);
141    let subtask4 = task.add_subtask(subtask4);
142
143    // add dependencies
144    task.add_subtask_dependency(subtask3, subtask1);
145    task.add_subtask_dependency(subtask3, subtask2);
146    task.add_subtask_dependency(subtask4, subtask3);
147
148    task.create_tests().ok();
149}
More examples
Hide additional examples
examples/example1.rs (line 110)
36fn main() {
37    // The first task you get an array of integers. You need to find the sum of all elements in the array minus the half of the maximum element.
38    // Also all elements in the array are even.
39
40    let mut task = ezcp::Task::new("Coupon", &PathBuf::from("task1"));
41    //task.debug_level = LevelFilter::Trace;
42
43    task.solution_source = SOLUTION.to_owned();
44
45    // Constraint: n = 1
46    let mut subtask1 = ezcp::Subtask::new();
47
48    // This checker is optional and can be omitted.
49    subtask1.set_checker(|mut input| {
50        // read an array from input
51        let array = input.get_array()?;
52        // expect end of input
53        input.expect_end()?;
54        let n = array.len();
55        if n != 1 {
56            ezcp::bail!("n should be 1");
57        }
58        // check if the only value is even
59        if array[0] % 2 != 0 {
60            ezcp::bail!("all array values should be even");
61        }
62        // check if the only value is in range
63        if !(0..=1_000_000_000).contains(&array[0]) {
64            ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
65        }
66        Ok(())
67    });
68
69    // add 5 tests where an array is generated with length 1 and even values between 0 and 1_000_000_000 (inclusive)
70    subtask1.add_test(5, ezcp::array_generator_custom(1, 1, |rng| rng.random_range(0..=500_000_000) * 2));
71    // this is a faulty test for testing the checker
72    //subtask1.add_test_str("1\n 0 0\n".to_owned());
73
74    // Constraint: all values are the same
75    let mut subtask2 = ezcp::Subtask::new();
76
77    subtask2.set_checker(|mut input| {
78        let array = input.get_array()?;
79        input.expect_end()?;
80        let n = array.len();
81        if !(1..=200_000).contains(&n) {
82            ezcp::bail!("n should be in range [1, 200_000]");
83        }
84        let x = array[0];
85        for i in array {
86            if i != x {
87                ezcp::bail!("all array values should be the same");
88            }
89            if i % 2 != 0 {
90                ezcp::bail!("all array values should be even");
91            }
92            if !(0..=1_000_000_000).contains(&i) {
93                ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
94            }
95        }
96        Ok(())
97    });
98
99    // add 5 random tests where each test is an array of length between 1 and 200_000 (inclusive) and all values are the same even value between 0 and 1_000_000_000 (inclusive)
100    subtask2.add_test(5, || {
101        let mut rng = rand::rng();
102        let n = rng.random_range(1..=200_000);
103        let x = rng.random_range(0..=500_000_000) * 2;
104        ezcp::array_to_string(&vec![x; n as usize], true)
105    });
106
107    // add an edge case where n is maximal
108    let mut rng = rand::rng();
109    let x = rng.random_range(0..=500_000_000) * 2;
110    subtask2.add_test_str(ezcp::array_to_string(&vec![x; 200_000], true));
111
112    // add 3 edge cases where all values are maximal
113    subtask2.add_test(3, ezcp::array_generator(1, 200_000, 1_000_000_000, 1_000_000_000));
114
115    // add an edge case where all values and n are maximal
116    subtask2.add_test_str(ezcp::array_to_string(&vec![1_000_000_000; 200_000], true));
117
118    // No additional constraints
119    let mut subtask3 = ezcp::Subtask::new();
120
121    subtask3.set_checker(|mut input| {
122        let array = input.get_array()?;
123        input.expect_end()?;
124        let n = array.len();
125        if !(1..=200_000).contains(&n) {
126            ezcp::bail!("n should be in range [1, 200_000]");
127        }
128        for i in array {
129            if i % 2 != 0 {
130                ezcp::bail!("all array values should be even");
131            }
132            if !(0..=1_000_000_000).contains(&i) {
133                ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
134            }
135        }
136        Ok(())
137    });
138
139    // add some random tests
140    subtask3.add_test(5, ezcp::array_generator_custom(1, 200_000, |rng| rng.random_range(0..=500_000_000) * 2));
141
142    // add 5 edge cases where n is maximal (other edge cases are handled by subtask2)
143    subtask3.add_test(5, ezcp::array_generator_custom(200_000, 200_000, |rng| rng.random_range(0..=500_000_000) * 2));
144
145    // add subtasks to task
146    let subtask1 = task.add_subtask(subtask1);
147    let subtask2 = task.add_subtask(subtask2);
148    let subtask3 = task.add_subtask(subtask3);
149
150    // add dependencies (dependencies are only if constraints of a dependency are a subset of constraints of a subtask)
151    task.add_subtask_dependency(subtask3, subtask1);
152    task.add_subtask_dependency(subtask3, subtask2);
153
154    // there is a partial solution that only reads 2 integers: n, x and prints x / 2 which is correct for subtask1 but should fail for subtask2 and subtask3
155    task.add_partial_solution(PARTIAL_SOLUTION.to_owned(), &[subtask1]);
156
157    // finally create the tests
158    task.create_tests().ok();
159}
Source

pub fn set_checker<F: Fn(Input) -> Result<()> + 'static>(&mut self, function: F)

This function sets the checker function for the subtask. The checker function receives the input and returns an error if the input is invalid. If the input is valid, it should return Ok(()). If the checker function is not set, the default checker will be used although it is not recommended.

Examples found in repository?
examples/example2.rs (lines 42-54)
32fn main() {
33    // In this task you have n coins with values a1, a2, ..., an. You need to find the smallest sum, you cannot get using these coins.
34    // For example, if you have coins with values 1, 2 and 4, you can get any sum from 1 to 7, but you cannot get 8.
35
36    let mut task = ezcp::Task::new("Coins", &PathBuf::from("task2"));
37    task.solution_source = SOLUTION.to_owned();
38
39    // Constraint: n = 1
40    let mut subtask1 = ezcp::Subtask::new();
41
42    subtask1.set_checker(|mut input| {
43        let array = input.get_array()?;
44        input.expect_end()?;
45        let n = array.len();
46        if n != 1 {
47            ezcp::bail!("n should be 1");
48        }
49        let x = array[0];
50        if !(1..=1_000_000_000).contains(&x) {
51            ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
52        }
53        Ok(())
54    });
55
56    subtask1.add_test(5, ezcp::array_generator(1, 1, 1, 1000));
57    subtask1.add_test_str("1\n 1\n".to_owned());
58
59    // Constraint: elements in the array are powers of 2 and n <= 30
60    let mut subtask2 = ezcp::Subtask::new();
61
62    subtask2.set_checker(|mut input| {
63        let array = input.get_array()?;
64        input.expect_end()?;
65        let n = array.len();
66        if !(1..=30).contains(&n) {
67            ezcp::bail!("n should be in range [1, 30]");
68        }
69        for (i, x) in array.iter().enumerate() {
70            if *x != 1 << i {
71                ezcp::bail!("all array values should be powers of 2");
72            }
73        }
74        Ok(())
75    });
76
77    subtask2.add_test(5, || {
78        let mut rng = rand::rng();
79        let n = rng.random_range(1..=30);
80        let mut array = Vec::new();
81        for i in 0..n {
82            array.push(1 << i);
83        }
84        ezcp::array_to_string(&array, true)
85    });
86
87    // Constraint: n <= 1000
88    let mut subtask3 = ezcp::Subtask::new();
89
90    subtask3.set_checker(|mut input| {
91        let array = input.get_array()?;
92        input.expect_end()?;
93        let n = array.len();
94        if !(1..=1000).contains(&n) {
95            ezcp::bail!("n should be in range [1, 1000]");
96        }
97        for x in array {
98            if !(1..=1_000_000_000).contains(&x) {
99                ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
100            }
101        }
102        Ok(())
103    });
104
105    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1000));
106    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1_000_000_000));
107    subtask3.add_test(5, ezcp::array_generator(1, 1000, 1, 1));
108    subtask3.add_test(5, ezcp::array_generator(1000, 1000, 1, 1000));
109    subtask3.add_test(5, ezcp::array_generator(1000, 1000, 1, 1_000_000_000));
110    subtask3.add_test(1, ezcp::array_generator(1000, 1000, 1, 1));
111
112    // Constraint: n <= 200_000
113    let mut subtask4 = ezcp::Subtask::new();
114
115    subtask4.set_checker(|mut input| {
116        let array = input.get_array()?;
117        input.expect_end()?;
118        let n = array.len();
119        if !(1..=200_000).contains(&n) {
120            ezcp::bail!("n should be in range [1, 200_000]");
121        }
122        for x in array {
123            if !(1..=1_000_000_000).contains(&x) {
124                ezcp::bail!("all array values should be in range [1, 1_000_000_000]");
125            }
126        }
127        Ok(())
128    });
129
130    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1000));
131    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1_000_000_000));
132    subtask4.add_test(5, ezcp::array_generator(1, 200_000, 1, 1));
133    subtask4.add_test(5, ezcp::array_generator(200_000, 200_000, 1, 1000));
134    subtask4.add_test(5, ezcp::array_generator(200_000, 200_000, 1, 1_000_000_000));
135    subtask4.add_test(1, ezcp::array_generator(200_000, 200_000, 1, 1));
136
137    // add subtasks to task
138    let subtask1 = task.add_subtask(subtask1);
139    let subtask2 = task.add_subtask(subtask2);
140    let subtask3 = task.add_subtask(subtask3);
141    let subtask4 = task.add_subtask(subtask4);
142
143    // add dependencies
144    task.add_subtask_dependency(subtask3, subtask1);
145    task.add_subtask_dependency(subtask3, subtask2);
146    task.add_subtask_dependency(subtask4, subtask3);
147
148    task.create_tests().ok();
149}
More examples
Hide additional examples
examples/example1.rs (lines 49-67)
36fn main() {
37    // The first task you get an array of integers. You need to find the sum of all elements in the array minus the half of the maximum element.
38    // Also all elements in the array are even.
39
40    let mut task = ezcp::Task::new("Coupon", &PathBuf::from("task1"));
41    //task.debug_level = LevelFilter::Trace;
42
43    task.solution_source = SOLUTION.to_owned();
44
45    // Constraint: n = 1
46    let mut subtask1 = ezcp::Subtask::new();
47
48    // This checker is optional and can be omitted.
49    subtask1.set_checker(|mut input| {
50        // read an array from input
51        let array = input.get_array()?;
52        // expect end of input
53        input.expect_end()?;
54        let n = array.len();
55        if n != 1 {
56            ezcp::bail!("n should be 1");
57        }
58        // check if the only value is even
59        if array[0] % 2 != 0 {
60            ezcp::bail!("all array values should be even");
61        }
62        // check if the only value is in range
63        if !(0..=1_000_000_000).contains(&array[0]) {
64            ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
65        }
66        Ok(())
67    });
68
69    // add 5 tests where an array is generated with length 1 and even values between 0 and 1_000_000_000 (inclusive)
70    subtask1.add_test(5, ezcp::array_generator_custom(1, 1, |rng| rng.random_range(0..=500_000_000) * 2));
71    // this is a faulty test for testing the checker
72    //subtask1.add_test_str("1\n 0 0\n".to_owned());
73
74    // Constraint: all values are the same
75    let mut subtask2 = ezcp::Subtask::new();
76
77    subtask2.set_checker(|mut input| {
78        let array = input.get_array()?;
79        input.expect_end()?;
80        let n = array.len();
81        if !(1..=200_000).contains(&n) {
82            ezcp::bail!("n should be in range [1, 200_000]");
83        }
84        let x = array[0];
85        for i in array {
86            if i != x {
87                ezcp::bail!("all array values should be the same");
88            }
89            if i % 2 != 0 {
90                ezcp::bail!("all array values should be even");
91            }
92            if !(0..=1_000_000_000).contains(&i) {
93                ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
94            }
95        }
96        Ok(())
97    });
98
99    // add 5 random tests where each test is an array of length between 1 and 200_000 (inclusive) and all values are the same even value between 0 and 1_000_000_000 (inclusive)
100    subtask2.add_test(5, || {
101        let mut rng = rand::rng();
102        let n = rng.random_range(1..=200_000);
103        let x = rng.random_range(0..=500_000_000) * 2;
104        ezcp::array_to_string(&vec![x; n as usize], true)
105    });
106
107    // add an edge case where n is maximal
108    let mut rng = rand::rng();
109    let x = rng.random_range(0..=500_000_000) * 2;
110    subtask2.add_test_str(ezcp::array_to_string(&vec![x; 200_000], true));
111
112    // add 3 edge cases where all values are maximal
113    subtask2.add_test(3, ezcp::array_generator(1, 200_000, 1_000_000_000, 1_000_000_000));
114
115    // add an edge case where all values and n are maximal
116    subtask2.add_test_str(ezcp::array_to_string(&vec![1_000_000_000; 200_000], true));
117
118    // No additional constraints
119    let mut subtask3 = ezcp::Subtask::new();
120
121    subtask3.set_checker(|mut input| {
122        let array = input.get_array()?;
123        input.expect_end()?;
124        let n = array.len();
125        if !(1..=200_000).contains(&n) {
126            ezcp::bail!("n should be in range [1, 200_000]");
127        }
128        for i in array {
129            if i % 2 != 0 {
130                ezcp::bail!("all array values should be even");
131            }
132            if !(0..=1_000_000_000).contains(&i) {
133                ezcp::bail!("all array values should be in range [0, 1_000_000_000]");
134            }
135        }
136        Ok(())
137    });
138
139    // add some random tests
140    subtask3.add_test(5, ezcp::array_generator_custom(1, 200_000, |rng| rng.random_range(0..=500_000_000) * 2));
141
142    // add 5 edge cases where n is maximal (other edge cases are handled by subtask2)
143    subtask3.add_test(5, ezcp::array_generator_custom(200_000, 200_000, |rng| rng.random_range(0..=500_000_000) * 2));
144
145    // add subtasks to task
146    let subtask1 = task.add_subtask(subtask1);
147    let subtask2 = task.add_subtask(subtask2);
148    let subtask3 = task.add_subtask(subtask3);
149
150    // add dependencies (dependencies are only if constraints of a dependency are a subset of constraints of a subtask)
151    task.add_subtask_dependency(subtask3, subtask1);
152    task.add_subtask_dependency(subtask3, subtask2);
153
154    // there is a partial solution that only reads 2 integers: n, x and prints x / 2 which is correct for subtask1 but should fail for subtask2 and subtask3
155    task.add_partial_solution(PARTIAL_SOLUTION.to_owned(), &[subtask1]);
156
157    // finally create the tests
158    task.create_tests().ok();
159}

Auto Trait Implementations§

§

impl Freeze for Subtask

§

impl !RefUnwindSafe for Subtask

§

impl !Send for Subtask

§

impl !Sync for Subtask

§

impl Unpin for Subtask

§

impl !UnwindSafe for Subtask

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V