0

How can I write an operation gcd(x : Integer, y : Integer) : Integer which returns the greatest common divisor of two positive integers (the largest integer which divides both of them exactly) in ocl?

any
  • 325
  • 5
  • 17

1 Answers1

0

Here is a simple solution for this (certainly not effective, but it works):

let divs : Sequence(Integer) = if x < y then Sequence{1..y} else Sequence{1..x} endif
in divs->select(z | x.mod(z) = 0 and y.mod(z) = 0)->last()

What is simply done is that a sequence of each potentials candidates is generated, then, from this sequence, only the ones that divide x and y are selected and stored in a new sequence (which is ordered). Finally, the last number from this filtered sequence is your greatest common divisor.

Now in details:

  1. we produce a sequence with Sequence{a..b}
  2. this sequence is goes from 1 to the higher number between x and y (if x < y then Sequence{1..y} else Sequence{1..x})
  3. this sequence is stored in a immutable variable divs (let divs : Sequence(Integer) = ... in ...)
  4. from divs, we select only the number z which is a divisor for x and z (divs->select(z | x.mod(z) = 0 and y.mod(z) = 0)
  5. finally, we only take the last element from the new sequence (select(...)->last())

If the last() function does not exist in your env (don't know why, but some OCL implementations bring their own functions), you can use:

->sortedBy(i | -i)->at(1)

instead of last(), which reverse the sequence and take the first element.

EDIT>

You can also reduce the expression this way:

let divs : Sequence(Integer) = Sequence{1..x.max(y)}
in divs->select(z | x.mod(z) = 0 and y.mod(z) = 0)->last()

or, by removing the use of divs

Sequence{1..x.max(y)}->select(z | x.mod(z) = 0 and y.mod(z) = 0)->last()
Vincent Aranega
  • 1,441
  • 10
  • 21
  • Is it support in standard OCL? what is the set to result or return? – any Jun 17 '16 at 08:59
  • I checked, `last()` is standard OCL (specification, p.170). It was the only point I was not sure about. Everything else is obviously standard. This expression does not work for you? – Vincent Aranega Jun 17 '16 at 09:02
  • Bytheway, you can reduce the expression (see my edit), and everything is still standard OCL. – Vincent Aranega Jun 17 '16 at 09:06