Merge code of same operation with two different conditions - if-statement

I have a question. I'm trying to tidy up some coding.
I have this part of code
if (self.type == self.BETAECM):
for line in contentInfo:
if line.startswith("caid:"):
caid = self.readEcmInfo(line)
if "x" in caid:
idx = caid.index("x")
caid = caid[(idx + 1):]
caid = caid[:4]
caid = caid.upper()
if (caid >= "1700") and (caid <= "17FF"):
return True
elif line.startswith("====="):
caid = self.readCaid(line)
if "x" in caid:
idx = caid.index("x")
caid = caid[(idx + 1):]
caid = caid[:4]
caid = caid.upper()
if (caid >= "1700") and (caid <= "17FF"):
return True
return False
As you can see there are two different conditions that are handled with the same operation
I want to tidy up everything so that the identical parts of the code (what starts with if "x" in caid) are only written once. Is this possible?
Thanks in advance!

I don't know this language, but I'll take a stab at it.
for line in contentInfo:
caid = "nothing"
if line.startswith("caid:"):
caid = self.readEcmInfo(line)
elif line.startswith("====="):
caid = self.readCaid(line)
if "x" in caid:
idx = caid.index("x")
caid = caid[(idx + 1):]
caid = caid[:4]
caid = caid.upper()
if (caid >= "1700") and (caid <= "17FF"):
return True

You need to join them using an OR operator. In other words you what one condition OR the other to be true in order to excecute your code.
if line.startswith("caid:") || line.startswith("====="):

Thank you soooo much!
What I was missing is that the last if statement (if "x" in caid:) had to go on the same level the previous one. It works now!
So if I want to merge another example:
def readEcmInfo(self, line):
if ":" in line:
idx = line.index(":")
line = line[(idx + 1):]
line = line.replace("\n", "")
while line.startswith(" "):
line = line[1:]
while line.endswith(" "):
line = line[:-1]
return line
else:
return ""
elif "CaID" in line:
idx = line.index("D")
line = line[(idx + 1):]
line = line.replace("\n", "")
while line.startswith(" "):
line = line[1:]
while line.endswith(" "):
line = line[:-1]
return line
else:
return ""
Should it go like this?
def readEcmInfo(self, line):
if ":" in line:
idx = line.index(":")
line = line[(idx + 1):]
line = line.replace("\n", "")
elif "CaID" in line:
idx = line.index("D")
line = line[(idx + 1):]
line = line.replace("\n", "")
while line.startswith(" "):
line = line[1:]
while line.endswith(" "):
line = line[:-1]
return line
else:
return ""

Related

GLPK output formats

I am new to GLPK, so my apologies in advance if I'm missing something simple!
I have a largeish LP that I am feeding through GLPK to model an energy market. I'm running the following command line to GLPK to process this:
winglpk-4.65\glpk-4.65\w64\glpsol --lp problem.lp --data ExampleDataFile.dat --output results2.txt
When I open the resulting text file I can see the outputs, which all look sensible. I have one big problem: each record is split over two rows, making it very difficult to clean the file. See an extract below:
No. Row name St Activity Lower bound Upper bound Marginal
------ ------------ -- ------------- ------------- ------------- -------------
1 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1990)_
NS 0 0 = < eps
2 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1991)_
NS 0 0 = < eps
3 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1992)_
NS 0 0 = < eps
4 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1993)_
NS 0 0 = < eps
5 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1994)_
NS 0 0 = < eps
6 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1995)_
NS 0 0 = < eps
7 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1996)_
NS 0 0 = < eps
8 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1997)_
NS 0 0 = < eps
9 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1998)_
NS 0 0 = < eps
10 c_e_SpecifiedDemand(UTOPIA_CSV_ID_1999)_
NS 0 0 = < eps
11 c_e_SpecifiedDemand(UTOPIA_CSV_ID_2000)_
NS 0 0 = < eps
12 c_e_SpecifiedDemand(UTOPIA_CSV_ID_2001)_
NS 0 0 = < eps
13 c_e_SpecifiedDemand(UTOPIA_CSV_ID_2002)_
NS 0 0 = < eps
14 c_e_SpecifiedDemand(UTOPIA_CSV_ID_2003)_
NS 0 0 = < eps
15 c_e_SpecifiedDemand(UTOPIA_CSV_ID_2004)_
NS 0 0 = < eps
I would be very grateful of any suggestions for either:
How I can get each record in the output text file onto a single row, or
Ideas on how to clean / post-process the existing text file output.
I'm sure I'm missing something simple here, but the output is in a very unhelpful format at the moment!
Thanks!
I wrote a Python parser for the GLPK output file. It is not beautiful and not save (try-catch) but it is working (for pure simplex problems).
You can call it on output file:
outp = GLPKOutput('myoutputfile')
print(outp)
val1 = outp.getCol('mycolvar','Activity')
val2 = outp.getRow('myrowname','Upper_bound') # row names should be defined
The class is as follows:
class GLPKOutput:
def __init__(self,filename):
self.rows = {}
self.columns = {}
self.nRows = 0
self.nCols = 0
self.nNonZeros = 0
self.Status = ""
self.Objective = ""
self.rowHeaders = []
self.rowIdx = {}
self.rowWidth = []
self.Rows = []
self.hRows = {}
self.colHeaders = []
self.colIdx = {}
self.colWidth = []
self.Cols = []
self.hCols = {}
self.wcols = ['Activity','Lower_bound','Upper bound','Marginal']
self.readFile(filename)
# split columns with weird line break
def smartSplit(self,line,type,job):
ret = []
line = line.rstrip()
if type == 'ROWS':
cols = len(self.rowHeaders)
idx = self.rowWidth
else:
cols = len(self.colHeaders)
idx = self.colWidth
if job == 'full':
start = 0
for i in range(cols):
stop = start+idx[i]+1
ret.append(line[start:stop].strip())
start = stop
elif job == 'part1':
entries = line.split()
ret = entries[0:2]
elif job == 'part2':
start = 0
for i in range(cols):
stop = start+idx[i]+1
ret.append(line[start:stop].strip())
start = stop
ret = ret[2:]
# print()
# print("SMART:",job,line.strip())
# print(" TO:",ret)
return ret
def readFile(self,filename):
fp = open(filename,"r")
lines = fp.readlines()
fp.close
i = 0
pos = "HEAD"
while pos == 'HEAD' and i<len(lines):
entries = lines[i].split()
if len(entries)>0:
if entries[0] == 'Rows:':
self.nRows = int(entries[1])
elif entries[0] == 'Columns:':
self.nCols = int(entries[1])
elif entries[0] == 'Non-zeros:':
self.nNonZeros = int(entries[1])
elif entries[0] == 'Status:':
self.Status = entries[1]
elif entries[0] == 'Objective:':
self.Objective = float(entries[3]) #' '.join(entries[1:])
elif re.search('Row name',lines[i]):
lines[i] = lines[i].replace('Row name','Row_name')
lines[i] = lines[i].replace('Lower bound','Lower_bound')
lines[i] = lines[i].replace('Upper bound','Upper_bound')
entries = lines[i].split()
pos = 'ROWS'
self.rowHeaders = entries
else:
pass
i+= 1
# formatting of row width
self.rowWidth = lines[i].split()
for k in range(len(self.rowWidth)): self.rowWidth[k] = len(self.rowWidth[k])
# print("Row Widths:",self.rowWidth)
i+= 1
READY = False
FOUND = False
while pos == 'ROWS' and i<len(lines):
if re.match('^\s*[0-9]+',lines[i]): # new line
if len(lines[i].split())>2: # no linebrak
entries = self.smartSplit(lines[i],pos,'full')
READY = True
else: # line break
entries = self.smartSplit(lines[i],pos,'part1')
READY = False
FOUND = True
else:
if FOUND and not READY: # second part of line
entries += self.smartSplit(lines[i],pos,'part2')
READY = True
FOUND = False
if READY:
READY = False
FOUND = False
# print("ROW:",entries)
if re.match('[0-9]+',entries[0]): # valid line with solution data
self.Rows.append(entries)
self.hRows[entries[1]] = len(self.Rows)-1
else:
print("wrong line format ...")
print(entries)
sys.exit()
elif re.search('Column name',lines[i]):
lines[i] = lines[i].replace('Column name','Column_name')
lines[i] = lines[i].replace('Lower bound','Lower_bound')
lines[i] = lines[i].replace('Upper bound','Upper_bound')
entries = lines[i].split()
pos = 'COLS'
self.colHeaders = entries
else:
pass #print("NOTHING: ",lines[i])
i+= 1
# formatting of row width
self.colWidth = lines[i].split()
for k in range(len(self.colWidth)): self.colWidth[k] = len(self.colWidth[k])
# print("Col Widths:",self.colWidth)
i+= 1
READY = False
FOUND = False
while pos == 'COLS' and i<len(lines):
if re.match('^\s*[0-9]+',lines[i]): # new line
if len(lines[i].split())>2: # no linebreak
entries = self.smartSplit(lines[i],pos,'full')
READY = True
else: # linebreak
entries = self.smartSplit(lines[i],pos,'part1')
READY = False
FOUND = True
else:
if FOUND and not READY: # second part of line
entries += self.smartSplit(lines[i],pos,'part2')
READY = True
FOUND = False
if READY:
READY = False
FOUND = False
# print("COL:",entries)
if re.match('[0-9]+',entries[0]): # valid line with solution data
self.Cols.append(entries)
self.hCols[entries[1]] = len(self.Cols)-1
else:
print("wrong line format ...")
print(entries)
sys.exit()
elif re.search('Karush-Kuhn-Tucker',lines[i]):
pos = 'TAIL'
else:
pass #print("NOTHING: ",lines[i])
i+= 1
for i,e in enumerate(self.rowHeaders): self.rowIdx[e] = i
for i,e in enumerate(self.colHeaders): self.colIdx[e] = i
def getRow(self,name,attr):
if name in self.hRows:
if attr in self.rowIdx:
try:
val = float(self.Rows[self.hRows[name]][self.rowIdx[attr]])
except:
val = self.Rows[self.hRows[name]][self.rowIdx[attr]]
return val
else:
return -1
def getCol(self,name,attr):
if name in self.hCols:
if attr in self.colIdx:
try:
val = float(self.Cols[self.hCols[name]][self.colIdx[attr]])
except:
val = self.Cols[self.hCols[name]][self.colIdx[attr]]
return val
else:
print("key error:",name,"not known ...")
return -1
def __str__(self):
retString = '\n'+"="*80+'\nSOLUTION\n'
retString += "nRows: "+str(self.nRows)+'/'+str(len(self.Rows))+'\n'
retString += "nCols: "+str(self.nCols)+'/'+str(len(self.Cols))+'\n'
retString += "nNonZeros: "+str(self.nNonZeros)+'\n'
retString += "Status: "+str(self.Status)+'\n'
retString += "Objective: "+str(self.Objective)+'\n\n'
retString += ' '.join(self.rowHeaders)+'\n'
for r in self.Rows: retString += ' # '.join(r)+' #\n'
retString += '\n'
retString += ' '.join(self.colHeaders)+'\n'
for c in self.Cols: retString += ' # '.join(r)+' #\n'
return retString

How to convert ASCII(not single character, complete sentence) to string

I have method called 'encode(string_argument)' which converts string(sentence) to ascii and reverse it. I have to write method which decode the string.
Code:
str1 = 'This is sample text'
def encode(str1):
encoded_str = ''
for i in str1:
encoded_str += str(ord(i))
return encoded_str[::-1]
def decode(encoded_str):
rev_encoded_str = encoded_str[::-1]
# Incomplete
encoded_str = encode(str1)
decode(encoded_str)
Input for encode():
This is sample text
Output from encode():
6110211016112310180121190179511235115012351150140148
Input for decode():
6110211016112310180121190179511235115012351150140148
Output from decode():
This is sample text
Thanks in advance.
Finally got the solution:
def encode(str1):
encoded_str = ''
for i in str1:
encoded_str += str(ord(i))
return encoded_str[::-1]
def decode(encoded_str):
reverse_string = encoded_str[::-1]
temp_array = convert_to_possible_string_ascii(reverse_string)
final_decoded_string = ""
for x in temp_array:
# print(str(chr(int(x)))+": "+x)
final_decoded_string = final_decoded_string + str(chr(int(x)))
print(final_decoded_string)
return final_decoded_string
def convert_to_possible_string_ascii(str_array):
temp_array = []
temp_char = ""
counter = 0
for current_char in range(0, len(str_array), 1):
temp_char = temp_char+str_array[current_char]
counter = counter+1
if counter==1:
temp_var = is_valid_string_ascii(temp_char)
if temp_var:
temp_array.append(temp_char)
counter = 0
temp_char = ""
elif counter==2:
temp_var = is_valid_string_ascii(temp_char)
if temp_var:
temp_array.append(temp_char)
counter = 0
temp_char = ""
elif counter==3:
temp_var = is_valid_string_ascii(temp_char)
if temp_var:
temp_array.append(temp_char)
counter = 0
temp_char = ""
return temp_array
def is_valid_string_ascii(ascii_value):
valid_list = list(range(65, 91)) + list(range(97, 123)) +[32]
boolean_var = False
if int(ascii_value) in valid_list:
boolean_var = True
return boolean_var
str1 = 'This is sample text'
encoded_str = encode(str1)
decode(encoded_str)

IndexError: Python list index out of range

I have an empty list, (r) and declared first element as r[0] = a
import time, urllib.request,random
def getDictionary():
word_site = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain"
response = urllib.request.urlopen(word_site)
txt = response.read()
return txt.splitlines()
def getWordsList(listOfWords, sample):
word = ""
randWords = []
for i in range(0,sample):
while(len(word) <=2):
word = random.choice(listOfWords).decode('utf-8')
randWords.append(word)
word = ""
return randWords
start = True
noOfWords = 25
words = getDictionary()
wordsList = getWordsList(words, noOfWords)
start = True
print ("\nINSTRUCTIONS\nWhen the coundown gets to zero, type the word in lowercase letters!\n That's the only rule!")
name = input("What is your name? ")
name = name.split(" ")
input("Press enter when ready...")
while start == True:
print("Game will start in: ")
print ("3 seconds")
time.sleep(1)
print ("2 seconds")
time.sleep(1)
print ("1 seconds")
time.sleep(1)
times = []
k = list()
r = list()
for i in range(25):
startTime = time.time()
userWord = input(str(i+1) + ". " + wordsList[i].capitalize() + " " )
k.append(wordsList[i].capitalize())
if (userWord.lower() == wordsList[i].lower()):
endTime = time.time()
times.append(endTime - startTime)
r[i] = str(endTime - startTime)
else:
times.append("Wrong Word")
r[i] = ("Wrong Word")
Above is where I am having a problem.
for i in range(25):
startTime = time.time()
print (str(i+1) + ". " + str(k[i]) + ": " + str(times[i]) )
a = 0
for i in range(25):
a = a+i
for i in range(25):
if r[i] == "Wrong Word":
r = r.pop(i)
b = (a/len(r))
c = round(b, 2)
print (c)
start = False
here is my error:
r[i] = "Wrong Word"
IndexError: list assignment index out of range
The pop() method removes an element from the list and returnes it (see an example). What I think is happening is that at some point the condition of the if statment resolves to true. Next, after calling r.pop(i) r is replaced by its i-th element. It's probpably a string so calling its (i+1)-th element later can result in Index out of range error.
In other words, something like this is happening:
r = ["a", "foo", "bar", "baz"]
for i in range(4):
if r[i] == "a": # for i=0 this gives "a" == "a"
r = r.pop(i) # later,this results in r = "a"
next loop iteration with i = 1 will result in "a"[1] which will result in Index out of range.
All in all instead of:
for i in range(25):
if r[i] == "Wrong Word":
r = r.pop(i)
you could just write:
r = [item for item in r if item != "Wrong word"]
which would be also more pythonic solution.

raw_input() invalid syntax

I want to input a string of five numbers with spaces between them and use raw_input() for it. However the second item(the portion that's between the first and second spaces) is claimed to be a syntax error. Code below:
#class for final output - used as an ad hoc static string
class StatString:
outstring = ""
#function to check if Boom or Trach or both
def BoomTrach(num,B,T):
Boom = False
Trach = False
temp = num
while temp != 0:
if num % B == 0:
Boom == True
break
if (temp % 10) % B == 0:
Boom = True
break
temp = (temp - temp % 10) / 10
temp = num
while temp != 0:
if num % T == 0:
Trach = True
break
if (temp % 10) % T == 0:
Trach = True
break
temp = (temp - temp % 10) / 10
if Boom and Trach:
herestring.outstring = herestring.outstring + "Boom-Trach"
elif Boom:
herestring.outstring = herestring.outstring + "Boom"
elif Trach:
herestring.outstring = herestring.outstring + "Trach"
else:
herestring.outstring = herestring.outstring + str(num)
#start of "main" portion
def main():
inS = raw_input() <<<--- Input here
arr = inS.split(' ')
X = int(arr[0])
Y = int(arr[1])
CountFrom = int(arr[2])
jump = int(arr[3])
CountUntil = int(arr[4])
#variable for error check
error = False
#checking for errors
if X < 1 or X > 9 or Y < 1 or Y > 9:
print "X and Y must be between 1 and 9"
error = True
if jump == 0:
print "jump cannot be 0"
error = True
elif (CountUntil - CountFrom) % jump != 0:
print "cannot jump from %d to %d",CountFrom,CountUntil
error = True
if error:
exit()
if CountFrom < 0 and CountUntil < 0 and jump > 0:
jump = jump * (-1)
herestring = StatString()
while CountFrom != CountUntil:
BoomTrach(CountFrom,X,Y)
CountFrom = CountFrom + jump
if(CountFrom != CountUntil):
herestring.outstring = herestring.outstring + ","
print herestring.outstring
error message: (the second 1 was marked as the source of the error)
>>> 1 1 1 1 1
SyntaxError: invalid syntax
>>>
I know what happened. You just run this module, and you thought that you start running it from the main function (like in C for example).
There is no problem with the raw_input line (the first line of the input). The problem is that your module does not try to read anything! You just typed "1 1 1 1 1" which is of course syntax error...
Append to your code this line to run the main function:
main()
You can also write the code of the main function not in some function, to get the same effect.

string comparision inside a file in python

I need to write a script in python for finding the output of line 7 which is "y" if my first line is true (6c00ff00 = 1). I am able capture all these values in a file (say "xyz") but I am unable to compare in the file.
>>> vi xyz
6c00ff00 = 1
6c01ff00 = BGSV 1
6c02ff00 = 08IS01191025
6c03ff00 = 192.11.13.5
7005ff00 = g430
e808ff00 = 249
6c0aff00 = y
7002ff00 = 35 .4 .0 /
7001ff00 = 0
7b00ff00 =
7100ff00 = 1
7003ff00 = 192.11.13.150
with open('xyz') as infile:
line1 = infile.readline().strip()
for _ in xrange(6):
line7 = infile.readline()
line7 = line7.strip()
print "The first line is '%s'" %line1
print "The seventh line is '%s'" %line7
if line1.split('=')[1].strip() == '1':
if line7.split('=')[1].strip() == 'y':
print "Correct"
else:
print "Wrong"