10
\$\begingroup\$

Newton's theory of gravitation says that the gravitational force between two point masses is

F=(Gm1m2)/ r2

Where

  • G is the gravitational constant: 6.674×10−11 N · (m/kg)2
  • m1 is the mass of the first object
  • m2 is the mass of the second object
  • r is the distance between their centers of mass

Challenge

You need to simulate the pull between two words. Each lowercase letter has mass given by its position in the alphabet. Capital letters have twice the mass of their lowercase counterparts! You will be given a string containing two words separated by several spaces, as well as a positive integer number of seconds, s. Output what the string would look like after s seconds.

Info

  • Because words are abstract they have a different set of units and constants
    • Mass: WMU (Word Mass Unit) - equal to the mass of the letter 'a'.
    • Distance: em, the length of one character.
    • Force: NW (Word Newton) = WMU · em/s2
    • Gravitational Constant: G = 1 Nw · (em/WMU)2
  • The first character corresponds to the position 0 on the x-axis.
  • All calculations should be done with as much precision as possible, only at the end do you round to the nearest em.
  • You do not need to use calculus, you just need to recalculate the F every second, automatically apply the new acceleration to the velocity, and after a second apply the velocity to the position (see example).
  • Once two words collide with each other (like catdog ), they don't move any further.

Center of Mass

The center of mass of a word can be found with the formula:

enter image description here

Where M is the total mass of the word, mi is the mass of a letter, and ri is the position of the letter.

Example:

(Note: Although this example doesn't show it, remember that capital letters have twice the mass of their lowercase counterparts.)

Input: cat dog, 2

  1. First what are the positions of each word? "cat" starts at position 0 and "dog" starts at position 9, so

    • xc = 0 and xd = 9
  2. Next, let's find the center of mass of "cat".

    • It has a mass of 24 WMU (3+1+20).
    • Rc = 1/24(3*0+1*1+20*2) = 41/24 = 1.70833 em
    • So unsurprisingly the center of mass is very close to the letter 't'.
  3. Now let's get the center of mass of "dog"

    • Rd = 1/26(4*9+15*10+7*11) = 263/26 = 10.11538 em
    • So the center of mass for dog is close to the letter 'o', slightly towards 'g'.
  4. Now we can calculate the force between the two words.

    • F = 24*26/(10.11538-1.70833)2 = 8.82871 Nw
  5. Now we need to apply this force to both words and get their accelerations

    • ac = 8.82871/24 = .36786 em/s2
    • ad = -8.82871/26 = -.33957 em/s2
  6. Following the rules above, we apply the acceleration to the velocity, so

    • vc = .36786 em/s
    • vd = -.33957 em/s
  7. Then we apply the velocity to the position, so after one second,

    • xc = .36786 em
    • xd = 9 -.33957 = 8.66043 em.
    • Rc = 1.70833+.36786 = 2.07619 em
    • Rd = 10.11538-.33957 = 9.77581 em
  8. Now we repeat the procedure one more time with the new positions:

    • F = 24*26/((9.77581)-(2.07619))2 = 10.52558 Nw
    • ac = 10.52558/24 = .43857 em/s2, ad = 10.52558/26 = -.40483 em/s2
    • vc = .36786 + .43857 = .80643 em/s, vd = -.33957 - .40483 = -.74440 em/s
    • xc = .36786 + .80643 = 1.17429 em, xd = 8.66043 - .74440 = 7.91603 em
    • Rc = 2.07619 + .80643 = 2.88262 em, Rd = 9.77581 - .74440 = 9.03141 em
  9. So we end up with "cat" at x=1.17429 and "dog" at x=7.91603.

    • We round those to the nearest integer so "cat" goes to position 1 and "dog" goes to position 8, so the output is cat dog

Handling Collisions

Remember that the new acceleration is immediately added to the velocity every second. Therefore, if two words collide at certain time, use algebra to find the point of collision. Take this example:

  • word 1 is 4 letters long (||w1|| = 4)
  • word 2 is 4 letters long (||w2|| = 4)
  • x1 = 3, x2 = 8
  • v1 = 2,v2 = -6

    Solve 3 + (4-1) + 2t = 8 - 6t. t = .25s. The position of the collision is xcol = 6.5. Therfore, the collision should appear as occurring between x = 6 and x = 7, as such

    ####@@@@ .

The explicit formula for the positions of the words after a collision is

  • x1 = floor(xcol)-||w1||+1
  • x2 = floor(xcol)+1
\$\endgroup\$
6
  • \$\begingroup\$ @FryAmTheEggman The last bullet point in "info" talks about collision. You can do it in one step but make sure to follow the rules laid out. \$\endgroup\$
    – geokavel
    Commented Jan 14, 2016 at 20:40
  • \$\begingroup\$ Might the words pass through each other? \$\endgroup\$
    – xnor
    Commented Jan 14, 2016 at 21:24
  • \$\begingroup\$ @xnor No, they're won't. I'm added a part about properly handling collisions. \$\endgroup\$
    – geokavel
    Commented Jan 14, 2016 at 21:31
  • \$\begingroup\$ I'm trying to understand the physics involved here. Consider the configuration xx a (one space between the words xx and a). In Newtonian physics, the force that a feels would be due to the closer x pulling from a distance of two em's, and the other x pulling from a distance of three em's, yes? That's not the same as the force of a single point-mass X pulling from a distance of 2.5 em's (i.e., the center of mass of the xx), due to the inverse-square law... \$\endgroup\$
    – mathmandan
    Commented Jan 14, 2016 at 22:00
  • 1
    \$\begingroup\$ ...so just to clarify, I'm supposed to treat each WORD as if it were a point-mass with all its mass concentrated at its center of mass, where by "its center of mass" we mean "where its center of mass would be if we instead treated its LETTERS as point-masses". Is this correct? \$\endgroup\$
    – mathmandan
    Commented Jan 14, 2016 at 22:01

1 Answer 1

3
\$\begingroup\$

Python 3, 556 bytes

Thanks to FryAmTheEggman and Sherlock9 for some bytes

s,E,a,b,e=str.split,enumerate,lambda c:ord(c)%32*-~c.isupper(),lambda w:sum(map(a,w)),' '
def j(w):z,y=map(len,s(w));h=w.count(e);return sum(i*a(x)for i,x in E(w)if i<z)/b(w[:z]),sum(i*a(x)for i,x in E(w)if i>=y+h)/b(w[-y:])
def f(w):x,v=j(w);m,n=map(b,s(w));return m*n/(x-v)**2
def q(w):x,v=s(w);return f(w)/b(x),-f(w)/b(v)
def p(w,t):
 x,v=q(w);c,d=x,v;m,n=map(b,s(w));r,u=j(w);g,h=r,u;
 for i in range(t):r+=x;u+=v;f=m*n/(r-u)**2;c,d=f/m,f/n;x+=c;v+=d
 return int(r-g),int(1+h-u)
def g(w,t):x,y=p(w,t);u,v=s(w);return e*x+u+e*(len(w)-len(u+v)-x-y)+v+e*y

g(w,t) takes the string (w) and the time (t), and returns the result. The other functions are helpers.

Try it online (prints out *s instead of spaces so that it is more visible)

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.