Run-Length Racer

18

Sie erhalten zwei Eingaben: eine Zeichenfolge in lauflängencodiertem Format, die die Laufstrecke definiert, und einen Großbuchstaben, der die Fahrspur darstellt, von der aus Sie beginnen möchten. Beispielsweise erweitert sich die Zeichenfolge "3a4A6b5B" zu "aaaAAAAbbbbbbBBBBB". Sie verwenden dann die erweiterte Zeichenfolge, um eine Spur als solche zu erstellen:

 A) aaaAAAA
 B) bbbbbbBBBBB

Dies ist eine Strecke mit zwei Spuren. Kleinbuchstaben stehen für Luft. Sie können nicht auf Luft laufen! Großbuchstaben stehen für eine Straße, auf der Sie fahren können. Ihr Ziel für diese Herausforderung ist es, mit einem Großbuchstaben anzugeben, wie weit ein auf dieser Spur startender Rennfahrer laufen könnte. Rennfahrer dürfen die Spur wechseln, wenn sich ein Stück Straße direkt über oder unter ihnen befindet. Sie dürfen auch rückwärts rennen! Auf dieser bestimmten Spur ist die Ausgabe für jede Buchstabeneingabe 0 , da keine der Spuren auf Position 1 eine fahrbare Straße aufweist.

Beispiele:

Eingabe: "4A5B4c3C", "A"

Dieser Code wird zu einer Spur erweitert, die folgendermaßen aussieht:

A) AAAA
B) BBBBB
C) ccccCCC

Die Ausgabe für dieses Beispiel ist 7 , da ein Läufer, der auf Spur A beginnt, auf Spur B und dann auf Spur C absteigen und an der 7. Position enden kann.

Eingabe: "4A2B3D", "D"

Spur:

A) AAAA
B) BB
C)
D) DDD

Die Ausgabe ist 3 , weil ein Läufer, der auf Spur D startet, nicht auf Spur B oder A gelangen kann

Eingabe: "4A4a4A3b6B5C", "A"

Spur:

A) AAAAaaaaAAAA
B) bbbBBBBBB
C) CCCCC

Die Ausgabe ist 12 , da der Läufer auf A auf B umschalten und am Ende wieder auf A zurückkehren kann. Der maximale Abstand für "C" beträgt ebenfalls 12. Für "B" ist er 0.

Eingabe: "12M4n10N11O", "M"

Spur:

M) MMMMMMMMMMMM
N) nnnnNNNNNNNNNN
O) OOOOOOOOOOO

Einfaches Beispiel mit mehrstelligen Lauflängen. Die Ausgabe ist 14 .

Eingabe: "4A5B1b2B4c3C", "A"

Spur:

A) AAAA
B) BBBBBbBB
C) ccccCCC

Die Ausgabe ist 8 , weil der Läufer bei A zu B, dann zu C und dann zu B zurückkehren kann. (Vielen Dank an FryAmTheEggman für dieses Beispiel.)

Eingabe: 1a2A2a2B1c1C1d3D, B

Spur:

A)aAAaa
B)BB
C)cC
D)dDDD

Ausgang ist 4 . Der Läufer muss beide Pfade überprüfen, um zu sehen, was weiter geht. (Vielen Dank an user81655 für dieses Beispiel.)

Eingabe: "2A1b1B2C1D3E", "A"

Spur:

A) AA
B) bB
C) CC
D) D
E) EEE

Ausgang ist 3 . Sie müssen rückwärts laufen, um das am weitesten entfernte Ziel zu erreichen. (Nochmals vielen Dank an user81655 für dieses Beispiel.)

Anmerkungen:

  • Wenn ein Titel an einer bestimmten Position keinen Buchstaben hat, gilt dies auch als Luft. Wenn also die Eingabe "Q" ist und keine Straße auf die Spur "Q" gelegt wurde, sollte die Ausgabe 0 sein .
  • Es gibt zwei Eingabemöglichkeiten. Die erste ist eine lauflängencodierte Zeichenfolge. Der zweite ist ein Großbuchstabe (Sie können hierfür einen String oder einen char-Datentyp verwenden.) Zur besseren Lesbarkeit sollte zwischen diesen Eingaben ein angemessenes Trennzeichen (Leerzeichen, neue Zeile, Tabulator, Komma, Semikolon) stehen.
  • Die lauflängencodierte Zeichenfolge listet Elemente immer in alphabetischer Reihenfolge auf
  • Die größte Länge einer Fahrspur kann 1000 sein. Daher ist die größtmögliche Ausgabe 1000.

Spur Generator:

Zu Ehren unserer ersten Antwort hier ein Trackgenerator. Versuchen Sie, sich etwas auszudenken, um die aktuellen Antworten zu überarbeiten! (Hinweis: Nur weil der Generator keine Fehlermeldung anzeigt, ist Ihr Trackcode nicht unbedingt gültig. Die korrekte Form finden Sie in den obigen Beispielen.)

function reset() {
    var t = document.getElementById("track");
    t.innerHTML = "";
    for(var i = 0;i<26;i++) {
      var c = String.fromCharCode(i+65);
      t.innerHTML += "<div><span>"+c+") </span><span id='"+c+"'></span></div>";
      
    }
  }

function rand() {
  var track = "";
  for(var i = 0;i<26;i++) {
  var blocks = Math.floor(Math.random()*4);
  var start = Math.floor(Math.random()*2);
  for(var j = 0;j<blocks;j++) {
    var letter = String.fromCharCode(65+i+32*((start+j)%2));
    var length = Math.floor(Math.random()*4)+1;
    track += length+letter;
  }
  }
  document.getElementById("code").value = track;
}

  function gen() {
  var s = document.getElementById("code").value;
    var check = s.match(/(\d+[A-Za-z])+/);
    if(check == null || check[0]!=s) {
      alert("Invalid Track");
      return false;
    }
    reset();
  var n = s.match(/\d+/g);
    var o = s.match(/[A-Za-z]/g);
    for(var i = 0;i<n.length;i++) {
      var c = o[i].toUpperCase();
      document.getElementById(c).textContent += o[i].repeat(n[i]);
    }
    return true;
    }
<body onload="reset()">
Track: <input type="text" id="code" size="75%" /><input type="submit" onclick="gen()" /><input type="button" value="Random Track" onclick="rand()" /><code id="track"/>
  </body>

Geokavel
quelle
3
Mit den Schaltern Entscheidungen und die rückwärts laufen , es ist eher ein Labyrinth als eine Spur jetzt: P
user81655
Gibt es immer nur eine Route - wie in den Testfällen?
RichieAHB
@RichieAHB Es kann mehr als eine Route geben.
Geokavel
Sie fragen sich nur, ob möglicherweise die Komplikation des Umgangs mit dem fehlenden C in 4A2B3Dbeseitigt werden kann? Zum Beispiel hinzufügen 0c? Wenn nicht, wird erwartet, dass 1A1Zdie Spuren BY existieren (aber leer sind)?
Kenney
1
Auch das Rückwärtslaufen ist ein großes Problem. Das 12M4n10N11OBeispiel, Ausgabe 14, ist dann falsch: Der längste Pfad beginnt bei M0 und endet bei C0 für eine Länge von 25.
Kenney

Antworten:

3

Perl, 231 219 203 192 189 Bytes

beinhaltet +1 für -p

sub f{my($l,$p,$m)=@_;map{$m=$_>$m?$_:$m}f($l,$p+1)+1,f($l-1,$p),f($l+1,$p),f($l,$p-1)-1if$L[$l][$p]&&!$V{$l}{$p}++;$m}s/(\d+)(.)\s*/push@{$L[ord$2&~32]},(0|$2lt'a')x$1;()/ge;$_=0|f(ord,0)

Weniger golfen:

sub f{                          # this is a recursive function, so we need locals.
    my($l,$p,$m)=@_;            # in: lane, position; local: max path length

    map{
      $m = $_ > $m ? $_ : $m    # update max
    }
    f( $l,   $p+1 )+1,          # same lane, forward
    f( $l-1, $p   ),            # left lane, same pos
    f( $l+1, $p   ),            # right lane, same pos
    f( $l,   $p-1 )-1           # same lane, backtrack
    if
        $L[$l][$p]              # check if there's road here
    && !$V{$l}{$p}++            # and we've not visited this point before.
    ;

    $m                          # return the max
}

s/(\d+)(.)\s*/                  # Parse RLE pattern, strip starting lane separator
  push@{ $L[ord$2&~32] }        # index @L using uppercase ascii-code, access as arrayref
  ,(0|$2lt'a')x$1               # unpack RLE as bitstring
  ;()                           # return empty list for replacement
/gex;                           # (x for ungolfing)
                                # $_ now contains trailing data: the start lane.

$_ =                            # assign output for -p
   0|                           # make sure we print 0 instead of undef/nothing
   f(ord,0)                     # begin calculation at start of current lane

Laufen

Speichern Sie den obigen Code in einer Datei (sagen wir 231.pl). Eingabe in Form von (\d+\w)+ *\w. Beispiel: Eingabe von Spur 4A5B4c3Cund Spur A:

echo 4A5B4c3C A | perl -p 231.pl

TestSuite

(nicht golfen)

printf "==== Testing %s\n", $file = shift // '231.pl';

sub t{
    my($input,$expect) = @_;
#   $input =~ s/\s//g;
    printf "TEST %-20s -> %-3s: ", $input, $expect;

    $output = `echo $input | perl -p $file`;

    printf "%-3s  %s\n", $output,
    $output == $expect
    ? " PASS"
    : " FAIL: $output != $expect";

}

t("4A5B4c3C A", 7);
t("4A5B4c3C C", 0);
t("4A2B3D D", 3);
t("4A4a4A3b6B5C A", 12);
t("4A4a4A3b6B5C B",  0);
t("4A4a4A3b6B5C C", 12);
t("12M4n10N11O M", 14 );
t("4A5B1b2B4c3C A", 8);
t("1a2A2a2B1c1C1d3D B", 4 );
t("2A1b1B2C1D3E A", 3 );
t("10A9b1B8c2C9D1E11F A", 11);
  • Update 219 spart 12 Bytes durch Überarbeitung der Array-Indizes.
  • update 203 Sparen Sie 16 Bytes durch Refactoring der Rekursion.
  • Update 192 spart 11 Bytes, indem die @L=map{[/./g]}@LNachbearbeitung entfällt .
  • update 189 spart 3 bytes durch postfixing ifmit mapanstelle von for.
Kenney
quelle
Ich weiß nicht, ob das eine Perl-Sache ist, aber das läuft SCHNELL.
Geokavel
6

JavaScript (ES6), 298 334 Byte

(t,s)=>[a=[],t.match(/\d+(.)(\d+\1)*/gi).map(l=>a[c=l.match`[A-Z]`+"",n=c.charCodeAt(),c==s?i=n:n]=l[r="replace"](/\d+./g,p=>(p.slice(-1)<"a"?"1":"0").repeat(parseInt(p))),i=o=-1),...a.join``,a[i]?a[i]=a[i][r](/^1/,2):0].map(_=>a.map((l,y)=>a[y]=l[r](/1/g,(c,x)=>((a[y-1]||s)[x]|(a[y+1]||s)[x]|l[x-1]|l[x+1])>1?(x>o?o=x:0,2):c)))&&o+1

Erläuterung

Grundsätzlich behandelt diese Lösung die Strecke als Labyrinth. Es ermittelt, wo sich alle Kacheln befinden, die der Läufer erreichen kann, und gibt den größten Wert des gefundenen X-Index zurück.

Das erste, was es tut, ist die Eingabezeichenfolge in ein Array von Zeilen zu dekodieren. Anstatt Buchstaben zu verwenden, wird ein Großbuchstabe in einen 1und ein Kleinbuchstabe in einen umgewandelt 0. Die resultierende Karte sieht ungefähr so ​​aus:

11100011
0011100
100111

Danach erstellt es das erste Plättchen der Startspur a 2(nur wenn es bereits vorhanden ist 1) und durchläuft jedes Plättchen, wobei benachbarte Plättchen auf a geprüft werden 2. Wenn a 1benachbart ist 2, wird es zu 2. Die obige Karte wird folgendermaßen aussehen, wenn der Läufer in der ersten Zeile gestartet ist:

22200011
0022200
100222

Der höchste X-Index für a 2wird zum Ergebnis.

Als ich die erste Version davon gemacht habe, habe ich ein kleines Versehen gemacht und es hat mich 36 Bytes gekostet, sie zu hacken, bis sie funktionierte, also gibt es wahrscheinlich eine Menge Verbesserungen, die daran vorgenommen werden könnten. *Seufzer*

Ungolfed

(t,s)=>
  [

    // Decode run-length encoded string into an array of track lanes
    a=[],                           // a = array of track line strings, 0 = air, 1 = tiles
    t.match(/\d+(.)(\d+\1)*/gi)     // regex magic that separates pairs by their letter
    .map(l=>                        // for each line of pairs
      a[                            // add the tiles to the array
        c=l.match`[A-Z]`+"",        // c = pair character
        n=c.charCodeAt(),           // n = index of line
        c==s?i=n:n                  // if this line is the starting line, set i
      ]=l[r="replace"](/\d+./g,p=>  // match each pair, p = pair
        (p.slice(-1)<"a"
          ?"1":"0").repeat(         // repeat 0 for air or 1 for ground
            parseInt(p)             // cast of match would return NaN because of the
          )                         //     letter at the end but parseInt works fine
      ),
        i=                          // i = index of starting line, initialise as invalid
          o=-1                      // o = output (max value of x)
    ),

  // Find all positions that are possible for the runner to get to
    ...a.join``,                   // add every letter of the track lines to an array
    a[i]?a[i]=a[i][r](/^1/,2):0    // set the starting tile to 2 if it is already 1
  ].map(_=>                        // loop for the amount of tiles, this is usually way
                                   //     more than necessary but allows for hard to reach
                                   //     tiles to be parsed
    a.map((l,y)=>                  // for each line l at index y
      a[y]=l[r](/1/g,(c,x)=>       // for each character c at index x

        // Replace a 1 with 2 if there is a 2 to above, below, left or right of it
        ((a[y-1]||s)[x]|(a[y+1]||s)[x]|l[x-1]|l[x+1])>1?
          (x>o?o=x:0,2):c          // set o to max value of x for a 2 tile
      )
    )
  )
  &&o+1                            // return o + 1

Prüfung

Bonus: Die Ausgabe enthält die analysierte Karte!

var solution = (t,s)=>[a=[],t.match(/\d+(.)(\d+\1)*/gi).map(l=>a[c=l.match`[A-Z]`+"",n=c.charCodeAt(),c==s?i=n:n]=l[r="replace"](/\d+./g,p=>(p.slice(-1)<"a"?"1":"0").repeat(parseInt(p))),i=o=-1),...a.join``,a[i]?a[i]=a[i][r](/^1/,2):0].map(_=>a.map((l,y)=>a[y]=l[r](/1/g,(c,x)=>((a[y-1]||s)[x]|(a[y+1]||s)[x]|l[x-1]|l[x+1])>1?(x>o?o=x:0,2):c)))&&o+1
function generateMap() { var start = 0; a.some((l, i) => l ? start = i : 0); var end = 0; a.map((l, i) => l && i <= 90 ? end = i : 0); for(var output = "", i = start; i < end + 1; i++) output += String.fromCharCode(i) + ") " + (a[i] || "") + "\n"; return output; }
Track = <input type="text" id="track" value="2A1b1B2C1D3E" /><br />
Starting Letter = <input type="text" id="start" value="A" /><br />
<button onclick="result.textContent=solution(track.value,start.value)+'\n\n'+generateMap()">Go</button>
<pre id="result"></pre>

user81655
quelle