text: fun main() {
      SOLAR_MASS = 4.0 * PI * PI;
      let n = argv(0).toInt32().unwrap();
      let bodies = NBodySystem();
  
      var i = 0;
      println(bodies.energy().toString());
  
      while i < n {
          bodies.advance(0.01);
          i = i + 1;
      }
  
      println(bodies.energy().toString());
  }
  
  class NBodySystem {
      let bodies: Array[Body] = Array::ofSizeUnsafe[Body](5L);
  
      {
          self.bodies(0L) = Body::sun();
          self.bodies(1L) = Body::jupiter();
          self.bodies(2L) = Body::saturn();
          self.bodies(3L) = Body::uranus();
          self.bodies(4L) = Body::neptune();
  
          var px = 0.0;
          var py = 0.0;
          var pz = 0.0;
  
          var i = 0L;
  
          while i < self.bodies.size() {
              px = px + self.bodies.get(i).vx * self.bodies.get(i).mass;
              py = py + self.bodies.get(i).vy * self.bodies.get(i).mass;
              pz = pz + self.bodies.get(i).vz * self.bodies.get(i).mass;
  
              i = i + 1L;
          }
  
          self.bodies.get(0L).offsetMomentum(px, py, pz);
      }
  
      fun advance(dt: Float64) {
          var i = 0L;
  
          while i < self.bodies.size() {
              let iBody = self.bodies.get(i);
              var j = i + 1L;
  
              while j < self.bodies.size() {
                  let dx = iBody.x - self.bodies.get(j).x;
                  let dy = iBody.y - self.bodies.get(j).y;
                  let dz = iBody.z - self.bodies.get(j).z;
  
                  let dSquared = dx * dx + dy * dy + dz * dz;
                  let distance = dSquared.sqrt();
                  let mag = dt / (dSquared * distance);
  
                  iBody.vx = iBody.vx - dx * self.bodies.get(j).mass * mag;
                  iBody.vy = iBody.vy - dy * self.bodies.get(j).mass * mag;
                  iBody.vz = iBody.vz - dz * self.bodies.get(j).mass * mag;
  
                  self.bodies.get(j).vx = self.bodies.get(j).vx + dx * iBody.mass * mag;
                  self.bodies.get(j).vy = self.bodies.get(j).vy + dy * iBody.mass * mag;
                  self.bodies.get(j).vz = self.bodies.get(j).vz + dz * iBody.mass * mag;
  
                  j = j + 1L;
              }
  
              i = i + 1L;
          }
  
          var i = 0L;
  
          while i < self.bodies.size() {
              let body = self.bodies.get(i);
  
              body.x = body.x + dt * body.vx;
              body.y = body.y + dt * body.vy;
              body.z = body.z + dt * body.vz;
  
              i = i + 1L;
          }
     }
  
     fun energy(): Float64 {
        var dx = 0.0;
        var dy = 0.0;
        var dz = 0.0;
        var distance = 0.0;
        var e = 0.0;
  
        var i = 0L;
  
        while i < self.bodies.size() {
           let iBody = self.bodies.get(i);
           e = e + 0.5 * iBody.mass *
              ( iBody.vx * iBody.vx
                  + iBody.vy * iBody.vy
                  + iBody.vz * iBody.vz );
  
          var j = i+1L;
  
          while j < self.bodies.size() {
              let jBody = self.bodies.get(j);
  
              dx = iBody.x - jBody.x;
              dy = iBody.y - jBody.y;
              dz = iBody.z - jBody.z;
  
              distance = (dx*dx + dy*dy + dz*dz).sqrt();
              e = e - (iBody.mass * jBody.mass) / distance;
  
              j = j + 1L;
          }
  
           i = i + 1L;
        }
  
        return e;
     }
  }
  
  const PI: Float64 = 3.141592653589793;
  var SOLAR_MASS: Float64;
  const DAYS_PER_YEAR: Float64 = 365.24;
  
  class Body {
      var x: Float64;
      var y: Float64;
      var z: Float64;
      var vx: Float64;
      var vy: Float64;
      var vz: Float64;
      var mass: Float64;
  
     fun offsetMomentum(px: Float64, py: Float64, pz: Float64): Body {
        self.vx = -px / SOLAR_MASS;
        self.vy = -py / SOLAR_MASS;
        self.vz = -pz / SOLAR_MASS;
        return self;
     }
  }
  
  module Body {
      fun jupiter(): Body {
          let p = Body();
          p.x = 4.84143144246472090e+00;
          p.y = -1.16032004402742839e+00;
          p.z = -1.03622044471123109e-01;
          p.vx = 1.66007664274403694e-03 * DAYS_PER_YEAR;
          p.vy = 7.69901118419740425e-03 * DAYS_PER_YEAR;
          p.vz = -6.90460016972063023e-05 * DAYS_PER_YEAR;
          p.mass = 9.54791938424326609e-04 * SOLAR_MASS;
          return p;
      }
  
     fun saturn(): Body {
        let p = Body();
        p.x = 8.34336671824457987e+00;
        p.y = 4.12479856412430479e+00;
        p.z = -4.03523417114321381e-01;
        p.vx = -2.76742510726862411e-03 * DAYS_PER_YEAR;
        p.vy = 4.99852801234917238e-03 * DAYS_PER_YEAR;
        p.vz = 2.30417297573763929e-05 * DAYS_PER_YEAR;
        p.mass = 2.85885980666130812e-04 * SOLAR_MASS;
        return p;
     }
  
     fun uranus(): Body {
        let p = Body();
        p.x = 1.28943695621391310e+01;
        p.y = -1.51111514016986312e+01;
        p.z = -2.23307578892655734e-01;
        p.vx = 2.96460137564761618e-03 * DAYS_PER_YEAR;
        p.vy = 2.37847173959480950e-03 * DAYS_PER_YEAR;
        p.vz = -2.96589568540237556e-05 * DAYS_PER_YEAR;
        p.mass = 4.36624404335156298e-05 * SOLAR_MASS;
        return p;
     }
  
     fun neptune(): Body {
        let p = Body();
        p.x = 1.53796971148509165e+01;
        p.y = -2.59193146099879641e+01;
        p.z = 1.79258772950371181e-01;
        p.vx = 2.68067772490389322e-03 * DAYS_PER_YEAR;
        p.vy = 1.62824170038242295e-03 * DAYS_PER_YEAR;
        p.vz = -9.51592254519715870e-05 * DAYS_PER_YEAR;
        p.mass = 5.15138902046611451e-05 * SOLAR_MASS;
        return p;
     }
  
     fun sun(): Body {
        let p = Body();
        p.mass = SOLAR_MASS;
        return p;
     }
  }
  