Rette die Gänse vor dem Aussterben

13

Die als Alex A bekannten Gänse sind dafür bekannt, dass sie in dreieckigen Gittern mit 64 Zellen leben:

Zellen
(Bild aus diesem nicht verwandten Project Euler-Problem .)

Wir beschriften jede Zelle mit den Nummern 0, 63die in der obersten Zeile beginnen und dann in jeder Zeile darunter von links nach rechts gehen. So ist die obere Zelle 0und die untere rechte Zelle 63.

Jede Zelle hat drei Ränder. Wir können jede Grenze in der Form etikettieren , a,bwo aund bsind die Zahlen der Zellen dieser Anteil die Grenze. Zum Beispiel die Grenze zwischen Zelle 0und 2würde 0,2oder heißen 2,0(es ist egal, in welcher Reihenfolge Sie sie eingeben).

Das Beschriftungssystem für Ränder am Rand des Rasters unterscheidet sich, da die Zellen am Rand des Rasters einen Rand haben, den sie nicht mit anderen Zellen gemeinsam haben. Wenn ein Rand nur ein Teil einer Zelle ist, verwenden wir den Buchstaben X. Zum Beispiel können die drei Ränder der Zelle 0sind 0,2, 0,Xund 0,X.

Einige der Zellen enthalten Gänse . Diese Gänse werden jedoch von bösen Füchsen (die von außerhalb des Gitters kommen) getötet, wenn Sie sie nicht schützen. Und wenn alle Gänse sterben, wird BrainSteel traurig sein. Deshalb werden wir ein Programm schreiben, das die Gänse umzäunt, um sie vor den Füchsen zu schützen. Die Gänse sollten in einem einzigen vollständig umschlossenen Polygon von Zäunen existieren. Unser Zaunbudget ist ziemlich niedrig, verwenden Sie also die geringstmögliche Anzahl von Zäunen.

Eingabebeschreibung

Eine Liste von Zahlen, die durch Kommas von 0bis getrennt sind 63und die Zellen darstellen, die Gänse enthalten. Beispiel:

6,12

Ausgabebeschreibung

Eine Liste von Grenzen, auf denen Zäune gebaut werden müssen, um die Gänse erfolgreich zu schützen. Dies sollte die kleinstmögliche Anzahl von Zäunen sein. Beispiel:

5,6 6,7 11,12 12,13 
Absinth
quelle
"Die Gänse sollten in einem vollständig geschlossenen Polygon von Zäunen existieren." Müssen alle Gänse im selben Polygon leben oder kann es mehrere (oder 0) Polygone geben?
Feersum
@feersum Alle Gänse sollten im selben Polygon leben. Ich habe die Frage bearbeitet, um es klar zu machen.
Absinth
@Katya Kann das Polygon Schnittpunkte oder Abschnitte mit null Breite haben? Denken Sie wie eine Sanduhrform.
Orlp
@orlp Was ist ein Abschnitt mit der Breite Null?
Absinth
2
@orlp Das Polygon sollte keine Abschnitte mit der Breite Null enthalten.
Absinth

Antworten:

10

C #, 530 Bytes

Vollständiges C # -Programm, Eingabe als einzelne Zeile von STDIN und Ausgabe einer einzelnen Zeile an STDOUT mit einem abschließenden "".

Das ist ziemlich lang ... und hat viel zu viele x / y / z-Wiederholungen, aber ich konnte es bisher nicht auf irgendetwas Sinnvolles reduzieren und habe eine Prüfung in 2 Stunden, könnte morgen darauf zurückkommen.

using Q=System.Console;class P{static void Main(){int q=9,w=0,e=9,r=0,t=9,u=0,i=0,x=0,y=0,z=0,p=0;System.Action V=()=>{z=(int)System.Math.Sqrt(i);p=(x=i-z*z)%2;x/=2;y=(++z*z--+~i)/2;},W=()=>{Q.Write(i+","+(x<0|y++<0|z>7?"X":""+(z*z+2*x+1-p))+" ");};foreach(var g in Q.ReadLine().Split(',')){i=int.Parse(g);V();q=q>x?x:q;w=w<x?x:w;e=e>y?y:e;r=r<y?y:r;t=t>z?z:t;u=u<z?z:u;}for(i=64;i-->0;){V();if(!(x<q|x>w|y<e|y>r|z<t|z>u))if(p>0){if(y==r)W();if(x++==w)W();x--;if(z--==t)W();}else{if(y--==e)W();if(x--==q)W();x++;if(z++==u)W();}}}}

Dieses Diagramm erklärt die meisten Vorgänge.

Das als x / y / z / (p) beschriebene Gitter zeigt eine beispielhafte Lösung

Erkennen Sie, dass ein "Sechseck" immer die billigste Form ist, da wir keine 0-breiten Abschnitte haben können (und den Gänsen den größtmöglichen Bewegungsspielraum bieten kann).

Das Programm übersetzt zunächst alle eingegebenen Zellenindizes in x / y / z-Koordinaten und ermittelt die Min / Max-Werte für x / y / z.

z = floor(root(i))
x = floor((i - z^2) / 2)
y = floor((z+1)^2 - i - 1) / 2)
p = (i - z^2) % 2

Als nächstes durchläuft es jeden Zellenindex und prüft, ob er in die von uns beschriebene 'Sechseck'-Grenze passt. Wenn dies der Fall ist, prüft es, ob es sich an einer der äußersten Kanten der Grenzen befindet (dh x = xmin oder y = ymax) und fügt entsprechende Kanten hinzu, wenn dies der Fall ist. Es muss den Index der Kante ermitteln, an der es sich befindet. Für x und z erhöhen / verringern wir sie nur nach Belieben und verwenden dann die folgende Formel:

i = z^2 + 2*x + (1-p)

Beachten Sie, dass sich die "Parität" immer ändert und dass y nicht beteiligt ist. Für y müssen wir nichts ändern, aber der Code ist ein bisschen chaotisch, weil er "Dreieck" -Begrenzungen durchführen muss, um festzustellen, ob die Zelle nebenan ein "X" sein sollte oder nicht.

Beispiellösung (Zellen mit Gänsen aus den drei Ecken):

Input
2,50,62

Output
62,63 61,X 59,X 57,X 55,X 53,X 51,X 50,49 48,X 36,X 35,X 25,X 24,X 16,X 15,X 9,X 8,X 4,X 3,X 2,0 1,X 

Ordentlicher Code mit Kommentaren:

using Q=System.Console;

class P
{
    static void Main()
    {
        int q=9,w=0,e=9,r=0,t=9,u=0, // min/max x/y/z/ (init min high, and max low)
        i=0, // index of cell we are looking at
        x=0,y=0,z=0,p=0; // x,y,z dimension

        System.Action V=()=>
            { // translates the index into x/y/z/p
                z=(int)System.Math.Sqrt(i);
                p=(x=i-z*z)%2; // 'parity'
                x/=2; // see p assignment
                y=(++z*z--+~i)/2; // ~i == -i - 1
            },
            W=()=>
            { // writes out the edge of i, and the cell described by x/z/inverse of p   (the inversion of p handles y +/-)
                Q.Write(i+","+ // write out the edge
                        (x<0|y++<0|z>7?"X":""+(z*z+2*x+1-p)) // either X (if we go out of 'trianlge' bounds), or we translate x/z/inverse of p into an index
                        +" "); // leaves a trailing space (as shown in example output)
            };

        foreach(var g in Q.ReadLine().Split(',')) // for each cell with geese
        {
            i=int.Parse(g); // grab index of cell
            V(); // compute x/y/z/p
            q=q>x?x:q; // sort out mins/maxes
            w=w<x?x:w;
            e=e>y?y:e;
            r=r<y?y:r;
            t=t>z?z:t;
            u=u<z?z:u;

            // code like the above suggests a solution with a couple of arrays would be better...
            // I've not had success with that yet, but maybe in a couple of days I will try again
        }

        for(i=64;i-->0;) // for each cell
        {
            V(); // compute x/y/z/p
            if(!(x<q|x>w|y<e|y>r|z<t|z>u)) // if we are inside the 'hex' bounds
                if(p>0)
                { // x max, y max, z min
                    // these checks check that we are on the extremes of the 'hex' bounds,
                    // and set up the appropriate vars for W calls to put the edges in
                    // must do y first, because W modifies it for us (saves 2 bytes in the next block)
                    if(y==r) // don't need the ++ (can't go out of 'trianlge' bounds)
                        W();
                    if(x++==w)
                        W();
                    x--;
                    if(z--==t)
                        W();
                    //z++; not used again
                }
                else
                { // x min, y min, z max
                    if(y--==e) // do need the -- (used for 'trianlge' bounds checking)
                        W();
                    // y is reset in W, as such
                    if(x--==q)
                        W();
                    x++;
                    if(z++==u)
                        W();
                    //z--; not used again
                }
        }
    }
}
VisualMelon
quelle
Mit können Sie ein Byte speichern using System;.
LegionMammal978
@ LegionMammal978 Infact gewinnt er zwei dabei .. Er verwendet es nur für Q.Write und Q.ReadLine. diese plus die using-Anweisung, die er jetzt hat, ist using Q=System.Console;Q.Write();Q.ReadLine()(45 Bytes) im Vergleich zu Ihrem Vorschlag using System;Console.Write();Console.ReadLine()(47 Bytes).
Kade
Sie können aber auch 10 Bytes nicht unnötig Initialisierung fallen i, x, y, z, und pauf 0
LegionMammal978
@ LegionMammal978 bist du sicher? Ich habe das versucht und es gibt Fehler für die Verwendung eines nicht zugewiesenen vairable.
Kade
@ Vioz- Welche Variablen? Welche Zeilen in der kommentierten Version?
LegionMammal978