런 길이 레이서


18

러닝 트랙을 정의하는 런 길이 인코딩 형식의 문자열과 시작 레인을 나타내는 대문자의 두 가지 입력이 제공됩니다. 예를 들어 문자열 "3a4A6b5B"는 "aaaAAAAbbbbbbBBBBB"로 확장됩니다. 그런 다음 확장 된 문자열을 사용하여 다음과 같이 트랙을 만듭니다.

 A) aaaAAAA
 B) bbbbbbBBBBB

이것은 2 개의 차선이있는 트랙입니다. 소문자는 공기를 나타냅니다. 당신은 공중에서 실행할 수 없습니다! 대문자는 주행 할 수있는 도로를 나타냅니다. 이 도전의 목표는 대문자로 주어진 레인에서 출발하는 레이서가 얼마나 멀리 달릴 수 있는지 출력하는 것입니다. 레이서 바로 위 또는 아래에 도로가 있으면 차선을 전환 할 수 있습니다. 그들은 또한 거꾸로 달릴 수 있습니다! 이 트랙에서 문자 입력에 대한 출력은 0 입니다. 트랙 중 어느 것도 트랙 1을 주행 할 수 없기 때문입니다.

예 :

입력 : "4A5B4c3C", "A"

이 코드는 다음과 같은 트랙으로 확장됩니다.

A) AAAA
B) BBBBB
C) ccccCCC

레인 A에서 시작하는 러너가 레인 B로 내려간 다음 레인 C로 이동하여 7 번째 위치에서 끝날 수 있기 때문에이 예제의 출력은 7 입니다.

입력 : "4A2B3D", "D"

과정:

A) AAAA
B) BB
C)
D) DDD

레인 D에서 시작하는 러너가 레인 B 또는 A에 도달 할 방법이 없기 때문에 출력은 3입니다

입력 : "4A4a4A3b6B5C", "A"

과정:

A) AAAAaaaaAAAA
B) bbbBBBBBB
C) CCCCC

A의 러너가 B로 전환 한 다음 끝에 A로 돌아올 수 있으므로 출력은 12 입니다. "C"의 최대 거리도 12입니다. "B"의 경우 0입니다.

입력 : "12M4n10N11O", "M"

과정:

M) MMMMMMMMMMMM
N) nnnnNNNNNNNNNN
O) OOOOOOOOOOO

여러 자리 길이의 간단한 예제입니다. 출력은 14 입니다.

입력 : "4A5B1b2B4c3C", "A"

과정:

A) AAAA
B) BBBBBbBB
C) ccccCCC

A의 러너가 B로 내려간 다음 C로 돌아간 다음 다시 B로 돌아올 수 있기 때문에 출력은 8 입니다.

입력 : "1a2A2a2B1c1C1d3D", "B"

과정:

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

출력은 4 입니다. 러너는 두 경로를 모두 확인해야합니다. (이 예제는 user81655에게 감사합니다.)

입력 : "2A1b1B2C1D3E", "A"

과정:

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

출력은 3 입니다. 가장 먼 목적지에 도달하려면 뒤로 이동해야합니다. (이 예제의 user81655 덕분에 다시 한 번 감사드립니다.)

노트:

  • 트랙에 특정 위치에 글자가 없으면 공기로도 계산됩니다. 따라서 입력이 "Q"이고 차선 "Q"에 도로가 없으면 출력은 0 이어야합니다 .
  • 두 가지 입력이 있습니다. 첫 번째는 실행 길이 인코딩 된 문자열입니다. 두 번째는 대문자입니다 (이 경우 문자열 또는 문자 데이터 유형을 사용할 수 있습니다). 가독성을 위해 이러한 입력 (공백, 줄 바꿈, 탭, 쉼표, 세미콜론) 사이에 적절한 구분 기호가 있어야합니다.
  • 실행 길이로 인코딩 된 문자열은 항상 알파벳 순서로 요소를 나열합니다
  • 레인의 전체 길이는 가장 길 수있는 길이는 1000입니다. 따라서 가능한 최대 출력은 1000입니다.

트랙 생성기 :

첫 번째 답변을 기리기 위해 여기에 트랙 생성기가 있습니다. 현재 답변을 그루터기 위해 무언가를 생각해보십시오! (참고 : 생성기에 오류 메시지가 표시되지 않는다고해서 트랙 코드가 반드시 유효한 것은 아닙니다. 올바른 형식은 위의 예를 참조하십시오.)

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>


3
스위치 결정과 후진 실행으로 현재 트랙보다 미로에
가깝습니다

테스트 사례와 같이 경로가 하나만 있습니까?
RichieAHB

@RichieAHB 둘 이상의 경로가있을 수 있습니다.
geokavel

누락 된 C를 처리하는 합병증을 4A2B3D제거 할 수 있는지 궁금한 가요? 예를 들어 0c? 그렇지 않다면, 1A1Z레인 BY가 존재한다고 가정하지만 (비어 있음) 예상 되는가?
Kenney

1
또한 거꾸로 달리는 것은 큰 문제입니다. 12M4n10N11O예는, 출력 (14)은 다음 거짓 : 25의 길이 C0에서 가장 긴 경로 M0에서 시작 단부
케니

답변:


3

231 219 203 192 189 바이트

+1 포함 -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)

덜 골프 :

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

달리는

코드를 파일에 저장하십시오 (예 :) 231.pl. 형식으로 입력하십시오 (\d+\w)+ *\w. 예 : 트랙 4A5B4c3C및 레인 입력 A:

echo 4A5B4c3C A | perl -p 231.pl

TestSuite

(골프하지 않음)

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);
  • 업데이트 219는 배열 인덱스를 재 작업하여 12 바이트를 절약합니다.
  • 업데이트 203 재귀를 리팩토링하여 16 바이트를 저장하십시오.
  • 업데이트 192@L=map{[/./g]}@L사후 처리 를 제거하여 11 바이트를 절약합니다 .
  • 업데이트 189 대신을 if사용하여 후위 수정 하여 3 바이트를 절약하십시오 .mapfor

이것이 Perl 일 경우에는 아니지만 FAST를 실행합니다.
geokavel

6

자바 스크립트 (ES6), 298 334 바이트

(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

설명

기본적으로이 솔루션은 트랙을 미로로 취급합니다. 러너가 도달 할 수있는 모든 타일이 어디에 있는지 찾아서 찾은 X 인덱스의 가장 큰 값을 반환합니다.

가장 먼저하는 일은 입력 문자열을 행 배열로 디코딩하는 것입니다. 그러나 문자를 사용하는 대신 대문자를 a 1로 바꾸고 소문자 를 a로 바꿉니다 0. 결과 맵은 다음과 같습니다.

11100011
0011100
100111

그런 다음 시작 트랙의 첫 번째 타일을 a로 만들고 2(이미있는 경우에만 1) 인접한 타일을 검사하여 모든 타일을 반복합니다 2. a 1가 인접한 경우 a 가 2됩니다 2. 러너가 첫 번째 라인에서 시작하면 위의 맵은 다음과 같습니다.

22200011
0022200
100222

에 대한 가장 높은 X 인덱스 2가 결과가됩니다.

나는 이것의 초기 버전을 할 때 아주 작은 감독을했으며 그것이 작동 할 때까지 해킹하는 데 36 바이트가 들었으므로 아마도 이것에 많은 개선이있을 것입니다. *한숨*

언 골프

(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

테스트

보너스 : 출력에 파싱 된 맵이 포함됩니다!

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>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.