I'd like to load the DIMACS CNF file in Rust.
If I write in Ruby, the code will be as follows, but how should I write Rust?
In particular, I haven't found a function that corresponds to Ruby's scan.
#Ruby code
default_dimacs_cnf_file(file_name)
cnf = [ ]
cause = [ ]
open(file_name, "r").readlines.reject {|line|line=~/^c/||line=~/^p/}.join().scan(/-?\d+/).collect {|literal|literal.to_i}.each {|literal|
if literal == 0
then
cnf<clause
cause = [ ]
else
close <literal
end
}
cnf
end
Sample Input
c
c comment
c
pcnf33
1 2 0
2 -3 0
3 0
Sample Output
[1,2], [2,-3], [3]]
The Rust code can only be written to the point where the file is loaded.
usestd::error::Error;
usestd::fs::File;
use std::io::prelude::*;
use std::path::Path;
fn read_dimacs_cnf_file(file_name:&str)->String{
let path = Path::new(file_name);
let mut file=matchFile::open(&path){
Err(msg)=>panic!("couldn't open file.{}, msg),
Ok(file) = > file,
};
let mutes = String::new();
match file.read_to_string(&muts){
Err(msg)=>panic!("couldn't read file.{}, msg),
Ok(_) = > returns,
};
}
US>fnmain(){
println!("{}, read_dimacs_cnf_file("test.cnf"));
}
In particular, I haven't found a function that corresponds to Ruby's scan.
Although Ruby's scan
and other regular expressions such as /-?\d+/
are used, Rust's standard library (std
crate) does not have regular expression functionality.If you use regular expressions, you must use regex
crate.
Cargo.toml
[dependencies]
regex = "1.7.0"
You can use the captures_iter
method in the regex
crate to retrieve a matching substring, such as scan
.
usestd::{
fs::File,
io::{prelude::*, BufReader},
};
use regex::Regex;
fn read_dimacs_cnf_file(file_name:&str)->Vec<Vec<i32>{
let file=File::open(file_name).expect("couldn't open file.");
let file = BufReader::new(file);
letre=Regex::new(r"-?\d+").unwrap();
let mut close = Vec::new();
let mut cnf = Vec::new();
// read line by line
for line in file.lines() {
let line = line.expect("couldn't read file.");
// Ignore lines that begin with c or p
ifline.starts_with("c")||line.starts_with("p"){
continue;
}
// Process each matched substring in the row
for token in re.captures_iter(&line) {
// convert a partial string to an integer
let literal=token[0].parse::<i32>().expect("couldn't parse number.");
if literal == 0 {
// If 0, add cause to cnf and empty cause
cnf.push(clause);
cause=Vec::new();
} else{
// If it is not 0, add it to the cause.
close.push(literal);
}
}
}
cnf
}
US>fnmain(){
println!("{:?}", read_dimacs_cnf_file("test.cnf"));
}
In this data format, numbers are separated by blank characters, so you can also use the str:split_whitespace
method of std
without using regular expressions.Rewrite two lines as follows to eliminate the need for regex
crates.
//Processing each substring separated by a blank character in the line
for token inline.split_whitespace(){
// convert a partial string to an integer
let literal=token.trim().parse::<i32>().expect("couldn't parse number.");
© 2024 OneMinuteCode. All rights reserved.