शहर: साइटलाइन


18

मैं एक अनंत द्वि-आयामी शहर की स्थिति (0, 0) पर हूं , जो प्रत्येक जाली बिंदु पर केंद्रित ब्लॉकों में विभाजित है, जिनमें से कुछ में इमारतें हैं। एक निश्चित बिंदु पर एक इमारत (x, y) अपनी सीमा सहित (x-.5, y-.5) और (x + .5, y + .5) विपरीत कोनों के साथ पूरे वर्ग को ऊपर ले जाती है। एक इमारत दिखाई देती है अगर इमारत में एक बिंदु पर (0, 0) से कुछ लाइन खंड है जो किसी अन्य इमारत को नहीं काटता है।

उदाहरण के लिए, मैं (a @) *निम्नलिखित शहर में 6 इमारतें ( ) देख सकता हूं :

  *
 *
*
*@
x**
 *  y

मैं इमारत xको (-1, -1) के साथ चिह्नित नहीं देख सकता क्योंकि यह उसके निकटवर्ती दो द्वारा बाधित है; या एक एक के साथ चिह्नित yपर (3, -2) , क्योंकि यह के किनारे से बाधित है (1, -1) निर्माण।

इनपुट

एक बहुस्तरीय स्ट्रिंग, या लाइनों की सूची, वैकल्पिक रूप से एक आयत में रिक्त स्थान के साथ गद्देदार। इसमें केवल शामिल होगा:

  • एक एकल @(मेरी स्थिति)
  • रिक्त स्थान
  • *, जो इमारतों का प्रतिनिधित्व करते हैं।

हमेशा कम से कम एक इमारत होगी, और इसलिए कम से कम एक दृश्यमान इमारत होगी।

उत्पादन

दृश्यमान इमारतों की संख्या।

परीक्षण के मामलों

*@
1

* *******
 @     * 
7

*****
**@**
*****
4

   *
  **
@ **
2

*      *
 *    * 
@
4

@
 *
  ***
1

शीर्षक के लिए @Geobits का धन्यवाद ।



टेस्ट केस 3 के बारे में, यह 8 * से घिरा हुआ है, लेकिन परिणाम 4 है। लेकिन उन कोनों को अन्य इमारतों द्वारा अवरुद्ध नहीं किया जाता है। क्या कोनों को शामिल नहीं करने का नियम है?
लुकस्टॉर्म्स

1
@LukStorms कल्पना करें कि प्रत्येक तारे वास्तव में क्यूब्स हैं, जैसे कि मिनीक्राफ्ट में। यदि आप उसके बीच में खड़े थे, तो आप
ब्लू

क्या आप इनाम देने से पहले मेरे गोल्फ समाधान (बहुत जल्द) में प्रवेश करने से पहले इंतजार करना चाहेंगे? :)
लीफ विलर्ट्स

जवाबों:


4

एकता + सी #, 589 बाइट्स

कोड गोल्फ को करने के लिए यह संभवतः सबसे खराब भाषा है (पढ़ें: जावा से भी बदतर), लेकिन एकता इस चुनौती के लिए बहुत सहायक सुविधाएँ लेकर आई है।

संपादित करें: रिक्त स्थान की एक जोड़ी याद आती है, सूची की लंबाई, काउंटर नहीं

golfed:

using UnityEngine;using System.Collections;public class c:MonoBehaviour{public int h(string[]i){ArrayList k=new ArrayList();for(int y=0;y<i.Length;y++){char[]l=i[y].ToCharArray();int x=0;foreach(char c in l){if(c=='*'){GameObject b=GameObject.CreatePrimitive(PrimitiveType.Cube);b.transform.position=new Vector3(x,y);}if(c=='@')transform.position=new Vector3(x,y);x++;}}for(int n=0;n<3600;n++){RaycastHit h;Physics.Raycast(transform.position,Quaternion.Euler(0,0,n/10)*Vector3.up,out h);if(h.collider!=null){GameObject o=h.collider.gameObject;if(!k.Contains(o))k.Add(o);}}return k.Count;}}

Ungolfed:

using UnityEngine;
using System.Collections;

public class citiessightlines : MonoBehaviour {

    public ArrayList todelete;   // Anything concerning this array just has to do with cleanup of 
                                 //objects for testing, and doesn't contribute to the byte count.
    void Start()
    {
        todelete = new ArrayList();
    }
    public int calcSight(string[]input)
    {
        todelete = new ArrayList();
        int total = 0;
        ArrayList check = new ArrayList();
        for (int y=0;y < input.Length; y++)
        {
            char[] line = input[y].ToCharArray();
            for (int x = 0; x < line.Length; x++)
            {
                char c = line[x];
                if (c == '*')
                {
                    GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    cube.transform.position = new Vector3(x, y);
                    todelete.Add(cube);
                }
                if (c == '@')
                {
                    transform.position = new Vector3(x, y);
                }
            }
        }
        for (int angle=0; angle < 3600; angle++)
        {
            RaycastHit hit;
            Physics.Raycast(transform.position, Quaternion.Euler(0, 0, angle/10) * Vector3.up, out hit);
            if (hit.collider!=null)
            {
                GameObject hitObject = hit.collider.gameObject;
                if (!check.Contains(hitObject)&&hitObject!=this)
                {
                    total += 1;
                    check.Add(hitObject);
                }
           }
        }
        return total;
    }
}

मैंने 3600 रेकास्ट का उपयोग किया, क्योंकि यह 5 वें परीक्षण के मामले में कम है। यह अभी भी बड़े / अधिक सटीक परीक्षण मामलों के लिए विफल हो सकता है।

दुर्भाग्य से, दोनों वेबलॉग और डेस्कटॉप बिल्ड टूटने लगते हैं, इसलिए मेरे पास जीथब पर परीक्षण करने के लिए स्रोत कोड है ।


read: worse than Javaयह जावा समाधान की तुलना में 383 बाइट्स छोटा है!
user8397947

@dorukayhan मेरा मतलब है कि ज्यादातर बिल्ट-इन जावा की तुलना में अधिक वर्बोज़ हैं
ब्लू

मैं के बारे में सी # पता नहीं है, लेकिन आप को बदल नहीं सका total+=1के साथ total++? मुझे लगता है कि कुछ पात्रों को बचाने का एक और तरीका यह है कि भवन के घन को बनाया जाए और इसे एक कथन में स्थान दिया जाए। आप cubeकहीं भी चर का पुन: उपयोग नहीं करते हैं ।
फ्रोज़न

@ फ़िरोज़ मैं वास्तव में अपने गोल्फ कोड
ब्लू

बस कोड को देखा और देखा कि आपने वहां गिनती बदल दी है। मैं हमेशा यह मानता हूं कि गोल्फ वाला संस्करण लंबे समय तक चलने वाला व्हाट्सएप संस्करण है, लेकिन जाहिर है कि यहां ऐसा नहीं है। दूसरे भाग के बारे में: मुझे लगता है कि आप करते हैं। यह है GameObject b=GameObject.CreatePrimitive(PrimitiveType.Cube);b.transform.position=new Vector3(x,y);। मुझे नहीं पता कि यह C # में संभव है लेकिन जावा में GameObject.CreatePrimitive(PrimitiveType.Cube).transform.position=new Vector3(x,y);इसके बजाय लिख सकते हैं ।
फ्रोज़न

3

जावा 8 लैम्ब्डा, 1506 1002 972 942 अक्षर

मैं इस चुनौती को हराना चाहता था, क्योंकि यह बहुत दिलचस्प है। परिणाम (बहुत गोल्फ नहीं) यहाँ देखा जा सकता है:

import java.util.*;f->{Set<double[]>B=new HashSet(),r,n;double a,M,m,P=Math.PI*2,z=.5;int x=0,y,v=0,i,j,c[],p,q,l=g.length;for(;x<l;x++)for(y=0;y<g[x].length;y++)if(g[x][y]>63)for(;;){c=new int[]{-1};M=2e31-1;for(i=0;i<l;i++)for(j=0;j<g[i].length;j++)if(g[i][j]==42)if((m=(p=x-i)*p+(q=y-j)*q)<M){M=m;c=new int[]{i,j};}if(c[0]<0)break;g[c[0]][c[1]]=0;double[]A={(a=Math.atan2((c[1]-=y)-z,(c[0]-=x)-z))<0?a+P:a,(a=Math.atan2(c[1]+z,c[0]-z))<0?a+P:a,(a=Math.atan2(c[1]+z,c[0]+z))<0?a+P:a,(a=Math.atan2(c[1]-z,c[0]+z))<0?a+P:a};r=new HashSet();M=-P;m=P;for(double d:A){M=d>M?d:M;m=d<m?d:m;}r.add(new double[]{m,M});for(double[]t:B){n=new HashSet();for(double[]h:r)for(double[]u:t[0]<h[0]?t[1]<h[0]?new double[][]{h}:t[1]<h[1]?new double[][]{{t[1],h[1]}}:new double[0][]:t[0]>h[1]?new double[][]{h}:t[1]>h[1]?new double[][]{{h[0],t[0]}}:new double[][]{{h[0],t[0]},{t[1],h[1]}})if(u[0]<u[1])n.add(u);r=n;}B.addAll(r);if(!r.isEmpty())v++;}return v;}

बेशक यह भी ungolfed संस्करण में मौजूद है:

import java.util.*;

public class AngleCheck {

    static int getViewableBuildingsC(char[][] grid) {

        Set<double[]> blocked = new HashSet(), ranges, newRanges;

        double angle, max, min, PI2 = Math.PI * 2, half = 0.5;

        int x = 0, y, viewable = 0, i, j, building[], dX, dY, length = grid.length;

        for (; x < length; x++) {
            for (y = 0; y < grid[x].length; y++) {
                if (grid[x][y] > 63) {
                    for (;;) {
                        building = new int[]{-1};
                        max = 2e31-1;
                        for (i = 0; i < length; i++) {
                            for (j = 0; j < grid[i].length; j++) {
                                if (grid[i][j] == 42) {
                                    if ((min = (dX = x - i) * dX + (dY = y - j) * dY) < max) {
                                        max = min;
                                        building = new int[]{i, j};
                                    }
                                }
                            }   
                        }

                        if (building[0] < 0)
                            break;

                        grid[building[0]][building[1]] = 0;
                        double[] angles = {
                                        (angle = Math.atan2((building[1] -= y) - half, (building[0] -= x) - half)) < 0 ? angle + PI2 : angle,
                                        (angle = Math.atan2(building[1] + half, building[0] - half)) < 0 ? angle + PI2 : angle,
                                        (angle = Math.atan2(building[1] + half, building[0] + half)) < 0 ? angle + PI2 : angle,
                                        (angle = Math.atan2(building[1] - half, building[0] + half)) < 0 ? angle + PI2 : angle};

                        ranges = new HashSet();

                        max = -PI2;
                        min = PI2;
                        for (double d : angles) {
                            max = d > max ? d : max;
                            min = d < min ? d : min;
                        }

                        ranges.add(new double[]{min, max});

                        for (double[] reference : blocked) {
                            newRanges = new HashSet();
                            for (double[] currentRange : ranges) {
                                for (double[] subRange : reference[0] < currentRange[0] ?
                                            reference[1] < currentRange[0] ?
                                                // whole range after referencerange
                                                new double[][]{currentRange}
                                            :
                                                reference[1] < currentRange[1] ?
                                                    // lower bound inside referencerange, but upper bound outside
                                                    new double[][]{{reference[1], currentRange[1]}}
                                                :
                                                    // whole range inside referencerange -> nothing free
                                                    new double[0][]
                                        :
                                            // greater or equal lower bound
                                            reference[0] > currentRange[1] ?
                                                // whole range before referencerange
                                                new double[][]{currentRange}
                                            :
                                                // ranges overlap
                                                reference[1] > currentRange[1] ?
                                                    // range starts before and ends in reference range
                                                    new double[][]{{currentRange[0], reference[0]}}
                                                :
                                                    // referencerange is in the range -> two free parts, one before, one after this
                                                    new double[][]{{currentRange[0], reference[0]}, {reference[1], currentRange[1]}}) {
                                    if (subRange[0] < subRange[1])
                                        newRanges.add(subRange);
                                }
                            }
                            ranges = newRanges;
                        }

                        blocked.addAll(ranges);
                        if (!ranges.isEmpty()) {
                            viewable++;
                        }
                    }
                }
            }
        }
        return viewable;
    }
}

तो यह बहुत मुश्किल लग रहा है, लेकिन यह जिस तरह से सोच सकता है उससे ज्यादा आसान है। मेरा पहला विचार कुछ चौराहे एल्गोरिदम का उपयोग करके यह जांचने के लिए था कि क्या मेरी स्थिति से इमारत तक कोई रेखा बिना किसी चौराहे के बनाई जा सकती है। ऐसा करने के लिए मैंने कोहेन-सदरलैंड एल्गोरिथ्म का उपयोग करने और इमारत के सभी चारों कोनों तक लाइनें खींचने का फैसला किया। इसने पहले परीक्षणों के लिए बहुत अच्छा काम किया, लेकिन अंतिम असफल रहा। मुझे जल्द ही पता चला, कि यह एक ऐसा मामला है जहाँ आप कोनों को नहीं बल्कि एक किनारे का हिस्सा देख सकते हैं। तो मैंने सोचा कि कुछ प्रकार की किरण के बारे में @Blue ने ऐसा किया है। मैंने उस चुनौती को दूर रखा, क्योंकि मुझे कुछ प्रगति नहीं मिली। फिर मैंने ब्लू का उत्तर देखा और मेरे दिमाग में निम्नलिखित सरल विचार आया: प्रत्येक इमारत कुछ कोण को अवरुद्ध करती है जिसमें कुछ और नहीं देखा जा सकता है। मुझे सिर्फ इस बात पर नज़र रखने की ज़रूरत है कि अन्य इमारतों द्वारा क्या देखा जा सकता है और क्या पहले से ही छिपा हुआ है। बस!

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

कभी-कभी सीमाएं इस तरह से ओवरलैप हो सकती हैं कि मैं 0 डिग्री की सीमा के साथ समाप्त हो जाए। इन श्रेणियों को गलत तरीके से एक इमारत जोड़ने के लिए फ़िल्टर किया जाएगा जो देखने योग्य भी नहीं है।

मुझे आशा है कि किसी ने इस स्पष्टीकरण को समझा :)

मुझे पता है कि यह कोड बहुत अधिक नहीं है, मैं इस asap करूँगा।

यह वास्तव में चुनौतीपूर्ण कार्य था। आपने सोचा था कि आपको एक समाधान मिला है जो काम करता है लेकिन इसके बजाय आप अभी भी दूर हैं। मुझे लगता है कि यह समाधान बहुत अच्छा काम करता है। यह बहुत तेज़ नहीं है, लेकिन कम से कम यह काम करता है;) उस पहेली के लिए धन्यवाद!


अपडेट करें

मैंने पूरी चीज़ को एक ही फंक्शन में नीचे गिराने का समय पाया, जिसे इस प्रकार एक मेमने में बदल दिया जा सकता है। सभी कार्यों को केवल एक बार बुलाया गया था और इस प्रकार एक विधि में रखा जा सकता है। मैं सूचियों से लेकर सेट तक स्विच करता हूं क्योंकि यह कुछ अतिरिक्त पात्रों को बचाता है। घोषणाओं को एक साथ रखा गया है। तुलनाओं को एक साथ रखा गया है और पात्रों को वहां एएससीआई मूल्य से बदल दिया गया है। तुलना करने वाली सीमा को कई ternaries के रूप में व्यक्त किया जा सकता है। यहाँ पर कुछ ट्रिक्स दिए गए हैं ताकि डबल.NEGATIVE_INFINITY जैसे लंबे एक्सप्रेशन को रोका जा सके। जहां संभव इनलाइन असेस्मेंट किए जाते हैं। थोड़ा और अधिक बचाने के लिए मैंने कोणों को डिग्रियों की तुलना में रेडियों की तुलना करने से रोका। पूरे बदलाव ने 500 से अधिक पात्रों को बचाया, मुझे उम्मीद है कि यह सब 1000 से कम होगा;)

मैंने उन जेनेरिक को हटा दिया जहां संभव हो और एक तत्व एरे को बनाकर वापसी की तुलना को छोटा कर दिया और इसके बदले मान की जांच की। मैंने PI.2 और -PI2 के साथ Double.NEGATIVE_INFINITY को भी बदल दिया क्योंकि ये कोण के ऊपरी और निचले सीमा हैं। अब यह अंततः 1000 वर्णों से कम लंबा है!

मैंने कुछ वर्णों को सहेजने के लिए व्यक्तियों के स्थान और भवन की खोज के लिए छोरों को मिला दिया। दुर्भाग्य से हमें लूप से रिटर्न को स्थानांतरित करने की आवश्यकता है और अभी भी एक ब्रेक का उपयोग करें लेकिन इस बार लेबल के बिना। मैं विलय कर दिया maxऔर distanceSquaredऔर minऔर newDistanceSquaredके रूप में वे एक ही समय में आवश्यकता नहीं है। मैं बदल Integer.MAX_VALUEगया 2e31-1। इसके अलावा मैंने एक स्थिरांक बनाया half = 0.5जिसका उपयोग भवन के कोनों की गणना करने के लिए किया जाता है। यह गोल्फ वाले संस्करण में छोटा है। कुल मिलाकर हमने एक और 30 अक्षर बचाए!


अच्छा गोल्फ! मैंने सभी अंतर्निहित रेकास्टिंग के साथ एक आसान मार्ग लिया, लेकिन यह जानने में अच्छा था कि मैंने मदद की! (BTW मैं शायद के रूप में अच्छी तरह से सेट करने के लिए बदल जाएगा)
ब्लू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.