I want to load a file in DIMACS CNF format.

Asked 1 years ago, Updated 1 years ago, 433 views

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"));
}

trust

2022-12-11 04:17

1 Answers

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 (stdcrate) does not have regular expression functionality.If you use regular expressions, you must use regexcrate.

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.");


2022-12-11 08:58

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.