case class Vect3(x: Double, y: Double, z: Double) {
	def +(v: Vect3) = Vect3(x+v.x, y+v.y, z+v.z)
	def -(v: Vect3) = Vect3(x-v.x, y-v.y, z-v.z)
	def *(c: Double) = Vect3(x*c, y*c, z*c)
	def /(c: Double) = Vect3(x/c, y/c, z/c)
}

case class ImmutableBody(p: Vect3, v: Vect3, mass: Double) {
	def step(a: Vect3, dt: Double) = {
		val nv = v+a*dt
		ImmutableBody(p+nv*dt, nv, mass)
	}
}

class NBodyImmutableClass(val numBodies: Int, val dt: Double) {

	private val bodies = initBodies()

	def initBodies(): Array[ImmutableBody] = {
		Array.tabulate(numBodies) { i =>
			ImmutableBody(Vect3(i,0,0), Vect3(0,math.sqrt(1.0/i),0),
				if(i==0) 1 else 1e-10)
		}
	}

	def forSim(steps: Int): Unit = {
		for(_ <- 1 to steps) {
			val accel = Array.fill(numBodies)(Vect3(0,0,0))
			for {
				i <- 0 until numBodies
				j <- i+1 until numBodies
			} {
				val pi = bodies(i)
				val pj = bodies(j)
				val d = pi.p - pj.p
				val dist = math.sqrt(d.x*d.x+d.y*d.y+d.z*d.z)
				accel(i) -= d*(pj.mass/(dist*dist*dist))
				accel(j) += d*(pi.mass/(dist*dist*dist))
			}
			for(i <- 0 until numBodies) {
				bodies(i) = bodies(i).step(accel(i), dt)
			}
		}
	}
}