यह कमरा कैसा है? 🔥 पीटी। 1


25

इस सवाल से संबंधित ।

एक कमरे को परिभाषित किया जाता है (आवश्यक रूप से उत्तल नहीं) गैर-प्रतिच्छेदन बहुभुज, जिसे 2-आयामी निर्देशांक की एक सूचीबद्ध सूची के रूप में व्यक्त किया जाता है। पर्याप्त रूप से उज्ज्वल लाइटबल्ब कमरे के अंदर एक विशिष्ट बिंदु पर रखा गया है, और हर दिशा में प्रकाश का उत्सर्जन करता है। आपका काम कमरे के कुल रोशन क्षेत्र का पता लगाना है। आप किसी भी उचित प्रारूप में इनपुट ले सकते हैं। बहुभुज / कमरे के साथ-साथ प्रकाश स्रोत के निर्देशांक तर्कसंगत अंक हैं। उन्हें दक्षिणावर्त या वामावर्त में लिया जा सकता है, या तो प्रारूप ठीक है। समस्या में परीक्षण मामले को वामावर्त दिया जाता है।

निम्न चित्र में दो उदाहरण कक्ष दिखाई देते हैं, जहां परप्लिश डॉट प्रकाश स्रोत का प्रतिनिधित्व करता है, और छायांकित क्षेत्र प्रबुद्ध क्षेत्र का प्रतिनिधित्व करता है।एक रोशन कमरे - छायांकित क्षेत्र का एक चित्र प्रकाशित किया गया है

परीक्षण का मामला:

(1/2, 18)
(1,3)
(5,1/2)
(7,5)
(12,7)
(16,3)
(15,11)
(8,19)
(3,7)
Light source located at (5,8)
Answer: 815523/6710 ≈ 121.538

यहाँ उस परीक्षण मामले के समाधान का एक चित्रमय चित्रण है। मूल बहुभुज पर नहीं है कि समाधान को परिभाषित करने वाले दो बिंदु हैं (55/61, 363/61) और (856/55, 357/55)। यहाँ छवि विवरण दर्ज करें

यह सूत्र क्षेत्र की गणना में सहायक हो सकता है। https://en.wikipedia.org/wiki/Shoelace_formula

चूंकि यह , बाइट्स में सबसे छोटा कोड जीतता है।


उन उत्सुक लोगों के लिए, भाग 2 को पोस्ट करने में थोड़ा समय लग सकता है क्योंकि यह मुझे चित्र खींचने के लिए हमेशा के लिए ले जाएगा, और मुझे यह भी नहीं पता कि इसे कैसे हल किया जाए।
धांधली

बहुभुज / कमरे के साथ-साथ प्रकाश स्रोत के निर्देशांक तर्कसंगत अंक हैं।
धांधली

वहाँ कोने की संख्या पर एक ऊपरी बाध्य है या अपने कार्यक्रम को सैद्धांतिक रूप से एक असीमित संख्या को संभालने में सक्षम होना चाहिए? साथ ही, आपका कोड-गोल्फ टैग टूट गया है। यह[tag:code-golf]
Veskah

3
आह, पुराने पुराने फावड़े का फार्मूला ! वैसे, हमारे पास वास्तव में MathJax है, इसलिए आपको एक छवि के रूप में सूत्र को एम्बेड करने की आवश्यकता नहीं है।
ग्यूसेप

1
हाँ, उन्हें घड़ी की सूई के लिए गारंटी दी जा सकती है, फिर। परीक्षण का मामला वामावर्त आदेश दिया है, लेकिन मैं इस के अंतर्गत आती है लगता है कि "किसी भी उचित प्रारूप।"
धांधली

जवाबों:


12

पायथन 3 , 388 398 408 409 415 417 493 बाइट्स


इसे और अधिक सटीक बनाने के लिए, बढ़ाएँ n

from random import*
u=uniform
c=lambda A,B,C:(C[1]-A[1])*(B[0]-A[0])>(B[1]-A[1])*(C[0]-A[0])
I=lambda A,B,C,D:c(A,C,D)!=c(B,C,D)and c(A,B,C)!=c(A,B,D)
def a(l,v,n=9**6,s=0):
 g=lambda i:(min(x[i]for x in v),max(x[i]for x in v))
 for _ in'x'*n:
  h=((u(*g(0)),u(*g(1))),l);s+=any([I(*f,*h)for f in list(zip(v,v[1:]+[v[0]]))])^1
 return(abs(g(0)[0]-g(0)[1])*abs(g(1)[0]-g(1)[1]))*float(s/n)

बेसिक मोंटे-कार्लो दृष्टिकोण। नीचे सूचीबद्ध चरण।

  1. एक्स और वाई पर्वतमाला का पता लगाएं कि आकार व्याप्त है।
  2. कोने द्वारा बनाई गई किनारों की एक सूची बनाएं
  3. बड़ी संख्या में Iterate (अधिक बेहतर)
  4. X, y श्रेणी के अंदर एक यादृच्छिक बिंदु (j, k) बनाएँ।
  5. जाँचें कि क्या किनारों में से कोई प्रकाश और यादृच्छिक बिंदु द्वारा बनाए गए रेखा-खंड के साथ अवरोधन करता है। यदि किनारों में से कोई भी अवरोधन होता है, तो चर को बढ़ाएँs
  6. sकुल संख्याओं से विभाजित करें , फिर कुल रेंज क्षेत्र से गुणा करें।

Ungolfed संस्करण:

import random

def ccw(A,B,C):
    return (C[1]-A[1])*(B[0]-A[0]) > (B[1]-A[1])*(C[0]-A[0])

def intersect(A,B,C,D):
    return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)

def lit_area(light, vertices):
    # points: list of points
    # i     : x => i=0
    #       : y => i=1
    get_range = lambda i: (min(x[i] for x in vertices), max(x[i] for x in vertices))
    xr = abs(get_range(0)[0] - get_range(0)[1])
    yr = abs(get_range(1)[0] - get_range(1)[1])

    edges = list(zip(vertices, vertices[1:] + [vertices[0]]))

    num_sims = 1000000

    num_successes = 0
    for _ in range(num_sims):
        guess_x = random.uniform(*get_range(0))
        guess_y = random.uniform(*get_range(1))

        light_guess_line = ((guess_x, guess_y), light)

        if not any([intersect(*e, *light_guess_line) for e in edges]):
            num_successes += 1
    return float(num_successes / num_sims) * (xr * yr)


if __name__ == "__main__":
    points = [
    (1/2, 18),
    (1,3),
    (5,1/2),
    (7,5),
    (12,7),
    (16,3),
    (15,11),
    (8,19),
    (3,7)
    ]
    light_source = (5,8)
    print("Area lit by light: %f"% lit_area(light_source, points))

इसे ऑनलाइन आज़माएं!

लाइन चौराहे एल्गोरिथ्म के लिए क्रेडिट

इसके अलावा, यह भी आगे कैसे गोल्फ के लिए सभी सहायक टिप्पणीकारों को श्रेय।


-2 बाइट्स के लिए पहली पंक्ति from random import*(लाइन ब्रेक) बन सकती हैu=uniform
कॉनर ओ'ब्रायन

1
आप एक ही स्थान के साथ फ़ंक्शन में 4 स्थानों में से प्रत्येक को बदलकर कुछ और बाइट्स दाढ़ी कर सकते हैं, और बाद में अंतरिक्ष को हटा सकते हैंg=lambda i:
कॉनर ओ'ब्रायन

n10 की शक्ति होना जरूरी है? अन्यथा आप एक बाइट को 9 की शक्ति का उपयोग करके बचा सकते हैं
नील ए।

नहीं, 10 की शक्तियों की आवश्यकता नहीं है। मैं आपके सभी सुझावों को कल रखूंगा! तब तक, सभी को वेलेंटाइन डे की शुभकामनाएँ!
JPeroutek

जैसा कि @ ConorO'Brien ने उल्लेख किया है, आप प्रमुख व्हाट्सएप के भार को हटा सकते हैं। और में जगह के अलावा i:(min, अंतरिक्ष में x[i]forभी हटाया जा सकता है। भी, return float(s/n)*(r*t)हो सकता है return(r*t)*float(s/n)। और मैं पूरी तरह यकीन नहीं है, लेकिन चर नहीं कर सकते हैं rऔर eहटा दिया जाना और, सीधे इस्तेमाल के बाद से आप केवल उन्हें एक बार का उपयोग करें? यह किसी भी तरह से थोड़ा अलग परिणाम देता है भले ही gसंशोधित न हो, इसलिए यह हिस्सा मुझे थोड़ा भ्रमित करता है (मैं पायथन से परिचित नहीं हूं यह समझने के लिए कि परिणाम थोड़ा अलग क्यों है)।
केविन क्रूज़सेन

5

हास्केल , 559 618 632 बाइट्स

r(a:b)=b++[a]
s=zip<*>r
(?)a=sum.zipWith(*)a
o(a,b)=r a?b-a?r b
(a,b)!(c,d)=(c-a,d-b)
(a,b)#(c,d)=a*d-b*c
x i a@(e,f)b j c d|let k@(g,h)=a!b;l=c!d;m=c!a;n=l#k;o=m#l/n;p=m#k/n;q|i>0=o<0||o>1|let=o<=0||o>=1;r|n==0||q||p<0||p*j>1=[]|let=[(e+o*g,f+o*h)]=r
(a&b)(c:e@(d:_))|let(f,g)=span(/=d)b;h=zip f$r$f++[d]=concat[[k,l]|(i,j)<-h,[[k],[l]]<-[x 1 i j 0 a<$>[c,d]],and[x 0 m n 1 a o==[]|o<-[k,l],(m,n)<-h,(m,n)/=(i,j)]]++(a&g)e
(_&_)_=[]
z a b=sum[o$unzip[c,a,d]|e@(f:_)<-[[c|c<-b,and[all(==c)$x 1 d e 1 a c|(d,e)<-s b]]],(c,d)<-s$a&until((f==).head)r b$e++[f]]/2

सटीक समाधान (कीड़े को छोड़कर)। हास्केल में बिलकुल सटीक तर्कसंगत अंकगणित है। इसे ऑनलाइन आज़माएं!

ध्यान दें कि यह देता है 815523/6710, 814643/6710उदाहरण के कमरे के लिए नहीं , और पहले दीवार चौराहे के रूप में गणना की जाती है (55/61, 363/61)। मुझे पूरा यकीन है कि यह सही है क्योंकि मोंटे कार्लो प्रविष्टि (धीरे) उसी परिणाम में परिवर्तित होती है।

लीजेंड:

z light roomPoints
    -- Main function, returns lit area.
    -- Compute list of visible corners in the room, then calls (&).
(&) light roomPoints' visibleCorners
    -- Compute visibility polygon. visibleCorners is the subset of points
    -- that are visible from the light. The first point of roomPoints'
    -- must coincide with the first visibleCorner.
x pEndpoints p1 p2 qSegment q1 q2
    -- Intersect line segments (p1, p2) and (q1, q2).
    -- If pEndpoints, exclude endpoints p1, p2.
    -- If not qSegment, allow intersection to extend past q2 (i.e. raycast).
r   -- Rotate list by one, used to construct closed loops etc.
s   -- Construct closed loop
(!) -- Vector between two points
(?) -- Dot product
(#) -- Cross product
o   -- Polygon area

बोनस: ग्लोस जीयूआई परीक्षण के लिए। उन्हें स्थानांतरित करने के लिए बिंदुओं के बगल में क्लिक करें।

import qualified Graphics.Gloss as G
import qualified Graphics.Gloss.Interface.IO.Interact as GI

solnPoly a b|let c@(d:_)=[c|c<-b,and[all(==c)$x 1 d e 1 a c|(d,e)<-s b]]=a&until((d==).head)r b$c++[d]
solnArea = z

main =
  let fromRatP (x, y) = (fromRational x, fromRational y)
      displayScale = 10
      scalePoints = G.scale (fromInteger displayScale) (fromInteger displayScale)
      displayMode = G.InWindow "" (512, 512) (0, 0)
      drawBasePoly pointSz ps =
          mconcat $ G.lineLoop ps :
                    [G.translate x y (G.circleSolid pointSz) | (x, y) <- ps]
      drawVisPolyOf light ps =
          G.color G.blue $ drawBasePoly 0.2 $ map fromRatP $ solnPoly light ps
      drawLight (x, y) =
          G.translate x y $
          G.color G.yellow (G.circleSolid 0.5) <> G.circle 0.5
      draw (light, ps) =
          mconcat [
              scalePoints $ drawLight (fromRatP light),
              scalePoints $ drawBasePoly 0.4 (map fromRatP ps),
              scalePoints $ drawVisPolyOf light ps,
              G.translate (-200) (-50) $ G.scale 0.2 0.2 $
                G.color G.blue $ G.text $ "Lit area: " ++ show (solnArea light ps)
          ]
      event (GI.EventKey (GI.MouseButton GI.LeftButton) GI.Down _ (curx_, cury_)) (light, ps) =
          let dist (x,y) (x',y') = (x'-x)^2 + (y'-y)^2
              curx = curx_ / fromInteger displayScale
              cury = cury_ / fromInteger displayScale
              cursorR = (fromInteger$round curx, fromInteger$round cury)
              maxDist = 3
              snapAmount = 1
              (d, i) = minimum [(dist p cursorR, i) | (p, i) <- zip (light : ps) [0..]]
              snapTo n a = fromInteger$n*round(a/fromInteger n)
              snapCursor = (snapTo snapAmount curx, snapTo snapAmount cury)
              light' | i == 0 && d < maxDist^2 = snapCursor
                     | otherwise = light
              ps' | i > 0 && d < maxDist^2 = take (i-1) ps ++ [snapCursor] ++ drop i ps
                  | otherwise = ps
          in (light', ps')
      event _ state = state
      state0 =
        ((2, 2), [(0, 0), (10, 0), (10, 5), (20, 0), (20, 20), (15, 5),
                  (10, 10), (6, 10), (10, 12), (0, 12), (4, 10), (0, 10)])
  in G.play displayMode G.white 60
            state0
            draw
            event
            (\_ -> id)

स्क्रीनशॉट


दरअसल, आप सही कह रहे हैं। मैंने टाइपो लोल बनाया होगा। उन संख्याओं को थोड़ा अद्यतन करेगा
धांधली

1

एपीएल + विन

यह इस दिलचस्प चुनौती का एक असंयमित संस्करण है जिसे मैं अपने तर्क को प्रदर्शित करने की पेशकश करता हूं। एपीएल + विन का मेरा प्राचीन संस्करण गोल्फिंग नेस्टेड कंट्रोल संरचनाओं के लिए अच्छी तरह से अनुकूल नहीं है। अधिक आधुनिक एपीएल बेहतर - चुनौती दे सकते हैं?

यदि पाठक तर्क को मान्य करते हैं तो मुझे इस समाधान को प्राप्त करने पर ध्यान देना होगा। यदि तर्क गलत है तो मैं बस हटा दूंगा।

r←b Room v

⍝Separate x and y coordinates of vertices               
x←v[;1] ⋄ y←v[;2]

⍝Intercept and slope of each line segment and ray through each vertex
s←(y,¨1⌽y)⌹¨(1E¯9+1,[1.1]¨x,¨1⌽1E¯9+x)
l←(y,¨b[2])⌹¨(1E¯9+1,[1.1]¨x,¨b[1]+1E¯9)                          

⍝Coordinates of vertices
x←x,¨1⌽x ⋄ y←y,¨1⌽y                                                  

⍝Initialise intersection matrix
r←((⍴s),0)⍴0

⍝Evaluate intersection matrix 
:for i :in ⍳⍴l 
    t←0⍴0
    :for j :in ⍳⍴s
        t←t,⍎1⍕∊((↑∊l[i])-↑∊s[j])÷((1↓∊s[j])-1↓∊l[i]) 
    :endfor
    z←r←r,t
:endfor 

⍝Identify x coordinates of valid intersections in the direction of the ray
:for i :in ⍳⍴l 
    t←(r[i;i])
    :for j :in ⍳⍴s
        :if t<b[1] 
            r[j;i]←r[j;i]×(r[j;i]<t)^r[j;i]>⌊/∊x[i]
        :else
            r[j;i]←r[j;i]×(r[j;i]>t)^r[j;i]<⌈/∊x[i]
        :endif
    :endfor
 :endfor

⍝Identify the edges intersected
e←(+/r≠0)/⍳⍴l 

⍝Intersection x coordinates
cx←(+/r)[e]

⍝Intersection y coordinates
cy←⍎1⍕+/¨(s[e])× 1,¨(+/r)[e]

⍝Replace original coordinates that are in shadow
x[e]←(1↓¨x[e]),¨cx
y[e]←(1↓¨y[e]),¨cy

⍝Calculate lit area
r←+/.5×(|-/¨x)×|-/¨y                                               

0

आर , 296 255 बाइट्स

function(s,l,u=cbind(s,s[,1]),d=t(diff(t(u))),q=l-u,r=apply(s,1,range),g=c(diff(r)))mean(replicate(1e6,!any((q[i<-1:ncol(s)*2]*(p=runif(2)*g+r[1,]-u)[j<-i-1]>p[i]*q[j])!=(q[i+2]*p[i+1]>q[i+1]*p[i+2])&(p[i]*d[j]>p[j]*d[i])!=(q[i]*d[j]>q[j]*d[i]))))*prod(g)

इसे ऑनलाइन आज़माएं!

यह पायथन उत्तर का एक और घटा हुआ संस्करण है । कोर मोंटे कार्लो विधि समान है, लेकिन मैंने उन्हें कम करने के लिए कुछ कार्यों को फिर से व्यवस्थित किया। अपने पहले पुनरावृत्ति में, मैं पुनर्व्यवस्थापन में अत्यधिक आक्रामक था, और मुझे तब एहसास हुआ कि मैं अजगर के करीब चौराहे एल्गोरिथ्म के एक संस्करण में लौटकर लंबाई और गति दोनों को अनुकूलित कर सकता हूं।

यहाँ एक अनगुल्ड संस्करण है जो परिणाम भी देता है:

find_lit_ungolf <- function(shape, light, plot = TRUE) {
  lines <- cbind(shape ,shape[,1])
  diffs <- t(diff(t(lines)))
  light_minus_lines <- light - lines
  shape_range <- apply(s,1,range)
  shape_range_diff <- c(diff(shape_range))
  successes <- t(replicate(
    n = 1e5,
    {
      random_point <- runif(2) * shape_range_diff + shape_range[1, ]
      random_minus_lines <- random_point - lines
      q <- light_minus_lines
      p <- random_minus_lines
      d <- diffs
      i <- 1:ncol(s)*2
      success <-
        !any((q[i]*p[i-1]>p[i]*q[i-1])!=(q[i+2]*p[i+1]>q[i+1]*p[i+2])&(p[i]*d[i-1]>p[i-1]*d[i])!=(q[i]*d[i-1]>q[i-1]*d[i]))
      c(random_point, success)
    }))
  colnames(successes) <- c("x", "y", "success")
  if (plot) {
    shape <- t(shape)
    colnames(shape) <- c("x", "y")
    print(ggplot(as_tibble(successes), aes(x, y)) +
      geom_point(aes(colour = factor(success)), alpha = 0.3) +
      geom_polygon(data = as_tibble(shape), alpha = 0.2) +
      annotate("point", light[1], light[2], col = "yellow"))
  }
  mean(successes[, 3]) * prod(shape_range_diff)
}
find_lit_ungolf(s, l)

कमरे में प्रकाश का प्लॉट

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.