Multiple != versus == operators - python-3.6

The following program works exactly as expected:
data = input("Input the length of three sides of a triangle: ").strip()
if data.count(',') != 2:
print("You did not enter the lengths of three sides: ")
a, b, c = data.split(', ')
def triangle_type(s1, s2, s3):
if s1 == s2 == s3:
return print("The values entered represent an equilateral triangle.")
elif s1 != s2 and s1 != s3 and s2 != s3:
return print("The values entered represent a scalene triangle.")
else:
if s1 == s2 or s1 == s3 or s2 == s3:
return print("The values entered represent an isosceles triangle.")
triangle_type(int(a), int(b), int(c))
However, if I change the second condition to the following:
elif s1 != s2 != s3:
it does NOT work as expected.
If I input 3, 6, 3 I get:
Input the length of three sides of a triangle: 3, 6, 3
The values entered represent a scalene triangle.
This is incorrect. This should clearly match condition #3 (isosceles).
It works correctly with the first version of the code.
I am confused on two things:
1) Why does the second version work improperly?
2) If the second version is invalid, then why does the first condition work
correctly?
Given the above behavior with the != operator, I would expect to have to treat a == b == c like a == b and a == c and b == c, but I don't have to.

When you chain comparisons in Python, it ands them together, and it only does as many comparisons as you have comparison operators. So
if s1 == s2 == s3:
is equivalent to
if s1 == s2 and s2 == s3:
That works because if both of those conditions are True, then s1 must also be equal to s3 (because they're both equal to s2).
However
if s1 != s2 != s3:
is equivalent to
if s1 != s2 and s2 != s3:
As you've discovered, for the values 3, 6, and 3, the above two conditions are True, but the third assumed condition (s1 != s3) is not True. This doesn't work as you expect because Python isn't making that third comparison.

The chained version is equivalent to s1 != s2 and s2 != s3; it does not require that s1 != s3, because inequality is not transitive.

Related

The game with the marbles

Problem: There are R red marbles, G green marbles and B blue marbles (R≤G≤B) Count the number of ways to arrange them in a straight line so that the two marbles next to each other are of different colors.
For example, R=G=B=2, the answer is 30.
I have tried using recursion and of course TLE:
Define r(R,B,G) to be the number of ways of arranging them where the first marble is red. Define b(R,B,G),g(R,B,G) respectively.
Then r(R, B, G) = b(R-1,B,G) + g(R-1,B,G)
And the answer is r(R,B,G) + b(R,B,G) + g(R,B,G)
But we can see that r(R, B, G) = b(B, R, G) ...
So, we just need a function f(x,y,z)=f(y,x−1,z)+f(z,x−1,y)
And the answer is f(x,y,z) + f(y,z,x) + f(z,x,y).
The time limit is 2 seconds.
I don't think dynamic is not TLE because R, G, B <= 2e5
Some things to limit the recursion:
If R>G+B+1, then there is no way to avoid having 2 adjacent reds. (Similar argument for G>R+B+1 & B>R+G+1.)
If R=G+B+1, then you alternate reds with non-reds, and your problem is reduced to how many ways you can arrange G greens and B blacks w/o worrying about adjacency (and should thus have a closed-form solution). (Again, similar argument for G=R+B+1 and B=R+G+1.)
You can use symmetry to cut down the number of recursions.
For example, if (R, G, B) = (30, 20, 10) and the last marble was red, the number of permutations from this position is exactly the same as if the last marble was blue and (R, G, B) = (10, 20, 30).
Given that R ≤ G ≤ B is set as a starting condition, I would suggest keeping this relationship true by swapping the three values when necessary.
Here's some Python code I came up with:
memo = {}
def marble_seq(r, g, b, last):
# last = colour of last marble placed (-1:nothing, 0:red, 1:green, 2:blue)
if r == g == b == 0:
# All the marbles have been placed, so we found a solution
return 1
# Enforce r <= g <= b
if r > g:
r, g = g, r
last = (0x201 >> last * 4) & 0x0f # [1, 0, 2][last]
if r > b:
r, b = b, r
last = (0x012 >> last * 4) & 0x0f # [2, 1, 0][last]
if g > b:
g, b = b, g
last = (0x120 >> last * 4) & 0x0f # [0, 2, 1][last]
# Abort if there are too many marbles of one colour
if b>r+g+1:
return 0
# Fetch value from memo if available
if (r,g,b,last) in memo:
return memo[(r,g,b,last)]
# Otherwise check remaining permutations by recursion
result = 0
if last != 0 and r > 0:
result += marble_seq(r-1,g,b,0)
if last != 1 and g > 0:
result += marble_seq(r,g-1,b,1)
if last != 2 and b > 0:
result += marble_seq(r,g,b-1,2)
memo[(r,g,b,last)] = result
return result
marble_seq(50,60,70,-1) # Call with `last` set to -1 initially
(Result: 205435997562313431685415150793926465693838980981664)
This probably still won't work fast enough for values up to 2×105, but even with values in the hundreds, the results are quite enormous. Are you sure you stated the problem correctly? Perhaps you're supposed to give the results modulo some prime number?

How to add elements to a Map?

I have a node type like the following :
type position = float * float
type node = position
I wrote these modules to use nodes as keys in my Map :
module MyMap =
struct
type t = node
let compare n1 n2 =
if n1 = n2 then 1
else 0
end
module Dist = Map.Make(MyMap)
Then I created an empty Map :
let mapTest = Dist.empty;;
let mapTest = Dist.add (1.,1.) 1. mapTest;;
I get the length of the Map like this :
Dist.cardinal mapTest;;
- : int = 1
I try to add another element :
let mapTest = Dist.add (2.,2.) 2. mapTest;;
But then my Map is still of length 1 when I use Dist.cardinal mapTest
More surprising, when I run :
Dist.find (1.,1.) mapTest;;
- : float = 2.
So now I'm left clueless about what's going on or what I've done wrong.
My goal is to be able to use the Map, add bindings etc.
Any ideas?
Thanks
The compare function does not behave as expected : it is expected to return 0 when n1 and n2 are equals, otherwise 1 if n1 is greater than n2, -1 if not.
The following code shall fix the issue :
module MyMap =
struct
type t = node
let compare (a1,b1) (a2,b2) =
if a1 > a2 then 1
else if a1 < a2 then -1
else if b1 > b2 then 1
else if b1 < b2 then -1
else 0
end
let compare n1 n2 =
if n1 = n2 then 1
else 0
It looks like you've misunderstood how compare is supposed to behave. Here's the description of compare from the documentation of OrderedType:
This is a two-argument function f such that f e1 e2 is zero if the keys e1 and e2 are equal, f e1 e2 is strictly negative if e1 is smaller than e2, and f e1 e2 is strictly positive if e1 is greater than e2.
So the way you defined it, n1 would be considered greater than n2 if n1 = n2 and otherwise n1 would be considered equal to n2. This does not follow any of the rules you'd expect from a comparison function: a key isn't considered equal to itself and "n1 is greater than n2" can (and in fact always will) be true at the same time as "n2 is greater than n1". Consequently the map will not behave in a sensible way.
Assuming you want to consider one node equal to another if and only if they contain the same values in the same order, you can just define compare using Stdlib.compare.
That is not how you're supposed to write the compare function.
To quote the manual:
A total ordering function over the keys. This is a two-argument
function f such that f e1 e2 is zero if the keys e1 and e2 are equal,
f e1 e2 is strictly negative if e1 is smaller than e2, and f e1 e2 is
strictly positive if e1 is greater than e2. Example: a suitable
ordering function is the generic structural comparison function
compare.
So your compare function should be:
let compare n1 n2 =
if n1 < n2 then -1
else if n1 > n2 then 1
else 0
Note that on floating point numbers, comparison is weird. First, the rounding makes some numbers that seem equal to not be so. Second and even worse, the standard comparisons are not total (they all always return false on a NaN).
Thankfully, you can trust the standard compare function to solve the latter problem:
let compare (n1:t) n2 = Stdlib.compare n1 n2

SML recursive programming with String.substring

I am trying to write a program that takes two strings s1 and s2 as arguments. The function should check whether s2 contains s1 and if it does, the program should write the position in s2 at which the first letter of s1 occurs.
I want to check: String.substring(s2, size s2 - size s1, size s1) = s1.
And I then need to do a recursion on (size s2 - 1) so that s2 gets smaller by one after each comparison and thereby "move the s1" comparison of s2 one letter to the left.
I have no problems with recursions like:
fun recurison 0 = 0
| recurison n = n + (n - 1)
But when i shall interact with other functions or String.substring it feels messy. How should I think when I'm trying to write some recursive stuff? Can you give me a hint on the problem? I love to come up with the solutions myself but need help to point out the right road.
First, there is already the function String.isSubstring : string -> string -> bool which does what you want. But since you are interested in implementing such a function yourself recursively you just have to think about the following:
What is the base-case (i.e., when does the recursion end)?
What is the step-case (i.e., how to get a solution from a smaller solution)?
Since in your description you started to check for substrings from the right and then move to the left, the base-case is when you arrive at the leftmost position (i.e., 0). As for the step-case, after you checked position i you have to check position i - 1.
First you might start with a function that handles the case of checking position i.
fun substringat s1 s2 i =
if size s1 + i > size s2 then false
else String.substring (s2, i, size s1) = s1;
Then the skeleton for the recursion
fun substringfrom s1 s2 i =
if i < 0 then ~1
else if substringat s1 s2 i then i
else substringfrom s1 s2 (i - 1);
Finally we initialize everything appropriately
fun substring s1 s2 = substringfrom s1 s2 (size s2 - 1);
To avoid some unnecessary checks we could combine all this to
fun substring s1 s2 =
let
val l1 = size s1;
val l2 = size s2;
fun substringat s1 s2 i =
if l1 + i > l2 then false
else String.substring (s2, i, l1) = s1;
fun substringfrom s1 s2 i =
if i < 0 then ~1
else if substringat s1 s2 i then i
else substringfrom s1 s2 (i - 1);
in
substringfrom s1 s2 (l2 - 1)
end

Minimum Weight Triangulation Taking Forever

so I've been working on a program in Python that finds the minimum weight triangulation of a convex polygon. This means that it finds the weight(The sum of all the triangle perimeters), as well as the list of chords(lines going through the polygon that break it up into triangles, not the boundaries).
I was under the impression that I'm using the dynamic programming algorithm, however when I tried using a somewhat more complex polygon it takes forever(I'm not sure how long it takes because I haven't gotten it to finish).
It works fine with a 10 sided polygon, however I'm trying 25 and that's what is making it stall. My teacher gave me the polygons so I assume that the 25 one is supposed to work as well.
Since this algorithm is supposed to be O(n^3), the 25 sided polygon should take roughly 15.625 times longer to calculate, however it's taking way longer seeing that the 10 sided seems instantaneous.
Am I doing some sort of n operation in there that I'm not realizing? I can't see anything I'm doing, except maybe the last part where I get rid of the duplicates by turning the list into a set, however in my program I put a trace after the decomp before the conversion happens, and it's not even reaching that point.
Here's my code, if you guys need anymore info just please ask. Something in there is making it take longer than O(n^3) and I need to find it so I can trim it out.
#!/usr/bin/python
import math
def cost(v):
ab = math.sqrt(((v[0][0] - v[1][0])**2) + ((v[0][1] - v[1][1])**2))
bc = math.sqrt(((v[1][0] - v[2][0])**2) + ((v[1][1] - v[2][1])**2))
ac = math.sqrt(((v[0][0] - v[2][0])**2) + ((v[0][1] - v[2][1])**2))
return ab + bc + ac
def triang_to_chord(t, n):
if t[1] == t[0] + 1:
# a and b
if t[2] == t[1] + 1:
# single
# b and c
return ((t[0], t[2]), )
elif t[2] == n-1 and t[0] == 0:
# single
# c and a
return ((t[1], t[2]), )
else:
# double
return ((t[0], t[2]), (t[1], t[2]))
elif t[2] == t[1] + 1:
# b and c
if t[0] == 0 and t[2] == n-1:
#single
# c and a
return ((t[0], t[1]), )
else:
#double
return ((t[0], t[1]), (t[0], t[2]))
elif t[0] == 0 and t[2] == n-1:
# c and a
# double
return ((t[0], t[1]), (t[1], t[2]))
else:
# triple
return ((t[0], t[1]), (t[1], t[2]), (t[0], t[2]))
file_name = raw_input("Enter the polygon file name: ").rstrip()
file_obj = open(file_name)
vertices_raw = file_obj.read().split()
file_obj.close()
vertices = []
for i in range(len(vertices_raw)):
if i % 2 == 0:
vertices.append((float(vertices_raw[i]), float(vertices_raw[i+1])))
n = len(vertices)
def decomp(i, j):
if j <= i: return (0, [])
elif j == i+1: return (0, [])
cheap_chord = [float("infinity"), []]
old_cost = cheap_chord[0]
smallest_k = None
for k in range(i+1, j):
old_cost = cheap_chord[0]
itok = decomp(i, k)
ktoj = decomp(k, j)
cheap_chord[0] = min(cheap_chord[0], cost((vertices[i], vertices[j], vertices[k])) + itok[0] + ktoj[0])
if cheap_chord[0] < old_cost:
smallest_k = k
cheap_chord[1] = itok[1] + ktoj[1]
temp_chords = triang_to_chord(sorted((i, j, smallest_k)), n)
for c in temp_chords:
cheap_chord[1].append(c)
return cheap_chord
results = decomp(0, len(vertices) - 1)
chords = set(results[1])
print "Minimum sum of triangle perimeters = ", results[0]
print len(chords), "chords are:"
for c in chords:
print " ", c[0], " ", c[1]
I'll add the polygons I'm using, again the first one is solved right away, while the second one has been running for about 10 minutes so far.
FIRST ONE:
202.1177 93.5606
177.3577 159.5286
138.2164 194.8717
73.9028 189.3758
17.8465 165.4303
2.4919 92.5714
21.9581 45.3453
72.9884 3.1700
133.3893 -0.3667
184.0190 38.2951
SECOND ONE:
397.2494 204.0564
399.0927 245.7974
375.8121 295.3134
340.3170 338.5171
313.5651 369.6730
260.6411 384.6494
208.5188 398.7632
163.0483 394.1319
119.2140 387.0723
76.2607 352.6056
39.8635 319.8147
8.0842 273.5640
-1.4554 226.3238
8.6748 173.7644
20.8444 124.1080
34.3564 87.0327
72.7005 46.8978
117.8008 12.5129
162.9027 5.9481
210.7204 2.7835
266.0091 10.9997
309.2761 27.5857
351.2311 61.9199
377.3673 108.9847
390.0396 148.6748
It looks like you have an issue with the inefficient recurision here.
...
def decomp(i, j):
...
for k in range(i+1, j):
...
itok = decomp(i, k)
ktoj = decomp(k, j)
...
...
You've ran into the same kind of issue as a naive recursive implementation of the Fibonacci Numbers, but the way this algorithm works, it'll probably be much worst on the run time. Assuming that is the only issue with you're algorithm, then you just need to use memorization to ensure that the decomp is only calculated once for each unique input.
The way to spot this issue is to print out the values of i, j and k as the triple (i,j,k). In order to obtain a runtime of O(N^3), you shouldn't see the same exact triple twice. However, the triple (22, 24, 23), appears at least twice (in the 25), and is the first such duplicate. That shows the algorithm is calculating the same thing multiple times, which is inefficient, and is bumping up the performance well past O(N^3). I'll leave figuring out what the algorithms actual performance is to you as an exercise. Assuming there isn't something else wrong with the algorithm the algorithm should eventually stop.

2 Dimentional array dereferencing ,how to evaluate through pointers

a[2][3] = {{-3,14,5},{1,-10,8}}
*(a[j]+k)
*(a[j+k-2])
(*(a+j))[k])
(*(a+k-1))[j]
*((*(a+j))+k))
(**(a+j)+k)
*(&a[0][0]+j+k)
when i printf these i get
Output:
8
1
8
-10
8
3
1
respectively
Please if anyone can explain in detail how the values are coming ,i am a new starter please pardon me for bad formatting here and also bothering you for with so much work :)
I assume j == 1 and k == 2:
*(a[j]+k) == *(a[1]+2) :
a[1] = {1, -10, 8};
So a[1]+2 is a pointer to 8, and *(a[1]+2) == 8
*(a[j+k-2]) == *(a[1+2-2]) == *(a[1]):
a[1] = {1, -10, 8}
Since *a[1] is the value of the first element in a[1], the expression evaluates to 1
(*(a+j))[k] == (*(a+1))[2]:
a+1 is a pointer to the second element in a, so *(a+1) == a[1] = {1, -10, 8}
a[1][2] == 8
(*(a+k-1))[j] == (*(a+2-1))[1] == (*(a+1))[1]:
*(a+1) == a[1] (see the last answer)
a[1][1] == -10
*((*(a+j))+k) == *((*(a+1))+2):
*(a+1) == a[1], so the expressions is equivalent to *(a[1]+2)
*(a[1]+2) is equivalent to a[1][2] for the same reasoning as above, which is 8
(**(a+j)+k) == (**(a+1)+2):
*(a+1) = a[1]
**(a+1) = a[1][0] == 1
Adding 2 to that gives 3
*(&a[0][0]+j+k) == *(&a[0][0]+1+2) == *(&a[0][0]+3):
&a[0][0] == a[0]
*(a[0]+3) == a[0][3];
This last one is returning 1, because it is extending in memory past the end of a[0] into a[1], and you're getting a[1][0]. I think this behavior is actually undefined though. It depends on whether the C standard guarantees that an initialized 2D array will be allocated sequentially in memory or not, and could result in a Segmentation fault or worse.

Resources