Question

So I am presented with the following problem:

"On the parabola y = x2/k, three points A(a, a2/k), B(b, b2/k) and C(c, c2/k) are chosen.

Let F(K, X) be the number of the integer quadruplets (k, a, b, c) such that at least one angle of the triangle ABC is 45-degree, with 1 ≤ k ≤ K and -X ≤ a < b < c ≤ X.

For example, F(1, 10) = 41 and F(10, 100) = 12492. Find F(106, 109)."

In aims to solve it I have exploited the geometric definition of the dot product: theta = cos^-1((A dot B)/(|A|*|B|)), where A and B are Euclidean vectors, |A| represents the magnitude of A, and theta is the angle between them.

I have read over my script multiple times and as far as I can see the only reason it is resulting in FoKX=22 instead of FoKX=41 is that there is an error in the trigonometic accuracy or conversion from radians to degrees. Let me know if this is the case or I have made a mistake somewhere that might account for this. Thanks always for the help!

K<-1
X<-10
FoKX<-0
for(l in 1:K){
  for(i in (-X):(X-2)){
    for(j in (i+1):(X-1)){
      for(k in (j+1):X){
        vecAB<-c(j-i,(j^2-i^2)/l)
        vecAC<-c(k-i,(k^2-i^2)/l)
        vecBA<--vecAB
        vecBC<-c(k-j,(k^2-j^2)/l)
        vecCA<--vecAC
        vecCB<--vecBC
        magAB<-sqrt(sum(vecAB^2))
        magAC<-sqrt(sum(vecAC^2))
        magBA<-magAB
        magBC<-sqrt(sum(vecBC^2))
        magCA<-magAC
        magCB<-magBC
        ABdotAC<-sum(vecAB*vecAC)
        BAdotBC<-sum(vecBA*vecBC)
        CAdotCB<-sum(vecCA*vecCB)
        angA<-acos(ABdotAC/(magAB*magAC))
        angB<-acos(BAdotBC/(magBA*magBC))
        angC<-acos(CAdotCB/(magCA*magCB))
        if(angA==pi/4||angB==pi/4||angC==pi/4){
          FoKX<-FoKX+1
        }
      }
    }
  }
}
Was it helpful?

Solution

Don't compare for exact equality with floating-point. Always include a fuzz factor.

        ....
        ....
        if(abs(angA - pi/4) < 1e-9 ||
           abs(angB - pi/4) < 1e-9 || 
           abs(angC - pi/4) < 1e-9){
          FoKX<-FoKX+1
        }
      }
    }
  }
}

FoKX
[1] 41

OTHER TIPS

I find this toy of mine helpful when dealing with floatingpoint equality: (free as in beer, free to modify as you like, etc)

approxeq <- function(x, y, tolerance = .Machine$double.eps ^ 0.5,...) {
  #input validation 
  if (length(x) != length(y)) warning('x,y lengths differ. Will recycle.')
  #don't care about dimensions so long as you're smart about inputs
  checkit <- abs(x-y) < tolerance
  return(invisible(checkit))
}

This returns a logical vector, unlike the builtin all.equal which has its own uses.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top