Office Escape: Çıkış yolunuzu planlayın!


32

Bu son sprint ... ve takımın yarısı hasta değil. Geç saatlere kadar çalışıyorsun, gün için son taahhüdünü yapıyorsun, dört gözle bekliyorum ... neden ışıklar söndü? Güvenlik görevlisinin geldiğini hatırlamıyorum ... oh hayır! Anahtarlarımı evde bıraktım!

Durumun dehşeti battığında siz buna karar verin kaçmaya verdiniz .

Görev Özeti

Kaçışını etkilemek için bir plana ihtiyacın var! Ancak, herhangi bir planın başarısız olma şansı olduğunu biliyorsunuz ve farklı planlar farklı çaba gerektirir.

Aç, yorgun ve bir mühendis olarak, karmaşıklıktan kaçmanın en iyi yolunu belirlemeye, başarı olasılığını ve harcayacağı çabayı dengelemek için kısa bir program yazmaya karar veriyorsunuz.

Binanın haritasını çıkarırsınız:

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

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

Ofisten kaçmak için haritadan çıkman gerekecek. Burada 2 pencere ( !) olduğunu görüyorsunuz , biri sizi özgürlüğe götürür, ancak sadece bir tanesine erişilebilir 'Harita dışı' olarak ayaklarınızı haritanın sınırları dışına çıkacak şekilde tanımlarız.

Hücre tipleri

  - 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

Başlangıçta kaçan tarafından tüketilen hücreler boşalmıştır.

Eylem Özellikleri

Tek kullanımlık işleminizde birçok olası işlem var. Bunlar, bazı tamsayı başarı olasılığı olan basit durum geçişleri ile tanımlanır. Örneğin, yürümek için, kaçış yolunu, bu geçişle temsil ettiğimiz bir hücreyi taşırsınız:

Adım

1 stp,% 100, ayna

 o.            o
 |.   -->      |
 #            #

Noktalar, boş (veya tırmanılabilir, ancak katı veya tahrip edilemez) olması gereken hücreleri göstermektedir, çünkü biz onun içine veya içinden geçiyoruz. % 100, kendinize zarar vermeme ve cesurca kaçmaya son vermeniz için% 100 şansınız olduğunu gösterir. Tüm olasılıklar% 1 ile% 100 arasında tam sayı olarak verilecektir. İlk diyagram başlangıç ​​durumunu gösterir (sağlam bir şey üzerinde durmak, biraz boş yerin yanında durmak). İkinci diyagram terminal durumunu gösterir (boş alana taşındı). Soldaki (başlangıç ​​durumu) belirtilmemiş hücrelerin (boşlukların ) özel bir şey olması için bir gereklilik yoktur . Belirtilmemiş hücreler (boşluk,(sağdaki) (terminal durumu) öncekiyle aynı olmalıdır (örneğin, kaçan kişinin arkasında ne varsa, veya üzerine yürüdüğüm her neyse (boş alan olsun veya olmasın). ) diyagramlar hücreleri yalnızca tahrip edilebilecek boştan boşa değiştirecek, başka bir değişiklik olmayacak. "1 stp" 1 stp'ye mal olduğu anlamına gelir: "stp" yi bir adım atması için gereken enerji miktarı olarak tanımlarız.

"ayna", bu eylemin iki biçimi olduğu anlamına gelir. "Sağ" eylem gösterilir, "sol" eylem tam bir aynadır, örneğin:

.o
.|
 # 

ayna (Sol) şeklidir

o.
|.
# 

Sağ eylem "Sağ" (örneğin, "Sağ Adım") olarak adlandırılır. Sol işlem "Sol" (örneğin, "Sol Adım") olarak adlandırılır.

Bu şemalarda kaçış yeri şov tarafından gösterilmektedir.

o
|

ayakta dururken (2 birim yüksekliğinde) ve

%

çömelirken (1 birim yüksekliğinde). Katı veya tahrip olması gereken hücreler, bir karma ile gösterilir #. Katı veya tahrip edilmemesi gereken hücreler bir nokta ile gösterilir .. Yıkılması gereken hücreler patlama ile gösterilir !. Yeni oluşturulan bir boş alan alt çizgi ile gösterilir _. xhareket etmeyen bir referans noktasıdır (mevcut değil, hücrenin ne olması gerektiği konusunda bir kısıtlama yoktur ).

Not: Zemine çarptığınızda hızlı yavaşlama sorununu görmezden geliyoruz ve evet, bu oyunda merdivenlere epik atlama yapabilir)

Adım

1 stp,% 100, ayna

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

Kapalı tırmanın

1 stp,% 100, ayna

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

Karıştır

3 stp,% 100, ayna

 %.         %
x#   -->  x# 

Yukarı tırmanmak

10 stp,% 95, ayna

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

Düşürmek

0 stp,% 100

 o         
 |  -->   o
x.       x|

Düşür (Stand)

0 stp,% 100

 %        o
x.  -->  x|

Tırmanmak

2 stp,% 100

 =        o
 o  -->   |
x|       x

çömelmek

2 stp,% 100

 o
 |  -->   %
x#       x#

durmak

4 stp,% 100

 .        o
 %  -->   |
x#       x#

Kısa atlama

4 stp,% 95, ayna

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

Uzun atlama

7 stp,% 75, ayna

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

Yüksek atlayış

12 stp,% 90, ayna

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

Sırtına sok!

20 stp,% 80, ayna

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

Yumruk

8 stp,% 90, ayna

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

tekme

8 stp,% 85, ayna

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

Kaşe

8 stp,% 90

 o        o
 |  -->   |
x!       x_

Planlar

Bir plan yukarıda tanımlanan eylemlerin bir dizisidir. Örneğin:

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

Damlaların dahil edildiğine dikkat edin. Bırakmaktan başka bir şey yapmanıza engel olmak için kurallar belirlenmeli, ama yine de bunu planlamanız gerekiyor!

Herhangi bir planın, her bir adım için gösterilen çabaların toplamı olan gerekli bir çabası vardır. Her bir eylemin başarı olasılığının ürünü olan bir başarı olasılığı da vardır. Basit örnek:

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%

Sayfanın üstündeki harita için 'çalışılmış bir örnek' öz olarak bulunabilir .

Giriş

Giriş iki kısım halinde gelir, bir tam sayı ve bir karakter dizisi veya dizesi.

Tam sayı sizin asgari (yüzde) başarı olasılığınızdır. Yüzde olarak yorumlanmalıdır, bu nedenle 80, planınızın% 80'den az olmayan bir olasılıkla başarılı olması gerektiği anlamına gelir.

Geçerli bir harita, ayakta kalan kaçağı (minimum 1x2 boyutunda) ve belirtilmemiş sembol içermeyen bir dikdörtgendir. Tüm satırlar aynı uzunlukta olacaktır. Girdiyi 1 boyutlu sınırlandırılmış bir dize olarak kabul edebilirsiniz (sınırlayıcı, tek bir tutarlı karakter veya CRLF ve LFCR çiftinden biri olmalıdır), benzer bir 1 boyutlu dizi veya 2 boyutlu dizi olarak. Seçtiğiniz giriş formatı haritanın genişliğini veya yüksekliğini bir şekilde belirtmiyorsa, bunlar için ek argümanlar kabul edebilirsiniz (cevabınıza bunu açıkça belirtmeniz gerekir). Komut satırı argümanlarını ve standart girişi size uygunsa karıştırabilirsiniz (örn. Stdin'den harita, argv'den minimum başarı olasılığı). Aşağıdaki örnek geçerli ve geçersiz haritalar.

Geçerli:

o
|

Geçerli:

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

Geçersiz (kaçış yok):

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

Geçersiz (kaçış her zaman ayakta başlar):

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

Geçersiz (geçersiz sembol):

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

Geçersiz (dikdörtgen değil / farklı uzunluktaki satırlar):

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

Girişinizin geçerli olduğunu kabul edebilirsiniz (geçersiz giriş verildiğinde programınızın ne yaptığı umurumda değil).

Çıktı

Çıktı metindir (ASCII). Dize olarak döndürülebilir veya standart çıktıya yazdırılabilir. Plan bir LF, CRLF veya LFCR ile sınırlandırılmalıdır. Benzer şekilde, Gerekli Efordan sonra başka bir LF, CRLF veya LFCR olmalıdır. Sondaki satır sonu isteğe bağlıdır.

İhtiyacı olan çabayla birlikte optimal bir plan hazırlamalısın ya da "Umut yok!" eğer böyle bir plan yoksa. Başarı olasılığını ortaya koymanıza gerek yoktur. Bu metin sonunda bir satır kesmesi olabilir veya olmayabilir.

En uygun plan, en azından verilen başarı olasılığına sahip minimum çabayı gerektiren bir plan (yukarı bakın) olarak tanımlanır. Olasılık hesaplamanızın kesin olması gerektiğine dikkat edin, kayan noktanın yeterince iyi olduğunu varsaymayabilirsiniz (Bu yüzden onları çıkarmanızı beklemiyorum). Bunu adil bir şekilde test etmek için test durumları tasarlamaya çalışacağım (bunları geçerseniz ve herhangi bir kesin varsayımda bulunmazsanız gönderiminizin geçerli olduğunu düşünebilirsiniz).

Biçim:

Required Effort: <effort>
<plan>

Örneğin, giriş için

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

Uygun bir çıktı:

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

Buradaki başarı olasılığı% 76,5.

Aynı harita için asgari% 80 başarı olasılığı için, daha fazla çaba gerektiren ancak başarı olasılık kriterlerini yerine getiren "arkanıza koymanız" gerekir. Asgari başarı olasılığı% 80'den fazlaysa, biraz daha sert düşünmeniz gerekir (ya bir kapının delinmesi veya tekmelenmesi ve karıştırılması). Asgari başarı olasılığı% 100 olsaydı, "Umut yok!" Diye yazmanız gerekir.

Örnekler

Bir giriş için birden fazla geçerli plan olması mümkündür, çıktınızın tam olarak bunlar olması gerekmez, ancak gereken doğru çabayı göstermesi ve geçerli bir plan olması gerekir. Çözümlerinizi kontrol etmek için doğrulayıcıyı kullanabilirsiniz (aşağıya bakınız)

Giriş:

100
o
|

Çıktı:

Required Effort: 0
Drop

Giriş:

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

Çıktı:

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

Giriş:

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

Çıktı:

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

Aynı harita için, ancak% 80, çıktı şöyle olmalıdır:

There is no hope!

Aynı harita için, ancak% 50, Gerekli çaba farklı bir planla 56 olur)

Giriş:

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

Çıktı:

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

Giriş:

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

Çıktı:

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

Giriş:

Bu, birinin kurban edebileceği ve sonuçta biraz tuhaf görünebilecek yanlış varsayımları kontrol etmek için tasarlanmıştır.

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

Başarı şansı kısıtlamasıyla çıktı 30:

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

Başarı şansı kısıtlamasıyla çıktı 32:

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

Haritayı en üstte bir girdi olarak kullanarak,% 1'lik başarı kısıtlama olasılığıyla, Gerekli Bir Efor elde etmelisin (başarı şansı ~% 32, bu test programımda 20 saniye sürdü).

Zafer Kriterleri

Bu kod golf, en kısa kod kazanabilir.

Hak kazanmak için, işleviniz veya programınız çalışmalı ve yukarıdaki test senaryolarının her birini makul bir makinede 30 dakikadan kısa sürede çözebilmelidir. Çözücüm her birini 30 saniyenin altında yapıyor. Eğer test betiği (aşağıda) 30 dakikadan az sürerse, kesinlikle gitmeniz iyi olur.

Örnek Çözücü, Verifier, Test Komut Dosyası ve TestCases (çözümlerle)

Bir çözücü için C # kodu ve çözüm doğrulayıcı burada bir öz olarak mevcuttur . Oyunda ayrıca file.txtyukarıda açıklanan eylemlerin bir makine tarafından okunabilir (yeterince) bir şekli vardır ve programın çalışması için gereklidir. Bu dosya ve özellik arasındaki herhangi bir uyuşmazlık kasıtlı değildir.

Özet ayrıca, birkaç test durumu (yukarıdaki tüm örnekler dahil) ve bunlara karşı otomatik olarak bir gönderiyi çalıştırmak için bir PowerShell betiği içerir. Komut dosyası size belirli bir testin başarısız olduğunu söylerse, OfficeEscapeSolver.exe testcase<n>.txt outputFromYourProgram.txtdaha fazla ayrıntı görmek için koşabilirsiniz . Bu test durumları için örnek çözümler başka bir Gist'tedir .

Tüm kod tam bir karışıklıktır (unungolfed), ancak static void Main(...)çıktı miktarını değiştirmek için çok uzağa gitmenize gerek yok (bu bilgiyi kullanmaktan çekinmeyin, sizin yararınıza verdim!).

Bir test senaryosunu geçmek, senaryo ve doğrulayıcı çok cömert olduğu için çıktınızın iyi şekillendiği anlamına gelmez. Çıktınızın geçerli olması için çıktınızın yukarıdaki şartnameye uygun olması gerekir.

Çözücü veya test komut dosyasıyla ilgili bir hata bulduğunuzu düşünüyorsanız, bir hata file.txtveya tehlikeli bir test çantası , o zaman lütfen bu yazıya yorum yapın ya da SE Sohbetinde bana ping atın ; Muhtemelen iletişim kurmak için başka bir girişimde bulunmayacağım.

Test komut dosyasını Bash veya Batch'te sunmayacağım, çünkü onları tanımıyorum, ancak bir çeviriyi eklemekten mutluyum ve insanlar isterse bir C # sürümü yazacak.

Amble Yayınla

Sorunuz var mı? Gecikme, bugün onlara sor!

Bu görev, ciddi golfçülere dişlerini batırmak için bir şeyler vermek için çaba sarfetmeyi gerektirir .

Giriş / Çıkış hakkındaki geri bildirimleri için ais523'e teşekkür ederim.

Eğer insanlar daha fazlasını istiyorsa (bu yazının daha fazla olmasını istemiyorsanız) veya kendilerinin bir kısmını sağlamak istiyorsanız, gist dosyasında daha fazla test çantası sağlayabilirim.


2
Büyük zorluk! Zamanım varken kesinlikle buna bir şans vereceğim. :)
R. Kap

Biliyorsunuz, düşme tehlikeleri (veya altındaki hızlı yavaşlama) düşme geçişine% 95 gibi bir olasılık vererek modellenebilirdi. ;) Güzel meydan okuma!
Martin Ender

Bir gökyüzü ışığı veya tünellerden kaçabilir misin? yani alanın üst ve alt kısmı? ya da sadece sol veya sağ?
Moogie

@Moogie gerçekten yapabilirsiniz! Ayaklarınız serbest kaldığı sürece, özgürsünüz (örneğin, çözümün bir kez düştüğü 1x2 test çantasına bakınız). Tavandan çıkmayı denemek için küçük bir test çantası ekleyeceğim.
VisualMelon

3
Soruya lütuf eklendi. Bu, cevapları hak eden harika bir soru.
programcı5000

Yanıtlar:


3

Perl 5, 1425 1464 1481 1469 1485 1438 bayt

Bu eğlenceli bir mücadele oldu! Şok edici bir şekilde, şu ana kadar 1.5kB'nin altında biraz en kısa kodum var! :)

Eminim sonunda bu çalışmaya başladım. Kullanılan sınırlayıcı :, üstte iki sıra ve her iki tarafta bir sütunun ekstra dolgusu vardır . Yani girişiniz için:

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

programım alacaktı: (Not: sonunda bir kolon olmalı, ama başında değil!)

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

Bir haritadan diğerine çeviri yapmak ve kaba kuvvetle çözmek için regexes kullanıyorum. Ancak, o haritaya daha az çabayla ve daha büyük veya eşit olasılıkla ulaşılmışsa, listeye harita eklemem. O noktadan tüm olası hareketler tükendikten sonra haritalar listeden çıkarılır. Program, yana veya aşağıya ulaştığımı gösteren ve "Umut yok!" haritaların listesi tükendiğinde.

Ne yazık ki, birkaç byte çıkarmak için alınıp satılan çok fazla verimlilik vardı, bu nedenle golf versiyonu oldukça yavaş;

Daha fazla elveda olmadan,

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;}}}}

Akıl sağlığı için, işte yeni satırlar ve birkaç yorum ile aynı şey:

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)

Birkaç bayttan daha fazlasını alabilmek için bir kaç yer görebiliyorum, fakat yine de bütün testleri tekrarlamak istemiyorum. Sonra! :)

Düzenleme: Çıktınızı zeminden kaçarken tam olarak sığdırmak için altına bir miktar dolgu maddesi eklendi. Bazı sürümler kaldırıldı, böylece kod da şimdi daha hızlı çalışabilir!

Düzenleme: Merdivenleri kullanmıyordu ve oldukça doğru düşüyor. Hala merdivenleri tam olarak idare edemiyor ... Şimdi düzeltmeye çalışıyorum.


Başkasının bununla eğlenmesine sevindim! Korkarım ki, şu anda olduğu gibi bunu kabul edemem, çünkü girişin üstte fazladan satır ya da dolgu olduğunu varsayamazsınız (ama ~ 1.5kB'de, hemen yerleştirmek zarar vermemelidir). çok fazla!). Bu makinede Perl yok, ancak bugün bunu test etmenin bir yolunu bulmaya çalışacağım, böylece çalışıp çalışabildiğini ve makul bir zaman diliminde çalıştığını kontrol edebiliyorum ve tekrar rapor edebiliyorum!
VisualMelon

1
@VisualMelon Sorun değil, giriş yöntemini değiştirdim ve dolguyu elle ekledim. Büyük bulmacalarda havaya uçma eğilimindedir, ancak test durumlarınızın çoğu için makul bir zaman diliminde çalışır.
Chris,

Bunu hala test etmedim, ancak notun, aşağıdan veya aşağıya indiğinizde algılamak için bir regex kullandığını belirtti, ancak tepeden kaçabileceğinizi de unutmayın ( bu amaç için eklenmiş testcase10'a bakın ). bu
VisualMelon

1
@VisualMelon Ah, çatıdan kaçmak için kaçan kişinin odanın üstüne çıkıp sonra yan tarafa, çatıdan yürümek zorunda kalacağını varsaydım. Şimdi ilgili cümleyi görüyorum.
Chris

2
Bir TIO bağlantısı ekler misiniz?
programcı5000

3

C #, 1814 1481 1395 bayt

Ne bir slog !! Şimdi bundan çok memnunum!

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);}}

Çevrimiçi Deneyin

Tamamlanmış program, girişi STDIN'e, çıkışı STDOUT'a alır. Temelde orijinal çözücümü yeniden yazın, en uygun yolu bulmak için basit ve verimsiz bir şekilde uygulanmış BFS kullanarak. Oldukça hızlı, diğer uygulamamdan daha yavaş olamaz (gerçekte zamanlamamıştım), kesinlikle süre içinde çalışıyor. Maliyetin çoğu, adı, 'eşleştir / parçala' eşlemesini ve mevcut her bir işlemin diğer özelliklerini kaydeden virgül ayrı değerler olarak kodlanan Eylem tablosu.

Asgari başarı olasılığını ve haritayı okuyarak başlar. Daha sonra kaçış yerini bulur, onu haritadan kaldırır ve bu bilgiyi içeren bir 'arama durumu' oluşturur. Ardından, sürekli olarak en az çabayla bir sonraki durum durumuna bakan BFS'yi gerçekleştirir (en uygun çözümü bulmasını sağlar). Düğümü genişletmeden önce, aynı harita ve kaçış konumu olan önceki düğümlerle olan çaba ve başarı olasılığını karşılaştırır ve bu duruma daha iyi bir yol bulunmuşsa, kendisini reddeder. Bundan kurtulursa, kendisini 'görülen' masaya ekler böylece durumu daha sonra reddedebilir. Tüm bunlar performans için ve onsuz dallanma faktörü çok büyük olurdu. Sonra kaçan harita dışı olup olmadığını kontrol eder. Öyleyse kazanır! Durumu geri izler (her önceki durum, her durumla kaydedilir) ve BFS döngüsünden çıkmadan önce planı (tersten) oluşturur. Aksi takdirde, her işlemi uygulamaya çalışır ve uygulamaya uygulanabilecek her şeyi ekler.due sıra, bu sıraya geçmeden önce sıradaki yinelemede en az çaba harcanması için.

Biçimlendirilmiş ve yorumlanmış kod:

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);
    }
}

İyi iş! Eski puanınız ve yeni puanınızın birbirlerinin anagramları olduğu
beni şaşırtıyor

C # Perl'i dövdü mü?
Esolanging Fruit
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.