2-आयामी किरण अनुरेखण


9

चुनौती 2-आयामी किरण अनुरेखण कार्यक्रम, पाठ-आधारित को लागू करना है।

सफेद रोशनी के स्रोत @प्रतीक हैं। R, Gऔर Bहल्के फिल्टर हैं। /और \80% परावर्तकता वाले दर्पण हैं। ?एक प्रकाश संवेदक है। >, <, ^और Vउचित दिशा में प्रकाश गठबंधन (जैसे अगर एक लाल और एक हरे रंग की एक में आया >सही की ओर उत्सर्जित किया जाएगा प्रकाश और यह पीला हो जाएगा)। अन्य गैर-व्हाट्सएप पात्र सभी प्रकाश को अवशोषित करते हैं। चार दिशाओं @में प्रतीकों से प्रकाश उत्सर्जित होता है ।

जब प्रोग्राम चलाया जाता है, तो उसे आउटपुट का इनपुट के समान उत्पादन करना चाहिए, लेकिन ट्रैस किरणों के साथ। क्योंकि यह 2 आयामी है, और मैं इनपुट में गारंटी देता हूं कि कोई भी किरण कभी भी पार नहीं होगी, इसके साथ कोई समस्या नहीं होगी। प्रत्येक किरण को एक पत्र द्वारा दर्शाया जाना चाहिए; आर = लाल, जी = हरा, बी = नीला, सी = सियान, एम = मैजेंटा, वाई = पीला, डब्ल्यू = सफेद। कभी भी कोई तीखा रंग नहीं होगा। आवरण को इनपुट से अलग करना महत्वपूर्ण है। उस आउटपुट के बाद, प्रश्न चिह्न (उनकी उपस्थिति के क्रम में, बाएं से दाएं ऊपर से नीचे तक) द्वारा कैप्चर किए गए प्रकाश के मूल्यों को प्रतिशत और रंगों के रूप में आउटपुट किया जाना चाहिए। उदाहरण के लिए, यह इनपुट:

 /                  @
                    -
 \R>                 ?

 @B/

आउटपुट देना चाहिए:

 /wwwwwwwwwwwwwwwwww@w
 w                  -
w\R>mmmmmmmmmmmmmmmmm?
 w b
 @B/

#1: 72% Magenta

ध्यान देने के लिए एक और महत्वपूर्ण बिंदु - जब दो रंगों को एक "प्रिज्म" (तीर) का उपयोग करके संयोजित किया जाता है, तो संयुक्त प्रकाश की ताकत दो की औसत ताकत बन जाती है। आउटपुट बिल्कुल निर्दिष्ट होना चाहिए (जैसे #x: [x] [x] x% रंग )।

यदि आपकी भाषा STDIN से नहीं पढ़ सकती है और STDOUT पर लिख सकती है, तो एक फ़ंक्शन (अनाम या लंबोदा उपलब्ध होने पर) बनाएं जो इनपुट को एक तर्क के रूप में स्वीकार करता है और परिणाम देता है।

संकलक को निर्देश, भाषा में बनाए गए सभी या अधिकांश कार्यक्रमों के लिए आवश्यक या अनुशंसित संरचनाएं छोड़ी जा सकती हैं। उदाहरण के लिए, #includeऔर usingनिर्देश (लेकिन नहीं #define) सी-स्टाइल भाषाओं में, #/usr/bin/perl -optionsपर्ल में और हटाए जा सकते हैं

 Module Module1
      Sub Main()
      End Sub
 End Module

उदाहरण के लिए, VB.NET में। यदि आप नाम स्थान आयात करते हैं या निर्देशों को शामिल करते हैं, तो कृपया उन्हें अपने उत्तर में नोट करें।

क्या यह काफी कठिन है, अब? :)


कोड गोल्फ से संबंधित : स्टैक ओवरफ्लो पर लेजर
dmckee --- पूर्व-मध्यस्थ ने

आपके उदाहरण में दर्पण के व्यवहार का कोई मतलब नहीं है। आपके पास a \ _ (भागने से टूट गया है) प्रकाश को प्रभावित करता है जो सीधे अतीत में जा रहा है। यह बहुत अधिक समझदार प्रतीत होता है कि प्रकाश एक ही पंक्ति में दर्पण के रूप में आता है और एक ही स्तंभ पर छोड़ देता है, या इसके विपरीत। इसी तरह >प्रकाश कैप्चर कर रहा है जो सीधे अतीत में जा रहा है। और अगर wऊपर से उस के माध्यम से जाता है R, तो bनीचे से चाहिए । अंत में (मुझे लगता है), आप किरणों को पार नहीं करने के बारे में गलत हैं। एक-पंक्ति का उदाहरण देने के लिए, सही आउटपुट क्या होगा @R> B@?
पीटर टेलर

आपने एक यादृच्छिक w क्यों जोड़ा और सभी रिक्ति को तोड़ दिया? और प्रकाश सीधे अतीत में नहीं जा रहा है, यह निश्चित नहीं है कि आपका क्या मतलब है।
Ry-

@ मिनिटेक, कि @नीचे-बाएँ चारों दिशाओं में प्रकाश उत्सर्जित करता है, है ना? तो विशेष रूप से, यह उस का उत्सर्जन करता है w। और मैंने किसी भी रिक्ति को नहीं तोड़ा है, कम से कम क्रोमियम में प्रस्तुत किया है। सीधे अतीत में जाने के कारण, मेरा संपादन स्पष्ट हो सकता है।
पीटर टेलर

5
minitech: भविष्य के कार्यों के लिए एक सलाह के रूप में: सबसे पहले सैंडबॉक्स या पज़ल लैब में टिप्पणियों के लिए पूछें, जो असंगतताओं और कार्यों के साथ शुरुआती समस्याओं का सामना करने के लिए पर्याप्त होना चाहिए। इस तरह, एक बार जब आप यहां कार्य पोस्ट करते हैं, तो आपको पता चल जाएगा कि यह पहले से ही कुछ अन्य लोगों द्वारा चेक किया गया है (और शायद कार्यान्वित किया गया है)।
जॉय

जवाबों:


2

पायथन, 602 559 614 चार्ट

import sys
S=sys.stdin.readlines()
X=max(len(s)for s in S)
I='#'*X+''.join(t[:-1]+' '*(X-len(t))+'\n'for t in S)+'#'*X
L=len(I)
R=range(L)
B=[0]*L
C=[0]*L
for p in R:
 if'@'!=I[p]:continue
 for d in(1,-1,X,-X):
  q=p;c=7;b=100.
  while 1:
   q+=d;a=I[q];B[q]+=b;C[q]|=c
   if a in'\/':d=(ord(a)/30-2)*X/d;b*=.8
   elif a in'RGB':c&=ord(a)/5-12
   elif a in'><^V':d={'>':1,'<':-1,'^':-X,'V':X}[a];b/=2
   elif' '!=a:break
print''.join(I[p]if' '!=I[p]else' bgcrmyw'[C[p]]for p in R[X:-X])
i=0
for p in R:
 if'?'==I[p]:i+=1;print'#%d:'%i,'%.0f%%'%B[p],[0,'Blue','Green','Cyan','Red','Magenta','Yellow','White'][C[p]]

संपादित करें: इसलिए इसे रिक्त स्थान की आवश्यकता नहीं है।


लगभग - लेकिन परीक्षण मामले का परिणाम गलत है। देखें: ideone.com/kUTxE । +1 वैसे भी, यह बहुत अच्छा है !!!
Ry-

@ मिनिटेक: मुझे लगता है कि यह ट्रेलिंग रिक्त स्थान की कमी के साथ करना है। मेरा कोड मानता है कि प्रत्येक पंक्ति एक ही लंबाई है, यदि आवश्यक हो तो रिक्त स्थान के साथ गद्देदार। क्या यह मामला नहीं है? यदि ऐसा है, तो आप कैसे जानते हैं, उदाहरण के लिए, ऊपरी प्रकाश स्रोत दाईं ओर कैसे जाता है?
कीथ रान्डेल

इसे पैड करने के लिए सबसे लंबी लाइन की लंबाई का उपयोग करके, आप पूरे ग्रिड का पता लगा सकते हैं। हालाँकि, रिक्त स्थान के साथ गद्देदार होने पर भी, यह इसे (इनपुट # 4) देता है: ideone.com/kUTxE
Ry-

@ मिनिटेक: आपको 4 वीं पंक्ति में एक स्थान याद आ रहा है। मैं अपना कोड ठीक करूंगा ताकि अनुगामी रिक्त स्थान की आवश्यकता न हो।
कीथ रान्डेल

ओह, वाह यह काम करता है !! बहुत बढ़िया। लेकिन हाँ, यह अच्छा होगा अगर इसे पैडिंग की आवश्यकता नहीं है।
Ry-

2

एफ #

#nowarn "0025"

open System

type MirrorDirection = bool
type LightDirection = bool * bool
type Sq =
  | Air // [ ]
  | Mirror of MirrorDirection // [/] [\]
  | FilterR
  | FilterG
  | FilterB
  | Sensor // [?]
  | Combine of LightDirection // [^] [v] [<] [>]
  | Emitter // [@]
  | Wall of Char // non-whitespace

let [ mL; mR ] : MirrorDirection list = [ true; false ]
(* true T^/
       F</>F
        /vT   false
 *)
let [ dN; dS; dW; dE ] : LightDirection list = [ true, true; false, true; true, false; false, false ]
let bounce (m : MirrorDirection) ((a, b) : LightDirection) =
  m <> a, not b

let dv (a : LightDirection) =
  if a = dN then 0, -1
  elif a = dS then 0, 1
  elif a = dW then -1, 0
  else 1, 0

let fo<'a> : (('a option)[,] -> 'a seq) =
  Seq.cast
  >> Seq.filter Option.isSome
  >> Seq.map Option.get

let input = Console.In.ReadToEnd().Replace("\r\n", "\n")
let sqs =
  input.Split('\n')
  |> Array.map (fun x ->
    x.ToCharArray()
    |> Array.map (
      function
      | ' ' | '\t' | '\v' -> Air
      | '/' -> Mirror mL
      | '\\' -> Mirror mR
      | 'R' -> FilterR
      | 'G' -> FilterG
      | 'B' -> FilterB
      | '?' -> Sensor
      | '^' -> Combine dN
      | 'v' -> Combine dS
      | '<' -> Combine dW
      | '>' -> Combine dE
      | '@' -> Emitter
      | x -> Wall x
    )
  )

let w =
  Array.map Array.length sqs
  |> Set.ofArray
  |> Set.maxElement
let h = sqs.Length

let ib x y = -1 < x && x < w && -1 < y && y < h

let arr = Array2D.init w h (fun x y ->
  if x < sqs.[y].Length then
    sqs.[y].[x]
  else
    Air
)

let board =
  Array2D.map (
    function
    | _ -> 0.0, 0.0, 0.0
  ) arr

let mutable rays =
  Array2D.mapi (fun x y a ->
    match a with
    | Emitter -> Some(x, y)
    | _ -> None
  ) arr
  |> fo
  |> Seq.map (fun (x, y) ->
    [|
      dN, x, y, 1., 1., 1.
      dS, x, y, 1., 1., 1.
      dW, x, y, 1., 1., 1.
      dE, x, y, 1., 1., 1.
    |]
  )
  |> Seq.reduce Array.append

for i = 0 to w * h * 2 do
  rays <-
    rays
    |> Array.map (
      (fun (dir, x, y, r, g, b) ->
        let dx, dy = dv dir
        dir, x + dx, y + dy, r, g, b
      )
      >> (fun (dir, x, y, r, g, b) ->
        if ib x y then
          match arr.[x, y] with
          | Wall _ -> Array.empty
          | Sensor -> [| dir, x, y, r, g, b |]
          | FilterR -> [| dir, x, y, r, 0., 0. |]
          | FilterG -> [| dir, x, y, 0., g, 0. |]
          | FilterB -> [| dir, x, y, 0., 0., b |]
          | Mirror d -> [| bounce d dir, x, y, r * 0.8, g * 0.8, b * 0.8 |]
          | _ -> [| dir, x, y, r, g, b |]
        else
          Array.empty
      ))
    |> Array.concat
  Array2D.mapi (fun x y a ->
    match a with
    | Combine d -> Some(x, y, d)
    | _ -> None
  ) arr
  |> fo
  |> Seq.iter (fun (x, y, d) ->
    for i = 0 to rays.Length - 1 do
      let (d', x', y', r, g, b) = rays.[i]
      if x' = x && y' = y then
        rays.[i] <- (d, x, y, r, g, b)
  )
  for d, x, y, r, g, b in rays do
    if ib x y then
      match board.[x, y] with
      | r', g', b' -> board.[x, y] <- r + r', g + g', b + b'

printfn "%s" (
  let mutable s = ""
  for y = 0 to h - 1 do
    for x = 0 to w - 1 do
      s <- s + (match arr.[x, y] with
                | Air ->
                  match board.[x, y] with
                  | r, g, b ->
                    if r + g + b = 0.0 then ' '
                    else
                      if g = 0.0 && b = 0.0 then 'r'
                      elif r = 0.0 && b = 0.0 then 'g'
                      elif r = 0.0 && g = 0.0 then 'b'
                      elif r = 0.0 then 'c'
                      elif g = 0.0 then 'm'
                      elif b = 0.0 then 'y'
                      else 'w'
                | Wall z -> z
                | Mirror z -> if z = mL then '/' else '\\'
                | FilterR -> 'R'
                | FilterG -> 'G'
                | FilterB -> 'B'
                | Sensor -> '?'
                | Combine z -> if z = dN then '^' elif z = dS then 'v' elif z = dW then '<' else '>'
                | Emitter -> '@'
                |> sprintf "%c")
    s <- s + "\n"
  s
)

Array2D.mapi (fun x y a ->
  match a with
  | Sensor -> Some(x, y)
  | _ -> None
) arr
|> fo
|> Seq.iteri (fun i (x, y) ->
  let (r, g, b) = board.[x, y]
  let desc =
    if r + g + b = 0.0 then "None"
    elif g = 0.0 && b = 0.0 then "Red"
    elif r = 0.0 && b = 0.0 then "Green"
    elif r = 0.0 && g = 0.0 then "Blue"
    elif r = 0.0 then "Cyan"
    elif g = 0.0 then "Magenta"
    elif b = 0.0 then "Yellow"
    else "White"
  let avg = int((r + g + b) * 100.0 / (match desc with
                                       | "White" | "None" -> 3.0
                                       | "Red" | "Green" | "Blue" -> 1.0
                                       | _ -> 2.0))
  printfn "#%d: %d%% %s" (i + 1) avg desc
)

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