This is an ICPC online round question. I checked sample input and my own imaginary inputs.
This is link to question
Here is my code. This code is in Python.
for _ in range(int(input())):
x1,y1,x2,y2=map(int,input().split())
if (x2-x1==y2-y1)or((x2-x1!=0)and(y2-y1!=0)):
print('sad')
elif (x2-x1==0 and y2-y1>0):
print('up')
elif (x2-x1==0 and y2-y1<0):
print('down')
elif (y2 - y1 == 0 and x2 - x1 > 0):
print('right')
elif (y2 - y1 == 0 and x2 - x1 < 0):
print('left')
Can anyone suggest inputs for that code will not work?? If code is correct for all inputs , any modification will be welcomed?.
Your code already does not parse the input correctly. Have a look:
python /tmp/test.py
1
0 0 0 1
Traceback (most recent call last):
File "/tmp/test.py", line 3, in <module>
x1, y1, x2, y2 = map(int, input().split())
File "<string>", line 1
0 0 0 1
^
Besides from that, it seems to be logical correct.
However, your coding style is improvable. Have a look at my version:
for _ in range(int(input())):
x1, y1, x2, y2 = map(int, input().split())
if x1 != x2 and y1 != y2:
print('sad')
elif x1 == x2 and y1 < y2:
print('up')
elif x1 == x2 and y1 > y2:
print('down')
elif y1 == y2 and x1 < x2:
print('right')
elif y1 == y2 and x1 > x2:
print('left')
The only thing I changed was to improve the conditions. Furthermore, I removed the redundant condition at the bottom.
As a former participant of NWERC and ACM-ICPC I can only suggest to have an eye on readable code. It is not as important as in production code bases, but it helps a lot when you have to debug printed code, as happens at real competitions.
Related
I just had to write a function that seemed simple to write, but when I actually did it, it turned out way gorier than I had expected. It's really bugging me, I feel like there's a better solution, but my brain is going crazy trying to think of it, so therefore I'm turning to you fine folks.
Basically, I have 2 triangles, and I want to know if they share a common edge. The triangles are indexed by their vertices (i.e. their vertices is just an index to an array containing the actual coordinates), so it comes down to finding if two sets of three numbers have two numbers in common. I.e. triangles (1,2,3) and (3,1,5) do share an edge, the (1,3) edge. However, triangles (1,2,3) and (1,5,6) does not share an edge (only a vertex) and neither does (1,2,3) and (4,5,6).
How would you write this "two numbers in common function"? You can assume all values inside each set are distinct (i.e. (1, 1, 2) is not going to be an input) and you can also assume that two sets don't equal each other (i.e. I'm not going to compare (1,2,3) and (1,3,2), because those two are the same triangle). However, no assumptions can be made regarding order, they are not sorted or anything like that.
This is basically what I came up with (assuming the sets are (x0, x1, x2) and (y0, y1, y2)):
// If the x0 is equal to any of (y0, y1, y2), make sure at least one of (x1, x2)
// is equal to one of the y numbers
if (x0 == y0) {
return x1 == y1 || x1 == y2 || x2 == y1 || x2 == y2;
} else if (x0 == y1) {
return x1 == y0 || x1 == y2 || x2 == y0 || x2 == y2;
} else if (x0 == y2) {
return x1 == y0 || x1 == y1 || x2 == y0 || x2 == y1;
} else {
// if x0 is not equal to any of (y0, y1, y2), then x1 and x2 both have
// to be equal to two of the y numbers.
return (x1 == y0 && x2 == y1)
|| (x1 == y0 && x2 == y2)
|| (x1 == y1 && x2 == y0)
|| (x1 == y1 && x2 == y2)
|| (x1 == y2 && x2 == y0)
|| (x1 == y2 && x2 == y1);
}
but it feels so gory to me! So many branches and such long boolean statements! I feel like i'm missing an obvious easy solution, and it's driving me insane.
In addition, this happens in an inner loop in a very performance sensitive application, so performance (branching, arithmetic, whatever) matters.
BTW, the code I'm writing is C#, but the question is the same in more or less any imperative language.
EDIT:
I put together a quick benchmark (here's the code) with the suggestions so far. Here are the results (running it at a million random pairs of triangles):
Original method result: 7035, time elapsed in ms: 8.6252
qwertyman method result: 7035, time elapsed in ms: 8.2537
midjji method result: 7035, time elapsed in ms: 8.7984
Single HashSet method result: 7035, time elapsed in ms: 184.4984
Many HashSets method result: 7035, time elapsed in ms: 190.5785
The numbers remain fairly consistent run to run, with #qwertyman's method always being a bit faster than my original version or #midjii's. It also has the advantage of being the cleanest and nicest of them all, so I'm going to go with that one.
I was actually a bit surprised that the "Many HashSets" was so close to "Single HashSet", I would have thought constructing a million HashSets would have a bigger overhead than around 16 milliseconds (though this obviously doesn't count the increased pressure on the garbage collector), though they're both obviously far behind the other methods.
Thanks for the help!
You can do something like this:
int n = 0;
// check if x0 is among the values in the second set
if (x0 == y0 || x0 == y1 || x0 == y2) {
n++;
}
// check if x1 is among the values in the second set
if (x1 == y0 || x1 == y1 || x1 == y2) {
n++;
}
// check if x2 is among the values in the second set
if (x2 == y0 || x2 == y1 || x2 == y2) {
n++;
}
return n >= 2;
This relies on the fact that (as you mentioned) the numbers in each set are distinct, resulting in a simpler logic.
If you are using C, you could write it shorter:
int n = 0;
n += x0 == y0 || x0 == y1 || x0 == y2;
n += x1 == y0 || x1 == y1 || x1 == y2;
n += x2 == y0 || x2 == y1 || x2 == y2;
return n >= 2;
I would use:
...
{
//ti= xi in y
bool t0= (x0==y0) ||(x0==y1)|| (x0==y2);
bool t1= (x1==y0) ||(x1==y1)|| (x1==y2);
bool t2= (x2==y0) ||(x2==y1)|| (x2==y2);
return (t0 && t1) || (t0 && t2) || (t1 && t2);
}
Mostly because I think its easier to read.
Performance-wise it is rather likely that with the right settings it should be as fast. Compilers are fantastic at optimizing self enclosed, no side effect, logical statements and use lazy evaluation for bool(assuming nothing silly has been done to ==).
When drawing a line with Bresenham line drawing algorithm,
where the line may not be within the bounds of the bitmap being written to - it would be useful to clip the results so they fit within the axis aligned bounds of the image being written to.
While its possible to first clip the line to the rectangle, then draw the line. This isn't ideal since it often gives a slightly different slant to the line (assuming int coords are being used).
Since this is such a primitive operation, are there established methods for clipping the line while maintaining the same shape?
In case it helps, here is a reference implementation of the algorithm - it uses int coords, which avoids int/float conversion while drawing the line.
I spent some time looking into this:
Problem is described in detail on virtual-dub's web page.
Possible solution from Alan Tiedemann... though I'd need to implement code based on the text - to see how well it works.
Bresenham's Line Generation Algorithm with Built-in Clipping(paper from 1995, couldn't find the entire document? - PDF is a single page without the C code it references, looks like its pay-walled).
Let's reframe the problem so we can see how Bresenham's algorithm really works...
Lets say you are drawing a mostly horizontal line (the method is the same for mostly vertical, but with the axes switched) from (x0,y0) to (x1,y1):
The full line can be described as a function of y in terms of x (all integers):
y = y0 + round( (x-x0) * (y1-y0) / (x1-x0) )
This describes precisely each pixel you will paint when drawing the full line, and when you clip the line consistently, it still describes precisely each pixel you will paint -- you just apply it to a smaller range of x values.
We can evaluate this function using all integer math, by calculating the divisor and remainder separately. For x1 >= x0 and y1 >= y0 (do the normal transformations otherwise):
let dx = (x1-x0);
let dy = (y1-y0);
let remlimit = (dx+1)/2; //round up
rem = (x-x0) * dy % dx;
y = y0 + (x-x0) * dy / dx;
if (rem >= remlimit)
{
rem-=dx;
y+=1;
}
Bresenham's algorithm is a just a fast way to update the result of this formula incrementally as you update x.
Here's how we can make use of incremental updates to draw the portion of the very same line from x=xs to x=xe:
let dx = (x1-x0);
let dy = (y1-y0);
let remlimit = (dx+1)/2; //round up
x=xs;
rem = (x-x0) * dy % dx;
y = y0 + (x-x0) * dy / dx;
if (rem >= remlimit)
{
rem-=dx;
y+=1;
}
paint(x,y);
while(x < xe)
{
x+=1;
rem+=dy;
if (rem >= remlimit)
{
rem-=dx;
y+=1;
}
paint(x,y);
}
If you want do to your remainder comparisons against 0, you can just offset it at the beginning:
let dx = (x1-x0);
let dy = (y1-y0);
let remlimit = (dx+1)/2; //round up
x=xs;
rem = ( (x-x0) * dy % dx ) - remlimit;
y = y0 + (x-x0) * dy / dx;
if (rem >= 0)
{
rem-=dx;
y+=1;
}
paint(x,y);
while(x < xe)
{
x+=1;
rem+=dy;
if (rem >= 0)
{
rem-=dx;
y+=1;
}
paint(x,y);
}
Bresenham's algorithm can be used, taking clipping values into account, based on the paper by Kuzmin & Yevgeny P:
For completeness, here is a working version of the algorithm, a single Python function, though its only using integer arithmetic - so can be easily ported to other languages.
def plot_line_v2v2i(
p1, p2, callback,
clip_xmin, clip_ymin,
clip_xmax, clip_ymax,
):
x1, y1 = p1
x2, y2 = p2
del p1, p2
# Vertical line
if x1 == x2:
if x1 < clip_xmin or x1 > clip_xmax:
return
if y1 <= y2:
if y2 < clip_ymin or y1 > clip_ymax:
return
y1 = max(y1, clip_ymin)
y2 = min(y2, clip_ymax)
for y in range(y1, y2 + 1):
callback(x1, y)
else:
if y1 < clip_ymin or y2 > clip_ymax:
return
y2 = max(y2, clip_ymin)
y1 = min(y1, clip_ymax)
for y in range(y1, y2 - 1, -1):
callback(x1, y)
return
# Horizontal line
if y1 == y2:
if y1 < clip_ymin or y1 > clip_ymax:
return
if x1 <= x2:
if x2 < clip_xmin or x1 > clip_xmax:
return
x1 = max(x1, clip_xmin)
x2 = min(x2, clip_xmax)
for x in range(x1, x2 + 1):
callback(x, y1)
else:
if x1 < clip_xmin or x2 > clip_xmax:
return
x2 = max(x2, clip_xmin)
x1 = min(x1, clip_xmax)
for x in range(x1, x2 - 1, -1):
callback(x, y1)
return
# Now simple cases are handled, perform clipping checks.
if x1 < x2:
if x1 > clip_xmax or x2 < clip_xmin:
return
sign_x = 1
else:
if x2 > clip_xmax or x1 < clip_xmin:
return
sign_x = -1
# Invert sign, invert again right before plotting.
x1 = -x1
x2 = -x2
clip_xmin, clip_xmax = -clip_xmax, -clip_xmin
if y1 < y2:
if y1 > clip_ymax or y2 < clip_ymin:
return
sign_y = 1
else:
if y2 > clip_ymax or y1 < clip_ymin:
return
sign_y = -1
# Invert sign, invert again right before plotting.
y1 = -y1
y2 = -y2
clip_ymin, clip_ymax = -clip_ymax, -clip_ymin
delta_x = x2 - x1
delta_y = y2 - y1
delta_x_step = 2 * delta_x
delta_y_step = 2 * delta_y
# Plotting values
x_pos = x1
y_pos = y1
if delta_x >= delta_y:
error = delta_y_step - delta_x
set_exit = False
# Line starts below the clip window.
if y1 < clip_ymin:
temp = (2 * (clip_ymin - y1) - 1) * delta_x
msd = temp // delta_y_step
x_pos += msd
# Line misses the clip window entirely.
if x_pos > clip_xmax:
return
# Line starts.
if x_pos >= clip_xmin:
rem = temp - msd * delta_y_step
y_pos = clip_ymin
error -= rem + delta_x
if rem > 0:
x_pos += 1
error += delta_y_step
set_exit = True
# Line starts left of the clip window.
if not set_exit and x1 < clip_xmin:
temp = delta_y_step * (clip_xmin - x1)
msd = temp // delta_x_step
y_pos += msd
rem = temp % delta_x_step
# Line misses clip window entirely.
if y_pos > clip_ymax or (y_pos == clip_ymax and rem >= delta_x):
return
x_pos = clip_xmin
error += rem
if rem >= delta_x:
y_pos += 1
error -= delta_x_step
x_pos_end = x2
if y2 > clip_ymax:
temp = delta_x_step * (clip_ymax - y1) + delta_x
msd = temp // delta_y_step
x_pos_end = x1 + msd
if (temp - msd * delta_y_step) == 0:
x_pos_end -= 1
x_pos_end = min(x_pos_end, clip_xmax) + 1
if sign_y == -1:
y_pos = -y_pos
if sign_x == -1:
x_pos = -x_pos
x_pos_end = -x_pos_end
delta_x_step -= delta_y_step
while x_pos != x_pos_end:
callback(x_pos, y_pos)
if error >= 0:
y_pos += sign_y
error -= delta_x_step
else:
error += delta_y_step
x_pos += sign_x
else:
# Line is steep '/' (delta_x < delta_y).
# Same as previous block of code with swapped x/y axis.
error = delta_x_step - delta_y
set_exit = False
# Line starts left of the clip window.
if x1 < clip_xmin:
temp = (2 * (clip_xmin - x1) - 1) * delta_y
msd = temp // delta_x_step
y_pos += msd
# Line misses the clip window entirely.
if y_pos > clip_ymax:
return
# Line starts.
if y_pos >= clip_ymin:
rem = temp - msd * delta_x_step
x_pos = clip_xmin
error -= rem + delta_y
if rem > 0:
y_pos += 1
error += delta_x_step
set_exit = True
# Line starts below the clip window.
if not set_exit and y1 < clip_ymin:
temp = delta_x_step * (clip_ymin - y1)
msd = temp // delta_y_step
x_pos += msd
rem = temp % delta_y_step
# Line misses clip window entirely.
if x_pos > clip_xmax or (x_pos == clip_xmax and rem >= delta_y):
return
y_pos = clip_ymin
error += rem
if rem >= delta_y:
x_pos += 1
error -= delta_y_step
y_pos_end = y2
if x2 > clip_xmax:
temp = delta_y_step * (clip_xmax - x1) + delta_y
msd = temp // delta_x_step
y_pos_end = y1 + msd
if (temp - msd * delta_x_step) == 0:
y_pos_end -= 1
y_pos_end = min(y_pos_end, clip_ymax) + 1
if sign_x == -1:
x_pos = -x_pos
if sign_y == -1:
y_pos = -y_pos
y_pos_end = -y_pos_end
delta_y_step -= delta_x_step
while y_pos != y_pos_end:
callback(x_pos, y_pos)
if error >= 0:
x_pos += sign_x
error -= delta_y_step
else:
error += delta_x_step
y_pos += sign_y
Example use:
plot_line_v2v2i(
# two points
(10, 2),
(90, 88),
# callback
lambda x, y: print(x, y),
# xy min
25, 25,
# xy max
75, 75,
)
Notes:
Clipping min/max values are inclusive(so max values should be image_width - 1, image_height - 1)
Integer divisions // is used everywhere.
Many languages (C/C++ for example) use floored rounding on division.See Fast floor of a signed integer division in C / C++ to avoid having slightly biased results with those languages.
There are some improvements over the code provided in the paper:
The line will always plot in the direction defined (from p1 to p2).
There was sometimes a subtle difference in the line gradient, so that rotating of flipping the points, calculating the line, then transforming back - would give slightly different results. The asymmetry was caused by the code swapping the X and Y axis to avoid code duplication.
For tests and more example usage, see:
The Python repository.
Rust version.
Basically I am generating numbers and they can't be equal to any other numbers I've generated. Is there a quicker way to do this because it looks slightly ridiculous.
Thanks
#possible generated values
x1 = 0
x2 = 1
x3 = 2
#generate co-ordinates
x4 = rand(7)
until x4 != x1 && x4 != x1+1 && x4 != x1+2 && x4 != x2 && x4 != x2+1 && x4 != x2+2 && x4 != x3 && x4 != x3+1 && x4 != x3+2 do
x4 = rand(7)
end
#possible generated values
y1 = 0
y2 = 1
y3 = 2
y4 = rand(7)
until y4 != y1 && y4 != y1+1 && y4 != y1+2 && y4 != y2 && y4 != y2+1 && y4 != y2+2 && y4 != y3 && y4 != y3+1 && y4 != y3+2 do
y4 = rand(7)
end
For Ruby 1.9+
(0..6).to_a.sample(x)
or for older versions
(0..6).to_a.shuffle.take(x)
where x is the number of integers you want to take. Since rand(7) does not include the number 7, you need your range to be one less than the number you'd pass to rand.
And obviously you can't take more numbers than are in the range.
Related to my previous question, just wonder how to solve a system of linear equations with non-negative integral solutions, for example:
c11*x+c12*y+c13*z=d1
c21*x+c22*y+c23*z=d2
Thanks a lot!
Edit
I meant efficiently. For example, I could have used FrobeniusSolve to get two solution lists and try to find the intersection. But sometimes, the individual solution list is probably hugely large. Or try to verify each individual solution returned by one FrobeniusSolve to see whether they satisfy all the remaining equations, but that suffers from the same drawback.
Reduce is able to solve these types of problems.
To answer the specific case in your comment above:
In[1]:= solns = Reduce[x1 + 2 x2 + 5 x3 + 7 x4 == 40 &&
x1 + x2 + 2 x3 + x4 == 20 &&
x1 > 0 && x2 > 0 && x3 > 0 && x4 > 0,
{x1, x2, x3, x4}, Integers]
Out[1]= (x1 == 6 && x2 == 11 && x3 == 1 && x4 == 1) ||
(x1 == 7 && x2 == 8 && x3 == 2 && x4 == 1) ||
(x1 == 8 && x2 == 5 && x3 == 3 && x4 == 1) ||
(x1 == 9 && x2 == 2 && x3 == 4 && x4 == 1) ||
(x1 == 11 && x2 == 5 && x3 == 1 && x4 == 2) ||
(x1 == 12 && x2 == 2 && x3 == 2 && x4 == 2)
Edit:
You can check that this is the same solution you get by solving the two equations separately and taking the intersection of their solutions:
In[2]:= a = Reduce[x1 + 2 x2 + 5 x3 + 7 x4 == 40 &&
x1 > 0 && x2 > 0 && x3 > 0 && x4 > 0,
{x1, x2, x3, x4}, Integers];
b = Reduce[x1 + x2 + 2 x3 + x4 == 20 &&
x1 > 0 && x2 > 0 && x3 > 0 && x4 > 0,
{x1, x2, x3, x4}, Integers];
In[4]:= solns == Intersection[a, b]
Out[4]= True
And you can extract the solutions by, e.g.,
turning the solutions into a list of replacement rules
and applying to the variables:
In[5]:= {x1, x2, x3, x4} /. {ToRules[solns]}
Out[5]= {{6, 11, 1, 1}, {7, 8, 2, 1}, {8, 5, 3, 1},
{9, 2, 4, 1}, {11, 5, 1, 2}, {12, 2, 2, 2}}
I have a set of inequalities, for example,
2 x1 >=3 x2 && 0<=x1<=1 && 0<=x2<=1
which can be solved with Reduce. Then I want to do an integration for the function f(x1,x2)=1/x1 in the area defined by the inequalities above. In this case, Reduce gives a result
(x1 == 0 && x2 == 0) || (0 < x1 <= 1 && 0 <= x2 <= (2 x1)/3)
Then I can do integration by using
Integrate[Integrate[1/x1, {x2, 0, 2 x1/3}], {x1, 0, 1}]
But these all need my manual intervention. How do I do this in a streamline fashion? Many thanks!
Integrate[1/x1 Boole[2 x1 >= 3 x2 && 0 <= x1 <= 1 &&0 <= x2 <= 1], {x1, -\[Infinity], \[Infinity]}, {x2, -\[Infinity], \[Infinity]}]