pub mod xcsp3_utils {
use crate::data_structs::xint_val_var::xcsp3_core::XVarVal;
use crate::errors::xcsp3error::xcsp3_core::Xcsp3Error;
pub fn list_to_vec_var_val(list: &str) -> Result<Vec<XVarVal>, Xcsp3Error> {
let mut ret: Vec<XVarVal> = vec![];
let lists: Vec<&str> = list.split_whitespace().collect();
for e in lists.iter() {
match XVarVal::from_string(e) {
None => {
return Err(Xcsp3Error::get_constraint_list_of_values_error(
"parse the list of values error. ",
))
}
Some(vv) => {
ret.push(vv);
}
}
}
Ok(ret)
}
pub fn size_to_string(id: &str, size: &[usize]) -> String {
let mut ret = id.to_string();
for e in size.iter() {
ret.push_str(&format!("[{}]", e))
}
ret
}
pub fn get_all_variables_between_lower_and_upper(
lower: Vec<usize>,
upper: Vec<usize>,
) -> Vec<Vec<usize>> {
let mut ret: Vec<Vec<usize>> = vec![];
let mut tmp: Vec<Vec<usize>> = vec![];
for i in lower[0]..upper[0] + 1 {
tmp.push(vec![i]);
}
for deep in 1..lower.len() {
for i in lower[deep]..upper[deep] + 1 {
for e in tmp.iter() {
let mut ee = e.clone();
ee.push(i);
ret.push(ee)
}
}
tmp = ret.clone();
ret.clear();
}
tmp
}
pub fn get_nth_square_of_name(id: &str) -> usize {
match id.find("[]") {
None => 0,
Some(v) => {
let mut cnt: usize = 0;
for (_, c) in id[..v].chars().enumerate() {
if c == '[' {
cnt += 1
}
}
cnt
}
}
}
pub fn list_to_scope_ids(list: &str) -> Vec<String> {
let mut ret: Vec<String> = Vec::new();
let lists: Vec<&str> = list.split_whitespace().collect();
for e in lists.iter() {
ret.push(e.to_string());
}
ret
}
pub fn list_to_transitions(list: &str) -> Result<Vec<(String, i32, String)>, Xcsp3Error> {
let mut ret: Vec<(String, i32, String)> = Vec::new();
let chars = list.chars();
if let Some(left) = list.find('(') {
if let Some(right) = list.find(')') {
ret.reserve(list.len() / (right - left));
}
}
let mut last = usize::MAX;
let mut last_comma1 = usize::MAX;
let mut last_comma2 = usize::MAX;
for (i, x) in chars.enumerate() {
if x == '(' {
last = i;
} else if x == ')' {
match list[last_comma1 + 1..last_comma2].parse::<i32>() {
Ok(num) => ret.push((
list[last + 1..last_comma1].to_string(),
num,
list[last_comma2 + 1..i].to_string(),
)),
Err(_) => {
return Err(Xcsp3Error::get_constraint_regular_transitions_error(
"parse the transitions error, ",
));
}
}
last_comma1 = usize::MAX;
} else if x == ',' {
if last_comma1 == usize::MAX {
last_comma1 = i;
} else {
last_comma2 = i;
}
}
}
Ok(ret)
}
pub fn list_to_matrix_ids(list: &str) -> Vec<Vec<String>> {
let mut ret: Vec<Vec<String>> = Vec::new();
let list = list
.to_string()
.replace(')', "@")
.replace('\n', "")
.replace('(', " ");
let lists: Vec<&str> = list.split('@').collect();
for e in lists.iter() {
if !e.is_empty() {
let ss = e.replace(',', " ");
ret.push(list_to_scope_ids(&ss));
}
}
ret
}
pub fn list_to_values(list: &str) -> Result<Vec<i32>, Xcsp3Error> {
let mut ret: Vec<i32> = Vec::new();
let lists: Vec<&str> = list.split_whitespace().collect();
for l in lists.iter() {
match l.parse::<i32>() {
Ok(n) => ret.push(n),
Err(_) => {
return Err(Xcsp3Error::get_constraint_list_of_values_error(
"parse the list of values error. ",
));
}
}
}
Ok(ret)
}
pub fn list_with_bracket_comma_to_values(list: &str) -> Result<Vec<XVarVal>, Xcsp3Error> {
let mut ret: Vec<XVarVal> = Vec::new();
let list = list.to_string().replace(['(', ')', ','], " ");
let lists: Vec<&str> = list.split_whitespace().collect();
for e in lists.iter() {
match e.parse::<i32>() {
Ok(n) => ret.push(XVarVal::IntArgument(n)),
Err(_) => {
return Err(Xcsp3Error::get_constraint_list_of_values_error(
"parse the list of values error. ",
));
}
}
}
Ok(ret)
}
pub fn tuple_to_vector(tuple_str: &str, is_unary: bool) -> Result<Vec<Vec<i32>>, Xcsp3Error> {
let mut ret: Vec<Vec<i32>> = Vec::new();
let err = Xcsp3Error::get_constraint_extension_error("parse the tuple of extension error");
if is_unary {
let tuples: Vec<&str> = tuple_str.split_whitespace().collect();
for tuple in tuples.iter() {
if tuple.contains("..") {
let interval: Vec<&str> = tuple.split("..").collect();
if interval.len() == 2 {
let left = interval[0].parse::<i32>();
let right = interval[1].parse::<i32>();
match left {
Ok(l) => match right {
Ok(r) => {
if l <= r {
for i in l..r + 1 {
ret.push(vec![i])
}
} else {
return Err(err);
}
}
Err(_) => {
return Err(err);
}
},
Err(_) => {
return Err(err);
}
}
}
} else {
match tuple.parse::<i32>() {
Ok(v) => ret.push(vec![v]),
Err(_) => {
return Err(err);
}
}
}
}
} else {
let chars = tuple_str.chars();
let mut last = 0;
let mut tt: Vec<i32> = vec![];
let mut n: usize = 0;
if let Some(left) = tuple_str.find('(') {
if let Some(right) = tuple_str.find(')') {
ret.reserve(tuple_str.len() / (right - left));
n = (right - left - 1) / 2;
}
}
for (i, x) in chars.enumerate() {
if x == '(' {
tt.clear();
tt.reserve(n);
last = i;
} else if x == ')' {
match tuple_str[last + 1..i].parse::<i32>() {
Ok(num) => {
tt.push(num);
}
Err(_) => {
if &tuple_str[last + 1..i] == "*" {
tt.push(i32::MAX);
} else {
return Err(err);
}
}
}
ret.push(tt.clone())
} else if x == ',' {
match tuple_str[last + 1..i].parse::<i32>() {
Ok(num) => {
tt.push(num);
}
Err(_) => {
if &tuple_str[last + 1..i] == "*" {
tt.push(i32::MAX);
} else {
return Err(err);
}
}
}
last = i;
}
}
}
Ok(ret)
}
pub fn sizes_to_double_vec(sizes: &str) -> Result<(Vec<usize>, Vec<usize>), Xcsp3Error> {
let mut lower: Vec<usize> = vec![];
let mut upper: Vec<usize> = vec![];
let sizes = sizes.replace("[]", "[*]").replace(['[', ']'], " ");
let nums: Vec<&str> = sizes.split_whitespace().collect();
for n in nums.iter() {
if n.find('*').is_some() {
lower.push(usize::MAX);
upper.push(usize::MAX);
} else if n.contains("..") {
let interval: Vec<&str> = n.split("..").collect();
if interval.len() == 2 {
let low = interval[0].parse::<usize>();
let up = interval[1].parse::<usize>();
match low {
Ok(l) => match up {
Ok(u) => {
lower.push(l);
upper.push(u);
}
Err(_) => {
return Err(Xcsp3Error::get_domain_for_error(
"parse the domain for error",
));
}
},
Err(_) => {
return Err(Xcsp3Error::get_domain_for_error(
"parse the domain for error",
));
}
}
}
} else {
match n.parse::<usize>() {
Ok(v) => {
lower.push(v);
upper.push(v);
}
Err(_) => {
return Err(Xcsp3Error::get_domain_for_error("parse the domain error"));
}
};
}
}
Ok((lower, upper))
}
pub fn sizes_to_vec(sizes: &str) -> Result<(Vec<usize>, usize), Xcsp3Error> {
let mut ret: Vec<usize> = vec![];
let mut sz: usize = 1;
let mut sizes = sizes.replace('[', " ");
sizes = sizes.replace(']', " ");
let nums: Vec<&str> = sizes.split_whitespace().collect();
for n in nums.iter() {
match n.parse::<usize>() {
Ok(v) => {
ret.push(v);
sz *= v;
}
Err(_) => {
return Err(Xcsp3Error::get_variable_size_invalid_error(
"parse the size of variable error",
));
}
};
}
Ok((ret, sz))
}
}