Vector

From Rosetta Code
Revision as of 23:56, 30 March 2015 by rosettacode>Gus.massa (Add Racket)
Vector is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Implement a Vector class (or a set of functions) that models a Physical Vector. You should implement The four basic operations and a 'pretty print' function. Your Vector may be initialized in any reasonable way.

- Start and end points and direction - Angular coefficient and value (length)

The four operations to be implemented are:

  • Vector+Vector addition
  • Vector-Vector subtraction
  • Vector*scalar multiplication
  • Vector/scalar division

J

These are primitive (built in) operations in J:

<lang J> 5 7+2 3 7 10

  5 7-2 3

3 4

  5 7*11

55 77

  5 7%2

2.5 3.5</lang>

A few things here might be worth noting:

J treats a sequences of space separated numbers as a single word, this is analogous to how languages which support a "string" data type support treating strings with spaces in them as single words. Put differently: '5 7' is a sequence of three characters but 5 7 (without the quotes) is a sequence of two numbers.

J uses the percent sign to represent division. This is a visual pun with the "division sign" or "obelus" which has been used to represent the division operation for hundreds of years.

In J, a single number (or single character) is special. It's not a treated as a sequence except in contexts where you explicitly declare it to be one (for example, by prefixing it with a comma). (If it were treated as a sequence the above operations would have been errors, because of the length mis-match.)

It's perhaps also worth noting that J allows you to specify complex numbers using polar coordinates, and complex numbers can be converted to vectors using the special token (+.) - for example:

<lang J> 2ad45 1.41421j1.41421

  +. 2ad45

1.41421 1.41421

  2ar0.785398

1.41421j1.41421

  +. 2ar0.785398

1.41421 1.41421</lang>

In the construction of these numeric constants, ad is followed by an angle in degrees while ar is followed by an angle in radians. This practice of embedding letters in a numeric constant is analogous to the use of exponential notation when describing some floating point numbers.

Racket

Translation of: Python

We store internally only the x, y components and calculate the norm, angle and slope on demand. We have two constructors one with (x,y) and another with (slope, norm).

We use fl* and fl/ to try to get the most sensible result for vertical vectors. <lang Racket>#lang racket

(require racket/flonum)

(define (rad->deg x) (fl* 180. (fl/ (exact->inexact x) pi)))

Custom printer
no shared internal structures

(define (vec-print v port mode)

 (write-string "Vec:\n" port)
 (write-string (format " -Slope: ~a\n" (vec-slope v)) port)
 (write-string (format " -Angle(deg): ~a\n" (rad->deg (vec-angle v))) port)
 (write-string (format " -Norm: ~a\n" (vec-norm v)) port)
 (write-string (format " -X: ~a\n" (vec-x v)) port)
 (write-string (format " -Y: ~a\n" (vec-y v)) port))

(struct vec (x y)

       #:methods gen:custom-write 
       [(define write-proc vec-print)])
Alternative constructor

(define (vec/slope-norm s n)

 (vec (* n (/ 1 (sqrt (+ 1 (sqr s)))))
      (* n (/ s (sqrt (+ 1 (sqr s)))))))
Properties

(define (vec-norm v)

 (sqrt (+ (sqr (vec-x v)) (sqr (vec-y v)))))

(define (vec-slope v)

 (fl/ (exact->inexact (vec-y v)) (exact->inexact (vec-x v))))

(define (vec-angle v)

 (atan (vec-y v) (vec-x v)))
Operations

(define (vec+ v w)

 (vec (+ (vec-x v) (vec-x w))
      (+ (vec-y v) (vec-y w))))

(define (vec- v w)

 (vec (- (vec-x v) (vec-x w))
      (- (vec-y v) (vec-y w))))

(define (vec*e v l)

 (vec (* (vec-x v) l)
      (* (vec-y v) l)))

(define (vec/e v l)

 (vec (/ (vec-x v) l)
      (/ (vec-y v) l)))</lang>

Tests <lang Racket>(vec/slope-norm 1 10)

(vec/slope-norm 0 10)

(vec 3 4)

(vec 0 10)

(vec 10 0)

(vec+ (vec/slope-norm 1 10) (vec/slope-norm 1 2))

(vec*e (vec/slope-norm 4 5) 2)</lang>

Output:
Vec:
 -Slope: 1.0
 -Angle(deg): 45.0
 -Norm: 10.0
 -X: 7.071067811865475
 -Y: 7.071067811865475

Vec:
 -Slope: 0.0
 -Angle(deg): 0.0
 -Norm: 10
 -X: 10
 -Y: 0

Vec:
 -Slope: 1.3333333333333333
 -Angle(deg): 53.13010235415597
 -Norm: 5
 -X: 3
 -Y: 4

Vec:
 -Slope: +inf.0
 -Angle(deg): 90.0
 -Norm: 10
 -X: 0
 -Y: 10

Vec:
 -Slope: 0.0
 -Angle(deg): 0.0
 -Norm: 10
 -X: 10
 -Y: 0

Vec:
 -Slope: 1.0
 -Angle(deg): 45.0
 -Norm: 11.999999999999998
 -X: 8.48528137423857
 -Y: 8.48528137423857

Vec:
 -Slope: 4.0
 -Angle(deg): 75.96375653207353
 -Norm: 10.000000000000002
 -X: 2.42535625036333
 -Y: 9.70142500145332

Python

Implements a Vector Class that is initialized with origin, angular coefficient and value.

<lang python>class Vector:

   def __init__(self,m,value):
       self.m = m
       self.value = value
       self.angle = math.degrees(math.atan(self.m))
       self.x = self.value * math.sin(math.radians(self.angle))
       self.y = self.value * math.cos(math.radians(self.angle))
   def __add__(self,vector):
       """
       >>> Vector(1,10) + Vector(1,2)
       Vector:
           - Angular coefficient: 1.0
           - Angle: 45.0 degrees
           - Value: 12.0
           - X component: 8.49
           - Y component: 8.49
       """
       final_x = self.x + vector.x
       final_y = self.y + vector.y
       final_value = pytagoras(final_x,final_y)
       final_m = final_y / final_x
       return Vector(final_m,final_value)
   def __neg__(self):
       return Vector(self.m,-self.value)
   def __sub__(self,vector):
       return self + (- vector)
       
   def __mul__(self,scalar):
       """
       >>> Vector(4,5) * 2
       Vector:
           - Angular coefficient: 4
           - Angle: 75.96 degrees
           - Value: 10
           - X component: 9.7
           - Y component: 2.43
       """
       return Vector(self.m,self.value*scalar)
   def __div__(self,scalar):
       return self * (1 / scalar)
   
   def __repr__(self):
       """
       Returns a nicely formatted list of the properties of the Vector.
       >>> Vector(1,10)
       Vector:
           - Angular coefficient: 1
           - Angle: 45.0 degrees
           - Value: 10
           - X component: 7.07
           - Y component: 7.07
       
       """
       return """Vector:
   - Angular coefficient: {}
   - Angle: {} degrees
   - Value: {}
   - X component: {}
   - Y component: {}""".format(self.m.__round__(2),
              self.angle.__round__(2),
              self.value.__round__(2),
              self.x.__round__(2),
              self.y.__round__(2))</lang>