Island Golf # 2: The Hermes Eccentric


19

นี่เป็นครั้งที่สองในชุดของความท้าทาย Island Golf ความท้าทายก่อนหน้า

ฤาษีสองคนมาถึงบนเกาะทะเลทราย เนื่องจากพวกเขามาแสวงหาความสันโดษพวกเขาต้องการอยู่ห่างไกลกันมากที่สุด พวกเขาควรจะสร้างกระท่อมของพวกเขาที่ไหนเพื่อเพิ่มระยะทางเดินระหว่างพวกเขาให้สูงสุด

การอ่านที่เกี่ยวข้อง

อินพุต

ข้อมูลที่คุณป้อนจะเป็นตารางสี่เหลี่ยมที่ประกอบด้วยอักขระสองตัวซึ่งแสดงถึงที่ดินและน้ำ ในตัวอย่างด้านล่างที่ดิน#และน้ำเป็น.แต่คุณอาจแทนที่อักขระสองตัวที่คุณต้องการ

...........
...##......
..#####....
..#######..
.#########.
...#######.
...#####.#.
....####...
...........

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

....
.#..
..#.
....

เอาท์พุต

รหัสต้องส่งออกของคุณตารางเดียวกันกับสองสถานที่กระท่อมทำเครื่องหมายบนมัน ในตัวอย่างด้านล่างสถานที่ตั้งของกระท่อมจะถูกทำเครื่องหมายด้วย X แต่คุณสามารถแทนที่อักขระใดก็ได้ตราบเท่าที่มันแตกต่างจากอักขระบนบกและน้ำ

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

ทางออกที่เป็นไปได้สำหรับเกาะด้านบน:

...........
...X#......
..#####....
..#######..
.#########.
...#######.
...#####.X.
....####...
...........

ระยะทางระหว่างจุดสองจุดนี้คือ 11 ซึ่งเป็นระยะทางที่ไกลที่สุดระหว่างจุดสองจุดบนเกาะนี้ มีอีกโซลูชันระยะทาง 11:

...........
...##......
..X####....
..#######..
.#########.
...#######.
...#####.X.
....####...
...........

รายละเอียด

วิธีการแก้ปัญหาของคุณอาจจะเป็นโปรแกรมเต็มรูปแบบหรือฟังก์ชั่น วิธีการอินพุตและเอาต์พุตดีฟอลต์ใด ๆนั้นเป็นที่ยอมรับ

อินพุตและเอาต์พุตของคุณอาจเป็นสตริงหลายบรรทัดรายการของสตริงหรือรายการอาร์เรย์ / ซ้อนสองมิติของอักขระ / สตริงอักขระเดี่ยว เอาต์พุตของคุณอาจ (เป็นทางเลือก) มีบรรทัดใหม่ต่อท้ายหนึ่งบรรทัด ดังที่ได้กล่าวไว้ข้างต้นคุณสามารถใช้อักขระที่แตกต่างกันสามตัวแทน#.X(โปรดระบุในการส่งอักขระที่คุณใช้)

กรณีทดสอบ

A.หมู่เกาะที่มีตำแหน่งเฉพาะ:

....
.##.
....

....
.XX.
....

......
......
..##..
...#..
......
......

......
......
..X#..
...X..
......
......

........
.#####..
.##..##.
.#..###.
.##..##.
........

........
.#####..
.##..##.
.#..###.
.#X..#X.
........

.........
.#####.#.
.#...#.#.
.#.###.#.
.#.....#.
.#######.
.........

.........
.#####.X.
.#...#.#.
.#.X##.#.
.#.....#.
.#######.
.........

B.ตัวอย่างเกาะที่มีทางออกที่เป็นไปได้หลายประการ:

........
....##..
...####.
..###...
.#####..
.#####..
..##....
........

ผลลัพธ์ที่เป็นไปได้:

........
....#X..
...####.
..###...
.#####..
.X####..
..##....
........

........
....#X..
...####.
..###...
.#####..
.#####..
..X#....
........

........
....##..
...###X.
..###...
.#####..
.X####..
..##....
........

........
....##..
...###X.
..###...
.#####..
.#####..
..X#....
........

C. กรณีทดสอบขนาดใหญ่เป็นส่วนสำคัญ


นี่คือ : รหัสที่สั้นที่สุดในแต่ละภาษาชนะ


2
สิ่งเหล่านี้เป็นความท้าทายเล็กน้อยที่ยอดเยี่ยม (โดยเฉพาะอย่างยิ่งฉันไม่ต้องทำการตรวจสอบอย่าง จำกัด !): รอคอยสิ่งต่อไป!
VisualMelon

ระยะทางคือแมนฮัตตันระยะทาง?
Sarge Borsch

@SargeBorsch ที่เกี่ยวข้องอย่างใกล้ชิด แต่ไม่เสมอกัน ระยะทางแมนฮัตตันเป็นเพียงΔx + Δy แต่ระยะการเดินอาจนานกว่าเพราะคุณไม่สามารถเดินข้ามแผ่นกระเบื้องมหาสมุทรได้ (ดูตัวอย่างสุดท้ายในหัวข้อ 'A' ระยะห่างระหว่างแมนฮัตตันระหว่าง X สองตัวคือ 6 แต่ระยะทางเดิน - ตามเกลียว - เท่ากับ 22)
DLosc

คำตอบ:


5

Python 3, 249 246 ไบต์

ลดขนาดลง 3 ไบต์ขอบคุณ DLosc

อินพุตและเอาต์พุตเป็นสตริงเดี่ยวโดยมี '.', '@' และ 'X' แทนน้ำกระท่อมและที่ดินตามลำดับ

A='@'
def f(s):
 w=s.find('\n')+1;d=u={(k,k):0for k,c in enumerate(s)if A<c}
 while u:d.update(u);u={(k,j):d[(k,i)]+1for k,i in d for j in{i+1,i+w,i-1,i-w}if A<s[j]and(k,j)not in d}
 k,j=sorted(max(d,key=d.get))
 return s[:k]+A+s[k+1:j]+A+s[j+1:]

รุ่นก่อนหน้า:

อินพุตเป็นสตริงเดี่ยวโดยมี '.' และ '#' แทนน้ำและที่ดินตามลำดับ 'X' หมายถึงกระท่อมในผลลัพธ์

def f(s):
 w=s.find('\n')+1;d=u={(k,k):0for k,c in enumerate(s)if'#'==c}
 while u:d.update(u);u={(k,j):d[(k,i)]+1 for k,i in d for j in{i+1,i+w,i-1,i-w}if'#'==s[j]and(k,j)not in d}
 k,j=sorted(max(d,key=d.get))
 return s[:k]+'X'+s[k+1:j]+'X'+s[j+1:]

คำอธิบาย:

โดยพื้นฐานแล้วจะทำการค้นหาแบบกว้างครั้งแรกจากจุดเริ่มต้นที่เป็นไปได้ทั้งหมดในเวลาเดียวกัน รักษาพจนานุกรม, d, ความยาวของเส้นทางที่ป้อนโดยจุดเริ่มต้นและจุดสิ้นสุดของเส้นทางเช่น d [(k, i)] คือระยะทางจาก k ถึง i จากนั้นวนซ้ำคีย์ในพจนานุกรม d และสร้างพจนานุกรมใหม่ u พร้อมพา ธ ที่ยาวกว่า 1 หน่วยโดยเลื่อนจุดสิ้นสุด 1 หน่วยไปยัง N, S, E, W, เช่น u [(k, i + 1)] = d [(k, i)] + 1 อย่ารวมเส้นทางที่มีอยู่แล้วใน d หากคุณไม่ว่างให้เพิ่มเส้นทางใหม่ที่ยาวกว่าไปยัง d แล้วทำซ้ำ เมื่อคุณว่างเปล่านั่นหมายความว่าจะไม่มีเส้นทางอีกต่อไป ตอนนี้ d มีเส้นทางและความยาวที่เป็นไปได้ทั้งหมด ดังนั้นมันเป็นเพียงเรื่องของการได้รับกุญแจกับเส้นทางที่ยาวที่สุด

golfed น้อยลงแสดงความคิดเห็นเวอร์ชัน:

def f(s):
  w=s.find('\n')+1                    # width of a row, or a move N or S

  d = {}                              # dictionary of all the paths.
                                      # The key is a tuple (k,j) and the
                                      # value is the distance from k to j.
  for k,c in enumerate(s):            # Initialize. Distance from k to k is 0
    if'#'==c:                         # Only do land.
      d[(k,k)] = 0

  u = d                               # dictionary of new paths. initialize it to d
                                      # so loop is entered. first d.update is
                                      # basically a NOP

  while u:                            # while there are new paths
    d.update(u)                       # add the new paths to the dict of old paths
    u={}                              #
    for k,i in d:                     # iterate over the known paths. k is the start, i is the end
      for j in{i+1,i+w,i-1,i-w}:      # iterate over squares 1 move to the E,S,W,N from i
        if'#'==s[j]and(k,j)not in d:  # if it's still land, and the path (k,j) isn't already in d,
          u[(k,j)] = d[(k,i)]+1       # then add the new path to u

  k,j=sorted(max(d,key=d.get))        # find the longest path

  return s[:k]+'X'+s[k+1:j]+'X'+s[j+1:]  # X marks the endpoints.

3

C #, 387 ไบต์

มารับลูกบอลกลิ้ง ...

using C=System.Console;class P{static void Main(){string D="",L;int W=0,H=0,z,n,q,h,b=0,c,a,i=0,j=0;for(;(L=C.ReadLine())!=null;H+=W=L.Length)D+=L+="\n";for(z=H;z-->0;){int[]S=new int[H],Q=new int[H*8];for(Q[h=q=0]=z;q<=h;)if((c=S[n=Q[q++]]-1)<0&D[S[n]=n]==35)for(a=4;a-->0;b=c<b?c+(i=z)*(j=n)*0:b)S[Q[++h]=new[]{1,-1,W,-W}[a]+n]=S[Q[h]]<1?c:1;}for(;++z<H;)C.Write(z==i|z==j?'X':D[z]);}}

ลองออนไลน์

เสร็จสิ้นโปรแกรมอ่านจาก STDIN เขียนถึง STDOUT มันไปทั่วแต่ละเซลล์และรัน BFS เพื่อคำนวณเซลล์ที่ไกลที่สุดโดยบันทึกทั้งคู่ถ้ามันอยู่ไกลที่สุดในการบันทึก ไม่มีอะไรจะทำได้จริง ๆ และฉันก็พบกับการเล่นกอล์ฟเพียงเล็กน้อยเท่านั้น

รูปแบบและรหัสความคิดเห็น:

using C=System.Console;

class P
{
    // \n 10
    // \r 13
    // . 46
    // # 35
    // x 88

    static void Main()
    {
        string D="", // map
            L; // line of input

        int W=0, // width
            H=0, // length
            z, // outer position
            n, // next position to expand
            q, // queue position pointer
            h, // queue head pointer
            b=0, // best
            c, // distance to this cell (negative)
            a, // counter
            i=0, // hermit 1 pos
            j=0; // hermit 2 pos

        for(;(L=C.ReadLine())!=null; // read a line, while we can
                H+=W=L.Length) // record the width, and add to length
            D+=L+="\n"; // add a newline, and add the line to the map

        for(z=H;z-->0;) // for each cell
        {
            int[]S=new int[H], // 'seen' >0 -> seen, else it is the distance we have found to it
                Q=new int[H*8]; // due queue (fewer than H*4 expantions, two ints each)

            // standard BFS
            for(Q[h=q=0] // reset currect 
                =z; // expand z first
                q<=h;)
                if((c=S[n=Q[q++]]-1)<0& // record 'seen', and check we havn't been seen
                    D[S[n]=n]==35) // mark as seen, and check we are a hash #
                    // 'move'
                    for(a=4;a-->0; // for each of the 4 neighbours
                            b=c<b? // if we have beaten the best
                            c+(i=z)*(j=n)*0: // set new best, record hermit positions
                            b)
                        S[Q[++h]=new[]{1,-1,W,-W}[a]+n]= // queue it for expantion
                        S[Q[h]]<1? // not seen? (this is BFS, don't need to check c is less thatn S[l+n]
                        c: // distance
                        1; // mark as seen (means it won't actually be expanded)
        }

        // z = -1
        for(;++z<H;) // for each cell
            C.Write(z==i|z==j?'X':D[z]); // print either the original char, or X if it is a hermit's home
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.