พาฉันออกไปจากที่นี่


12

ท้าทาย

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

ป้อนคำอธิบายรูปภาพที่นี่


อินพุต

  • N : ขนาดกริดN x N
  • P : ตำแหน่งของผู้เล่น[playerposx, playerposy]
  • T : ตำแหน่งของเป้าหมาย[targetposx, targetposy]
  • O : ตำแหน่งของอุปสรรค[[x1, y1], [x2, y2],...,[xn, yn]]

เอาท์พุต

เส้นทาง : ผู้เล่นเส้นทางสามารถใช้เพื่อเข้าถึงเป้าหมาย[[x1, y1], [x2, y2],...,[xn, yn]]


กฎระเบียบ

  1. จุด[0,0]อยู่ที่มุมบนซ้ายของตาราง
  2. ตำแหน่งของผู้เล่นจะอยู่ทางด้านซ้ายของกริดเสมอ
  3. ตำแหน่งของเป้าหมายจะอยู่ทางด้านขวาของกริดเสมอ
  4. ตารางจะมีสิ่งกีดขวางอย่างน้อยหนึ่งรายการเสมอ
  5. คุณสามารถสันนิษฐานได้ว่าไม่มีสิ่งกีดขวางผู้เล่นหรือตำแหน่งที่ทับซ้อนกัน
  6. คุณไม่จำเป็นต้องค้นหาเส้นทางขั้นต่ำ
  7. ผู้เล่นสามารถเลื่อนไปทางซ้ายขวาบนและล่างไม่ได้ตามแนวทแยงมุม
  8. คุณสามารถรับอินพุตได้อย่างสะดวกสบาย
  9. คุณสามารถสันนิษฐานได้ว่าเส้นทางสำหรับผู้เล่นที่จะไปถึงเป้าหมายนั้นจะมีอยู่เสมอ
  10. เห็นได้ชัดว่าสำหรับแต่ละเส้นทางมีหลายเส้นทางที่ใช้ได้ให้เลือกหนึ่งเส้นทาง
  11. สมมติดังนั้นตารางจะมีอย่างน้อยN > 23 x 3

ตัวอย่าง

การป้อนข้อมูล: 9, [6, 0], [3, 8], [[0, 5], [2, 2], [6, 4], [8, 2], [8, 7]]
เอาท์พุทเป็นไปได้:[[6, 0], [6, 1], [6, 2], [6, 3], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [5, 8], [4, 8], [3, 8]]

การป้อนข้อมูล: 6, [1, 0], [3, 5], [[1, 2], [2, 5], [5, 1]]
เอาท์พุทเป็นไปได้:[[1, 0], [1, 1], [2, 1], [2, 2], [2, 3], [2, 4], [3, 4], [3, 5]]


บันทึก

ขอให้สังเกตว่าXสำหรับแถวและYสำหรับ cols อย่าสับสนกับพิกัดในภาพ

แก้ไข

ในฐานะที่เป็น @digEmAll ชี้ให้เห็นเนื่องจากกฎระเบียบ#2และ#3, และplayerY = 0 targetY = N-1ดังนั้นถ้าคุณต้องการคุณสามารถใช้เป็นอินพุตเท่านั้นplayerXและtargetX(ถ้านั่นทำให้รหัสของคุณสั้นลง)


1
"ตำแหน่งผู้เล่นจะอยู่ทางซ้ายและเป้าหมายทางด้านขวา": นี่หมายความว่า player-y = 0 และ target-y = N-1 หรือไม่ ถ้าเป็นเช่นนั้นเราสามารถยอมรับพิกัด x (หมายเลขหนึ่ง) สำหรับผู้เล่นและเป้าหมายได้หรือไม่?
digEmAll

1
@digEmAll จุดดี สุจริตฉันไม่ได้คิดอย่างนี้และใช่คุณสามารถแก้ไขได้
DimChtz

ที่เกี่ยวข้องแต่ง่ายขึ้น เกี่ยวข้องแต่ยากกว่า
user202729

เส้นทางต้องอยู่ตั้งแต่ต้นจนจบหรือเป็นไปในทิศทางตรงกันข้ามได้หรือไม่?
kamoroso94

1
@ kamoroso94 ใช่เริ่มต้นกำหนดเป้าหมาย (เสร็จสิ้น) :)
DimChtz

คำตอบ:


5

JavaScript (ES6), 135 ไบต์

รับอินพุตเป็น(width, [target_x, target_y], obstacles)(source_x, source_y)โดยที่อุปสรรคคืออาร์เรย์ของสตริงใน"X,Y"รูปแบบ

ส่งคืนอาร์เรย์ของสตริงใน"X,Y"รูปแบบ

(n,t,o)=>g=(x,y,p=[],P=[...p,v=x+','+y])=>v==t?P:~x&~y&&x<n&y<n&[...o,...p].indexOf(v)<0&&[0,-1,0,1].some((d,i)=>r=g(x+d,y-~-i%2,P))&&r

ลองออนไลน์!

แสดงความคิดเห็น

(n, t, o) =>              // n = width of maze, t[] = target coordinates, o[] = obstacles
  g = (                   // g() = recursive search function taking:
    x, y,                 //   (x, y) = current coordinates of the player
    p = [],               //   p[] = path (a list of visited coordinates, initially empty)
    P = [                 //   P[] = new path made of:
      ...p,               //     all previous entries in p
      v = x + ',' + y     //     the current coordinates coerced to a string v = "x,y"
    ]                     //
  ) =>                    //
    v == t ?              // if v is equal to the target coordinates:
      P                   //   stop recursion and return P
    :                     // else:
      ~x & ~y             //   if neither x nor y is equal to -1
      && x < n & y < n    //   and both x and y are less than n
      & [...o, ...p]      //   and neither the list of obstacles nor the path
        .indexOf(v) < 0   //   contains a position equal to the current one:
      && [0, -1, 0, 1]    //     iterate on all 4 possible directions
        .some((d, i) =>   //     for each of them:
          r = g(          //       do a recursive call with:
            x + d,        //         the updated x
            y - ~-i % 2,  //         the updated y
            P             //         the new path
          )               //       end of recursive call
        ) && r            //     if a solution was found, return it

5

R , 227 ไบต์

function(N,P,G,O){M=diag(N+2)*0
M[O+2]=1
b=c(1,N+2)
M[row(M)%in%b|col(M)%in%b]=1
H=function(V,L){if(all(V==G+2))stop(cat(L))
M[t(V)]=2
M<<-M
for(i in 0:3){C=V+(-1)^(i%/%2)*(0:1+i)%%2
if(!M[t(C)])H(C,c(L,C-2))}}
try(H(P+2,P),T)}

ลองออนไลน์!

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

ขอบคุณ JayCe สำหรับการปรับปรุงการจัดรูปแบบผลลัพธ์


+1 ฉันชอบวิธีที่คุณพิมพ์ผลลัพธ์ (ไม่ใช่รายการที่น่าเบื่อทั่วไป) :)
DimChtz

@DimChtz: ขอบคุณมาก แต่ ... นั่นคือฟังก์ชั่นตัวช่วยฟังก์ชั่น code-golf เพิ่งพิมพ์รายการพิกัดx1 y1 x2 y2 ... xn yn: D
digEmAll

1
ใช่ฉันรู้ว่า: P แต่ก็ยังดี
DimChtz

1
เห็นด้วยกับ @DimChtz ... และฉันคิดว่ามันดูดียิ่งขึ้นหากคุณwrite(t(mx),1,N)แทนของprintไอเอ็นจี :)
Jayce

@ JayCe: ความคิดที่ดีมีการเปลี่ยนแปลง!
digEmAll


3

Haskell , 133 131 130 ไบต์

  • -1 ไบต์ต้องขอบคุณBWO
(n!p)o=head.(>>=filter(elem p)).iterate(\q->[u:v|v@([x,y]:_)<-q,u<-[id,map(+1)]<*>[[x-1,y],[x,y-1]],all(/=u)o,x`div`n+y`div`n==0])

ลองออนไลน์! (มีตัวอย่างทดสอบเล็กน้อย)

ฟังก์ชั่น!รับเป็นอินพุต

  • n :: Int ขนาดของตาราง
  • p :: [Int] ตำแหน่งของผู้เล่นเป็นรายการ [xp, yp]
  • o :: [[Int]] ตำแหน่งอุปสรรคเป็นรายการ [[x1, y1], [x2, y2], ...]
  • t :: [[[Int]]](โดยนัย) ตำแหน่งของเป้าหมายเป็นรายการ[[[xt, yt]]](สามรายการเพื่อความสะดวก)

[[xp, yp], [x1, y1], ..., [xt, yt]]และกลับมาเส้นทางที่ถูกต้องเป็นรายการ

ในฐานะโบนัสจะพบ (หนึ่งใน) เส้นทางที่สั้นที่สุดและใช้งานได้กับตำแหน่งของผู้เล่นและเป้าหมาย ในทางกลับกันมันไม่มีประสิทธิภาพมาก (แต่ตัวอย่างที่มีให้ในระยะเวลาที่เหมาะสม)

คำอธิบาย

(n ! p) o =                                                         -- function !, taking n, p, o and t (implicit by point-free style) as input
    head .                                                          -- take the first element of
    (>>= filter (elem p)) .                                         -- for each list, take only paths containing p and concatenate the results
    iterate (                                                       -- iterate the following function (on t) and collect the results in a list
        \q ->                                                       -- the function that takes a list of paths q...
            [u : v |                                                -- ... and returns the list of paths (u : v) such that:
                v@([x, y] : _) <- q,                                -- * v is an element of q (i.e. a path); also let [x, y] be the first cell of v
                u <- [id, map (+ 1)] <*> [[x - 1,y], [x, y - 1]],   -- * u is one of the neighbouring cells of [x, y]
                all (/= u) o,                                       -- * u is not an obstacle
                x `div` n + y `div` n == 0                          -- * [x, y] is inside the grid
            ]
    )

iteratekk1[[xt, yt]]

การแสดงออกชัดเจนเห็นได้ชัดว่า[id, map (+ 1)] <*> [[x - 1,y], [x, y - 1]]เป็นเพียง "golfy" (-1 ไบต์) [[x + 1, y], [x, y + 1], [x - 1, y], [x, y - 1]]รุ่น


2
ยินดีต้อนรับสู่ PPCG! คำตอบแรกที่ดี!
Arnauld

1
@Arnauld ขอบคุณ! จริง ๆ แล้วฉันใช้เวลาหลายชั่วโมงในการพยายามบีบทางออกไม่กี่ไบต์เพื่อเอาชนะ 135 ของคุณ ^^
Delfad0r

1
กอล์ฟดี! คุณสามารถบันทึกหนึ่งไบต์โดยใช้โอเปอเรเตอร์แทนฟังก์ชั่น: ลองออนไลน์!
ბიმო

@BWO ขอบคุณสำหรับเคล็ดลับ ฉันใหม่ที่นี่ดังนั้นจึงมีกลอุบายมากมายที่ฉันไม่เคยได้ยิน
Delfad0r

1
Btw มีส่วนที่มีเคล็ดลับสำหรับ Haskell โดยเฉพาะที่คุณสามารถค้นหาสิ่งนี้และลูกเล่นอื่น ๆ อีกมากมาย โอ้และก็มักจะมีการแชทเช่นกัน: จาก Monads and Men
იოო

1

เรติน่า 0.8.2 , 229 ไบต์

.
$&$&
@@
s@
##
.#
{`(\w.)\.
$1l
\.(.\w)
r$1
(?<=(.)*)\.(?=.*¶(?<-1>.)*(?(1)$)\w)
d
}`\.(?=(.)*)(?<=\w(?(1)$)(?<-1>.)*¶.*)
u
+T`.`#`.(?=(.)*)(?<=d#(?(1)$)(?<-1>.)*¶.*)|(?<=(.)*.).(?=.*¶(?<-2>.)*(?(2)$)u#)|(?<=#r).|.(?=l#)
.(.)
$1

ลองออนไลน์! ไม่แน่ใจว่ารูปแบบ I / O มีคุณสมบัติหรือไม่ คำอธิบาย:

.
$&$&

ทำซ้ำแต่ละเซลล์ สำเนาด้านซ้ายใช้เป็นพื้นที่ทำงานชั่วคราว

@@
s@

ทำเครื่องหมายจุดเริ่มต้นของเขาวงกตที่เข้าเยี่ยมชม

##
.#

ทำเครื่องหมายจุดสิ้นสุดของเขาวงกตว่าว่างเปล่า

{`(\w.)\.
$1l
\.(.\w)
r$1
(?<=(.)*)\.(?=.*¶(?<-1>.)*(?(1)$)\w)
d
}`\.(?=(.)*)(?<=\w(?(1)$)(?<-1>.)*¶.*)
u

ในขณะที่มีเซลล์ที่ใช้งานได้ให้ชี้ไปที่เซลล์ที่เคยเยี่ยมชมก่อนหน้านี้

+T`.`#`.(?=(.)*)(?<=d#(?(1)$)(?<-1>.)*¶.*)|(?<=(.)*.).(?=.*¶(?<-2>.)*(?(2)$)u#)|(?<=#r).|.(?=l#)

ติดตามเส้นทางจากทางออกไปยังจุดเริ่มต้นโดยใช้เซลล์ที่ทำงานเป็นแนวทาง

.(.)
$1

ลบเซลล์ที่ใช้งาน


1

JavaScript ขนาด 450 ไบต์

(n, {playerx, playery}, {targetx, targety}, [{obstaclex, obstacley}])จะเข้าเป็น {hopx, hopy}ส่งกลับอาร์เรย์ของ

j=o=>JSON.stringify(o);l=a=>a.length;c=(a,o)=>{let i=l(a);while(i>0){i--;if(j(a[i])==j(o)){return 1;}}return 0;}h=(p,t,o)=>{if(p.y<t.y&&!c(o,{x:p.x,y:p.y+1})){return{x:p.x,y:p.y+1};}if(p.y>t.y&&!c(o,{x:p.x,y:p.y-1})){return{x:p.x,y:p.y-1};}if(p.x<t.x&&!c(o,{x:p.x+1,y:p.y})){return{x:p.x+1,y:p.y};}if(p.x>t.x&&!c(o,{x:p.x-1,y:p.y})){return{x:p.x-1,y:p.y};}return t;}w=(n,p,t,o)=>{let r=[];r.push(p);while(j(p)!==j(t)){p=h(p,t,o);r.push(p);}return r;}

นี่เป็นเวอร์ชันที่ไม่มีใครเห็นอกเห็นใจในระเบียบของฉัน

// defining some Array's function for proper comparaisons
json = (object) => { return JSON.stringify(object) };
length = (array) => { return array.length; }
contains = (array, object) => {
    let i = length(array);
    while (i > 0) {
    i--;
        if (json(array[i]) == json(object)) { return true; }
    }
    return false;
}
//return next found hop
getNextHop = (player, target, obstacles) => {
    //uggly serie of conditions
    //check where do we have to go and if there is an obstacle there
    if(player.y<target.y && !contains(obstacles, [x:player.x, y:player.y+1])) { return [x:player.x, y:player.y+1]; }
    if(player.y>target.y && !contains(obstacles, [x:player.x, y:player.y-1])) { return [x:player.x, y:player.y-1]; }
    if(player.x<target.x && !contains(obstacles, [x:player.x+1, y:player.y])) { return [x:player.x+1, y:player.y]; }
    if(player.x>target.x && !contains(obstacles, [x:player.x-1, y:player.y])) { return [x:player.x-1, y:player.y]; }
    return target;
}
//return found path
getPath = (gridsize, player, target, obstacles) => {
    let path = [];
    path.push(player);
    //while player is not on target
    while(json(player)!=json(target)) {
        player = getNextHop(player, target, obstacles); //gridsize is never used as player and target are in the grid boundaries
        path.push(player);
    }
    return path;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.