เหนื่อยหอบ Run-Length


18

คุณจะได้รับอินพุตสองส่วน: สตริงในรูปแบบที่เข้ารหัสแบบรันไทม์ที่กำหนดแทร็กการวิ่งและอักษรตัวใหญ่ที่แสดงถึงช่องทางที่จะเริ่มต้น ตัวอย่างเช่นสตริง "3a4A6b5B" ขยายเป็น "aaaAAAAbbbbbbbBBBBB" จากนั้นคุณใช้สตริงที่ขยายเพื่อสร้างแทร็กเช่น:

 A) aaaAAAA
 B) bbbbbbBBBBB

นี่คือแทร็กที่มีสองเลน อักษรตัวพิมพ์เล็กเป็นตัวแทนของอากาศ คุณไม่สามารถวิ่งบนอากาศได้! ตัวอักษรตัวพิมพ์ใหญ่แสดงถนนที่คุณสามารถวิ่งได้ เป้าหมายของคุณสำหรับความท้าทายนี้คือให้อักษรตัวใหญ่แสดงว่านักแข่งที่เริ่มวิ่งบนเลนนั้นสามารถวิ่งได้ไกลแค่ไหน นักแข่งได้รับอนุญาตให้เปลี่ยนเลนหากมีชิ้นส่วนของถนนอยู่ด้านบนหรือด้านล่าง พวกเขายังได้รับอนุญาตให้วิ่งถอยหลัง! ในแทร็คนี้โดยเฉพาะผลลัพธ์คือ0สำหรับอินพุตตัวอักษรใด ๆ เนื่องจากไม่มีแทร็กใดที่วิ่งบนถนนที่ตำแหน่ง 1

ตัวอย่าง:

อินพุต: "4A5B4c3C", "A"

รหัสนี้ขยายไปยังแทร็กที่มีลักษณะดังนี้:

A) AAAA
B) BBBBB
C) ccccCCC

ผลลัพธ์สำหรับตัวอย่างนี้คือ7เนื่องจากนักวิ่งที่เริ่มต้นบนเลน A สามารถเลื่อนลงไปที่เลน B จากนั้นเลน C และจบที่ตำแหน่งที่ 7

อินพุต: "4A2B3D", "D"

ติดตาม:

A) AAAA
B) BB
C)
D) DDD

ผลลัพธ์คือ3เนื่องจากนักวิ่งที่เริ่มต้นบนเลน D ไม่มีทางที่จะไปยังเลน B หรือ A

อินพุต: "4A4a4A3b6B5C", "A"

ติดตาม:

A) AAAAaaaaAAAA
B) bbbBBBBBB
C) CCCCC

ผลลัพธ์คือ12เพราะนักวิ่งบน A สามารถสลับไปที่ B แล้วกลับมาที่ A ในตอนท้าย ระยะทางสูงสุดสำหรับ "C" คือ 12 สำหรับ "B" คือ 0

อินพุต: "12M4n10N11O", "M"

ติดตาม:

M) MMMMMMMMMMMM
N) nnnnNNNNNNNNNN
O) OOOOOOOOOOO

ตัวอย่างง่าย ๆ ที่มีความยาวหลายหลัก เอาท์พุทเป็น14

อินพุต: "4A5B1b2B4c3C", "A"

ติดตาม:

A) AAAA
B) BBBBBbBB
C) ccccCCC

ผลลัพธ์คือ8เพราะนักวิ่งที่ A สามารถลงไปที่ B จากนั้นลงไปที่ C จากนั้นกลับมาที่ B (ขอบคุณ FryAmTheEggman สำหรับตัวอย่างนี้)

อินพุต: "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
ด้วยการตัดสินใจของสวิตช์และการวิ่งถอยหลังเป็นเรื่องของเขาวงกตมากกว่าแทร็กในขณะนี้: P
user81655

มีเพียงเส้นทางเดียวเท่านั้น - ในกรณีทดสอบหรือไม่?
RichieAHB

@RichieAHB อาจมีมากกว่าหนึ่งเส้นทาง
geokavel

เพียงแค่สงสัยว่าอาจจะมีความยุ่งยากในการจัดการ C ที่หายไป4A2B3Dหรือไม่? ตัวอย่างเช่นการเพิ่ม0c? หากไม่เป็นเช่นนั้นคาดว่า1A1Zจะได้รับเมื่อมีการพูดเลนโดยจะถือว่ามีอยู่ (แต่ว่างเปล่า)?
Kenney

1
นอกจากนี้การวิ่งถอยหลังเป็นปัญหาใหญ่ 12M4n10N11Oตัวอย่างเช่นการส่งออก 14 นั้นก็เป็นเท็จเส้นทางที่ยาวที่สุดเริ่มต้นที่ M0 และสิ้นสุดที่ C0 สำหรับความยาวของ 25
เคนนีย์

คำตอบ:


3

Perl, 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บันทึก 11 ไบต์โดยกำจัดการ@L=map{[/./g]}@Lประมวลผลภายหลัง
  • อัปเดต 189บันทึก 3 ไบต์โดย postfixing ifใช้แทนmapfor

ฉันไม่ได้ถ้านี่คือสิ่ง Perl แต่นี่ทำงานได้อย่างรวดเร็ว
geokavel

6

JavaScript (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 ที่พบ

สิ่งแรกที่ทำคือถอดรหัสสตริงอินพุตให้เป็นอาร์เรย์ของบรรทัด แทนการใช้ตัวอักษร แต่มันกลับกลายเป็นอักษรตัวใหญ่เป็นและตัวอักษรตัวพิมพ์เล็กเป็น1 0แผนที่ผลลัพธ์จะมีลักษณะดังนี้:

11100011
0011100
100111

หลังจากนี้ก็จะทำให้กระเบื้องแรกของการเริ่มต้นติดตาม2(เฉพาะถ้ามันมีอยู่แล้ว1) 2และลูปผ่านการตรวจสอบกระเบื้องกระเบื้องที่อยู่ติดกันสำหรับทุกคน ถ้า1มีที่อยู่ติดกันมันจะกลายเป็น2 2แผนที่ด้านบนจะกลายเป็นสิ่งนี้หากนักวิ่งเริ่มต้นในบรรทัดแรก:

22200011
0022200
100222

ดัชนี X สูงสุดสำหรับ a 2กลายเป็นผลลัพธ์

ฉันทำการกำกับดูแลเล็กน้อยมากเมื่อฉันทำรุ่นเริ่มต้นของสิ่งนี้และมีค่าใช้จ่ายฉัน 36 ไบต์ในการแฮ็คจนกว่ามันจะทำงานได้ดังนั้นอาจมีการปรับปรุงมากมายที่สามารถทำได้ * * * * * * * * ถอนหายใจ

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

ทดสอบ

โบนัส: เอาท์พุทรวมแผนที่แยกวิเคราะห์!

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.