Question

I have written some code to load a cnf from a file which store the cnf according to the standard described here.

the file is:

c  simple_v3_c2.cnf      // lines bigining by c are comments
c  
p cnf 3 2                // the line bigining by p is the description of the pb
1 -3 0                   // folowing lines are formulation of the pb, with 0 as ending caractere
2 3 -1 0

I want to load it into [[1, -3][2,3,-1]]

The code I have written works, but it seems ugly to me. I would be interested in having some feedback on it. (I am new to python).

def loadCnfFile(fileName='example.cnf'):
""" retourne une liste de listes d'entiers decrivants la forme normale conjonctive"""
cnf=[]
cnfFile = open(fileName, 'r')
for line in cnfFile:
    if line[0]!="c" and line[0]!="p":
        l=line.split("0")[0].strip().split(" ")
        m=[]
        for k in l:
            m.append(int(k))
        cnf.append(m)
cnfFile.close()
return cnf

Thanks !

Was it helpful?

Solution 2

using list comprehension:

In [66]: with open("example.cnf") as f:
        print [map(int,line.split("0")[0].split()) for line in f if line and \
                            not (line.startswith("c") or line.startswith("p"))]
   ....:     
[[1, -3], [2, 3, -1]]

or:

with open("example.cnf") as f:
         x= lambda y,c:y.startswith(c)
         print [map(int,line.split("0")[0].split()) for line in f if line and \
                                not any(x(line,z) for z in ("c","p"))]
   ....:     
[[1, -3], [2, 3, -1]]

OTHER TIPS

I guess the best feedback on your code would be to rewrite it in a more "pythonic" manner. For example:

def cnf_lines(path):
    """Yields cnf lines as lists from the file."""

    with open(path) as fp:
        for line in fp:
            if not line.startswith(('c', 'p')):
                items = map(int, line.split())
                yield items[:-1]

Key points:

  • PEP-8 conformance (no camelCase in python please)
  • context managers (with) for file operations
  • generators (yield) instead of accumulating lists

NB: this code is intentionally simplified and does not fully support the specs you linked to.

Ashwini'S code is correct and appealing to an experienced programmer (thank you), but for someone new to python (what you seem to be) maybe a plain for-loop is easier to understand:

result = []
with open("example.cnf") as f:
    for line in f:
        if not (line.startswith("c") or line.startswith("p")):
            result.append([int(x) for x in line.rstrip("0").rstrip("0\n").split()])
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top