Task

Struct Task 

Source
pub struct Task {
    pub tests_path: PathBuf,
    pub time_limit: f32,
    pub tests_archive_path: PathBuf,
    pub get_input_file_name: Box<dyn Fn(i32, i32, i32) -> String>,
    pub get_output_file_name: Box<dyn Fn(i32, i32, i32) -> String>,
    pub solution_source: String,
    pub debug_level: LevelFilter,
    /* private fields */
}
Expand description

This struct represents an entire task. You can add subtasks, partial solutions and set the time limit. Once you are done, you can create tests for the task.

Fields§

§tests_path: PathBuf§time_limit: f32§tests_archive_path: PathBuf§get_input_file_name: Box<dyn Fn(i32, i32, i32) -> String>§get_output_file_name: Box<dyn Fn(i32, i32, i32) -> String>§solution_source: String§debug_level: LevelFilter

Implementations§

Source§

impl Task

Source

pub fn new(name: &str, path: &Path) -> Self

This function creates a new task with the given name and path. The path should be a relative path to the task folder in which the tests will be generated. The solution should be at solution_path which is path/solution.cpp by default but can be changed.

Examples found in repository?
examples/example2.rs (line 36)
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 40)
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_subtask(&mut self, subtask: Subtask) -> usize

This function adds a subtask to the task. The subtask must be ready as it cannot be modified after it is added to the task. The function returns the index of the subtask.

Examples found in repository?
examples/example2.rs (line 138)
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 146)
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_subtask_dependency(&mut self, subtask: usize, dependency: usize)

This function adds a dependency between two subtasks. A dependency means, that the first subtask must be solved before the second subtask. In practice that means that all the tests from the dependency subtask will be added before the tests from the subtask. Dependencies apply recursively but do not duplicate tests. The subtask must be added to the task before this function is called.

Examples found in repository?
examples/example2.rs (line 144)
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 151)
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_partial_solution( &mut self, solution_source: String, passes_subtasks: &[usize], )

This function adds a partial solution to the task. A partial solution is a solution that only solves a subset of subtasks. When the task is generated, the partial solution will be run on all tests of the subtasks it solves. If the partial solution does not solve the exact subtasks it should, an error will be thrown.

Examples found in repository?
examples/example1.rs (line 155)
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 create_tests(&mut self) -> Result<()>

This creates tests and prints the error message if there is an error.

Examples found in repository?
examples/example2.rs (line 148)
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 158)
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 Task

§

impl !RefUnwindSafe for Task

§

impl !Send for Task

§

impl !Sync for Task

§

impl Unpin for Task

§

impl !UnwindSafe for Task

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