Run-Length Racers

18

Otrzymasz dwa dane wejściowe: ciąg znaków w zakodowanym formacie określającym bieżnię i wielką literę reprezentującą linię, od której chcesz zacząć. Na przykład ciąg „3a4A6b5B” rozwija się do „aaaAAAAbbbbbbBBBBB”. Następnie użyj rozwiniętego ciągu, aby utworzyć ścieżkę jako taką:

 A) aaaAAAA
 B) bbbbbbBBBBB

To trasa z dwoma pasami. Małe litery oznaczają powietrze. Nie możesz biegać na antenie! Wielkie litery oznaczają drogę, po której można biegać. Twoim celem w tym wyzwaniu jest, biorąc pod uwagę dużą literę, wynik, jak daleko biegacz startujący na tej linii może uciec. Kierowcy mogą zmieniać pas, jeśli kawałek drogi znajduje się bezpośrednio nad nimi lub pod nimi. Mogą także biegać wstecz! Na tej konkretnej ścieżce wyjście wynosi 0 dla dowolnego wpisania litery, ponieważ żadna z ścieżek nie ma drogi przejezdnej w pozycji 1.

Przykłady:

Wejście: „4A5B4c3C”, „A”

Ten kod rozwija się do ścieżki, która wygląda następująco:

A) AAAA
B) BBBBB
C) ccccCCC

Wynik dla tego przykładu wynosi 7 , ponieważ biegacz rozpoczynający się na linii A mógłby zejść na linię B, a następnie na linię C i skończyć na 7. pozycji.

Wejście: „4A2B3D”, „D”

Tor:

A) AAAA
B) BB
C)
D) DDD

Wyjście to 3 , ponieważ biegacz rozpoczynający się na linii D nie ma możliwości przedostania się na linię B lub A.

Wejście: „4A4a4A3b6B5C”, „A”

Tor:

A) AAAAaaaaAAAA
B) bbbBBBBBB
C) CCCCC

Wyjście wynosi 12 , ponieważ biegacz na A może przełączyć się na B, a następnie powrócić do A na końcu. Maksymalna odległość dla „C” wynosi również 12. Dla „B” wynosi 0.

Wejście: „12M4n10N11O”, „M”

Tor:

M) MMMMMMMMMMMM
N) nnnnNNNNNNNNNN
O) OOOOOOOOOOO

Prosty przykład z wielocyfrowymi długościami. Wyjście wynosi 14 .

Wejście: „4A5B1b2B4c3C”, „A”

Tor:

A) AAAA
B) BBBBBbBB
C) ccccCCC

Wynik wynosi 8 , ponieważ biegacz w A może zejść do B, następnie do C, a następnie wrócić do B. (Dziękuję FryAmTheEggman za ten przykład).

Wejście: „1a2A2a2B1c1C1d3D”, „B”

Tor:

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

Wyjście to 4 . Biegacz musi sprawdzić obie ścieżki dwa, aby zobaczyć, która idzie dalej. (Podziękowania dla user81655 za ten przykład.)

Wejście: „2A1b1B2C1D3E”, „A”

Tor:

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

Wyjście to 3 . Musisz pobiec do tyłu, aby dotrzeć do najdalszego celu. (Jeszcze raz dziękuję użytkownikowi 81655 za ten przykład.)

Uwagi:

  • Jeśli utwór nie ma litery w określonej pozycji, liczy się to również jako powietrze. W związku z tym, jeśli dane wejściowe to „Q” i żadna droga nie została ustawiona na pasie „Q”, dane wyjściowe powinny wynosić 0 .
  • Istnieją dwa elementy danych wejściowych. Pierwszy to ciąg zakodowany w czasie wykonywania. Druga to duża litera (w tym celu można użyć typu danych ciąg lub char.) Aby zapewnić czytelność, należy wprowadzić rozsądny separator między tymi danymi wejściowymi (spacja, nowy wiersz, tabulator, przecinek, średnik).
  • Łańcuch zakodowany w czasie przebiegu zawsze będzie wyświetlał elementy w kolejności alfabetycznej
  • Najdłuższa długość całej linii może wynosić 1000. Dlatego największa możliwa wydajność to 1000.

Generator śladów:

Na cześć naszej pierwszej odpowiedzi, oto generator ścieżek. Spróbuj wymyślić coś, co zaskoczy obecne odpowiedzi! (Uwaga: fakt, że generator nie wyświetla komunikatu o błędzie, nie oznacza, że ​​kod śledzenia jest koniecznie prawidłowy. Aby uzyskać prawidłową formę, zobacz powyższe przykłady).

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
źródło
3
Z decyzjami o przełączeniu i biegiem wstecz jest to bardziej labirynt niż ścieżka: P
user81655
Czy jest tylko jedna droga - jak w przypadkach testowych?
RichieAHB,
@RichieAHB Może być więcej niż jedna trasa.
geokavel,
Zastanawiam się, czy może 4A2B3Duda się usunąć komplikacje związane z obsługą brakującego C ? Na przykład dodając 0c? Jeśli nie, czy należy się spodziewać, kiedy 1A1Zpodano, że zakłada się, że pasy BY istnieją (ale są puste)?
Kenney,
1
Również bieg wsteczny jest ogromnym problemem. 12M4n10N11OPrzykład, wyjście 14 jest następnie fałszywa najdłuższe ścieżki zaczyna się i kończy w M0 w C0, na długości 25
Kenney

Odpowiedzi:

3

Perl, 231 219 203 192 189 bajtów

zawiera +1 dla -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)

Mniej golfa:

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

Bieganie

Zapisz powyższy kod w pliku (powiedzmy 231.pl). Dane wejściowe w postaci (\d+\w)+ *\w. Przykład: wprowadzanie ścieżki 4A5B4c3Ci pasa A:

echo 4A5B4c3C A | perl -p 231.pl

TestSuite

(nie grał w golfa)

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);
  • aktualizacja 219 oszczędza 12 bajtów, przerabiając indeksy tablic.
  • aktualizacja 203 Zaoszczędź 16 bajtów, refaktoryzując rekurencję.
  • zaktualizuj 192, zapisz 11 bajtów, eliminując @L=map{[/./g]}@Lprzetwarzanie końcowe.
  • aktualizacja 189 zapisz 3 bajty przez postfiks ifużywając mapzamiast for.
Kenney
źródło
Nie wiem, czy to Perl, ale działa to SZYBKO.
geokavel,
6

JavaScript (ES6), 298 334 bajty

(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

Wyjaśnienie

Zasadniczo to rozwiązanie traktuje tor jak labirynt. Sprawdza, gdzie znajdują się wszystkie kafelki, do których biegacz może dotrzeć, i zwraca największą wartość znalezionego indeksu X.

Pierwszą rzeczą, jaką robi, jest dekodowanie ciągu wejściowego na tablicę wierszy. Zamiast używać liter, zamienia wielką literę na 1a małą literę na 0. Powstała mapa będzie wyglądać mniej więcej tak:

11100011
0011100
100111

Następnie tworzy pierwszy kafel ścieżki początkowej a 2(tylko jeśli już jest 1) i przechodzi przez każdy kafel sprawdzając sąsiednie kafelki pod kątem a 2. Jeśli a 1ma sąsiadujący 2staje się 2. Powyższa mapa stanie się taka, jeśli biegacz zacznie od pierwszej linii:

22200011
0022200
100222

Najwyższy wskaźnik X dla a 2staje się wynikiem.

Zrobiłem bardzo niewielki niedopatrzenie, kiedy zrobiłem pierwszą wersję tego i kosztowało mnie 36 bajtów włamania się do niego, dopóki nie zadziałało, więc prawdopodobnie można wprowadzić wiele ulepszeń. *westchnienie*

Bez golfa

(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

Test

Bonus: Dane wyjściowe obejmują przeanalizowaną mapę!

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>

użytkownik 81655
źródło