Office Escape: วางแผนทางออกของคุณ!


32

มันเป็นการวิ่งครั้งสุดท้าย ... และครึ่งหนึ่งของทีมคุณไม่ดี คุณทำงานช้าแล้วแค่ทำสิ่งสุดท้ายในวันนี้รอคอย ... ทำไมไฟดับไป? ฉันจำไม่ได้ว่าคนที่รักษาความปลอดภัยมารอบ ... โอ้ไม่! ฉันทิ้งกุญแจไว้ที่บ้าน!

ในฐานะที่เป็นความน่ากลัวของอ่างล้างมือในสถานการณ์ที่คุณตัดสินใจว่าคุณกำลังจะหลบหนี

สรุปภารกิจ

หากต้องการเอฟเฟกต์การหลบหนีคุณต้องมีแผน! อย่างไรก็ตามคุณรู้ว่าแผนใด ๆ มีโอกาสล้มเหลวและแผนการที่แตกต่างต้องการความพยายามที่แตกต่างกัน

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

คุณสร้างแผนที่อาคาร:

#######################
#                =    #
!                =    !    <-- window
#          !     =    #        (freedom!)
#################=    #
#    #           =    #
#    #           =    #
#    #           =    #
# o  !   # #  !  =    #
##|  !  ## #  !  =    #
#######################

  ^  ^           ^
  me my door     ludicrously high shelves
     (locked)    (climbable)

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

เซลล์ชนิดต่างๆ

  - empty, you can be here (i.e. the escapee can consume this cell)
# - solid (your desk, your in-tray), you can't be here, but you can stand on it
! - destructible, (co-worker's desk, door, window), you can't be here until you smash it first (turning it into an empty cell)
= - climbable, (fire ladder, filing cabinet, etc.), you can be here

แต่เดิมเซลล์ที่ผู้หลบหนีใช้ไปนั้นว่างเปล่า

ข้อกำหนดการดำเนินการ

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

ขั้นตอน

1 stp, 100%, มิเรอร์

 o.            o
 |.   -->      |
 #            #

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

"มิเรอร์" หมายถึงการกระทำนี้มีสองรูปแบบ การกระทำที่ "ถูกต้อง" จะปรากฏขึ้นการกระทำที่ "ซ้าย" เป็นมิเรอร์ที่แน่นอนตัวอย่างเช่น:

.o
.|
 # 

เป็นรูปแบบกระจก (ซ้าย) ของ

o.
|.
# 

การกระทำที่ถูกต้องเรียกว่า "ขวา" (เช่น "ก้าวขวา") การกระทำด้านซ้ายเรียกว่า "ซ้าย" (เช่น "ก้าวซ้าย")

ในไดอะแกรมเหล่านี้จะแสดง escapee

o
|

เมื่อยืน (สูง 2 หน่วย) และ

%

เมื่อหมอบ (1 หน่วยสูง) เซลล์ที่ต้องแข็งหรือถูกทำลายจะถูกระบุโดยแฮช, #. .เซลล์ที่จะต้องไม่ถูกของแข็งหรือถูกทำลายจะมีการแสดงจุด !เซลล์ที่จะต้องถูกทำลายจะมีการแสดงปัง _พื้นที่ว่างที่สร้างขึ้นใหม่จะปรากฏโดยการขีดเส้นใต้ xเป็นจุดอ้างอิงที่ไม่ย้าย (ไม่มีอยู่ไม่มีข้อ จำกัด ในสิ่งที่เซลล์นั้นต้องเป็น (เช่นช่องว่าง)

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

ขั้นตอน

1 stp, 100%, มิเรอร์

 o.         o
 |.  -->    |
x#        x#

ปีนออกไป

1 stp, 100%, มิเรอร์

 =         =
 o.  -->    o
 |.         |
x=        x= 

สับเปลี่ยน

3 stp, 100%, มิเรอร์

 %.         %
x#   -->  x# 

ปีนขึ้นไป

10 stp, 95%, กระจก

 o.         %
 |#  -->    #
x#        x#

Drop

0 stp, 100%

 o         
 |  -->   o
x.       x|

วาง (ยืน)

0 stp, 100%

 %        o
x.  -->  x|

ปีนขึ้นไป

2 stp, 100%

 =        o
 o  -->   |
x|       x

หมอบคลาน

2 stp, 100%

 o
 |  -->   %
x#       x#

ยืน

4 stp, 100%

 .        o
 %  -->   |
x#       x#

กระโดดสั้น

4 stp, 95%, กระจก

 o..          o
 |..  -->     |
x#         x#

กระโดดไกล

7 stp, 75%, กระจก

 o...           o
 |...  -->      |
x#          x#

กระโดดสูง

12 stp, 90%, กระจก

 ..         o
 o.  -->    |
 |          
x#        x# 

ใส่กลับของคุณเป็นมัน!

20 stp, 80%, กระจก

 o!.         _o
 |!.  -->    _|
x#         x#

หมัด

8 stp, 90%, กระจก

 o!        o_
 |   -->   |
x#        x#

เตะ

8 stp, 85%, กระจก

 o         o
 |!  -->   |_
x#        x#

ประทับ

8 stp, 90%

 o        o
 |  -->   |
x!       x_

แผน

แผนคือลำดับของการกระทำที่กำหนดไว้ด้านบน ตัวอย่างเช่น:

Step Left
High Jump Left
Crouch
Shuffle Left
Shuffle Left
Stand
Long Jump Left
Put your back into it! Left
Step Left

สังเกตการรวมของหยด ควรตั้งกฎให้หยุดไม่ให้ทำอะไรนอกจากตกหล่น แต่คุณยังต้องวางแผน!

แผนใดมีความพยายามที่จำเป็นซึ่งเป็นผลรวมของความพยายามในแต่ละขั้นตอน นอกจากนี้ยังมีความน่าจะเป็นความสำเร็จซึ่งเป็นผลมาจากความน่าจะเป็นที่จะประสบความสำเร็จของแต่ละการกระทำ ตัวอย่างง่ายๆ:

Step Right:          1stp,  100%
Long Jump Right:     7stp,  75%
Step Right:          1stp,  100%
Stamp:               8stp,  90%
Drop:                0stp,  100%
Drop:                0stp,  100%
Drop:                0stp,  100%
Drop:                0stp,  100%
Step Left:           1stp,  100%
Step Left:           1stp,  100%
High Jump Left:      12stp, 90%

Effort = 1+7+1+8+1+1+12 = 31
Success Probability = 75%*90*90% = 60.75%

A 'ตัวอย่างเช่นทำงานสำหรับแผนที่ที่ด้านบนของหน้าสามารถพบได้เป็นส่วนสำคัญ

อินพุต

อินพุตมีสองส่วนคือจำนวนเต็มและอาร์เรย์หรือสตริงอักขระ

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

แผนที่ที่ถูกต้องคือสี่เหลี่ยมผืนผ้าที่มีตัวย่อยืน (ขนาดขั้นต่ำ 1x2) และไม่มีสัญลักษณ์ที่ไม่ระบุ แถวทั้งหมดจะมีความยาวเท่ากัน คุณอาจยอมรับอินพุตเป็นสตริงที่กำหนดมิติ 1 มิติ (ตัวคั่นต้องเป็นอักขระที่สอดคล้องกันหนึ่งตัวหรือหนึ่งในคู่ของ CRLF และ LFCR) เป็นอาร์เรย์ 1 มิติที่คล้ายกันหรืออาร์เรย์ 2 มิติ หากรูปแบบการป้อนข้อมูลที่คุณเลือกไม่ได้ระบุความกว้างหรือความสูงของแผนที่ในบางกรณีคุณอาจยอมรับข้อโต้แย้งเพิ่มเติมสำหรับสิ่งเหล่านี้ (คุณต้องระบุสิ่งนี้อย่างชัดเจนในคำตอบของคุณ) คุณอาจผสมอาร์กิวเมนต์บรรทัดคำสั่งและอินพุตมาตรฐานถ้ามันเหมาะสมกับคุณ (เช่น map จาก stdin, ความน่าจะเป็นความสำเร็จขั้นต่ำจาก argv) ต่อไปนี้เป็นตัวอย่างแผนที่ที่ถูกต้องและไม่ถูกต้อง

ถูกต้อง:

o
|

ถูกต้อง:

  #     #
  !   o #
  !   | #
#########

ไม่ถูกต้อง (ไม่มี escapee):

  #     #
  !     #
  !     #
#########

ไม่ถูกต้อง (escapee เริ่มยืนอยู่เสมอ):

  #     #
  !     #
  !   % #
#########

ไม่ถูกต้อง (สัญลักษณ์ที่ไม่ถูกต้อง):

  #     #
  !  ~  #
  !     #
#########

ไม่ถูกต้อง (ไม่ใช่แถวที่มีความยาวสี่เหลี่ยมผืนผ้า / แตกต่างกัน):

  #     #
  !   o #
  !   | # 
#########

คุณอาจจะถือว่าข้อมูลที่คุณป้อนนั้นถูกต้อง (ฉันไม่สนใจว่าโปรแกรมของคุณจะทำอะไรถ้ามันถูกส่งเข้าที่ไม่ถูกต้อง)

เอาท์พุต

เอาท์พุทเป็นข้อความ (ASCII) อาจถูกส่งคืนเป็นสตริงหรือพิมพ์ไปยังเอาต์พุตมาตรฐาน แผนจะต้องถูกกำหนดโดย LF, CRLF หรือ LFCR ในทำนองเดียวกันจะต้องมี LF, CRLF หรือ LFCR อื่นหลังจากความพยายามที่จำเป็น ตัวแบ่งบรรทัดต่อท้ายเป็นตัวเลือก

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

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

รูปแบบ:

Required Effort: <effort>
<plan>

ตัวอย่างเช่นสำหรับการป้อนข้อมูล

50
  #     #
  !   o #
  !   | #
#########

ผลลัพธ์ที่เหมาะสมคือ:

Required Effort: 23
Step Left
Step Left
Step Left
Kick Left
Punch Left
Step Left
Step Left
Step Left
Step Left

ความน่าจะเป็นของความสำเร็จที่นี่คือ 76.5%

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

ตัวอย่าง

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

การป้อนข้อมูล:

100
o
|

เอาท์พุท:

Required Effort: 0
Drop

การป้อนข้อมูล:

5
# =      #
# =      !
# = !  ! !
# =#######
# =      #
# =   o  #
# = ! |  #
##########

เอาท์พุท:

Required Effort: 57
Step Left
Kick Left
Step Left
Step Left
Step Left
Climb Up
Climb Up
Climb Up
Climb Up
Climb off Right
High Jump Right
Long Jump Right
Step Right
Drop
Kick Right
Crouch
Shuffle Right
Shuffle Right

การป้อนข้อมูล:

60
#########
# ! #   #
! ! ! o #
! # ! | #
#########

เอาท์พุท:

Required Effort: 58
Step Left
Kick Left
Crouch
Shuffle Left
Shuffle Left
Stand
Punch Left
Clamber Up Left
Shuffle Left
Drop (Stand)
Kick Left
Crouch
Shuffle Left
Shuffle Left

สำหรับแผนที่เดียวกัน แต่ 80% ผลลัพธ์ควรเป็น:

There is no hope!

สำหรับแผนที่เดียวกัน แต่ 50% ความพยายามที่จำเป็นกลายเป็น 56 ด้วยแผนอื่น)

การป้อนข้อมูล:

50
#######################
#          #     =    #
!          #     =    !
#          #     =    #
######  #####!## =### #
#=   ##       #  =    #
#=#############  =    #
#=               =    #
#= o             =    #
#!!|             =    #
#######################

เอาท์พุท:

Required Effort: 121
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Climb Up
Climb Up
Climb Up
Climb Up
Climb Up
Climb Up
Climb off Right
Long Jump Left
Step Left
Step Left
Stamp
Drop
Drop
Crouch
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Stand
Clamber Up Left
Stand
Clamber Up Left
Stand
Step Left
Step Left
Step Left
Step Left
Punch Left
Clamber Up Left
Shuffle Left

การป้อนข้อมูล:

66
######
#  ###
#o ! !
#| ! !
### ##
######

เอาท์พุท:

Required Effort: 37
Step Right
Put your back into it! Right
Kick Right
Crouch
Shuffle Right
Shuffle Right

การป้อนข้อมูล:

อันนี้ถูกออกแบบมาเพื่อตรวจสอบข้อสันนิษฐานที่ผิดพลาดจำนวนหนึ่งที่อาจตกเป็นเหยื่อและอาจดูแปลก ๆ

30
###################
# ## # # #   #  = #
! ## #   #   #  = #
#      #   #    = #
##  ############= #
# ## #         #= #
# =  #         #= #
! =  #         #= #
# =  #         #= #
#o=  !          ==#
#|=  !           =#
#!= # ==########==#
#   #    !   !!  =#
#   #    !!  !  = #
#   # !!!!#########
#   # #           #
#   # #           #
###################

ผลผลิตที่มีโอกาสประสบความสำเร็จในข้อ จำกัด 30:

Required Effort: 199
Long Jump Right
Put your back into it! Right
<snip>

ผลผลิตที่มีโอกาสประสบความสำเร็จในข้อ จำกัด 32:

Required Effort: 200
Long Jump Right
Punch Right
<snip>

การใช้แผนที่ที่ด้านบนเป็นตัวป้อนข้อมูลด้วยความน่าจะเป็นของข้อ จำกัด ความสำเร็จ 1% คุณควรได้รับความพยายามที่จำเป็น 116 (โอกาสของความสำเร็จ ~ 32% สิ่งนี้ใช้เวลาประมาณ 20 วินาทีในการทดสอบโปรแกรมของฉัน)

เกณฑ์ชัยชนะ

นี่คือรหัสกอล์ฟอาจเป็นรหัสที่สั้นที่สุดที่จะชนะ

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

ตัวอย่าง Solver, Verifier, สคริปต์ทดสอบและ TestCases (พร้อมโซลูชัน)

รหัส C # สำหรับแก้และวิธีการแก้ปัญหาตรวจสอบที่มีอยู่ที่นี่เป็นส่วนสำคัญ ส่วนสำคัญยังมีfile.txtซึ่งเป็นรูปแบบของเครื่องที่สามารถอ่านได้ (เพียงพอ) ของการกระทำที่อธิบายไว้ข้างต้นและเป็นสิ่งจำเป็นสำหรับโปรแกรมที่จะเรียกใช้ ความคลาดเคลื่อนระหว่างไฟล์และสเป็คใด ๆ นั้นไม่ได้มีเจตนา

ส่วนสำคัญยังมีกรณีทดสอบจำนวนหนึ่ง (รวมถึงตัวอย่างทั้งหมดข้างต้น) และสคริปต์ PowerShell เพื่อเรียกใช้การส่งข้อมูลโดยอัตโนมัติ หากสคริปต์บอกคุณว่าการทดสอบบางอย่างล้มเหลวคุณสามารถเรียกใช้OfficeEscapeSolver.exe testcase<n>.txt outputFromYourProgram.txtเพื่อดูรายละเอียดเพิ่มเติม โซลูชั่นตัวอย่างสำหรับกรณีทดสอบเหล่านี้อยู่ในกระทู้อื่น

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

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

หากคุณคิดว่าคุณพบข้อผิดพลาดที่มีตัวแก้ไขหรือ testcript ข้อผิดพลาดในfile.txtหรือ testcase หลบซึ่งโปรดแสดงความคิดเห็นในโพสต์นี้หรือ ping ฉันใน SE Chat; ฉันอาจจะไม่สังเกตเห็นความพยายามในการสื่อสารอื่น ๆ

ฉันจะไม่ให้สคริปต์ทดสอบใน Bash หรือ Batch เพราะฉันไม่รู้จักพวกเขา แต่ฉันยินดีที่จะรวมการแปลและจะเขียนเวอร์ชัน C # หากผู้ใช้ต้องการ

โพสต์ Amble

มีคำถาม? อย่ารอช้าถามพวกเขาวันนี้!

งานนี้มีขึ้นเพื่อต้องการความพยายามในการมอบบางสิ่งบางอย่างให้กับนักกอล์ฟอย่างจริงจัง

ขอบคุณ ais523 สำหรับข้อเสนอแนะของเขาเกี่ยวกับอินพุต / เอาต์พุต

ฉันสามารถให้ทดสอบเพิ่มเติมในไฟล์ส่วนสำคัญหากผู้คนต้องการมากขึ้น (ไม่ต้องการให้โพสต์นี้กลายเป็นอีกต่อไป) หรือต้องการให้บางส่วนของพวกเขาเอง


2
ท้าทายมาก! ฉันจะให้ช็อตนี้เมื่อฉันมีเวลา :)
R. Kap

คุณรู้หรือไม่ว่าอันตรายของการตก (หรือการลดลงอย่างรวดเร็วที่ด้านล่าง) อาจเป็นแบบจำลองโดยให้ความน่าจะเป็นลดลง 95% หรือประมาณนั้น ;) ความท้าทายที่ดี!
Martin Ender

คุณจะรอดจากไฟท้องฟ้าหรืออุโมงค์ได้หรือไม่? เช่นด้านบนและหรือด้านล่างของสนาม? หรือซ้ายหรือขวาเท่านั้น?
Moogie

@ Moogie คุณสามารถแน่นอน! ตราบใดที่เท้าของคุณว่างคุณก็ว่าง (ตัวอย่างเช่นดู 1x2 testcase ซึ่งคำตอบนั้นลดลงเพียงครั้งเดียว) ฉันจะเพิ่ม testcase ขนาดเล็กเพื่อสรุปสาระสำคัญเพื่อทดสอบการปิดเพดาน
VisualMelon

3
เพิ่มความโปรดปรานให้กับคำถาม นี่เป็นคำถามที่ยอดเยี่ยมที่สมควรได้รับคำตอบ
programmer5000

คำตอบ:


3

Perl 5, 1425 1464 1481 1469 1485 1438 1438 ไบต์

นั่นเป็นความท้าทายที่สนุก! และน่าตกใจดูเหมือนว่าฉันมีรหัสสั้นที่สุดที่น้อยกว่า 1.5kB! :)

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

60
#########
# ! #   #
! ! ! o #
! # ! | #
#########

โปรแกรมของฉันจะใช้เวลา: (NB: จะต้องมีลำไส้ใหญ่ในตอนท้าย แต่ไม่ใช่จุดเริ่มต้น!)

60
#########:# ! #   #:! ! ! o #:! # ! | #:#########:

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

น่าเสียดายที่มีการแลกเปลี่ยนประสิทธิภาพอย่างมากเพื่อทำการปิดการใช้งานไม่กี่ไบต์ดังนั้นรุ่น golfed ค่อนข้างช้า;) Perl ดูเหมือนว่าจะพบหลักฐานโดยเฉพาะอย่างยิ่งที่จะเจ็บปวดมาก

โดยไม่ต้องลาเพิ่มเติม

chop($P=<>,$_=<>);s/:/ : /g;$w++until/:.{$w}:/;$z=$"x$w;$_="(.{".$w--."})"for($c,$h,$i,$j);$_="$z:$z: $_$z";$n="[ =]";$d="([!#])";@s=split/,/,'Drop,Drop (Stand),Stepx,Climb offx,Shufflex,Clamber Upx,Put your back into it!x,Punchx,Kickx,Short Jumpx,Long Jumpx,High Jumpx,Crouch,Stand,Climb Up,Stamp';@c=split/,/,"o$c\\|$c$n/ \$1o\$2|,%$c$n/o\$1|,o$n$h\\|$n$h${d}/ o\$1 |\$2\$3,=${c}o$n$h\\|$n$h=/=\$1=o\$2=|\$3=,%$n$h$d/ %\$1\$2,o$n$h\\|${d}$h${d}/ %".'$1 $2$3$4,'."o!$n$i\\|!$n$i${d}/  o\$1  |\$2\$3,o!$h\\|$c$d/o \$1|\$2\$3,\\|!$h$d/| \$1\$2,o$n$n$i\\|$n$n$i${d}/  o\$1  |\$2\$3,o$n$n$n$j\\|$n$n$n$j${d}/   o\$1   |\$2\$3,$n$n${h}o$n$h\\|$c$d/ o".'$1 |$2 $3$4,'."o$c\\|$c${d}/ \$1%\$2\$3,$n$c%$c${d}/o\$1|\$2\$3,=${c}o$c\\|/o\$1|\$2=,\\|$c!/|\$1 ";eval"*$_=sub{\$Q=\"$s[$_]\";s/$c[$_]/}"for(0..15);sub M{$_=join":",map{join'',reverse split//}split/:/};push@M,[$_,0,100,$P];$B{$_}=100;@E=(0,0,1,1,3,10,20,8,8,4,7,12,2,4,2,8);@P=map{100-$_}(0,0,0,0,0,5,20,10,15,5,25,10,0,0,0,10);$z='$N=[$_,$G+0,$t,$t[3]*100,"$t[4]$Q\n"];$N->[4]=~s/x/';do{sub A{@N=@$N;if($N[2]/$N[3]>$B{$N[0]}){push@M,$N;$B{$N[0]}=$N[2]/$N[3]}};die"There is no hope!\n"if(!(@M=grep$G-$_->[1]<21,@M));$e=-1;while(++$e<@M){@t=@{$M[$e]};$m=$_=$t[0];die"Required Effort: $t[1]\n$t[4]"if(/([|%]:|:[|%])/||/[|%][^:]*$/||/^$c:[^:]*[%|]/);for$x(0..15){$_=$m;$t=$t[2]*$P[$x];if($G==$E[$x]+$t[1]and$t>=$t[3]*100){&$x;eval"$z Right/";A;$_=$m;M;&$x;M;eval"$z Left/";A;}}}}

เพื่อความมีสตินี่คือสิ่งเดียวกันกับการขึ้นบรรทัดใหม่และความคิดเห็นเล็กน้อย:

chop($P=<>,$_=<>); #Take input
s/:/ : /g; #Pad columns on either side so escapee can leave that way
$w++until/:.{$w}:/; #Find width
$z=$"x$w;#Setup a blank line for use in padding later
$_="(.{".$w--."})"for($c,$h,$i,$j); #Set up some generic capturing regexes for reuse
$_="$z:$z: $_$z"; #Pad the top and bottom so the escapee can leave those ways
$n="[ =]"; #Regex for nonsolid block
$d="([!#])"; #Regex for solid block
@s=split/,/,'Drop,Drop (Stand),Stepx,Climb offx,Shufflex,Clamber Upx,Put your back into it!x,Punchx,Kickx,Short Jumpx,Long Jumpx,High Jumpx,Crouch,Stand,Climb Up,Stamp'; #Movement names
@c=split/,/,"o$c\\|$c$n/ \$1o\$2|,%$c$n/o\$1|,o$n$h\\|$n$h${d}/ o\$1 |\$2\$3,=${c}o$n$h\\|$n$h=/=\$1=o\$2=|\$3=,%$n$h$d/ %\$1\$2,o$n$h\\|${d}$h${d}/ %".'$1 $2$3$4,'."o!$n$i\\|!$n$i${d}/  o\$1  |\$2\$3,o!$h\\|$c$d/o \$1|\$2\$3,\\|!$h$d/| \$1\$2,o$n$n$i\\|$n$n$i${d}/  o\$1  |\$2\$3,o$n$n$n$j\\|$n$n$n$j${d}/   o\$1   |\$2\$3,$n$n${h}o$n$h\\|$c$d/ o".'$1 |$2 $3$4,'."o$c\\|$c${d}/ \$1%\$2\$3,$n$c%$c${d}/o\$1|\$2\$3,=${c}o$c\\|/o\$1|\$2=,\\|$c!/|\$1 ";#Movement regexes
eval"*$_=sub{\$Q=\"$s[$_]\";s/$c[$_]/}"for(0..15); #Setup methods to apply regexes. Name of these methods are 0,1,2,3, etc, so we can easily call them in a loop
sub M{$_=join":",map{join'',reverse split//}split/:/}; #Method to mirror the map. All the regexes are right-moving, so the mirror effects are achieved by M;&$x;M
push@M,[$_,0,100,$P]; #Array for initial map position. Encodes: [Map,Effort value,Probability value 1,Probability value 2,Movements(initially undef)]. Two integers are used for the probability to avoid floating point (although after enough steps they overflow and are automatically converted to f.p.)
$B{$_}=100; #Hash map to hold best probability of reaching a map. A new map is never added if it requires at least as much effort and doesn't give a better probability.
@E=(0,0,1,1,3,10,20,8,8,4,7,12,2,4,2,8); #Effort values
@P=map{100-$_}(0,0,0,0,0,5,20,10,15,5,25,10,0,0,0,10); #Probability values
$z='$N=[$_,$G+0,$t,$t[3]*100,"$t[4]$Q\n"];$N->[4]=~s/x/'; #Setup map values
do{ #Loop over all efforts. Do-while loop starts at undef, which is converted to zero automatically when used in a numeric context
    sub A{@N=@$N;if($N[2]/$N[3]>$B{$N[0]}){push@M,$N;$B{$N[0]}=$N[2]/$N[3]}}; #Method to add a map to list.
    die"There is no hope!\n"if(!(@M=grep$G-$_->[1]<21,@M)); #Pares away maps that no longer can produce new maps, and prints "There is no hope!" to stderr if there are no maps left.
    $e=-1;
    while(++$e<@M){ #Loop over all maps. Note that this loops over even maps that are created during the loop
        @t=@{$M[$e]}; #Dereference info about each map
        $m=$_=$t[0]; $Setup map variables
        die"Required Effort: $t[1]\n$t[4]"if(/([|%]:|:[|%])/||/[|%][^:]*$/||/^$c:[^:]*[%|]/); #Checks if escaped, and gives message if so.
        for$x(0..15){
            $_=$m; #Put map into $_
            $t=$t[2]*$P[$x]; #Probability calculation
            if($G==$E[$x]+$t[1]and$t>=$t[3]*100){ #If effort values are right and probability is over threshold
                &$x; #Run regex
                eval"$z Right/"; #Set up map info
                A; #Add map to list @M (only if probability works out right)
                $_=$m;
                M;&$x;M; #Same thing, but mirrored now (generates movement left)
                eval"$z Left/";
                A;
            }
        }
    }
}while(++$G)

ฉันสามารถเห็นสถานที่สองสามแห่งที่จะตัดออกไปอีกสองสามไบต์ แต่ฉันยังไม่ต้องการผ่านการทดสอบทั้งหมดอีกครั้ง ภายหลัง! :)

แก้ไข: เพิ่มช่องว่างด้านล่างบางส่วนเพื่อให้พอดีกับผลลัพธ์ของคุณมากขึ้นเมื่อหนีออกมาจากพื้น ลบ evals บางส่วนออกดังนั้นรหัสอาจทำงานเร็วขึ้นเช่นกัน!

แก้ไข: ไม่จัดการบันไดและลดลงค่อนข้างถูก ยังไม่จัดการบันไดค่อนข้างถูก ... พยายามแก้ไขในตอนนี้


ดีใจที่มีคนอื่นสนุกกับมัน! ฉันกลัวว่าฉันไม่สามารถยอมรับสิ่งนี้ได้ในขณะนี้เนื่องจากคุณไม่สามารถสรุปได้ว่าอินพุตที่มีแถวพิเศษหรือช่องว่างภายในที่ด้านบน (แต่ที่ ~ 1.5kB เพียงแทรกทันทีไม่ควรเจ็บ มากเกินไป!) ฉันไม่มี Perl บนเครื่องนี้ แต่ฉันจะพยายามหาวิธีทดสอบในวันนี้ดังนั้นฉันสามารถตรวจสอบการทำงานและทำงานในกรอบเวลาที่สมเหตุสมผลแล้วรายงานกลับมา!
VisualMelon

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

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

1
@VisualMelon อ่าฉันคิดว่าการหลบหนีจากหลังคาผู้หลบหนีจะต้องขึ้นไปบนห้องแล้วเดินไปที่ด้านข้างออกจากหลังคา ฉันเห็นประโยคที่เกี่ยวข้องตอนนี้ ฉันจะแก้ไขได้ :)
คริส

2
คุณสามารถเพิ่มลิงค์ TIO ได้หรือไม่?
programmer5000

3

C #, 1814 1481 1395 ไบต์

ช่างเป็นสิ่งที่หวด !! ตอนนี้ฉันพอใจมากแล้ว!

using C=System.Console;using System.Linq;class S{string M,N="";int x,y,E,c;decimal P=1;static void Main(){int W=0,H=0,x,i,j,k,X,Y,f,m,P=int.Parse(C.ReadLine());string l,M="",B,R="There is no hope!";for(;(l=C.ReadLine())!=null;H++,M+=l)W=l.Length;x=M.IndexOf("|");var D=new[]{new S{M=M,x=x%W,y=x/W}}.ToList();for(var N=D.ToDictionary(s=>R,s=>D);D.Count>0;D.Sort((z,w)=>z.E-w.E)){S s=D[f=0];D.Remove(s);var n=N[l=s.x+s.M+s.y+s.c]=N.ContainsKey(l)?N[l]:new S[0].ToList();if(n.All(o=>o.P<s.P|o.E>s.E)){n.Add(s);X=s.x;Y=s.y;if((X|Y|-X/W-Y/H)<0){R="Required Effort: "+s.E+s.N;break;}for(var A="0110d,Step,*** * #*,0110d,Climb off,=** * =*,3310d,Shuffle,***** #*,2:1/_,Clamber Up,*** *##*,0420_,Short Jump,****  *  #**,0730K,Long Jump,*****   *   #***,0<1/Z,High Jump,  * **#*,0D20P,Put your back into it!,****! *! #**,0800Z,Punch,***!**#*,0800U,Kick,*****!#*,0001d,Drop,*** ,1001d,Drop (Stand),*** ,2200d,Crouch,***#,1400d,Stand,* *#,020/d,Climb Up,=***,0800Z,Stamp,***!".Split(',');f<26;){l=A[k=f*3%48];B=A[++k]+(f>15?" Right":f>9?"":" Left");M=A[++k];m=f++/16*2-1;var Q=s.M.ToArray();var K=s.P*l[4]>=P&s.c==l[k=0]%2;for(j=Y-3;j++<=Y;)for(i=X;i!=X+m*M.Length/4;i+=m)if((K&="==  *!!##*!*=*|*| o*o ".Contains(""+((i|j)>=0&j<H&i<W?Q[x=j*W+i]:' ')+M[k]))&M[k++]==33)Q[x]=' ';if(K)D.Add(new S{M=new string(Q),N=s.N+"\n"+B,x=X+l[2]%48*m,y=Y+l[3]-48,c=l[0]/50,E=s.E+l[1]-48,P=s.P*l[4]/100});}}}C.Write(R);}}

ลองใช้ออนไลน์

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

มันเริ่มต้นจากการอ่านในความน่าจะเป็นขั้นต่ำของความสำเร็จและแผนที่ จากนั้นจะหาที่ตั้งของ escapee ลบเขาออกจากแผนที่และสร้าง 'สถานะการค้นหา' ที่มีข้อมูลนี้ จากนั้นจะดำเนินการ BFS ซึ่งจะตรวจสอบสถานะที่กำหนดต่อไปอย่างซ้ำ ๆ ด้วยความพยายามอย่างน้อยที่สุด ก่อนที่จะขยายโหนดมันจะเปรียบเทียบความพยายามและความน่าจะเป็นที่จะประสบความสำเร็จกับโหนดก่อนหน้านี้ด้วยแผนที่และตำแหน่งหลบหลีกเดียวกันและปฏิเสธตัวเองหากพบเส้นทางที่ดีกว่าในสถานะนี้แล้ว หากมันยังมีชีวิตอยู่มันจะเพิ่มตัวเองลงในตาราง 'มองเห็น' เพื่อให้สามารถปฏิเสธสถานะในภายหลัง ทั้งหมดนี้มีไว้สำหรับประสิทธิภาพการทำงานและหากไม่มีปัจจัยการแตกแขนงก็จะมีขนาดใหญ่ จากนั้นจะตรวจสอบว่าผู้หลบหนีออกจากแผนที่หรือไม่ ถ้าเป็นเช่นนั้นก็ชนะ! มันติดตามสถานะ (แต่ละสถานะก่อนหน้าจะถูกบันทึกด้วยแต่ละสถานะ) และสร้างแผน (ย้อนกลับ) ก่อนออกจากลูป BFS มิฉะนั้นจะพยายามใช้ทุกการกระทำและเพิ่มสิ่งที่สามารถนำไปใช้กับdue คิวก่อนที่จะส่งต่อคิวนี้เพื่อให้เราได้รับความพยายามน้อยที่สุดระบุการทำซ้ำครั้งถัดไป

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

using C=System.Console;
using System.Linq;

// ascii
//   32
// ! 33
// = 61
// . 46
// * 42
// # 35
// | 124
// 0 48

class S // SearchState
{
    string M, // map
        N=""; // plan
    int x, // pos x
        y, // pos y
        E, // effort
        c; // crouching?
    decimal P=1; // chance (Probability)

    static void Main()
    {
        int W=0, // map width
            H=0, // map height
            x, // various temps
            i, // local x
            j, // local y
            k, // position in match/smash map
            X, // s.x
            Y, // s.y

            // action loop
            f, // T idx
            m, // A idx, action mirror (direction)

            P=int.Parse(C.ReadLine()); // probability of success constraint

        string l, // line, Act 'block' params, map hash, match pairs; all sorts!
            M="", // initial map
            B, // name of action
            R="There is no hope!"; // result string

        // read map
        for(;(l=C.ReadLine())!=null; // while there is input to read
            H++,M+=l) // increment height, and append to M
            W=l.Length; // record width

        // detect the escapee
        x=M.IndexOf("|");

        // create first state, and add it to Due list
        var D=new[]{new S{M=M,x=x%W,y=x/W}}.ToList();

        // 'seen' table, stores all the states we've been in which looked similar
        for(var N=D.ToDictionary(s=>R,s=>D); // these values are meaningless (and necessarily can't interfere), we just use it to save having to spec the type
            D.Count>0; // keep going until we run out of states to expand (-> no escape)
            D.Sort((z,w)=>z.E-w.E)) // enforce Breadth First Search
        {
            // get next State to expand, and remove it from Due
            S s=D[f=0];
            D.Remove(s);

            // retrieve or create seen list
            var n=N[l=s.x+s.M+s.y+s.c]= // store it, and cache it, l is 'hash', containing map and escapee state
                N.ContainsKey(l)? // already got a seen list for ths map?
                N[l]: // then use it!
                new S[0].ToList(); // otherwise create a new (empty) one

            // perf: only proceed if we havn't seen this map with better Effort and Chance yet
            if(n.All(o=>o.P<s.P|o.E>s.E))
            {
                // record that we have been seen
                n.Add(s);
                X=s.x;
                Y=s.y;

                if((X|Y|-X/W-Y/H)<0) // check if we our outside the bounds - this took 2.5hour to write. 1 byte.
                { // quit if both are positive or both are negative
                    // freedom
                    R="Required Effort: "+s.E+s.N;

                    // finished
                    break;
                }

                // [Crouch,Effort,dx,dy,Probability],Name,MatchSmash (first 10 are mirrors)
                // 0110d,Step,*** * #*,
                // 0110d,Climb off,=** * =*,
                // 3310d,Shuffle,***** #*,
                // 2:1/_,Clamber Up,*** *##*,
                // 0420_,Short Jump,****  *  #**,
                // 0730K,Long Jump,*****   *   #***,
                // 0<1/Z,High Jump,  * **#*,
                // 0D20P,Put your back into it!,****! *! #**,
                // 0800Z,Punch,***!**#*,
                // 0800U,Kick,*****!#*,
                // 0001d,Drop,*** ,
                // 1001d,Drop (Stand),*** ,
                // 2200d,Crouch,***#,
                // 1400d,Stand,* *#,
                // 020/d,Climb Up,=***,
                // 0800Z,Stamp,***!

                // attempt to expand this node with every action
                for(var A="0110d,Step,*** * #*,0110d,Climb off,=** * =*,3310d,Shuffle,***** #*,2:1/_,Clamber Up,*** *##*,0420_,Short Jump,****  *  #**,0730K,Long Jump,*****   *   #***,0<1/Z,High Jump,  * **#*,0D20P,Put your back into it!,****! *! #**,0800Z,Punch,***!**#*,0800U,Kick,*****!#*,0001d,Drop,*** ,1001d,Drop (Stand),*** ,2200d,Crouch,***#,1400d,Stand,* *#,020/d,Climb Up,=***,0800Z,Stamp,***!".Split(','); // Act string
                    f<26;) // read A into T // (cycle over first 10 twice, making them mirrors)  (very convieniently, 3*16==48=='0'==x!)
                {
                    // 'parse' next action
                    l=A[k=f*3%48]; // [Effort,Crouch,dx,dy,Probability]
                    B=A[++k]+(f>15?" Right":f>9?"":" Left"); // action name
                    M=A[++k]; // Match and Smash table (4x?, escapee at 0,2, #: solid, !: smashable (and is smashed), .: empty,  : don't care, =: climable)
                    //c=l[1]-48; // crouching transition (0: standing -> standing, 1: crouching -> standing, 2: standing -> crouching, 3: crouching -> crouching)
                    m=f++/16*2-1;

                    // this will be the new map
                    var Q=s.M.ToArray();

                    // K is whether we are allowed to apply this action
                    var K=s.P*l[4]>=P& // within chance limit
                        s.c==l[k=0]%2; // crouching matches

                    // compare the map to the Match/Smash map, to make sure we can apply this transform (and smash any ! we meet)
                    for(j=Y-3;j++<=Y;) // for the 4 rows
                        for(i=X;i!=X+m*M.Length/4;i+=m) // for each column (a.M has height 4, but variable width)
                            if((K&= // K still true?
                                "==  *!!##*!*=*|*| o*o ".Contains(""+ // check for an allowed pairing (cache pairing in M) (this includes the escapee, much cheaper to do this than remove him)
                                    ((i|j)>=0&j<H&i<W?Q[x=j*W+i]:' ') // we are within bounds and match, we are out of bounds (empty)
                                    +M[k])) // char from MatchSmash map
                                &M[k++]==33) // if it is destructible ('!' == 33)
                                Q[x]=' '; // then blank it out (x is necessarily set by the cell check)

                    if(K) // if K holds
                        D.Add(new S{M=new string(Q),N=s.N+"\n"+B, // assemble plan as we go (this will chew up memory, but none of the problems are big enough for it to matter)
                            x=X+l[2]%48*m,y=Y+l[3]-48,c=l[0]/50,E=s.E+l[1]-48,P=s.P*l[4]/100}); // add the resulting state to Due
                }
            }
        }

        C.Write(R);
    }
}

งานที่ดี! มันทำให้ฉันสนุกไม่รู้จบว่าคะแนนเก่าและคะแนนใหม่ของคุณเป็นแอนนาแกรมของกันและกัน ... lol
HyperNeutrino

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