Dây xích giữa hai điểm (Chuỗi treo)


8

Đây là một trong một số thử thách dành cho cộng đồng bởi Sở thích của Calvin .

Đường cong mà một sợi dây treo hoặc dây xích lý tưởng hóa tạo ra là một dây xích .

Một chuỗi hình thành một dây xích
Hình ảnh của Bin im Garten, qua Wikimedia Commons. Được sử dụng theo giấy phép CC-By-SA 3.0 .

Viết một chương trình mà sẽ vẽ một dây xích, như là một hình ảnh, trong góc phần tư 1 trong tổng số máy bay cho hai điểm (x 1 , y 1 ) , (x 2 , y 2 ) , và "chiều dài sợi dây thừng" L . L sẽ lớn hơn khoảng cách giữa hai điểm.

Bạn cũng phải vẽ các trục ở bên trái và dưới cùng của hình ảnh (400x400 px phút) cho tỷ lệ. Chỉ vẽ góc phần tư từ x và y trong phạm vi 0 đến 100. (Bạn có thể giả sử các điểm nằm trong phạm vi.)

Các dấu chấm, hoặc một cái gì đó tương tự, nên được vẽ tại các điểm cuối (x 1 , y 1 ) , (x 2 , y 2 ) để phân biệt chúng. Đường cong chỉ nên được vẽ trong khoảng trống giữa các điểm này.


Làm thế nào chính xác để chúng ta phải được? Có phải hình ảnh phải được khử răng cưa? Làm thế nào rộng phải / có thể là dòng?
Sparr

Chúng tôi cũng cho rằng chính đường cong (không chỉ các điểm) nằm trong phạm vi, phải không? Hay chúng ta sẽ vẽ hai cung bị cắt bởi trục nếu nó nằm dưới đó?
Geobits

@Sparr Hình ảnh không cần phải khử răng cưa. Dòng phải dày ít nhất 1px. Dây xích phải chính xác như số học dấu phẩy động của ngôn ngữ của bạn có thể làm.
absinthe

5
Tôi sẽ làm điều này cho đến khi tôi nhận ra rằng toán học có thể phức tạp hơn một chút so với tính toán trước hiện tại của tôi. Có thể năm sau.
Căng thẳng điên cuồng

1
@BetaDecay Tôi không biết đó là gì. Hãy nói 0.
absinthe

Câu trả lời:


5

Python + NumPy + Matplotlib, 1131

Chỉ để giúp chúng tôi bắt đầu, đây là một nỗ lực không sử dụng kiến ​​thức về tính toán hay vật lý nào ngoài thực tế là dây xích giảm thiểu năng lượng của chuỗi. Này, thuật toán của tôi có thể không hiệu quả, nhưng ít nhất nó cũng không được triển khai hiệu quả!

import math
import random
import numpy as np
import matplotlib.pyplot as plt
length, x0, y0, x1, y1 = input(), input(), input(), input(), input()
chain = np.array([[x0] + [length / 1000.]*1000, [y0] + [0.] * 1000])
def rotate(angle, x, y):
 return x * math.cos(angle) + y * math.sin(angle), -x * math.sin(angle) + y  * math.cos(angle)
def eval(chain, x1, y1):
 mysum = chain.cumsum(1)
 springpotential = 1000 * ((mysum[0][-1] - x1) ** 2 + (mysum[1][-1] - y1)  ** 2)
 potential = mysum.cumsum(1)[1][-1]
 return springpotential + potential
def jiggle(chain, x1, y1):
 for _ in xrange(100000):
  pre = eval(chain, x1, y1)
  angle = random.random() * 2 * math.pi
  index = random.randint(1,1000)
  chain[0][index], chain[1][index] = rotate(angle, chain[0][index], chain[1][index])
  if( pre < eval(chain, x1, y1)):
   chain[0][index], chain[1][index] = rotate(-angle, chain[0][index], chain[1][index])
jiggle(chain, x1, y1)
sum = chain.cumsum(1)
x1 = 2 * x1 - sum[0][-1]
y1 = 2 * y1 - sum[1][-1]
jiggle(chain, x1, y1)
sum = chain.cumsum(1)
plt.plot(sum[0][1:], sum[1][1:])
plt.show()

3

BBC Basic, 300 ký tự ASCII, kích thước tệp được mã hóa 260

  INPUTr,s,u,v,l:r*=8s*=8u*=8v*=8l*=8z=0REPEATz+=1E-3UNTILFNs(z)/z>=SQR(l^2-(v-s)^2)/(u-r)a=(u-r)/2/z
  p=(r+u-a*LN((l+v-s)/(l-v+s)))/2q=(v+s-l*FNc(z)/FNs(z))/2MOVE800,0DRAW0,0DRAW0,800CIRCLEu,v,8CIRCLEr,s,8FORx=r TOu
    DRAW x,a*FNc((x-p)/a)+q
  NEXT
  DEFFNs(t)=(EXP(t)-EXP(-t))/2
  DEFFNc(t)=(EXP(t)+EXP(-t))/2

Trình giả lập tại http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

Điều này rõ ràng đã được giải quyết trước đây, vì vậy điều đầu tiên tôi làm là xem những gì người khác đã làm.

Phương trình của một dây xích tập trung ở gốc tọa độ đơn giản y=a*cosh(x/a). Nó trở nên phức tạp hơn một chút nếu nó không tập trung ở điểm gốc.

Nhiều nguồn khác nhau nói rằng nếu biết chiều dài và điểm cuối thì giá trị aphải được xác định bằng số. Có một tham số không xác định htrong bài viết trên wikipedia. Vì vậy, tôi đã tìm thấy một trang web khác và về cơ bản theo phương pháp ở đây: http://www.math.niu.edu/~rusin/ Unknown-math / 99_income / catenary

BBC Basic không có sinhcoshđược tích hợp sẵn, vì vậy tôi đã xác định hai hàm ở cuối chương trình để tính toán chúng bằng cách sử dụngEXP

tọa độ cho điểm bên trái phải được cung cấp trước điểm bên phải, OP xác nhận điều này là OK. Chiều dài được đưa ra cuối cùng. Các giá trị có thể được phân tách bằng dấu phẩy hoặc dòng mới.

Mã bị đánh cắp

  INPUT r,s,u,v,l

  REM convert input in range 0-100 to graphic coordinates in range 0-800 
  r*=8 s*=8 u*=8 v*=8 l*=8

  REM solve for z numerically
  z=0
  REPEAT
    z+=1E-3
  UNTIL FNs(z)/z>=SQR(l^2-(v-s)^2)/(u-r)

  REM calculate the curve parameters
  a=(u-r)/2/z
  p=(r+u-a*LN((l+v-s)/(l-v+s)))/2
  q=(v+s-l*FNc(z)/FNs(z))/2

  REM draw axes, 800 graphics units long = 400 pixels long (2 graphics units per pixel)
  MOVE 800,0
  DRAW 0,0
  DRAW 0,800

  REM draw markers at end and beginning of curve (beginning last, so that cursor is in right place for next step)
  CIRCLE u,v,8
  CIRCLE r,s,8

  REM draw curve from beginning to end
  FORx=r TOu
    DRAW x,a*FNc((x-p)/a)+q
  NEXT

  REM definitions of sinh and cosh
  DEF FNs(t)=(EXP(t)-EXP(-t))/2
  DEF FNc(t)=(EXP(t)+EXP(-t))/2

nhập mô tả hình ảnh ở đây


1

Python 2.7 + matplotlib, 424

Chạy như

python thisscript.py [length] [x0] [y0] [x1] [y1]

Nếu tôi có thể giả sử rằng x0 luôn nhỏ hơn số ký tự x1 giảm xuống còn 398

from numpy import *
from pylab import *
from scipy.optimize import *
import sys
c=cosh
l,p,q,u,w=map(float,sys.argv[1:])
if p>u:
 p,q,u,w=u,w,p,q
h=u-p
v=w-q
a=brentq(lambda a:(2.*h/a*sinh(0.5*a))**2-l**2-v**2,1e-20,600)
b=brentq(lambda b:c(a*(1.-b))-c(a*b)-a*v/h,-600/a,600/a)
r=linspace(p,u,100)
plot([p,u],[q,w],'ro')
plot(r,h/a*c(((r-p)/h-b)*a)-h/a*c(a*b)+q,'k-')
gca().set_xlim((0,100))
gca().set_ylim((0,100))
show()

Số ma thuật 600 mà bạn thấy xuất hiện ở một số nơi là do cosh (x) và sinh (x) bắt đầu tràn vào khoảng x = 710 (vì vậy 600 để giữ một số lề)

Về cơ bản, tôi giải quyết vấn đề trong khung mà dây xích đi qua máng (0,0) và (x1-x0, (y1-y0) / (x1-x0)) và sau đó ánh xạ lại vào khung ban đầu. Điều này cải thiện sự ổn định số rất nhiều .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.