ฉันต้องการที่จะดูคุณตายจากความกระหาย


12

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

กฎระเบียบ

ทะเลทรายมีลักษณะดังนี้: ตาราง WxH ของพื้นที่ว่างเปล่าส่วนใหญ่ พื้นที่ที่ทำเครื่องหมายไว้Sคือจุดเริ่มต้นของคุณEคือที่ที่คุณต้องการสิ้นสุดและสี่เหลี่ยมจัตุรัสที่มีหมายเลข N ถือ N หน่วยของน้ำ สี่เหลี่ยมที่ทำเครื่องหมายด้วยการ.ถือน้ำเป็นศูนย์

.....................................
........S............................
.....................................
.........7...........................
.....................................
.......................3.............
.....5...............................
................................2....
.....................................
.....................................
.....................................
...............................E.....
.....................................
....................7................
.....................................
.....................................

คุณเริ่มต้นที่ S ด้วยน้ำ 5 หน่วย

คุณสามารถบรรทุกน้ำได้มากที่สุด 5 หน่วย

ทุกครั้งที่คุณหัน

  1. เลื่อนหนึ่งช่องขึ้น, ลง, ซ้ายหรือขวา
  2. กินน้ำ 1 หน่วยที่คุณถืออยู่
  3. เลือกขึ้นหรือลดลงจำนวนหน่วยของน้ำ

เลี้ยวเป็น notated ดังนี้: (direction)(+|-)(units of water), +แสดงว่าคุณจะหยิบขึ้นมาน้ำ-ที่คุณกำลังลดต่ำลง

ตัวอย่างผลัดกัน:

D+0        Move Down
R+0        Move Right
D+2        Move Down, pick up two units of water.
U-1        Move Up, drop one unit of water.

หากคุณทำท่าเหล่านี้โดยเริ่มต้นที่ S ในตัวอย่างด้านบนทะเลทรายจะมีลักษณะเช่นนี้ในภายหลัง

.....................................
........S............................
.........1...........................
.........5...........................
.....................................
.......................3.............
.....5...............................
................................2....
.....................................
.....................................
.....................................
...............................E.....
.....................................
....................7................
.....................................
.....................................

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

คุณสามารถรับน้ำได้สูงสุด 5 ยูนิตเท่านั้น

ไม่มีไทล์สามารถเก็บได้มากกว่า 9 หน่วยยกเว้น S ที่มียูนิตอินฟินิตี้

คุณสามารถหยดน้ำได้มากเท่าที่คุณถืออยู่ในปัจจุบัน

น้ำบนพื้นดินยังคงไม่เปลี่ยนแปลงจนกว่าคุณจะหยิบมันขึ้นมาอีกครั้ง

หากคุณกลับไปที่ S คุณสามารถรับน้ำปริมาณใด ๆ โดยไม่ทำให้เสีย

ถ้าคุณถึง E แล้วคุณจะชนะ คุณยังคงชนะถ้าคุณใช้น้ำหน่วยสุดท้ายของคุณใน E

ถ้าหลังจากการเปิดของคุณคุณจะมีน้ำเป็นศูนย์และคุณไม่ได้อยู่ใน E, คุณตาย

อินพุตและเอาต์พุต

โปรแกรมของคุณจะได้รับแผนที่เริ่มต้นที่มีขนาดตามอำเภอใจSTDINเป็นรูปแบบ ASCII ในรูปแบบด้านบน คุณสามารถสันนิษฐานได้ว่ามันเป็นรูปสี่เหลี่ยมผืนผ้านั่นคือทุกบรรทัดมีความยาวเท่ากันนั่นคือหนึ่งSและหนึ่งEตารางทุกบรรทัดถูกยุติด้วย\nและ STDIN ทั้งหมดจะสอดคล้องกับ regex นี้:/^[SE1-9\.\n]+$/

โปรแกรมของคุณจะเขียนผลลัพธ์ต่อไปนี้ไปยัง STDOUT:

  1. รายการเคลื่อนไหว
  2. สถานะสุดท้ายของแผนที่

คุณสามารถส่งออกรายการการเคลื่อนไหวในรูปแบบที่สะดวก

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

อินพุตตัวอย่าง :

.....S.
.......
.......
E......
....8..

ตัวอย่างผลงานที่ชนะ:

D+0
D+0
D+0
D+0
L+5
L+0
L+0
L+0
L+0
U+0
.....S.
.....#.
.....#.
E....#.
####3#.

Nontriviality

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

  • S และ E อยู่ห่างกันอย่างน้อย 10 ครั้ง
  • สี่เหลี่ยมจัตุรัสใด ๆ ซึ่งในขั้นต้นมีหน่วยของน้ำ N จะต้องล้อมรอบด้วยเส้นขอบความกว้าง N ซึ่งสี่เหลี่ยมทั้งหมดเป็น.(ไม่มีน้ำไม่ใช่ S หรือ E)

ตัวอย่าง

........2.
..........
..........
S.1..2....
..........
..........
........1.
..3.......
.........E

หากคุณเพิ่มปริมาณน้ำบนกระเบื้องใด ๆ ข้างต้นจะไม่สำคัญ

ความต้องการ

สันนิษฐานว่าโปรแกรมของคุณจะประสบกับความพยายามที่ล้มเหลวหลายครั้งก่อนที่จะพบวิธีแก้ไขหากมี

  1. โปรแกรมของคุณต้องแก้ปัญหาอินพุตที่แก้ไขได้ในที่สุด
  2. ฉันต้องการที่จะดูคุณตาย - โปรแกรมของคุณจะส่งออกการเคลื่อนไหวและแผนที่ขั้นสุดท้ายของเส้นทางสู่ความตายสำหรับทุก ๆความพยายามที่ล้มเหลวในการหาทางออก
  3. หากคุณพบวิธีการแก้ปัญหาที่ชนะพิมพ์ออกเต็มรูปแบบสำหรับที่และยุติ
  4. เรียกใช้จนกว่าจะพบวิธีแก้ไขปัญหา แต่อย่าพยายามแก้ปัญหาเดียวกันสองครั้งความตายทั้งหมดควรอยู่ในเส้นทางที่ต่างกัน
  5. ใช้อินพุตทดสอบนี้:

(ต้องย้ายอย่างน้อยหนึ่งครั้งเพื่อปล่อยแคชน้ำที่จุดกึ่งกลาง)

 S........
 .........
 .........
 ........E

รหัสที่สั้นที่สุดซึ่งถูกโพสต์พร้อมกับอินพุตการสาธิตที่ไม่สำคัญซึ่งจะแก้ปัญหาการชนะ


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

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

คุณกำลังหยุดใช้อัลกอริธึมเช่น A * และวางพา ธ 5 หน่วยในแต่ละไทล์ที่คุณต่อเนื่องกันและย้อนกลับไปที่จุดเริ่มต้นถ้าคุณก้าวไปบนไทล์ที่ไม่มีน้ำ 5 อัน?
บลู

ไม่มีอะไร ไปข้างหน้า
spraff

กลยุทธ์ 'อุ้มน้ำทั้งหมดจาก S' ควรใช้งานได้แม้ว่ามันจะน่าเบื่ออย่างยิ่ง พิจารณา S.,.,.,.,. e .... E โดยที่และ e เป็นจุดจริงๆ เครื่องหมายจุลภาคเป็นที่ที่คุณเก็บการหยุดของคุณไปพร้อมกันและ 'e' เป็นที่ที่คุณต้องมี 5 น้ำเพื่อให้วิ่งสำหรับ E 4 ขั้นตอนเพื่อย้าย 1 น้ำไปยังเครื่องหมายจุลภาคแรก (E + 0 E-1 W + 0 W + 4) 16 ขั้นตอนในการเคลื่อนย้าย 1 น้ำไปยังเครื่องหมายจุลภาคที่สอง 52 ถึงสาม 160 ถึงสี่ 484 เพื่อปล่อยน้ำ 1 หยดถึง e และกลับไปที่ S. 1926 ก้าวและคุณอยู่ที่ถือน้ำ 5 ใบและอีก 5 วิ่งไปยัง E, 1931 ก้าว เส้นทางทุกสองขั้นตอนจะเพิ่มความยาวของโซลูชันของคุณเป็นสามเท่า
Sparr

คำตอบ:


12

Perl, 299 + 1 = 300 254 + 1 = 255 ไบต์

นี่จะเป็นอีกหนึ่งภาษาที่ตีกอล์ฟเมื่อผู้คนเห็นอัลกอริทึมของฉัน :-)

ทำงานด้วย-n(การลงโทษ 1 ไบต์)

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

push@a,[split//];($s,$t)=(length$`,$.)if/S/;($e,$f)=(length$`,$.)if/E/}{$_.=$s<$e?($s++,R):$s>$e?($s--,L):$t<$f?($t++,D):($t--,U);$\=reverse$";$".=y/LRUD/RLDU/r.Y.reverse.($"=~y/Y/X/r);$a[$t-1][$s]=~y/./#/;$\.=$s-$e||$t-$f?redo:$_;print map{join'',@$_}@a

ตัวอย่าง (ฉันได้เพิ่มตัวแบ่งบรรทัดลงในเอาต์พุตเพื่อหลีกเลี่ยงการเลื่อนและเพื่อแสดงโครงสร้าง):

E .....
# .....
# .....
# .....
##### S
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLXRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLUXDRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLXRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLUUXDDRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLXRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLUXDRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLXRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLUUUUYDDDRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLXRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLUXDRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLXRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLUUYDDRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLXRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLUYDRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLXRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLLYRRRRRR
 LXR LLXRR LXR LLLXRRR LXR LLXRR LXR LLLLYRRRR
 LXR LLXRR LXR LLLYRRR LXR LLYRR LYR LLLLLUUUUU

ในสัญกรณ์ใช้โดยโปรแกรมการเคลื่อนไหวเป็นตัวแทนผ่านL, R, UและDสำหรับซ้ายขึ้นขวาลงตามลำดับ โดยค่าเริ่มต้นคุณจะได้รับน้ำ 1 หน่วยหลังจากทุกการเคลื่อนไหว แต่สิ่งนี้สามารถแก้ไขได้โดยการต่อท้ายอักขระ:

  • X: วางน้ำ 2 หน่วยแทนที่จะเก็บ 1 ตัว
  • Y: วางน้ำ 1 หน่วยแทนที่จะหยิบ 1 ขึ้น
  • (เช่นช่องว่าง): เติมน้ำอย่างสมบูรณ์ (เอาท์พุทเฉพาะหลังจากที่ย้ายไปSยังโปรแกรมจะถูกส่งออกด้วยพื้นที่ชั้นนำซึ่งทำให้รู้สึกเพราะคุณเริ่มเต็มไปด้วยน้ำ)

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

เหตุผลที่เราต้องการทั้งXและY(และรหัสพิเศษเล็กน้อยเพื่อให้แน่ใจว่าเรามีXตลอดทั้งกลยุทธ์ส่วนใหญ่ แต่เป็นครั้งคราวYในตอนท้าย) ก็คือข้อมูลจำเพาะต้องการเวอร์ชั่นสุดท้ายของแผนที่ที่จะส่งออก วิธีที่ง่ายที่สุดในการดำเนินการนี้คือการปล่อยให้แผนที่ไม่ถูกแตะต้องทั้งหมด (นอกเหนือจากเส้นทางของเราผ่านช่องว่างที่ว่างเปล่าในตอนแรก) โดยเฉพาะอย่างยิ่งเมื่อจตุรัสที่เริ่มต้นด้วย9น้ำจะจบลงด้วย10(ทำลายศิลปะ ASCII) และเราใช้เท่านั้นXดังนั้นเราจำเป็นต้องหาวิธีแก้ปัญหาที่หลีกเลี่ยงการปล่อยน้ำเพิ่มลงบนแผนที่ อัลกอริทึมที่นี่จะ "ธรรมชาติ" ลดลง 1 หน่วยน้ำพิเศษในแต่ละตารางในเส้นทาง; ดังนั้นเวลาสุดท้ายที่เราเข้าชมแต่ละตารางเราลดปริมาณน้ำที่ลดลง 1 ผ่านการใช้ Y แทน X เพื่อให้ในการเยี่ยมชมครั้งสุดท้ายของเราเราระบายสี่เหลี่ยมกลับสู่ปริมาณน้ำเดิมมากกว่า ปล่อยให้มันเปียกเล็กน้อยกว่าเมื่อเราเริ่ม

ฉันขอแนะนำไม่ให้เรียกใช้งานบนแผนที่ขนาดใหญ่เนื่องจากมีประสิทธิภาพ O (2 ^ n) (แม้ว่าบอทจะไม่ตายเพราะกระหาย แต่ก็มีความเป็นไปได้ที่จะคิดว่ามันจะตายจากความหิวโหยโดยใช้กลยุทธ์เช่นนี้)

รุ่นที่อ่านได้:

# implicit with -n: read a line of input into $_
push @a, [split //]; #/ split $_ into characters, store at the end of @a
($s,$t) = (length$`,$.) if /S/; # if we see S, store its coordinates
($e,$f) = (length$`,$.) if /E/  # if we see E, store its coordinates
}{ # Due to -n, loop back to start if there are more lines.

# From here onwards, $" stores the partial solution this iteration;
#                    $\ stores the partial solution last iteration;
#                    $_ stores the path from ($s,$t) to S.
# At the start of the program, $" is a space, $\ and $_ are empty.

$_ .=  # Work out the next step on the path:
  $s < $e ? ($s++,R) # if too far left, move right, record that in $_;
: $s > $e ? ($s--,L) # if too far right, move left, record that in $_;
: $t < $f ? ($t++,D) # if too far up,    move down, record that in $_;
: ($t--,U);          # in other cases we must be too far down.
$\ = reverse $";     # Store last iteration; $" is constructed backwards.
$" .=                # Extend $" by appending
  y/LRUD/RLDU/r .    # the path from ($s, $t) back to S;
  Y .                # a literal 'Y';
  reverse .          # $/ backwards (i.e. the path from S to ($s, $t);
  ($"=~y/Y/X/r);     # a copy of $" with all 'Y' changed to 'X'.
$a[$t-1][$s] =~      # At the current path coordinate,
  y/./#/;            # replace any '.' with '#'.
$\ .=                # Start appending to $\;
  $s-$e||$t-$f?redo  # if we're not at E, abort that and jump back to {{,
: $_;                # otherwise append $_ (the path from S to E).
print map            # For each element of some array
  {join'',@$_}       # output its concatenated elements
  @a                 # specifying that array as @a.
# Implicitly: print $\ (which specifies the sort of newline print uses).

น้ำท่วมจะทำให้โลกเต็มไปด้วยเกลียวเป็นรหัสน้อยกว่าบล็อกของเงื่อนไขเพื่อหาทางออกหรือไม่?
Sparr

1
ฉันไม่คิดว่ามันจะเป็น (แม้ว่าเป็นไปได้มีวิธีที่ฉันไม่ได้เห็นมันเป็นความคิดที่คุ้มค่าที่จะพิจารณา) คุณยังต้องจัดการกับสี่ทิศทางและตอนนี้คุณต้องจัดการกับขอบของแผนที่สิ่งที่ไม่เป็นปัญหาในอัลกอริทึมรุ่นนี้

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