Grafik Üzerindeki Gerginlik, Bölüm I: Dalgalı Bir Dize


21

Let senaryosu bir işlev f (x) = sin (πx) + 0.5 sin (3πx) etki alanında [-3,3] . Bunu bir tahtada yatan gevşek bir dize olarak yorumlayabiliriz. Şimdi n nü tahtaya sürelim (x 1 , y 1 ) ila (x n , y n ) , burada x i ∈ (-3,3) ve y i y [-1,1] . İpin sonunda, (-3,0) ve (3,0) konumlarında iki halka bulunduğunu düşünün.. Şimdi ipin uçlarını alabilir ve ip gergin oluncaya kadar deliklerden geçirebiliriz. Bu, grafiğimizi parçalı bir lineer fonksiyona dönüştürecektir.

Bazı resimler yardımcı olabilir. (-2.8, -0.7), (-2.5, -0.9), (-1.2, .2), (-0.5, .8), (0.5, .4), (1.2, -0.9) 'da 8 çivi alın , (1.5, -6.6), (1.8, -0.8) . Aşağıdaki üç grafik yukarıda açıklanan süreci göstermektedir:

görüntü tanımını buraya girin

Daha büyük sürüm için: Sağ tıklayın -> Yeni sekmede aç

Ve işte görselleştirmede biraz zorluk çekiyorsanız, dizgenin sıkılaştırılmasının bir animasyonu:

görüntü tanımını buraya girin

Meydan okuma

Bir "tırnakların" listesi (verilen sıralamaya dahil değildir) verildiğinde, yukarıdaki f işlevinin şeklinden başlıyorsa, bu tırnakları ve gergin ipi çizin .

Bir program veya fonksiyon yazabilir ve STDIN, ARGV veya fonksiyon argümanı ile giriş yapabilirsiniz. Sonucu ekranda görüntüleyebilir veya görüntüyü bir dosyaya kaydedebilirsiniz.

Sonuç rasterleştirilirse, en az 300 piksel genişliğinde ve 100 piksel yüksekliğinde olması gerekir. Koordinat aralığı (-3, -1.1) ila (3,1.1), görüntünün yatay ve dikey boyutunun en az% 75'ini kapsamalıdır. X ve y'nin uzunluk ölçekleri aynı olmak zorunda değildir. Çivileri (en az 3x3 piksel kullanarak) ve dizeyi (en az 1 piksel genişliğinde) göstermeniz gerekir. Eksenleri içerebilir veya içermeyebilirsiniz.

Renkler sizin seçiminiz, ancak en az iki ayırt edici renge ihtiyacınız var: biri arka plan, diğeri çivi ve dize için (bunlar farklı renklere sahip olabilir).

Tüm tırnakların f'den en az 10-5 birim uzakta olduğunu varsayabilir (böylece kayan noktaların yanlışlığı hakkında endişelenmenize gerek kalmaz).

Bu kod golf, yani en kısa cevap (bayt cinsinden) kazanır.

Daha fazla örnek

İşte iki tane daha (daha basit) örnek:

{{-2.5, 1}, {-1.5, -1}, {-0.5, 1}, {0.5, -1}, {1.5, 1}, {2.5, -1}}

görüntü tanımını buraya girin

(Dize x- ekseni ile çakışmaktadır .)

{{-2.7, -0.5}, {-2.3, -0.5}, {-1.7, 0.5}, {-1.3, 0.5}, {-0.7, -0.5}, {-0.3, -0.5}, {0.5, 1}, {1.5, -1}, {2.5, 1}}

görüntü tanımını buraya girin

Başka bir Challenge ister misiniz?

İşte Bölüm II!


Çivilerin soldan sağa doğru sıralandığını varsayabilir miyiz?
Ell

@Ell Ah, iyi yakala. Başlamak için belirtmediğim için hayır. Bunu açıklığa kavuşturacağım.
Martin Ender

Yanıtlar:


8

piton + Pycairo, 727 708 608, + PyLab, 383

from pylab import*
def f(N):
 def P(u,w,N):
    T=lambda v,p:(C(v-u,p-u)>0)==(C(w-v,p-v)>0)==(C(u-w,p-w)>0);M=[(i,n)for i,n in enumerate(N)if T(V([n[0],sin(pi*n[0])+sin(3*pi*n[0])/2]),n)]
    if M:i,n=max(M,key=lambda n:C(n[1]-u,w-u)**2);M=P(u,n,N[:i])+[n]+P(n,w,N[i+1:])
    return M
 V=array;C=cross;a=V([3,0]);plot(*zip(*([-a]+P(-a,a,map(V,sorted(N)))+[a])));N and scatter(*zip(*N));show()

Örnek

f([(-2.8,-0.7),(-2.5,-0.9),(-1.2,0.2),(-0.5,0.8),(0.5,0.4),(1.2,-0.9),(1.5, -0.6),(1.8, -0.8)])

örnek 1

Nasıl çalışır

Gergin dizenin A ve B iki noktasından geçtiğini bildiğimizi varsayalım (her zaman
A = (-3, 0) ve B = (3, 0) ile başlayabiliriz .) Dizeyi çekerken "almak" ister A ve B arasında mümkün olan en kısa yol , yani ideal olarak AB segmenti . Ancak, fonksiyonla sınırlandırılmış alanda çivi varsa ( sin AB x + ... ) ve AB ise , bunlardan en az birinin ipi engellemesi gerekir. Özellikle, söz konusu alan içinde AB'den en uzak olan tırnak (lar) ipi bloke etmelidir. Bu nedenle, eğer C bu çivi ise, gergin ipin içinden geçmesi gerektiğini biliyoruz.C , A ve B'ye ek olarak . Artık AC ve CB segmentleri için işlemi tekrarlayabiliriz ve sonunda bu şekilde müdahale eden çiviler kalmayana kadar bu şekilde devam edebiliriz. Şekil 1

Bu, her adımda doğrusal bir taramaya sahip bir ikili bölme ve fethetme algoritmasıdır, bu nedenle O (n log n) en iyi durum karmaşıklığına ve O (n 2 ) en kötü durum karmaşıklığına sahiptir .


Noktaların listesi boşsa hata verir. Ama ondan başka, açıkça umutsuz!
feersum

@ feersum İyi yakalamak. Sabit.
Ell

3

Python + pylab, 576 bayt

Algoritma:

Problemi (-3, 0) ' dan (3, 0)' a kadar olan en kısa yolu bulmak olarak yorumladım, öyle ki yoldaki bir noktayı f (x) üzerindeki bir noktaya bağlayan dikey bir çizgi kesimi asla bir çiviyi geçmez.

Her At x en az bir çivi var, en küçük üst bağlanmış ve en büyük, en çivi tarafından verilen bağlı düşük bulmak x . Bu sınırlar tarafından verilen noktaları ve grafikteki köşeler için başlangıç ​​ve bitiş noktalarını düşünün. Her bir ara x koordinatı için aralarındaki çizgi parçası üst ve alt sınırların içine düşerse, iki köşe arasındaki Öklid mesafesinden verilen ağırlığı olan bir kenar ekleyin. Bu grafikteki en kısa yolu bulun.

27 rastgele puan ile örnek:

(-0.367534, -0.722751), (-0.710649, -0.701412), (1.593101, -0.484983), (1.771199, 0.681435), (-1.878764, -0.491436), (-0.061414, 0.628570), (-0.326483, -0.512950), (0.877878, 0.858527), (1.256189, -0.300032), (1.528120, -0.606809), (-1.343850, -0.497832), (1.078216, 0.232089), (0.930588, -0.053422), (-2.024330, -0.296681), (-2.286014, 0.661657), (-0.009816, 0.170528), (2.758464, 0.099447), (-0.957686, 0.834387), (0.511607, -0.428322), (-1.657128, 0.514400), (1.507602, 0.507458), (-1.469429, -0.239108), (0.035742, 0.135643), (1.194460, -0.848291), (2.345420, -0.892100), (2.755749, 0.061595), (0.283293, 0.558334), 

topal örnek

golfed

for j in R(i&~1)Döngüdeki birkaç girinti alanı olarak görünen şey aslında bir sekme olmalıdır.

from pylab import*
P=((3,0),(-3,0))+input()
X=sorted(set(zip(*P)[0]))
l=len(X)*2
if l>4:scatter(*zip(*P[2:]))
f=lambda x:sin(pi*x)+sin(3*pi*x)/2
B=[[max([-9]+[p[1]for p in P if x==p[0]and p[1]<f(x)]),min([9]+[p[1]for p in P if x==p[0]and p[1]>f(x)])]for x in X]
b=zeros(l);b[2:]=inf
v=list(b)
R=range
for i in R(l):
 for j in R(i&~1):
    A=B[j/2][j&1];D,d=B[i/2][i&1]-A,X[i/2]-X[j/2];K=1;c=b[j]+norm((d,D))
    for k in R(j/2+1,i/2):C=A+D/d*(X[k]-X[j/2]);K&=C<B[k][1];K&=C>B[k][0]
    if(c<b[i])&K:b[i]=c;v[i]=j,(X[j/2],A)
l-=2
s=P[:1]
while l/2:l,p=v[l];s+=(p,)
plot(*zip(*s))
show()

Ungolfed

from pylab import*
P = input()
Xn,Yn = zip(*P)
X = set(Xn+(3,-3))
f = lambda x:sin(pi*x)+sin(3*pi*x)/2
ylb = {x: max([-9]+[p[1] for p in P if p[0] == x and p[1] < f(x)]) for x in X}
yub = {x: min([9]+[p[1] for p in P if p[0] == x and p[1] > f(x)]) for x in X}
ylb[-3] = yub[3] = ylb[3] = 0
X = sorted(X)
l = len(X)
best = zeros((l,2))
best[1:] = inf
prev = [ [0,0] for i in range(l) ]
for i in range(l): # calculate min path to X[i] lb or ub
  for ib in 0,1:
    for j in range(i): # point to come from
      for jb in 0,1:
          Y2, Y1 = (ylb, yub)[ib][X[i]], (ylb, yub)[jb][X[j]]
          dy,dx = Y2 - Y1, X[i] - X[j]
          if all([Y1 + dy/dx*(x - X[j]) < yub[x] and Y1 + dy/dx*(x - X[j]) > ylb[x] for x in X[j+1:i]]):
             c = best[j][jb] + (dy**2+dx**2)**.5
             if c < best[i][ib]:
                 best[i][ib] = c
                 prev[i][ib] = j, jb, (X[j], Y1)
j, jb = l-1,0
pts = [(3,0)]
while j:
    j, jb, p = prev[j][jb]
    pts += [p]
plot(*zip(*pts))
scatter(Xn,Yn)
show()

PyLab kesinlikle daha akıllıca bir seçimdi :)
Ell
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.