Runtime error in UVA Online Judge, Problem 839, Python - python

Problem
The program takes input that has information on mobiles (the kind that consists of wires and strings supsending weights). The program should check if the mobile is in equilibrium, that is the weight of the mobile is equal on both sides. Done by this equation weightLeft * distanceLeft = weightRight * distanceRight. However one mobiles weight on one side can be the result of another subMobile hanging below. So in the example that will be shown there is a whole "tree" of mobiles connected to one antoher.
More specific explanation here: https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=780
Example input
First line consists of how many testcases are to follow. Each line contaning numbers is a description of a mobile according to this templete (weightLeft, distanceLeft, weightRight, distanceLeft). If there is a zero on the weight value then the weight is the total weight of a submobile below. If a mobile has two zeros then both the weights come from different mobiles on the following lines, first the left then the right always.
5
0 2 0 4
0 3 0 1
1 2 1 1
2 4 4 2
1 6 3 2
0 2 0 4
0 3 0 1
2 1 1 1
2 4 4 2
1 6 3 2
0 2 0 4
0 3 0 1
1 1 1 1
2 4 4 2
1 6 3 2
0 2 0 4
0 3 0 1
1 1 1 1
2 4 4 2
1 6 3 2
0 2 0 4
0 3 0 1
1 1 1 1
2 4 4 2
1 6 3 2
My Code
My code is below and it does work acording to the input i typed my self according to the description (i think). No error, nothing wrong. But when i submit it to the online judge, it fails. I get a runtime error and a have no idea why. Anyone who could help my out would be much appreciated.
testcases = int(input())
input()
equal = True
def begin():
global equal
input_data = input().split()
left_side = int(input_data[0])
right_side = int(input_data[2])
if input_data[0] == '0':
left_side = begin()
if input_data[2] == '0':
right_side = begin()
if (left_side * int(input_data[1])) != (right_side * int(input_data[3])):
equal = False
return left_side + right_side
for x in range(testcases):
equal = True
begin()
if equal:
print("YES")
else:
print("NO")
print("")
input()

The Answer
After trying and playing around with the input i noticed that the program was reading input and printing at the end of the testcase no matter what. This caused problems at the end of the input because the very last row of the porgram reads input when there is no more input. So after making these changes to the code, i got the program accepted by the UVA Judge
for x in range(testcases):
equal = True
begin()
if equal:
print("YES")
else:
print("NO")
if not x == (testcases -1):
print()
input()

Related

Skip particular repetition in nested foor loop - Python

for k in range(8):
for i in range(2): #number of columns
for j in range(4): #number of row
print(k,j,i)
I want an output like this. no repetition of first for loop
k,j,i
-----
0 0 0
1 1 0
2 2 0
3 3 0
4 0 1
5 1 1
6 2 1
7 3 1
How I will achieve this?
Normally i would do
for i in range(8):
print(i, i%4, i%2)
Output:
0 0 0
1 1 1
2 2 0
3 3 1
4 0 0
5 1 1
6 2 0
7 3 1
But to reproduce your exact output:
for i in range(8):
print(i, i%4, int(i>3))
Output:
0 0 0
1 1 0
2 2 0
3 3 0
4 0 0
5 1 1
6 2 1
7 3 1
You can use if statements to say things like if k == 7 or something along those lines. This will only allow it to loop the first loop before moving on to the second loop.
Other answers have shown similar ways to produce your exact output, but this is another way to do it, and this would still work if you wanted the number of rows to be more than 8 and you wanted i to keep increasing
for i in range(8):
print(i, i%4, i//4)
I hope this is useful, sorry if it isn't
Looking at i and j, you have the cartesian product of {0,1} and {0,1,2,3}. You can compute that with itertools.product(range(2), range(4)), then use enumerate to number them for your k value.
from itertools import product
for k, (i, j) in enumerate(product(range(2), range(4))):
print(k, j, i)
Earlier arguments to product vary more slowly than later arguments.

Why does this Python nested for loop produce the output I get?

I'm very new to learning python, though I understand the basics of the looping, I am unable to understand the method in which output is arrived at.
In particular, how does the mapping of all three for loops happen to give the desired output, as I finding it impossible to understand the logic to be applied, when I try to write the output on paper without referring to IDE.
Code:
n = 4
a = 3
z = 2
for i in range(n):
for j in range(a):
for p in range(z):
print(i, j, p)
Output is:
0 0 0
0 0 1
0 1 0
0 1 1
0 2 0
0 2 1
1 0 0
1 0 1
1 1 0
1 1 1
1 2 0
1 2 1
2 0 0
2 0 1
2 1 0
2 1 1
2 2 0
2 2 1
3 0 0
3 0 1
3 1 0
3 1 1
3 2 0
3 2 1
The first loop iterates four times.
The second loop iterates three times. However since it is embedded inside the first loop, it actually iterates twelve times (4 * 3.)
The third loop iterates two times. However since it is embedded inside the first and second loops, it actually iterates twenty-four times (4 * 3 * 2).

Finding contiguous, non-unique slices in Pandas series without iterating

I'm trying to parse a logfile of our manufacturing process. Most of the time the process is run automatically but occasionally, the engineer needs to switch into manual mode to make some changes and then switches back to automatic control by the reactor software. When set to manual mode the logfile records the step as being "MAN.OP." instead of a number. Below is a representative example.
steps = [1,2,2,'MAN.OP.','MAN.OP.',2,2,3,3,'MAN.OP.','MAN.OP.',4,4]
ser_orig = pd.Series(steps)
which results in
0 1
1 2
2 2
3 MAN.OP.
4 MAN.OP.
5 2
6 2
7 3
8 3
9 MAN.OP.
10 MAN.OP.
11 4
12 4
dtype: object
I need to detect the 'MAN.OP.' and make them distinct from each other. In this example, the two regions with values == 2 should be one region after detecting the manual mode section like this:
0 1
1 2
2 2
3 Manual_Mode_0
4 Manual_Mode_0
5 2
6 2
7 3
8 3
9 Manual_Mode_1
10 Manual_Mode_1
11 4
12 4
dtype: object
I have code that iterates over this series and produces the correct result when the series is passed to my object. The setter is:
#step_series.setter
def step_series(self, ss):
"""
On assignment, give the manual mode steps a unique name. Leave
the steps done on recipe the same.
"""
manual_mode = "MAN.OP."
new_manual_mode_text = "Manual_Mode_{}"
counter = 0
continuous = False
for i in ss.index:
if continuous and ss.at[i] != manual_mode:
continuous = False
counter += 1
elif not continuous and ss.at[i] == manual_mode:
continuous = True
ss.at[i] = new_manual_mode_text.format(str(counter))
elif continuous and ss.at[i] == manual_mode:
ss.at[i] = new_manual_mode_text.format(str(counter))
self._step_series = ss
but this iterates over the entire dataframe and is the slowest part of my code other than reading the logfile over the network.
How can I detect these non-unique sections and rename them uniquely without iterating over the entire series? The series is a column selection from a larger dataframe so adding extra columns is fine if needed.
For the completed answer I ended up with:
#step_series.setter
def step_series(self, ss):
pd.options.mode.chained_assignment = None
manual_mode = "MAN.OP."
new_manual_mode_text = "Manual_Mode_{}"
newManOp = (ss=='MAN.OP.') & (ss != ss.shift())
ss[ss == 'MAN.OP.'] = 'Manual_Mode_' + (newManOp.cumsum()-1).astype(str)
self._step_series = ss
Here's one way:
steps = [1,2,2,'MAN.OP.','MAN.OP.',2,2,3,3,'MAN.OP.','MAN.OP.',4,4]
steps = pd.Series(steps)
newManOp = (steps=='MAN.OP.') & (steps != steps.shift())
steps[steps=='MAN.OP.'] += seq.cumsum().astype(str)
>>> steps
0 1
1 2
2 2
3 MAN.OP.1
4 MAN.OP.1
5 2
6 2
7 3
8 3
9 MAN.OP.2
10 MAN.OP.2
11 4
12 4
dtype: object
To get the exact format you listed (starting from zero instead of one, and changing from "MAN.OP." to "Manual_mode_"), just tweak the last line:
steps[steps=='MAN.OP.'] = 'Manual_Mode_' + (seq.cumsum()-1).astype(str)
>>> steps
0 1
1 2
2 2
3 Manual_Mode_0
4 Manual_Mode_0
5 2
6 2
7 3
8 3
9 Manual_Mode_1
10 Manual_Mode_1
11 4
12 4
dtype: object
There a pandas enhancement request for contiguous groupby, which would make this type of task simpler.
There is s function in matplotlib that takes a boolean array and returns a list of (start, end) pairs. Each pair represents a contiguous region where the input is True.
import matplotlib.mlab as mlab
regions = mlab.contiguous_regions(ser_orig == manual_mode)
for i, (start, end) in enumerate(regions):
ser_orig[start:end] = new_manual_mode_text.format(i)
ser_orig
0 1
1 2
2 2
3 Manual_Mode_0
4 Manual_Mode_0
5 2
6 2
7 3
8 3
9 Manual_Mode_1
10 Manual_Mode_1
11 4
12 4
dtype: object

Listing distributions in Python

I have a sheet of numbers, separated by spaces into columns. Each column represents a different category, and within each column, each number represents a different value. For example, column number four represents age, and within the column, the number 5 represents an age of 44-55. Obviously, each row is a different person's record. I'd like to use a Python script to search through the the sheet, and find all columns where the sixth column is number "1." After that, I want to know how many times each number in column one appears where the number in column six is equal to "1." The script should output to the user that "While column six equals '1', the value '1' appears 12 times in column one. The value '2' appears 18 times..." etc. I hope I'm being clear here. I just want it to list the numbers, basically. Anyway, I'm new to Python. I've attached my code below. I think I should be using dictionaries, but I'm just not totally sure how. So far, I haven't really come close to figuring this out. I would really appreciate if someone could walk me through the logic that would be behind such code. Thank you so much!
ldata = open("list.data", "r")
income_dist = {}
for line in ldata:
linelist = line.strip().split(" ")
key_income_dist = linelist[6]
if key_income_dist in income_dist:
income_dist[key_income_dist] = 1 + income_dist[key_income_dist]
else:
income_dist[key_income_dist] = 1
ldata.close()
print value_no_occupations
First, indentation is majorly important in Python and the above is bad: the 5 lines following linelist = line.strip().split(" ") need to be indented to be in the loop like they should be.
Next they should be indented further and this line added before them:
if len(linelist)>6 and linelist[6]=="1":
This line skips over short lines (there are some), and tests for what you said you wanted: "where column six equals "1."" This is column [6] where the first number on the line is referenced as [0] (these are "offsets", not "cardinal", or counting, numbers).
You'll probably want to change key_income_dist = linelist[6] to key_income_dist = linelist[0] or [1] to get what you want. Play around if necessary.
Finally, you should say print income_dist at the end to get a look at your results. If you want fancier output, study up on formatting.
This is actually easier than it seems! The key is collections.Counter
from collections import Counter
ldata = open("list.data")
rows = [tuple(row.split()) for row in ldata if row.split()[5]==1]
# warning this will break if some rows are shorter than 6 columns
first_col = Counter(item[0] for item in rows)
If you want the distribution of every column (not just the first) do:
distribution = {column: Counter(item[column] for item in rows) for column in range(len(rows[0]))}
# warning this will break if all rows are not the same size!
Considering that the data file has ~9000 rows of data, if you don't want to keep the original data, you can combine step 1 & 2 to make the program use less memory and a little faster.
ldata = open("list.data", "r")
# read in all the rows, note that the list values are strings instead of integers
# keep only the rows with 6th column = '1'
only1 = []
for line in ldata:
if line.strip() == '': # ignor blank lines
continue
row = tuple(line.strip().split(" "))
if row[5] == '1':
only1.append(row)
ldata.close()
# tally the statistics
income_dist = {}
for row in only1:
if row[0] in income_dist:
income_dist[row[0]] += 1
else:
income_dist[row[0]] = 1
# print result
print "While column six equals '1',"
for num in sorted(income_dist):
print "the value %s appears %d times in column one." % (num, income_dist[num])
Sample Test Data in list.data:
9 2 1 5 4 5 5 3 3 0 1 1 7 NA
9 1 1 5 5 5 5 3 5 2 1 1 7 1
9 2 1 3 5 1 5 2 3 1 2 3 7 1
1 2 5 1 2 6 5 1 4 2 3 1 7 1
1 2 5 1 2 6 3 1 4 2 3 1 7 1
8 1 1 6 4 8 5 3 2 0 1 1 7 1
1 1 5 2 3 9 4 1 3 1 2 3 7 1
6 1 3 3 4 1 5 1 1 0 2 3 7 1
2 1 1 6 3 8 5 3 3 0 2 3 7 1
4 1 1 7 4 8 4 3 2 0 2 3 7 1
1 1 5 2 4 1 5 1 1 0 2 3 7 1
4 2 2 2 3 2 5 1 2 0 1 1 5 1
8 2 1 3 6 6 2 2 4 2 1 1 7 1
7 2 1 5 3 5 5 3 4 0 2 1 7 1
1 1 5 2 3 9 4 1 3 1 2 3 7 1
6 1 3 3 4 1 5 1 1 0 2 3 7 1
2 1 1 6 3 8 5 3 3 0 2 3 7 1
4 1 1 7 4 8 4 3 2 0 2 3 7 1
1 1 5 2 4 9 5 1 1 0 2 3 7 1
4 2 2 2 3 2 5 1 2 0 1 1 5 1
Following your original program logic, I come up with this version:
ldata = open("list.data", "r")
# read in all the rows, note that the list values are strings instead of integers
linelist = []
for line in ldata:
linelist.append(tuple(line.strip().split(" ")))
ldata.close()
# keep only the rows with 6th column = '1'
only1 = []
for row in linelist:
if row[5] == '1':
only1.append(row)
# tally the statistics
income_dist = {}
for row in only1:
if row[0] in income_dist:
income_dist[row[0]] += 1
else:
income_dist[row[0]] = 1
# print result
print "While column six equals '1',"
for num in sorted(income_dist):
print "the value %s appears %d times in column one." % (num, income_dist[num])

Writing Sudoku Solver wih Python

Here is my Sudoku Solver written in python language, When I run this program there seems to be a problem with in Update function and Solve function.
No matter how much time I look over and move the codes around, I seem to have no luck
Can anyone Help me?
import copy
def display (A):
if A:
for i in range (9):
for j in range (9):
if type (A[i][j]) == type ([]): print A[i][j][0],
else: print A[i][j]
print
print
else: print A
def has_conflict(A):
for i in range(9):
for j in range(9):
for (x,y) in get_neighbors(i,j):
if len(A[i][j])==1 and A[i][j]==A[x][y]: return True
return False
def get_neighbors(x,y):
neighbors = []
for i in range(3):
for j in range(3):
a = 3*(x / 3)+i
b = 3*(y / 3)+j
if (x,y) != (a,b):
neighbors += [(a,b)]
for i in range(9):
if (x,y) != (x,i) and (x,i) not in neighbors:
neighbors += [(x,i)]
if (x,y) != (i,y) and (i,y) not in neighbors:
neighbors += [(i,y)]
return neighbors
def update(A,x,y,value):
B = copy.deepcopy(A)
B[x][y] = [value]
for (i,j) in get_neighbors(x,y):
if B[i][j] == B[x][y]:
if len(B[i][j]) > 1: B[i][j].remove(value)
else: return []
if has_conflict(B) == True: return []
else: return B
def solve(A):
for x in range (9):
for y in range(9):
if len(A[x][y]) == 1: return A[x][y]
if len(A[x][y]) > 1:
lst = update(A,x,y,A[x][y])
if len(lst[x][y]) > 1: solve(lst)
if lst == []: return []
if len(lst[x][y]) == 1: return lst
else: return A[x][y]
A=[]
infile = open('puzzle1.txt','r')
for i in range(9):
A += [[]]
for j in range(9):
num = int(infile.read(2))
if num: A[i] += [[num]]
else: A[i] += [[1,2,3,4,5,6,7,8,9]]
for i in range(9):
for j in range(9):
if len(A[i][j])==1: A = update(A, i, j, A[i][j][0])
if A == []: break
if A==[]: break
if A<>[]: A = solve(A)
display(A)
Here are some puzzles:
Puzzle 1
0 0 0 2 6 0 7 0 1
6 8 0 0 7 0 0 9 0
1 9 0 0 0 4 5 0 0
8 2 0 1 0 0 0 4 0
0 0 4 6 0 2 9 0 0
0 5 0 0 0 3 0 2 8
0 0 9 3 0 0 0 7 4
0 4 0 0 5 0 0 3 6
7 0 3 0 1 8 0 0 0
Puzzle 2
1 0 0 4 8 9 0 0 6
7 3 0 0 0 0 0 4 0
0 0 0 0 0 1 2 9 5
0 0 7 1 2 0 6 0 0
5 0 0 7 0 3 0 0 8
0 0 6 0 9 5 7 0 0
9 1 4 6 0 0 0 0 0
0 2 0 0 0 0 0 3 7
8 0 0 5 1 2 0 0 4
Puzzle 3
0 2 0 6 0 8 0 0 0
5 8 0 0 0 9 7 0 0
0 0 0 0 4 0 0 0 0
3 7 0 0 0 0 5 0 0
6 0 0 0 0 0 0 0 4
0 0 8 0 0 0 0 1 3
0 0 0 0 2 0 0 0 0
0 0 9 8 0 0 0 3 6
0 0 0 3 0 6 0 9 0
I would avoid things like "move the codes around". This is called "Programming by Coincidence" (see The Pragmatic Programmer). Programming like this won't make you a better programmer.
Instead, you should take out a paper and pencil, and start thinking how things should work. Then, read the code and carefully write what it actually does. Only when you understand, go back to the computer terminal.
If you want to stabilize your code, then write small test cases for each function which make sure that they work correctly.
In your case, run a puzzle, and determine which field is wrong. Then guess which function might produce the wrong output. Call it with the input to see what it really does. Repeat for every bug you find.
[EDIT] The module unittest is your friend.
I'd like to help you in a way that you can write the actual code, so here is some explanation, and some pseudo-code.
Those sudoku solvers that don't mimic human deduction logic are bruteforce-based. Basically, you'll need a backtrack algorithm. You have your has_conflict method, which checks whether the candidate is ok at first look. Then you write the backtrack algorithm like this:
Solve(s):
Pick a candidate.
Does it have a conflict? If yes, go back, and pick another one.
No more empty cells? Then cool, return True.
Have you run out of candidates? Then it cant be solved, return False.
At this point, it seems ok. So call Solve(s) again, lets see how it works
out with the new candidate.
If Solve returned false, then after all it was a bad candidate. Go
back to picking another one.
If Solve returned True, then you solved the sudoku!
The main idea here is that if your guess was wrong, despite not having a conflict at first look, then a confliction will reveal itself somewhere deeper in the call tree.
The original sudokus have only one solution. You can extend this method to different solutions for sudokus that have them by trying any candidates despite the return value of Solve (but that will be very slow with this approach).
There's a nice trick to find out if a sudoku has more than one solutions. First try the candidates in natural order in every call of solve. Then try them backwards. Then do these two steps again, but this time run the algorithm from the last cell of the sudoku, stepping backwards. If these four solutions are identical, then it has only one solution. Unfortunately I don't have a formal proof, but it seemed to work all the time. I tried to prove it, but I'm not that great with graphs.
Solving sudoku need some bruteforcing method, I dont see those in your codes.
I also tried to do before, but finally I saw norvig's codes, its just working perfect.
and ended up with learning his codes finally.

Categories

Resources