ความตึงเครียดบนกราฟส่วนที่ 1: สตริงหยัก


21

พล็อต Let 's ฟังก์ชันf (x) = sin (πx) + 0.5 บาป (3πx)มากกว่าโดเมน[-3,3] เราสามารถตีความสิ่งนี้ว่าเป็นสายหลวมที่วางอยู่บนกระดาน ตอนนี้ให้ไดรฟ์nเล็บเข้าไปในคณะกรรมการที่ตำแหน่ง(x 1 , y 1 )การ(x n , y n )ที่x ฉัน ∈ (-3,3)และY ฉัน[-1,1] ลองนึกภาพว่ามีรูร้อยสองเส้นที่ส่วนท้ายของสตริงนั่นคือที่ตำแหน่ง(-3,0)และ(3,0). ตอนนี้เราสามารถใช้ปลายสายและดึงผ่านตาไก่จนเชือกตึง สิ่งนี้จะทำให้กราฟของเรากลายเป็นฟังก์ชันเชิงเส้นเป็นเส้นตรง

รูปภาพบางรูปอาจช่วยได้ ใช้ 8 เล็บที่(-2.8, -0.7), (-2.5, -0.9), (-1.2, .2), (-0.5, .8), (0.5, .4), (1.2, -0.9), (1.5 -0.6), (1.8 -0.8) สามแปลงต่อไปนี้แสดงกระบวนการที่อธิบายข้างต้น:

ป้อนคำอธิบายรูปภาพที่นี่

สำหรับรุ่นใหญ่: คลิกขวา -> เปิดในแท็บใหม่

และนี่คือแอนิเมชั่นของการรัดให้แน่นถ้าคุณมีปัญหาในการมองเห็น:

ป้อนคำอธิบายรูปภาพที่นี่

ความท้าทาย

ได้รับรายชื่อของ "เล็บ" (ซึ่งไม่จำเป็นต้องเรียง) ที่พล็อตเล็บเหล่านั้นและสตริงตึงถ้ามันเริ่มต้นจากรูปร่างของฟังก์ชั่นดังกล่าวข้างต้นฉ

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่นและรับอินพุตผ่าน STDIN, ARGV หรืออาร์กิวเมนต์ของฟังก์ชัน คุณสามารถแสดงผลบนหน้าจอหรือบันทึกภาพเป็นไฟล์

หากผลลัพธ์เป็น rasterised จะต้องมีความกว้างอย่างน้อย 300 พิกเซลและสูง 100 พิกเซล ช่วงพิกัดตั้งแต่ (-3, -1.1) ถึง (3,1.1) จะต้องครอบคลุมอย่างน้อย 75% ของขอบเขตแนวนอนและแนวตั้งของภาพ สเกลความยาวของxและyไม่จำเป็นต้องเหมือนกัน คุณต้องแสดงตะปู (ใช้อย่างน้อย 3x3 พิกเซล) และสตริง (กว้างอย่างน้อย 1 พิกเซล) คุณสามารถหรือไม่รวมแกน

สีเป็นตัวเลือกของคุณ แต่คุณต้องมีอย่างน้อยสองสีที่แตกต่าง: หนึ่งสำหรับพื้นหลังและหนึ่งสำหรับเล็บและสายอักขระ (ซึ่งอาจมีสีที่แตกต่างกัน)

คุณอาจสันนิษฐานได้ว่าเล็บทั้งหมดอยู่ห่างจากfอย่างน้อย 10 -5หน่วย(เพื่อให้คุณไม่ต้องกังวลเกี่ยวกับความไม่ถูกต้องของจุดลอยตัว)

นี่คือรหัสกอล์ฟดังนั้นคำตอบที่สั้นที่สุด (เป็นไบต์) ชนะ

ตัวอย่างเพิ่มเติม

นี่คืออีกสองตัวอย่าง (เรียบง่าย):

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

ป้อนคำอธิบายรูปภาพที่นี่

(สตริงเกิดขึ้นพร้อมกับx -axis)

{{-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}}

ป้อนคำอธิบายรูปภาพที่นี่

ต้องการความท้าทายอื่นหรือไม่?

นี่คือส่วนที่สอง!


เราสามารถสมมติว่าเล็บเรียงจากซ้ายไปขวาได้ไหม?
Ell

@Ell Ah จับได้ดี เนื่องจากฉันไม่ได้ระบุไว้เพื่อเริ่มต้นด้วยไม่ ฉันจะอธิบายอย่างนั้น
Martin Ender

คำตอบ:


8

หลาม + 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()

ตัวอย่าง

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)])

ตัวอย่างที่ 1

มันทำงานอย่างไร

สมมติว่าเรารู้ว่าสตริงตึงผ่านสองจุดAและ B (เราสามารถเริ่มต้นด้วย
A = (-3, 0)และB = (3, 0) .) เมื่อเราดึงสตริงมัน "ต้องการ" ที่จะใช้ เส้นทางที่สั้นที่สุดที่เป็นไปได้ระหว่าง และBที่เป็นความนึกคิดส่วนAB อย่างไรก็ตามหากมีเล็บใด ๆ ในพื้นที่ที่ล้อมรอบด้วยฟังก์ชั่น ( บาปπx + ... ) และABดังนั้นอย่างน้อยหนึ่งในนั้นจะต้องปิดกั้นสตริง โดยเฉพาะอย่างยิ่งเล็บที่อยู่ห่างจากABมากที่สุดในพื้นที่ดังกล่าวจะต้องปิดกั้นสตริง ดังนั้นถ้าCคือเล็บนี้เรารู้ว่าสตริงตึงต้องผ่านCนอกเหนือไปจากและB ตอนนี้เราสามารถทำซ้ำกระบวนการสำหรับส่วนACและCBและดำเนินการต่อในรูปแบบนี้จนในที่สุดก็ไม่มีเล็บเข้ามาแทรกแซง นี้เป็นไบนารีหารและพิชิตอัลกอริทึมที่มีเส้นสแกนในแต่ละขั้นตอนจึงมีความซับซ้อนกรณีที่ดีที่สุดของO (n log n)และเลวร้ายที่สุดกรณีความซับซ้อนของO (n 2 )รูปที่ 1


มันผิดพลาดหากรายการคะแนนว่างเปล่า แต่อย่างอื่นที่ไม่ใช่ของฉันนั่นคือความสิ้นหวังอย่างชัดเจน!
feersum

@feersum จับได้ดี คงที่
Ell

3

Python + pylab, 576 ไบต์

ขั้นตอนวิธีการ:

ฉันตีความปัญหาว่าการค้นหาเส้นทางที่สั้นที่สุดจาก(-3, 0)ถึง(3, 0)เช่นนั้นส่วนของเส้นแนวตั้งเชื่อมต่อจุดบนเส้นทางไปยังจุดบนf (x)ไม่เคยข้ามเล็บ

ในแต่ละxที่มีอยู่อย่างน้อยหนึ่งเล็บหาสิ่งที่ผูกพันน้อยบนและขอบเขตล่างที่ยิ่งใหญ่ที่สุดที่ได้รับจากเล็บที่ว่าx พิจารณาคะแนนที่กำหนดโดยขอบเขตเหล่านี้รวมถึงจุดเริ่มต้นและจุดสิ้นสุดเพื่อเป็นจุดยอดในกราฟ เพิ่มขอบด้วยน้ำหนักที่กำหนดโดยปริภูมิแบบยุคลิดระหว่างสองจุดยอดถ้าส่วนของเส้นตรงอยู่ระหว่างขอบด้านบนและด้านล่างสำหรับพิกัด x แต่ละจุด ค้นหาเส้นทางที่สั้นที่สุดบนกราฟนี้

ตัวอย่างที่มี 27 คะแนนสุ่ม:

(-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), 

ตัวอย่างอ่อนแอ

แข็งแรงเล่นกอล์ฟ

สิ่งที่ปรากฏเป็นช่องว่างหลายเยื้องในfor j in R(i&~1)ลูปจริงควรเป็นแท็บ

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 เป็นตัวเลือกที่ฉลาดกว่าแน่นอน :)
Ell
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.