แก้ปัญหาเขาวงกตน้ำแข็ง


19

Ice mazes เป็นหนึ่งในเกมหลักที่ฉันชอบในเกมโปเกมอนตั้งแต่เปิดตัวในPokémon Gold และ Silver งานของคุณคือการสร้างโปรแกรมที่แก้ปัญหาประเภทนี้

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

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

คุณต้องส่งออกรายการการเคลื่อนไหว (4 ค่าที่แตกต่างพร้อมกับการใส่ลงใน N, E, S, W) ที่จะทำให้ผู้เล่นมาถึงจุดสิ้นสุดเมื่อดำเนินการ

ข้อมูลที่ป้อนจะมีเส้นรอบวงของหินที่ปิดอยู่รอบเขาวงกตดังนั้นคุณจึงไม่ต้องกังวลกับผู้เล่นที่ออกจากเขาวงกต

นี่คือเพื่อที่ไบต์ที่น้อยที่สุดจะชนะ

กรณีทดสอบ

ที่นี่.จะแสดงถึงน้ำแข็ง~จะเป็นตัวแทนของดินและOจะเป็นตัวแทนของหิน พิกัดเป็น 1 ดัชนี ตัวอักษรแต่ละตัวในโซลูชันแสดงถึงทิศทางที่ขึ้นต้นด้วยตัวอักษรนั้น (เช่นN= North)


อินพุต

OOOOO
OO.OO
O...O
OOOOO

Start : 3,3
End   : 3,2

เอาท์พุต

N

อินพุต

OOOOOOOOOOOOOOOOO
O........O.....OO
O...O..........OO
O.........O....OO
O.O............OO
OO.......O.....OO
O.............OOO
O......O.......~O
O..O...........~O
O.............OOO
O.......O......OO
O.....O...O....OO
O..............OO
OOOOOOOOOOOOOO~~O
OOOOOOOOOOOOOOOOO

Start : 15,12
End   : 16,8

เอาท์พุต

N,W,N,E,N,E,S,W,N,W,S,E,S,E,N,E,N

อินพุต

OOOOOOOOOOOOOOOO
O~~~~~OOOOO~~~~O
O~~O~OOOOOOO~~OO
O...O..........O
O........O.....O
O..............O
OO.............O
O.............OO
O....~....O....O
O..............O
O..............O
OOOOOOOOOOOOOOOO

Start : 2,2
End   : 14,3

เอาท์พุต

E,S,S,W,N,E,N

อินพุต

OOOOOOOOOOOOOOOOOOO
O~~~~~~~OOOOOOOOOOO
O~~~~...OOOOOOOOOOO
OO~O~..OOOOOOOOOOOO
O..OO.............O
O..............O..O
O....O............O
O.O............~..O
O........OOOO.....O
O.......OOOOO.....O
O.......O~~~O.....O
O.......~~~~~.....O
O.......~~~~~.....O
O..........O......O
O..O..~...........O
O...............O.O
O.....O...........O
O.................O
OOOOOOOOOOOOOOOOOOO

Start : 2,2
End   : 11,11

เอาท์พุต

E,E,E,E,E,S,S,E,N,W,S,E,N,N,N

อินพุตจะมีโซลูชันที่ใช้ได้อย่างน้อยหนึ่งโซลูชันเสมอหรือไม่
Pavel

@Pavel คุณสามารถสมมติได้
ข้าวสาลีตัวช่วยสร้าง

กรณีทดสอบ (แถว, คอลัมน์) หรือ (คอลัมน์, แถว) หรือไม่? มีการจัดทำดัชนี 1 หรือ 0 ขอบกระดานนับเป็นผนังหรือไม่
MildlyMilquetoast


2
@busukxuan คุณสามารถติดอยู่ในเขาวงกตอย่างถาวร (ดูตัวอย่างที่ 1)
Wheat Wizard Wizard

คำตอบ:


4

Mathematica ขนาด 247 ไบต์

(p=x#[[##&@@x]];m={c,v}Switch[p[c+v],0,m[c+v,v],1,c+v,_,c];g=Cases[Array[List,Dimensions@#],c_/;p@c<2,{2}];a=cm[c,#]&/@{{1,0},{-1,0},{0,1},{0,-1}};e=Flatten[Table[#->c,{c,a@#}]&/@g,1];Normalize/@Differences@FindPath[Graph[e],#2,#3][[1]])&

ด้วยตัวแบ่งบรรทัด:

(
p=x#[[##&@@x]];
m={c,v}Switch[p[c+v],0,m[c+v,v],1,c+v,_,c];
g=Cases[Array[List,Dimensions@#],c_/;p@c<2,{2}];
a=cm[c,#]&/@{{1,0},{-1,0},{0,1},{0,-1}};
e=Flatten[Table[#->c,{c,a@#}]&/@g,1];
Normalize/@Differences@FindPath[Graph[e],#2,#3][[1]]
)&

FindPathความคิดทันทีของฉันคือการเป็นตัวแทนของน้ำแข็งและดินตำแหน่งเป็นโหนดในกราฟที่มีขอบกำกับที่สอดคล้องกับการเคลื่อนไหวทางกฎหมายการใช้งานแล้ว บางคนอาจคิดว่าการพิจารณาการเคลื่อนไหวทางกฎหมายนั้นเป็นส่วนที่ง่ายและการหาทางออกจะเป็นส่วนที่ยาก สำหรับฉันมันเป็นสิ่งที่ตรงกันข้าม เปิดคำแนะนำเกี่ยวกับวิธีคำนวณขอบ

อาร์กิวเมนต์แรก#คืออาร์เรย์ 2 มิติที่0แสดงถึงน้ำแข็ง1แทนดินและ2เป็นหิน

อาร์กิวเมนต์ที่สอง#2และอาร์กิวเมนต์ที่สามจะเริ่มต้นและจุดสิ้นสุดตามลำดับในรูปแบบ#3{row,column}

เป็น 3 ไบต์การใช้งานส่วนตัวของตัวละครที่เป็นตัวแทนของU+F4A1\[Function]

คำอธิบาย

p=x#[[##&@@x]];

กำหนดฟังก์ชั่นpที่จะใช้รายการxของรูปแบบ{row,column}และเอาท์พุท#[[row,column]]; เช่นค่าน้ำแข็ง / ดิน / หินที่พิกัดนั้น

m={c,v}Switch[p[c+v],0,m[c+v,v],1,c+v,_,c]

กำหนดฟังก์ชั่นmที่ใช้cเวกเตอร์ตำแหน่งและทิศทางเริ่มต้นvและกำหนดตำแหน่งที่คุณจะสิ้นสุดซ้ำ ถ้าc+vเป็นน้ำแข็งเราก็เลื่อนจากจุดนั้นm[c+v,v]ต่อไป ถ้าc+vเป็นดินเราก็ย้ายไปc+vและหยุด ไม่เช่นนั้น (ถ้าc+vเป็นหินหรืออยู่นอกขอบเขต) คุณจะไม่เคลื่อนไหว โปรดทราบว่าสิ่งนี้มีจุดประสงค์เพื่อให้เรียกบนตำแหน่งน้ำแข็งหรือดินเท่านั้น

g=Cases[Array[List,Dimensions@#],c_/;p@c<2,{2}];

กำหนดรายการgตำแหน่งน้ำแข็งและดิน ( pค่าน้อยกว่า2)

a=cm[c,#]&/@{{1,0},{-1,0},{0,1},{0,-1}}; 

กำหนดฟังก์ชั่นaซึ่งจะมีตำแหน่งเริ่มต้นcและผลตอบแทนในการเคลื่อนย้ายในที่{1,0}, {-1,0}, {0,1}และ{0,-1}ทิศทาง อาจมีความซ้ำซ้อน อีกครั้งสมมติว่าcสอดคล้องกับน้ำแข็งหรือดิน

e=Flatten[Table[#->c,{c,a@#}]&/@g,1];

กำหนดรายการeขอบกำกับที่แสดงถึงการเคลื่อนไหวทางกฎหมาย สำหรับแต่ละตำแหน่ง#ในgคำนวณตารางของขอบ#->cสำหรับแต่ละในc a@#จากนั้นเนื่องจากเราจะจบด้วยรายการย่อยสำหรับแต่ละตำแหน่ง#ฉันจึงเรียบระดับแรก อาจมีลูปและขอบหลายอัน

Normalize/@Differences@FindPath[Graph[e],#2,#3][[1]]

Graph[e]คือกราฟที่โหนดอยู่ในตำแหน่งที่ถูกต้องตามกฎหมาย (น้ำแข็งหรือดิน) และขอบเป็นตัวแทนของการเคลื่อนไหวทางกฎหมาย (อาจชนเข้ากับก้อนหินและไม่เคลื่อนที่) จากนั้นเราจะใช้FindPathเพื่อค้นหาเส้นทางจาก#2เพื่อ#3แสดงเป็นรายการของโหนด เนื่องจากสามารถใช้อาร์กิวเมนต์เพิ่มเติมเพื่อหาเส้นทางมากกว่าหนึ่งผลจริงจะเป็นรายการที่มีเส้นทางเดียวดังนั้นผมใช้องค์ประกอบแรกที่ใช้FindPath [[1]]จากนั้นฉันก็นำDifferencesค่าพิกัดและNormalizeพวกมันต่อเนื่องกัน ดังนั้นขึ้น{-1,0}ลงเป็น{1,0}ขวาเป็นซ้ายและเป็น{0,1}{0,-1}

กรณีทดสอบ

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

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

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

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

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


4

JavaScript (ES6) 180 183

(m,[x,y],[t,u],o=~m.search`
`,s=[[x-y*o,[]]],k=[])=>eval("for(i=0;[p,l]=s[i++],k[p]=t-u*o-p;)[-1,o,1,-o].map(d=>k[q=(M=p=>+m[p+=d]?m[p]<8?M(p):p:p-d)(p)]||s.push([q,[...l,d]]));l")

การใช้BFSเหมือนที่ฉันทำเพื่อแก้ปัญหาที่เกี่ยวข้องนี้

การป้อนข้อมูล
แผนที่เขาวงกตเป็นสตริงหลายบรรทัดใช้Oหรือ0สำหรับหิน8สำหรับดินและตัวเลขใด ๆ ที่ไม่ใช่ศูนย์น้อยกว่า 8 สำหรับน้ำแข็ง ( 7ดูดี)
ตำแหน่งเริ่มต้นและจุดสิ้นสุดเป็นศูนย์

เอาต์พุต
รายการออฟเซ็ตโดยที่ -1 คือW, 1 คือE, ลบน้อยกว่า -1 คือNและบวกมากกว่า 1 คือS

น้อย golfed

(m,[x,y],[t,u])=>{
  o=~m.search`\n`
  s=[[x-y*o,[]]]
  k=[]
  for(i=0; [p,l]=s[i++], k[p]=1, t-u*o != p;)
  {
    [-1,o,1,-o].map(d=>(
      M=p=>+m[p+=d] ? m[p]<8 ? M(p) : p : p-d,
      q=M(p),
      k[q]||s.push([q,[...l,d]])
    ))
  }
  return l
}

ทดสอบ

Solve=
(m,[x,y],[t,u],o=~m.search`
`,s=[[x-y*o,[]]],k=[])=>eval("for(i=0;[p,l]=s[i++],k[p]=t-u*o-p;)[-1,o,1,-o].map(d=>k[q=(M=p=>+m[p+=d]?m[p]<8?M(p):p:p-d)(p)]||s.push([q,[...l,d]]));l")

function Go(maze) {
  var map = maze.textContent;
  var [sx,sy, dx,dy] = map.match(/\d+/g)
  --sx, --sy // zero based
  --dx, --dy // zero based
  map = map.split('\n').slice(1).join('\n') // remove first line
  var result = Solve(map.replace(/\./g, 7).replace(/~/g, 8), [sx,sy], [dx,dy])
  S.textContent = result
  Animate(maze, map, result, sx, sy)
}

function Display(maze, map, pos) {
  var row0 = maze.textContent.split('\n')[0]
  map = [...map]
  map[pos] = '☻'
  maze.textContent = row0+'\n'+map.join('')
}

function Animate(maze, map, moves, x, y) {
  console.log('A',moves)
  var offset = map.search('\n')+1
  var curPos = x + offset * y
  var curMove = 0
  var step = _ => {
    Display(maze, map, curPos)
    if (curMove < moves.length) 
    {
      curPos += moves[curMove]
      if (map[curPos] == 'O')
      {
        curPos -= moves[curMove]
        ++curMove
      }  
      else 
      {
        if (map[curPos] == '~') {
          ++curMove
        }
      }
      setTimeout(step, 100)
    }
    else
      setTimeout(_=>Display(maze,map,-1),500)
  }
  step()
}
td { 
  border: 1px solid #888;
}
Select maze<pre id=S></pre>
<table cellspacing=5><tr>
<td valign=top><input type=radio name=R onclick='Go(M1)'><br>
<pre id=M1>3,3 to 3,2  
OOOOO
OO.OO
O...O
OOOOO</pre></td>
<td valign=top><input type=radio name=R onclick='Go(M2)'><br>
<pre id=M2>15,12 to 16,8
OOOOOOOOOOOOOOOOO
O........O.....OO
O...O..........OO
O.........O....OO
O.O............OO
OO.......O.....OO
O.............OOO
O......O.......~O
O..O...........~O
O.............OOO
O.......O......OO
O.....O...O....OO
O..............OO
OOOOOOOOOOOOOO~~O
OOOOOOOOOOOOOOOOO</pre></td>
<td valign=top><input type=radio name=R onclick='Go(M3)'><br>
<pre id=M3>2,2 to 14,3
OOOOOOOOOOOOOOOO
O~~~~~OOOOO~~~~O
O~~O~OOOOOOO~~OO
O...O..........O
O........O.....O
O..............O
OO.............O
O.............OO
O....~....O....O
O..............O
O..............O
OOOOOOOOOOOOOOOO</pre></td>
<td valign=top><input type=radio name=R onclick='Go(M4)'><br>
<pre id=M4>2,2 to 11,11
OOOOOOOOOOOOOOOOOOO
O~~~~~~~OOOOOOOOOOO
O~~~~...OOOOOOOOOOO
OO~O~..OOOOOOOOOOOO
O..OO.............O
O..............O..O
O....O............O
O.O............~..O
O........OOOO.....O
O.......OOOOO.....O
O.......O~~~O.....O
O.......~~~~~.....O
O.......~~~~~.....O
O..........O......O
O..O..~...........O
O...............O.O
O.....O...........O
O.................O
OOOOOOOOOOOOOOOOOOO</pre></td>
</tr></table>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.