รหัสกอล์ฟ: เลเซอร์


152

ความท้าทาย

รหัสที่สั้นที่สุดโดยนับจำนวนตัวอักษรเพื่อป้อนเป็นตัวแทนของคณะกรรมการ 2D และเอาท์พุท 'ความจริง' หรือ 'ผิด' ตามการป้อนข้อมูล

กระดานทำจากกระเบื้อง 4 ประเภท:

 # - A solid wall
 x - The target the laser has to hit
 / or \ - Mirrors pointing to a direction (depends on laser direction)
 v, ^, > or < - The laser pointing to a direction (down, up, right and left respectively)

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

ยิงเลเซอร์เรย์และเคลื่อนที่จากจุดกำเนิดไปยังทิศทางที่ชี้ไป หากแสงเลเซอร์พุ่งทะลุกำแพงก็จะหยุด หากแสงเลเซอร์พุ่งเข้าหากระจกมันจะสะท้อน 90 องศาตามทิศทางที่กระจกชี้ไป กระจกมีสองด้านซึ่งหมายความว่าทั้งสองด้านนั้นเป็น 'ไตร่ตรอง' และอาจสะท้อนแสงได้สองวิธี หากรังสีเลเซอร์กระทบกับเลเซอร์ ( ^v><) ตัวมันเองจะถือว่าเป็นกำแพง (ลำแสงเลเซอร์ทำลายลำแสงและดังนั้นมันจะไม่ชนกับเป้าหมาย)

กรณีทดสอบ

การป้อนข้อมูล:
    ##########
    # / \ #
    # #
    # \ x #
    #> / #
    ########## 
เอาท์พุท:
    จริง

การป้อนข้อมูล:
    ##########
    # vx #
    # / #
    # / #
    # \ #
    ##########
เอาท์พุท:    
    เท็จ

การป้อนข้อมูล:
    #############
    # # #
    #> # #
    # # #
    # # x #
    # # #
    #############
เอาท์พุท:
    เท็จ

การป้อนข้อมูล:
    ##########
    # / \ / \ / \ #
    # \\ // \\\ #
    # // \ / \ / \\ #
    # \ / \ / \ / x ^ #
    ##########
เอาท์พุท:
    จริง

การนับรหัสประกอบด้วยอินพุต / เอาต์พุต (เช่นโปรแกรมเต็มรูปแบบ)


84
IMMA CHARGIN 'MAH LAZER!
Ólafur Waage

37
นี้เป็นที่น่ากลัว
GManNickG

33
อย่าข้ามลำแสง
GManNickG

49
@GameFreak: ที่ได้รับจริงๆเก่า
Artelius

24
อันที่จริงแล้ว '^' เป็นฉลามที่มี lazer ที่แปลกประหลาดอยู่บนหัวหรือไม่?
นาธาน Feger

คำตอบ:


78

Perl, 166 160 ตัวอักษร

Perl, 251 248 246 222 214 208 203 201 193 190 180 176 173 170 166 -> 160 ตัวอักษร

วิธีการแก้ปัญหามี 166 ครั้งเมื่อการประกวดนี้สิ้นสุดลง แต่ A. Rex ได้พบสองวิธีในการโกนอักขระอีก 6 ตัว:

s!.!$t{$s++}=$&!ge,$s=$r+=99for<>;%d='>.^1<2v3'=~/./g;($r)=grep$d|=$d{$t{$_}},%t;
{$_=$t{$r+=(1,-99,-1,99)[$d^=3*/\\/+m</>]};/[\/\\ ]/&&redo}die/x/?true:false,$/

โหลดบรรทัดแรกป้อนข้อมูลลงใน%tตารางของคณะกรรมการที่$t{99*i+j}ถือตัวละครที่แถวฉันคอลัมน์J จากนั้น

%d=split//,'>.^1<2v3' ; ($r)=grep{$d|=$d{$t{$_}}}%t

มันค้นหาองค์ประกอบของ%tอักขระที่ตรงกับ> ^ <หรือvและตั้ง$dค่าเป็น 0 และ 3 พร้อมกันซึ่งระบุทิศทางเริ่มต้นของลำแสงเลเซอร์

ที่จุดเริ่มต้นของการวนซ้ำแต่ละครั้งในการวนซ้ำหลักเราจะอัปเดต$dว่าลำแสงอยู่บนกระจกหรือไม่ XOR'ing by 3 ให้พฤติกรรมที่ถูกต้องสำหรับ\กระจกและ XOR'ing by 1 ให้พฤติกรรมที่ถูกต้องสำหรับ/กระจก

$d^=3*/\\/+m</>

จากนั้นตำแหน่งปัจจุบัน$rจะได้รับการอัพเดตตามทิศทางปัจจุบัน

$r+=(1,-99,-1,99)[$d] ; $_ = $t{$r}

เรากำหนดอักขระที่ตำแหน่งปัจจุบัน$_เพื่อให้สะดวกในการใช้ตัวดำเนินการจับคู่

/[\/\\ ]/ && redo

ดำเนินการต่อถ้าเราอยู่ในพื้นที่ว่างหรือตัวอักษรกระจก มิฉะนั้นเราจะยุติtrueหากเราอยู่ในเป้าหมาย ( $_ =~ /x/) และเป็นfalseอย่างอื่น

ข้อ จำกัด : อาจไม่ทำงานกับปัญหาที่มีมากกว่า 99 คอลัมน์ ข้อ จำกัด นี้สามารถนำออกได้โดยมีค่าใช้จ่ายเพิ่มอีก 3 ตัวอักษร


โอเคมีตัวอักษรได้ไม่เกิน 323 ตัว = D
strager

5
ฉันสามารถเปลี่ยน 99 เป็น 1E5 เพื่อให้แข็งแกร่งมากด้วยค่าใช้จ่าย 3 ตัวอักษร
ม็อบ

2
ทางออกที่ดีที่สุดของคุณจะเห็นได้ชัดเจนกว่าที่ด้านบนของโพสต์
แปลกหน้า

13
แต่ใช้การแสดงผลปกติเพื่อหมุนกระดาน? นั่นป่วย นั่นเป็นเหมือนโบนัสอัตโนมัติ 20 สโตรก
ม็อบ

1
@mobrule: บันทึกหกครั้ง: เรียงลำดับบรรทัดแรกs!.!$t{$s++}=$&!ge,$s=$r+=99for<>;ใหม่เปลี่ยน%d=split//,.." to % d = .. = ~ /./ g , and change grep {.. }% t` เป็นgrep..,%t
A. Rex

75

Perl, 177 ตัวอักษร

สามารถลบเส้นแรกออกได้ อีกสองคนเป็นข้อบังคับ

$/=%d=split//,' >/^\v';$_=<>;$s='#';{
y/v<^/>v</?do{my$o;$o.=" 
"while s/.$/$o.=$&,""/meg;y'/\\'\/'for$o,$s;$_=$o}:/>x/?die"true
":/>#/?die"false
":s/>(.)/$s$d{$1}/?$s=$1:1;redo}

คำอธิบาย:

$/ = %d = (' ' => '>', '/' => '^', '\\' => 'v');

หากลำแสงเคลื่อนที่ขวาวิ่งเข้ามาใน {พื้นที่ว่าง, กระจกมุมฉาก, กระจกมองมุม} มันจะกลายเป็น {ลำแสงเคลื่อนที่ขวา, คานเลื่อนสูง, ลำแสงเคลื่อนที่ต่ำ} เริ่มต้น$/ตามทาง - โชคดีที่ "6" ไม่ใช่อักขระอินพุตที่ถูกต้อง

$_ = <>;

$_อ่านบอร์ดเป็น

$s="#";

$sเป็นสัญลักษณ์ของสิ่งที่คานนั่งอยู่ด้านบนของตอนนี้ เนื่องจากตัวส่งเลเซอร์เป็นเสมือนกำแพงให้ตั้งเป็นกำแพงที่จะเริ่มต้น

if (tr/v<^/>v</) {
  my $o;
  $o .= "\n" while s/.$/$o .= $&, ""/meg;
  tr,/\\,\\/, for $o, $s;
  $_ = $o;
}

หากลำแสงเลเซอร์ชี้ไปทางใดทางหนึ่งยกเว้นด้านขวาให้หมุนสัญลักษณ์แล้วหมุนบอร์ดทั้งบอร์ดให้เข้าที่ (หมุนสัญลักษณ์สำหรับกระจกด้วย) มันเป็นการหมุนซ้ายไป 90 องศาซึ่งทำได้อย่างมีประสิทธิภาพโดยการกลับแถวในขณะที่ทำการสลับแถวและคอลัมน์ในลักษณะที่โหดเหี้ยมเล็กน้อยs///eกับผลข้างเคียง ในรหัส golfed tr ถูกเขียนในรูปแบบy'''ซึ่งทำให้ฉันสามารถข้ามแบ็กสแลชหนึ่งแบ็กสแลชได้

die "true\n" if />x/; die "false\n" if />#/;

ยุติด้วยข้อความที่ถูกต้องหากเราโจมตีเป้าหมายหรือกำแพง

$s = $1 if s/>(.)/$s$d{$1}/;

หากมีพื้นที่ว่างด้านหน้าเลเซอร์ให้เลื่อนไปข้างหน้า หากมีกระจกหน้าเลเซอร์ให้เลื่อนไปข้างหน้าและหมุนลำแสง ในกรณีใดกรณีหนึ่งให้ใส่ "สัญลักษณ์ที่บันทึกไว้" กลับเข้าไปในตำแหน่งลำแสงเก่าและใส่สิ่งที่เราเพิ่งเขียนทับลงในสัญลักษณ์ที่บันทึกไว้

redo;

ทำซ้ำจนกว่าจะสิ้นสุด {...;redo}เป็นตัวละครทั้งสองน้อยกว่าและสามน้อยกว่าfor(;;){...}while(1){...}


4
หมุนกระดาน ... Regexp ... Crazier O_o
แปลกหน้า

39
คุณ ... คุณปีศาจ!
LiraNuna

4
LiraNuna: ฉันเลือกที่จะเป็นคำชม
hobbs

21
กอล์ฟจบแล้ว คุณจะเอาชนะการหมุนกระดาน 2D ด้วยนิพจน์ปกติได้อย่างไร!
Konrad Rudolph

13
WTF? โปรแกรมเมอร์ perl เป็นพ่อมด
Johannes Schaub - litb

39

C89 (209 ตัวอักษร)

#define M(a,b)*p==*#a?m=b,*p=1,q=p:
*q,G[999],*p=G;w;main(m){for(;(*++p=getchar())>0;)M(<,-1)M
(>,1)M(^,-w)M(v,w)!w&*p<11?w=p-G:0;for(;q+=m,m=*q&4?(*q&1?
-1:1)*(m/w?m/w:m*w):*q&9?!puts(*q&1?"false":"true"):m;);}

คำอธิบาย

สิ่งที่น่าประหลาดใจนี้อาจเป็นเรื่องยากที่จะติดตามหากคุณไม่เข้าใจ C. เพียงแค่คำเตือนล่วงหน้า

#define M(a,b)*p==*#a?m=b,*p=1,q=p:

แมโครเล็ก ๆ นี้ตรวจสอบว่าอักขระปัจจุบัน ( *p) เท่ากับสิ่งที่aอยู่ในรูปแบบอักขระ ( *#a) หากมีค่าเท่ากันให้ตั้งค่าเวกเตอร์การเคลื่อนไหวเป็นb( m=b) ทำเครื่องหมายตัวละครนี้เป็นวอลล์ ( *p=1) และตั้งค่าจุดเริ่มต้นเป็นตำแหน่งปัจจุบัน ( q=p) มาโครนี้รวมถึงส่วน "else"

*q,G[999],*p=G;
w;

ประกาศตัวแปรบางอย่าง * qคือตำแหน่งปัจจุบันของแสง * Gเป็นกระดานเกมที่มีอาร์เรย์ 1D * pเป็นตำแหน่งการอ่านปัจจุบันเมื่อเติมGข้อมูล * wคือความกว้างของบอร์ด

main(m){

mainชัดเจน mเป็นตัวแปรที่เก็บเวกเตอร์การเคลื่อนไหว (เป็นพารามิเตอร์mainที่ใช้เป็นการเพิ่มประสิทธิภาพ)

    for(;(*++p=getchar())>0;)

วนซ้ำตัวอักขระทั้งหมดGโดยใช้ pข้ามไปG[0]เป็นการปรับให้เหมาะสม (ไม่จำเป็นต้องเขียนตัวอักษรpซ้ำอีกในส่วนที่สามของfor)

        M(<,-1)
        M(>,1)
        M(^,-w)
        M(v,w)

ใช้แมโครดังกล่าวข้างต้นเพื่อกำหนด lazer ถ้าเป็นไปได้ -1และ1สอดคล้องกับซ้ายและขวาตามลำดับ-wและwขึ้นและลง

        !w&*p<11
            ?w=p-G
            :0;

หากอักขระปัจจุบันเป็นเครื่องหมายสิ้นสุดของบรรทัด (ASCII 10) ให้ตั้งค่าความกว้างหากยังไม่ได้ตั้งค่า ข้ามG[0]ช่วยให้เราสามารถเขียนแทนw=p-G w=p-G+1นอกจากนี้ยังเสร็จสิ้นการปิด?:ห่วงโซ่จากMของ

    for(;
        q+=m,

ย้ายแสงโดยเวกเตอร์การเคลื่อนไหว

        m=
        *q&4
            ?(*q&1?-1:1)*(
                m/w?m/w:m*w
            )

สะท้อนเวกเตอร์การเคลื่อนไหว

            :*q&9
                ?!puts(*q&1?"false":"true")
                :m
        ;

หากนี่เป็นวอลล์หรือxออกจากข้อความที่เหมาะสม ( m=0ยุติการวนซ้ำ) มิฉะนั้นอย่าทำอะไรเลย (noop; m=m)

    );
}

8
ฮึ ฉันกำลังทำงานกับโซลูชัน C เมื่อสัญญาณเตือนไฟไหม้ดังขึ้นในห้องชุดของฉัน ตอนนี้ฉันได้รับรางวัล ทางออกที่ดีว่า
rlbond

การคิดเลขโดยใช้ตัวแปร temp สำหรับขั้นตอนการสลับและสลับ / การปฏิเสธของคุณจะช่วยให้คุณประหยัดอักขระได้ไม่กี่ตัว
Artelius

@Artelius ใช่ฉันตระหนักว่าและสิ่งอื่น ๆ ขอบคุณ
แปลกหน้า

1
ทีซีซีจริงไม่ชอบการประกาศ untyped และข้อผิดพลาดออกมาพร้อมกับg.c:3: declaration expected:(
มาร์ค Rushakoff

2
putsแม้ว่าการประกาศของการถอดช่วย แต่ก็ไม่เพียงพอที่จะนำมาใช้ในระดับต่ำกว่า 170. 209 นั้นค่อนข้างดีดังนั้นฉันคิดว่าฉันจะทิ้งไว้ที่นั่น ขอบคุณสำหรับความช่วยเหลือของคุณ ฉันซาบซึ้งจริงๆ =] (สิ่งใดที่จะกำจัดแม่มด Perl เหล่านั้นได้!)
แปลกหน้า

36

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

ดูเถิด ... ฉันมาเสนอวิธีแก้ปัญหาที่นี่

Befunge-93!

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

Caveat : ฉันเขียนล่าม Befunge-93 ของฉันเองใน Perl เมื่อไม่นานมานี้และน่าเสียดายที่นี่คือทั้งหมดที่ฉันมีเวลาที่จะทำการทดสอบ ฉันค่อนข้างมั่นใจในความถูกต้องโดยทั่วไป แต่อาจมีข้อ จำกัด แปลก ๆ เกี่ยวกับ EOF: เนื่องจาก<>ตัวดำเนินการของ Perl ส่งคืน undef เมื่อสิ้นสุดไฟล์การประมวลผลนี้จะเป็น 0 ในบริบทตัวเลข สำหรับการใช้งานแบบ C ซึ่ง EOF มีค่าต่างกัน (-1 พูด) รหัสนี้อาจใช้ไม่ได้

003pv   >~v>  #v_"a"43g-!#v_23g03p33v>v
>39#<*v   ::   >:52*-!v   >"rorrE",vg2*
######1   >^vp31+1g31$_03g13gp vv,,<15,
    a#3     >0v       vp30+1g30<>,,#3^@
######p $     0vg34"a"<   >       >vp
^<v>  > ^   p3<>-#v_:05g-!|>:15g-!| $
 >     v^     <   <   <   >^v-g52:< $ 
  v _  >52*"eslaf",,vv|-g53:_      v   
  : ^-"#">#:< #@,,,,<<>:43p0 v0 p34< 
  >">"-!vgv<  ^0p33g31p32-1g3<       
 ^     <#g1|-g34_v#-g34_v#-g34"><v^"<<<<
    v!<^<33>13g1v>03g1-v>03g1+03p$v  $$
>^  _#-v 1>g1-1v>+13pv >03p       v  pp
^_:"^"^#|^g30 <3#   $<           $<>^33
 ^!-"<":<>"v"v^># p#$<>            $^44
^      >#^#_ :" "-#v_ ^   >         ^gg
v  g34$<   ^!<v"/":< >$3p$^>05g43p$ ^55
 >,@   |!-"\"  :_$43g:">"-!|>      ^$32
 *v"x":<      >-^    ^4g52<>:"^" -#v_^
 5>-!#v_"ror"vv$p34g51:<>#|  !-"<":<#|
 ^2,,, ,,"er"<>v      #^^#<>05g43p$$^>^
      >52*"eurt",,,,,@>15g4 3p$$$$  ^#
>:"v"\:"<"\: "^"   -!#^_-!#^_-!      ^
               >                       ^

คำอธิบาย

หากคุณไม่คุ้นเคยกับไวยากรณ์ Befunge และการดำเนินงานตรวจสอบที่นี่

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

อีกที่หนึ่งอยู่ใกล้กับมุมบนซ้าย:

######
    a#
######

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

โปรแกรมเริ่มต้นด้วยการวาง (0,27) เป็นตำแหน่งเคอร์เซอร์เริ่มต้น จากนั้นอินพุตจะอ่านทีละหนึ่งอักขระและวางในตำแหน่งเคอร์เซอร์ การขึ้นบรรทัดใหม่ทำให้พิกัด y เพิ่มมากขึ้นและพิกัด x กลับไปที่ 0 เหมือนกับการรับคืนรถจริง ในที่สุดล่ามจะถูกอ่านโดยล่ามและมีการใช้ค่าอักขระ 0 เพื่อส่งสัญญาณจุดสิ้นสุดของอินพุตและไปยังขั้นตอนการทำซ้ำเลเซอร์ เมื่ออ่านอักขระเลเซอร์ [<> ^ v] จะถูกคัดลอกไปยังที่เก็บหน่วยความจำ (เหนืออักขระ 'a') และพิกัดจะถูกคัดลอกไปยังคอลัมน์ทางด้านซ้าย

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

หลังจากนั้นตำแหน่งลำแสงจะถูกคัดลอกกลับไปยังตำแหน่งเคอร์เซอร์และดำเนินการทำซ้ำต่อไปนี้:

  • ตรวจสอบทิศทางของลำแสงปัจจุบันและเพิ่มหรือลดพิกัดเคอร์เซอร์อย่างเหมาะสม (ฉันทำสิ่งนี้ก่อนเพื่อหลีกเลี่ยงการจัดการกับมุมของลำแสงเลเซอร์ในการเคลื่อนที่ครั้งแรก)
  • อ่านตัวละครที่ตำแหน่งนั้น
  • หากตัวละครเป็น "#" ให้ขึ้นบรรทัดใหม่และ "false" บนสแต็กพิมพ์และสิ้นสุด
  • เปรียบเทียบกับอักขระคานทั้งหมด [<> ^ v]; หากมีการแข่งขันให้พิมพ์ "false \ n" และสิ้นสุด
  • หากอักขระนั้นเป็นช่องว่างให้ล้างสแต็กและดำเนินการต่อ
  • หากตัวละครเป็นเครื่องหมายทับหน้าให้หาทิศทางของลำแสงไปยังสแต็กและเปรียบเทียบกับอักขระทิศทางแต่ละอัน เมื่อพบหนึ่งทิศทางใหม่จะถูกเก็บไว้ที่จุดเดียวกันในรหัสและวนซ้ำ
  • หากตัวละครเป็นแบ็กสแลชให้ทำสิ่งเดียวกันกับข้างต้น (ยกเว้นการแม็พที่เหมาะสมสำหรับแบ็กสแลช)
  • หากตัวละครคือ 'x' เราจะไปถึงเป้าหมาย พิมพ์ "true \ n" และออก
  • หากตัวละครไม่ใช่สิ่งเหล่านี้ให้พิมพ์ "error \ n" และออก

หากมีความต้องการเพียงพอฉันจะพยายามชี้ให้เห็นว่าในรหัสทั้งหมดนี้สำเร็จได้อย่างไร


14
+1 - เพียงเพราะมันอาจตีความผิดว่า EXE ถูกเปิดใน notepad
Kyle Rosendo

1
อืม ... ศักดิ์สิทธิ์ **** ฉันยุ่งกับ Befunge และนี่มันช่างน่าประทับใจจริงๆ
Almo

รหัสกอล์ฟในภาษาที่สับสน ... เช่นเนยถั่วและพริกป่น!
wberry

29

F #, 36 บรรทัดสามารถอ่านได้มาก

ตกลงเพื่อรับคำตอบจากที่นั่น:

let ReadInput() =
    let mutable line = System.Console.ReadLine()
    let X = line.Length 
    let mutable lines = []
    while line <> null do
        lines <- Seq.to_list line :: lines
        line <- System.Console.ReadLine()
    lines <- List.rev lines
    X, lines.Length, lines

let X,Y,a = ReadInput()
let mutable p = 0,0,'v'
for y in 0..Y-1 do
    for x in 0..X-1 do 
        printf "%c" a.[y].[x]
        match a.[y].[x] with 
        |'v'|'^'|'<'|'>' -> p <- x,y,a.[y].[x]
        |_ -> ()
    printfn ""

let NEXT = dict [ '>', (1,0,'^','v')
                  'v', (0,1,'<','>')
                  '<', (-1,0,'v','^')
                  '^', (0,-1,'>','<') ]
let next(x,y,d) =
    let dx, dy, s, b = NEXT.[d]
    x+dx,y+dy,(match a.[y+dy].[x+dx] with
               | '/' -> s
               | '\\'-> b
               | '#'|'v'|'^'|'>'|'<' -> printfn "false"; exit 0
               | 'x' -> printfn "true"; exit 0
               | ' ' -> d)

while true do
    p <- next p    

ตัวอย่าง:

##########
#   / \  #
#        #
#   \   x#
# >   /  #
##########
true

##########
#   v x  #
# /      #
#       /#
#   \    #
##########
false

#############
#     #     #
# >   #     #
#     #     #
#     #   x #
#     #     #
#############
false

##########
#/\/\/\  #
#\\//\\\ #
#//\/\/\\#
#\/\/\/x^#
##########
true

##########
#   / \  #
#        #
#/    \ x#
#\>   /  #
##########
false

##########
#  /    \#
# / \    #
#/    \ x#
#\^/\ /  #
##########
false

54
ฉันสามารถอ่านหนึ่งนี้จริง ๆ ! ปาฏิหาริย์!
เจฟฟ์แอด

17
Java / C # code golf ถูกนับด้วยบรรทัดที่ไม่ใช่อักขระ นั่นคือแต้มต่อ
นาธาน Feger

3
@ strager มันไม่ได้น่าหดหู่ใน 3 ปีเมื่อคุณได้รับการว่าจ้างในการรักษารหัสและนักพัฒนาดั้งเดิมได้ทิ้งไว้นาน
นาธาน Feger

สิ่งนี้ล้มเหลวในการใช้ F # ใน Visual Studio 2010 Seq.to_list ไม่มีอยู่ (ตกลงเปลี่ยนเป็น toList) แล้วบรรทัดที่ 25 การจับคู่รูปแบบที่ไม่สมบูรณ์
Russell

2
ใช่เปลี่ยน to_list เป็น toList ทันที คำเตือนการจับคู่ที่ไม่สมบูรณ์นั้นใช้ได้ มันเป็นรหัสกอล์ฟดังนั้นฉันไม่ได้ทำโค้ดเช่น: | _ -> failwith "เป็นไปไม่ได้"
Brian

29

Golfscript - 83 chars (ตอบโต้กับผู้ใช้ได้ของฉันและคนแปลกหน้า)

บรรทัดใหม่เป็นเพียงที่นี่เพื่อห่อ

:|'v^><'.{|?}%{)}?:$@=?{.[10|?).~)1-1]=$+
:$|=' \/x'?\[.\2^.1^'true''false']=.4/!}do

Golfscript - 107 ตัวอักษร

ขึ้นบรรทัดใหม่เพื่อความชัดเจน

10\:@?):&4:$;{0'>^<v'$(:$=@?:*>}do;
{[1 0&--1&]$=*+:*;[{$}{3$^}{1$^}{"true "}{"false"}]@*=' \/x'?=~5\:$>}do$

มันทำงานอย่างไร.

บรรทัดแรกจะใช้ตำแหน่งและทิศทางเริ่มต้น
บรรทัดที่สองก้าวผ่านการเลี้ยวทุกครั้งที่แสงเลเซอร์กระทบกับกระจก


18

353 ตัวอักษรใน Ruby:

ตอนนี้314 277 ตัวอักษร!

ตกลง 256 ตัวอักษรใน Ruby และตอนนี้ฉันทำเสร็จแล้ว หมายเลขรอบที่ดีที่จะหยุดที่ :)

247 ตัวอักษร ฉันหยุดไม่ได้

223 203 201 ตัวอักษรใน Ruby

d=x=y=-1;b=readlines.each{|l|d<0&&(d="^>v<".index l[x]if x=l.index(/[>^v<]/)
y+=1)};loop{c=b[y+=[-1,0,1,0][d]][x+=[0,1,0,-1][d]]
c==47?d=[1,0,3,2][d]:c==92?d=3-d:c==35?(p !1;exit):c<?x?0:(p !!1;exit)}

ด้วยช่องว่าง:

d = x = y = -1
b = readlines.each { |l|
  d < 0 && (d = "^>v<".index l[x] if x = l.index(/[>^v<]/); y += 1)
}

loop {
  c = b[y += [-1, 0, 1, 0][d]][x += [0, 1, 0, -1][d]]

  c == 47 ? d = [1, 0, 3, 2][d] :
  c == 92 ? d = 3 - d :
  c == 35 ? (p !1; exit) :
  c < ?x ? 0 : (p !!1; exit)
}

refactored เล็กน้อย:

board = readlines

direction = x = y = -1
board.each do |line|
  if direction < 0
    x = line.index(/[>^v<]/)
    if x
      direction = "^>v<".index line[x]
    end
    y += 1
  end
end

loop do
  x += [0, 1, 0, -1][direction]
  y += [-1, 0, 1, 0][direction]

  ch = board[y][x].chr
  case ch
  when "/"
    direction = [1, 0, 3, 2][direction]
  when "\\"
    direction = 3 - direction
  when "x"
    puts "true"
    exit
  when "#"
    puts "false"
    exit
  end
end

แต่ ... คุณสามารถเปลี่ยนชื่อchเป็นCหรือตัวอักษรชาร์ต 1 ตัวเพื่อบันทึก 2 ตัวอักษร!
LiraNuna

ตกลงตกลงดี ... ฉันรู้จริง ๆ แล้วว่าตัวแปรทั้งหมดไม่จำเป็นเพราะฉันใช้ครั้งเดียวเท่านั้น สิ่งนี้และการปรับปรุงอื่น ๆ สองสามอย่างทำให้มันลดลงเหลือ 247 ตัวอักษร
Jeremy Ruten

1
ไม่i++(แทนi+=1)?
LiraNuna

6
Nope คุณสามารถทำ ++ ฉันได้ แต่มันทำให้มันเป็นเชิงบวกอย่างที่มันเคยเป็น
DigitalRoss

ฉันชอบรุ่นที่บีบอัด: #; p
SeanJA

17

หลาม

294 277 253 240 232 ตัวอักษรรวมถึงบรรทัดใหม่:

(อักขระตัวแรกในบรรทัด 4 และ 5 คือแท็บไม่ใช่ช่องว่าง)

l='>v<^';x={'/':'^<v>','\\':'v>^<',' ':l};b=[1];r=p=0
while b[-1]:
 b+=[raw_input()];r+=1
 for g in l:
    c=b[r].find(g)
    if-1<c:p=c+1j*r;d=g
while' '<d:z=l.find(d);p+=1j**z;c=b[int(p.imag)][int(p.real)];d=x.get(c,' '*4)[z]
print'#'<c

ฉันลืม Python แม้จะมีเครื่องหมายอัฒภาคก็ได้

มันทำงานอย่างไร

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

l='>v<^';รายการของสัญลักษณ์เลเซอร์ คำสั่งนั้นถูกเลือกเพื่อให้ดัชนีของอักขระทิศทางเลเซอร์สอดคล้องกับกำลังของ sqrt (-1)

x={'/':'^<v>','\\':'v>^<',' ':l};ตารางการแปลงกำหนดทิศทางการเปลี่ยนแปลงเมื่อลำแสงออกจากกระเบื้องที่แตกต่างกัน ไทล์เป็นกุญแจสำคัญและทิศทางใหม่คือค่า

b=[1];ถือคณะกรรมการ องค์ประกอบแรกคือ 1 (ประเมินว่าเป็นจริง) เพื่อให้ห่วงขณะที่จะทำงานอย่างน้อยหนึ่งครั้ง

r=p=0 rคือหมายเลขแถวปัจจุบันของอินพุตpคือตำแหน่งปัจจุบันของลำแสงเลเซอร์

while b[-1]: หยุดการโหลดข้อมูลบอร์ดเมื่อ raw_input ส่งคืนสตริงว่าง

b+=[raw_input()];r+=1 เพิ่มบรรทัดถัดไปของอินพุตเข้ากับบอร์ดและเพิ่มตัวนับแถว

for g in l: คาดเดาทิศทางของเลเซอร์แต่ละอัน

c=b[r].find(g) ตั้งค่าคอลัมน์เป็นตำแหน่งของเลเซอร์หรือ -1 หากไม่อยู่ในบรรทัด (หรือชี้ไปในทิศทางที่ต่างออกไป)

if-1<c:p=c+1j*r;d=gหากเราพบเลเซอร์ให้กำหนดตำแหน่งpและทิศทางdปัจจุบัน dเป็นหนึ่งในตัวอักษรในl

หลังจากโหลดบอร์ดเข้าสู่bตำแหน่งpและทิศทางปัจจุบันdได้ถูกตั้งค่าให้กับแหล่งเลเซอร์

while' '<d: ช่องว่างมีค่า ASCII ต่ำกว่าสัญลักษณ์ทิศทางใด ๆ ดังนั้นเราจึงใช้มันเป็นธงหยุด

z=l.find(d);ดัชนีของอักขระทิศทางปัจจุบันในlสตริง zถูกนำมาใช้ในภายหลังเพื่อกำหนดทิศทางของลำแสงใหม่โดยใช้xตารางและเพื่อเพิ่มตำแหน่ง

p+=1j**z;เพิ่มตำแหน่งโดยใช้พลังของ i ตัวอย่างเช่นl.find('<')==2-> i ^ 2 = -1 ซึ่งจะย้ายไปทางซ้ายหนึ่งคอลัมน์

c=b[int(p.imag)][int(p.real)]; อ่านถ่านที่ตำแหน่งปัจจุบัน

d=x.get(c,' '*4)[z]ค้นหาทิศทางใหม่ของลำแสงในตารางการแปลง หากอักขระปัจจุบันไม่มีอยู่ในตารางให้ตั้งdเป็นช่องว่าง

print'#'<c พิมพ์ false ถ้าเราหยุดสิ่งอื่นที่ไม่ใช่เป้าหมาย


9
p+=1j**z: นั่นหวานจัง
dmckee --- ผู้ดูแลอดีตลูกแมว

16

นี้มีที่ เป็นพอร์ตโดยตรงของการแก้ปัญหาของไบรอันกับ C # 3 ลบปฏิสัมพันธ์คอนโซล นี่ไม่ใช่รายการในการท้าทายเนื่องจากไม่ใช่โปรแกรมที่สมบูรณ์ฉันแค่สงสัยว่าบางส่วนของโครงสร้าง F # ที่เขาใช้สามารถแสดงใน C # ได้อย่างไร

bool Run(string input) {
    var a = input.Split(new[] {Environment.NewLine}, StringSplitOptions.None);
    var p = a.SelectMany((line, y) => line.Select((d, x) => new {x, y, d}))
             .First(x => new[] {'v', '^', '<', '>'}.Contains(x.d));
    var NEXT = new[] {
            new {d = '>', dx = 1, dy = 0, s = '^', b = 'v'},
            new {d = 'v', dx = 0, dy = 1, s = '<', b = '>'},
            new {d = '<', dx = -1, dy = 0, s = 'v', b = '^'},
            new {d = '^', dx = 0, dy = -1, s = '>', b = '<'}
        }.ToDictionary(x => x.d);
    while (true) {
        var n = NEXT[p.d];
        int x = p.x + n.dx,
            y = p.y + n.dy;
        var d = a[y][x];
        switch (d) {
            case '/':  d = n.s; break;
            case '\\': d = n.b; break;
            case ' ':  d = p.d; break;
            default: return d == 'x';
        }
        p = new {x, y, d};
    }
}

แก้ไข:หลังจากการทดลองบางอย่างรหัสการค้นหาค่อนข้างละเอียดดังต่อไปนี้:

int X = a[0].Length, Y = a.Length;
var p = new {x = 0, y = 0, d = 'v'};
for (var y = 0; y < Y; y++) {
    for (var x = 0; x < X; x++) {
        var d = a[y][x];
        switch (d) {
            case 'v': case '^': case '<': case '>':
                p = new {x, y, d}; break;
        }
    }
}

ได้ถูกแทนที่ด้วย LINQ ไปยังรหัสวัตถุที่กะทัดรัดกว่า:

var p = a.SelectMany((line, y) => line.Select((d, x) => new {x, y, d}))
         .First(x => new[] {'v', '^', '<', '>'}.Contains(x.d));

8
พระเจ้าช่วย. เป็นตัวอย่างที่ดีที่แสดงให้เห็นว่า linq และ c # อันยิ่งใหญ่กลายเป็นอย่างไร 1+ สำหรับฉันเป็นแฟนตัวยง x)
Emiswelt

16

F #, 255 chars (และยังค่อนข้างสามารถอ่านได้!):

ตกลงหลังจากพักผ่อนฉันได้ปรับปรุงสิ่งนี้มาก:

let a=System.Console.In.ReadToEnd()
let w,c=a.IndexOf"\n"+1,a.IndexOfAny[|'^';'<';'>';'v'|]
let rec n(c,d)=
 let e,s=[|-w,2;-1,3;1,0;w,1|].[d]
 n(c+e,match a.[c+e]with|'/'->s|'\\'->3-s|' '->d|c->printfn"%A"(c='x');exit 0)
n(c,"^<>v".IndexOf a.[c])

มาคุยกันทีละบรรทัด

ขั้นแรกให้ป้อนข้อมูลทั้งหมดในอาร์เรย์ขนาดใหญ่หนึ่งมิติ (อาร์เรย์ 2D อาจไม่ดีสำหรับโค้ดกอล์ฟเพียงใช้อาร์เรย์ 1D และเพิ่ม / ลบความกว้างของหนึ่งบรรทัดไปยังดัชนีเพื่อเลื่อนขึ้น / ลงบรรทัด)

ต่อไปเราคำนวณ 'w' ความกว้างของสายอินพุตและ 'c' ตำแหน่งเริ่มต้นโดยการทำดัชนีในอาร์เรย์ของเรา

ทีนี้เรามานิยามฟังก์ชัน 'ถัดไป' 'ซึ่งใช้ตำแหน่งปัจจุบัน' c 'และทิศทาง' d 'ซึ่งคือ 0,1,2,3 สำหรับการขึ้น, ซ้าย, ขวา, ลง

index-epsilon 'e' และ what-new-direction-if-we-hit-a-slash 's' คำนวณโดยตาราง ตัวอย่างเช่นหากทิศทางปัจจุบัน 'd' เป็น 0 (ขึ้นไป) องค์ประกอบแรกของตารางจะบอกว่า "-w, 2" ซึ่งหมายความว่าเราจะลดดัชนีโดย w และถ้าเรากดทับทิศทางใหม่คือ 2 (ขวา).

ทีนี้เราจะได้ฟังก์ชั่นถัดไป 'n' ด้วย (1) ดัชนีถัดไป ("c + e" - current plus epsilon) และ (2) ทิศทางใหม่ซึ่งเราคำนวณโดยมองไปข้างหน้าเพื่อดูว่ามีอะไรอยู่ในอาร์เรย์ เซลล์ต่อไป ถ้าถ่าน lookahead เป็นสแลชทิศทางใหม่คือ 's' ถ้าเป็นแบ็กสแลชทิศทางใหม่คือ 3-s (การเลือกที่เราเข้ารหัส 0123 ทำให้มันใช้งานได้) ถ้ามันเป็นช่องว่างเราแค่เดินไปในทิศทางเดียวกัน 'd' และถ้ามันเป็นตัวละครอื่น ๆ 'c' เกมก็จบลงพิมพ์ 'จริง' ถ้า char เป็น 'x' และเท็จอย่างอื่น

ในการเริ่มต้นสิ่งต่าง ๆ เราเรียกฟังก์ชัน recursive 'n' ด้วยตำแหน่งเริ่มต้น 'c' และทิศทางเริ่มต้น (ซึ่งเป็นการเข้ารหัสเริ่มต้นของทิศทางเป็น 0123)

ฉันคิดว่าฉันยังคงสามารถโกนตัวละครออกไปได้อีกสองสามตัว แต่ฉันก็ค่อนข้างพอใจกับมันเช่นนี้ (และ 255 เป็นตัวเลขที่ดี)


11

การชั่งน้ำหนักที่ 18203 ตัวอักษรเป็นวิธีการของ Python ที่สามารถ:

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

มันยังต้องการความเรียบร้อยค่อนข้างมากและฉันไม่รู้ว่าฟิสิกส์ 2 มิติบอกว่าลำแสงไม่สามารถข้ามตัวเองได้ ...

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
The shortest code by character count to input a 2D representation of a board, 
and output 'true' or 'false' according to the input.

The board is made out of 4 types of tiles:

# - A solid wall
x - The target the laser has to hit
/ or \ - Mirrors pointing to a direction (depends on laser direction)
v, ^, > or < - The laser pointing to a direction (down, up, right and left
respectively)

There is only one laser and only one target. Walls must form a solid rectangle 
of any size, where the laser and target are placed inside. Walls inside the
'room' are possible.

Laser ray shots and travels from it's origin to the direction it's pointing. If
a laser ray hits the wall, it stops. If a laser ray hits a mirror, it is bounces
90 degrees to the direction the mirror points to. Mirrors are two sided, meaning
both sides are 'reflective' and may bounce a ray in two ways. If a laser ray
hits the laser (^v><) itself, it is treated as a wall (laser beam destroys the
beamer and so it'll never hit the target).
"""



SOLID_WALL, TARGET, MIRROR_NE_SW, MIRROR_NW_SE, LASER_DOWN, LASER_UP, \
LASER_RIGHT, LASER_LEFT = range(8)

MIRRORS = (MIRROR_NE_SW, MIRROR_NW_SE)

LASERS = (LASER_DOWN, LASER_UP, LASER_RIGHT, LASER_LEFT)

DOWN, UP, RIGHT, LEFT = range(4)

LASER_DIRECTIONS = {
    LASER_DOWN : DOWN,
    LASER_UP   : UP,
    LASER_RIGHT: RIGHT,
    LASER_LEFT : LEFT
}

ROW, COLUMN = range(2)

RELATIVE_POSITIONS = {
    DOWN : (ROW,     1),
    UP   : (ROW,    -1),
    RIGHT: (COLUMN,  1),
    LEFT : (COLUMN, -1)
}

TILES = {"#" : SOLID_WALL,
         "x" : TARGET,
         "/" : MIRROR_NE_SW,
         "\\": MIRROR_NW_SE,
         "v" : LASER_DOWN,
         "^" : LASER_UP,
         ">" : LASER_RIGHT,
         "<" : LASER_LEFT}

REFLECTIONS = {MIRROR_NE_SW: {DOWN : LEFT,
                              UP   : RIGHT,
                              RIGHT: UP,
                              LEFT : DOWN},
               MIRROR_NW_SE: {DOWN : RIGHT,
                              UP   : LEFT,
                              RIGHT: DOWN,
                              LEFT : UP}}



def does_laser_hit_target(tiles):
    """
        Follows a lasers trajectory around a grid of tiles determining if it
        will reach the target.

        Keyword arguments:
        tiles --- row/column based version of a board containing symbolic
                  versions of the tiles (walls, laser, target, etc)
    """

    #Obtain the position of the laser
    laser_pos = get_laser_pos(tiles)

    #Retrieve the laser's tile
    laser = get_tile(tiles, laser_pos)

    #Create an editable starting point for the beam
    beam_pos = list(laser_pos)

    #Create an editable direction for the beam
    beam_dir = LASER_DIRECTIONS[laser]

    #Cache the number of rows
    number_of_rows = len(tiles)

    #Keep on looping until an ultimate conclusion
    while True:

        #Discover the axis and offset the beam is travelling to
        axis, offset = RELATIVE_POSITIONS[beam_dir]

        #Modify the beam's position
        beam_pos[axis] += offset

        #Allow for a wrap around in this 2D scenario
        try:

            #Get the beam's new tile
            tile = get_tile(tiles, beam_pos)

        #Perform wrapping
        except IndexError:

            #Obtain the row position
            row_pos = beam_pos[ROW]

            #Handle vertical wrapping
            if axis == ROW:

                #Handle going off the top
                if row_pos == -1:

                    #Move beam to the bottom
                    beam_pos[ROW] = number_of_rows - 1

                #Handle going off the bottom
                elif row_pos == number_of_rows:

                    #Move beam to the top
                    beam_pos[ROW] = 0

            #Handle horizontal wrapping
            elif axis == COLUMN:

                #Obtain the row
                row = tiles[row_pos]

                #Calculate the number of columns
                number_of_cols = len(row)

                #Obtain the column position
                col_pos = beam_pos[COLUMN]

                #Handle going off the left hand side
                if col_pos == -1:

                    #Move beam to the right hand side
                    beam_pos[COLUMN] = number_of_cols - 1

                #Handle going off the right hand side
                elif col_pos == number_of_cols:

                    #Move beam to the left hand side
                    beam_pos[COLUMN] = 0

            #Get the beam's new tile
            tile = get_tile(tiles, beam_pos)

        #Handle hitting a wall or the laser
        if tile in LASERS \
        or tile == SOLID_WALL:
            return False

        #Handle hitting the target
        if tile == TARGET:
            return True

        #Handle hitting a mirror
        if tile in MIRRORS:
            beam_dir = reflect(tile, beam_dir)

def get_laser_pos(tiles):
    """
        Returns the current laser position or an exception.

        Keyword arguments:
        tiles --- row/column based version of a board containing symbolic
                  versions of the tiles (walls, laser, target, etc)
    """

    #Calculate the number of rows
    number_of_rows = len(tiles)

    #Loop through each row by index
    for row_pos in range(number_of_rows):

        #Obtain the current row
        row = tiles[row_pos]

        #Calculate the number of columns
        number_of_cols = len(row)

        #Loop through each column by index
        for col_pos in range(number_of_cols):

            #Obtain the current column
            tile = row[col_pos]

            #Handle finding a laser
            if tile in LASERS:

                #Return the laser's position
                return row_pos, col_pos

def get_tile(tiles, pos):
    """
        Retrieves a tile at the position specified.

        Keyword arguments:
        pos --- a row/column position of the tile
        tiles --- row/column based version of a board containing symbolic
                  versions of the tiles (walls, laser, target, etc)
    """

    #Obtain the row position
    row_pos = pos[ROW]

    #Obtain the column position
    col_pos = pos[COLUMN]

    #Obtain the row
    row = tiles[row_pos]

    #Obtain the tile
    tile = row[col_pos]

    #Return the tile
    return tile

def get_wall_pos(tiles, reverse=False):
    """
        Keyword arguments:
        tiles --- row/column based version of a board containing symbolic
                  versions of the tiles (walls, laser, target, etc)
        reverse --- whether to search in reverse order or not (defaults to no)
    """

    number_of_rows = len(tiles)

    row_iter = range(number_of_rows)

    if reverse:
        row_iter = reversed(row_iter)

    for row_pos in row_iter:
        row = tiles[row_pos]

        number_of_cols = len(row)

        col_iter = range(number_of_cols)

        if reverse:
            col_iter = reversed(col_iter)

        for col_pos in col_iter:
            tile = row[col_pos]

            if tile == SOLID_WALL:
                pos = row_pos, col_pos

                if reverse:
                    offset = -1
                else:
                    offset = 1

                for axis in ROW, COLUMN:
                    next_pos = list(pos)

                    next_pos[axis] += offset

                    try:
                        next_tile = get_tile(tiles, next_pos)
                    except IndexError:
                        next_tile = None

                    if next_tile != SOLID_WALL:
                        raise WallOutsideRoomError(row_pos, col_pos)

                return pos

def identify_tile(tile):
    """
        Returns a symbolic value for every identified tile or None.

        Keyword arguments:
        tile --- the tile to identify
    """

    #Safely lookup the tile
    try:

        #Return known tiles
        return TILES[tile]

    #Handle unknown tiles
    except KeyError:

        #Return a default value
        return

def main():
    """
        Takes a board from STDIN and either returns a result to STDOUT or an
        error to STDERR.

        Called when this file is run on the command line.
    """

    #As this function is the only one to use this module, and it can only be
    #called once in this configuration, it makes sense to only import it here.
    import sys

    #Reads the board from standard input.
    board = sys.stdin.read()

    #Safely handles outside input
    try:

        #Calculates the result of shooting the laser
        result = shoot_laser(board)

    #Handles multiple item errors
    except (MultipleLaserError, MultipleTargetError) as error:

        #Display the error
        sys.stderr.write("%s\n" % str(error))

        #Loop through all the duplicated item symbols
        for symbol in error.symbols:

            #Highlight each symbol in green
            board = board.replace(symbol, "\033[01;31m%s\033[m" % symbol)

        #Display the board
        sys.stderr.write("%s\n" % board)

        #Exit with an error signal
        sys.exit(1)

    #Handles item missing errors
    except (NoLaserError, NoTargetError) as error:

        #Display the error
        sys.stderr.write("%s\n" % str(error))

        #Display the board
        sys.stderr.write("%s\n" % board)

        #Exit with an error signal
        sys.exit(1)

    #Handles errors caused by symbols
    except (OutsideRoomError, WallNotRectangleError) as error:

        #Displays the error
        sys.stderr.write("%s\n" % str(error))

        lines = board.split("\n")

        line = lines[error.row_pos]

        before = line[:error.col_pos]

        after = line[error.col_pos + 1:]

        symbol = line[error.col_pos]

        line = "%s\033[01;31m%s\033[m%s" % (before, symbol, after)

        lines[error.row_pos] = line

        board = "\n".join(lines)

        #Display the board
        sys.stderr.write("%s\n" % board)

        #Exit with an error signal
        sys.exit(1)

    #Handles errors caused by non-solid walls
    except WallNotSolidError as error:

        #Displays the error
        sys.stderr.write("%s\n" % str(error))

        lines = board.split("\n")

        line = lines[error.row_pos]

        before = line[:error.col_pos]

        after = line[error.col_pos + 1:]

        symbol = line[error.col_pos]

        line = "%s\033[01;5;31m#\033[m%s" % (before, after)

        lines[error.row_pos] = line

        board = "\n".join(lines)

        #Display the board
        sys.stderr.write("%s\n" % board)

        #Exit with an error signal
        sys.exit(1)

    #If a result was returned
    else:

        #Converts the result into a string
        result_str = str(result)

        #Makes the string lowercase
        lower_result = result_str.lower()

        #Returns the result
        sys.stdout.write("%s\n" % lower_result)

def parse_board(board):
    """
        Interprets the raw board syntax and returns a grid of tiles.

        Keyword arguments:
        board --- the board containing the tiles (walls, laser, target, etc)
    """

    #Create a container for all the lines
    tiles = list()

    #Loop through all the lines of the board
    for line in board.split("\n"):

        #Identify all the tiles on the line 
        row = [identify_tile(tile) for tile in line]

        #Add the row to the container
        tiles.append(row)

    #Return the container
    return tiles

def reflect(mirror, direction):
    """
        Returns an updated laser direction after it has been reflected on a
        mirror.

        Keyword arguments:
        mirror --- the mirror to reflect the laser from
        direction --- the direction the laser is travelling in
    """

    try:
        direction_lookup = REFLECTIONS[mirror]
    except KeyError:
        raise TypeError("%s is not a mirror.", mirror)

    try:
        return direction_lookup[direction]
    except KeyError:
        raise TypeError("%s is not a direction.", direction)

def shoot_laser(board):
    """
        Shoots the boards laser and returns whether it will hit the target.

        Keyword arguments:
        board --- the board containing the tiles (walls, laser, target, etc)
    """

    tiles = parse_board(board)

    validate_board(tiles)

    return does_laser_hit_target(tiles)

def validate_board(tiles):
    """
        Checks an board to see if it is valid and raises an exception if not.

        Keyword arguments:
        tiles --- row/column based version of a board containing symbolic
                  versions of the tiles (walls, laser, target, etc)
    """

    found_laser = False
    found_target = False

    try:
        n_wall, w_wall = get_wall_pos(tiles)
        s_wall, e_wall = get_wall_pos(tiles, reverse=True)
    except TypeError:
        n_wall = e_wall = s_wall = w_wall = None

    number_of_rows = len(tiles)

    for row_pos in range(number_of_rows):
        row = tiles[row_pos]

        number_of_cols = len(row)

        for col_pos in range(number_of_cols):

            tile = row[col_pos]

            if ((row_pos in (n_wall, s_wall) and
                 col_pos in range(w_wall, e_wall))
                or
                (col_pos in (e_wall, w_wall) and
                 row_pos in range(n_wall, s_wall))):
                if tile != SOLID_WALL:
                    raise WallNotSolidError(row_pos, col_pos)
            elif (n_wall != None and
                  (row_pos < n_wall or
                   col_pos > e_wall or
                   row_pos > s_wall or
                   col_pos < w_wall)):

                if tile in LASERS:
                    raise LaserOutsideRoomError(row_pos, col_pos)
                elif tile == TARGET:
                    raise TargetOutsideRoomError(row_pos, col_pos)
                elif tile == SOLID_WALL:
                    if not (row_pos >= n_wall and
                            col_pos <= e_wall and
                            row_pos <= s_wall and
                            col_pos >= w_wall):
                        raise WallOutsideRoomError(row_pos, col_pos)
            else:
                if tile in LASERS:
                    if not found_laser:
                        found_laser = True
                    else:
                        raise MultipleLaserError(row_pos, col_pos)
                elif tile == TARGET:
                    if not found_target:
                        found_target = True
                    else:
                        raise MultipleTargetError(row_pos, col_pos)

    if not found_laser:
        raise NoLaserError(tiles)

    if not found_target:
        raise NoTargetError(tiles)



class LasersError(Exception):
    """Parent Error Class for all errors raised."""

    pass

class NoLaserError(LasersError):
    """Indicates that there are no lasers on the board."""

    symbols = "^v><"

    def __str__ (self):
        return "No laser (%s) to fire." % ", ".join(self.symbols)

class NoTargetError(LasersError):
    """Indicates that there are no targets on the board."""

    symbols = "x"

    def __str__ (self):
        return "No target (%s) to hit." % ", ".join(self.symbols)

class MultipleLaserError(LasersError):
    """Indicates that there is more than one laser on the board."""

    symbols = "^v><"

    def __str__ (self):
        return "Too many lasers (%s) to fire, only one is allowed." % \
               ", ".join(self.symbols)

class MultipleTargetError(LasersError):
    """Indicates that there is more than one target on the board."""

    symbols = "x"

    def __str__ (self):
        return "Too many targets (%s) to hit, only one is allowed." % \
               ", ".join(self.symbols)

class WallNotSolidError(LasersError):
    """Indicates that the perimeter wall is not solid."""

    __slots__ = ("__row_pos", "__col_pos", "n_wall", "s_wall", "e_wall",
                 "w_wall")

    def __init__(self, row_pos, col_pos):
        self.__row_pos = row_pos
        self.__col_pos = col_pos

    def __str__ (self):
        return "Walls must form a solid rectangle."

    def __get_row_pos(self):
        return self.__row_pos

    def __get_col_pos(self):
        return self.__col_pos

    row_pos = property(__get_row_pos)
    col_pos = property(__get_col_pos)

class WallNotRectangleError(LasersError):
    """Indicates that the perimeter wall is not a rectangle."""

    __slots__ = ("__row_pos", "__col_pos")

    def __init__(self, row_pos, col_pos):
        self.__row_pos = row_pos
        self.__col_pos = col_pos

    def __str__ (self):
        return "Walls must form a rectangle."

    def __get_row_pos(self):
        return self.__row_pos

    def __get_col_pos(self):
        return self.__col_pos

    row_pos = property(__get_row_pos)
    col_pos = property(__get_col_pos)

class OutsideRoomError(LasersError):
    """Indicates an item is outside of the perimeter wall."""

    __slots__ = ("__row_pos", "__col_pos", "__name")

    def __init__(self, row_pos, col_pos, name):
        self.__row_pos = row_pos
        self.__col_pos = col_pos
        self.__name = name

    def __str__ (self):
        return "A %s was found outside of a 'room'." % self.__name

    def __get_row_pos(self):
        return self.__row_pos

    def __get_col_pos(self):
        return self.__col_pos

    row_pos = property(__get_row_pos)
    col_pos = property(__get_col_pos)

class LaserOutsideRoomError(OutsideRoomError):
    """Indicates the laser is outside of the perimeter wall."""

    def __init__ (self, row_pos, col_pos):
        OutsideRoomError.__init__(self, row_pos, col_pos, "laser")

class TargetOutsideRoomError(OutsideRoomError):
    """Indicates the target is outside of the perimeter wall."""

    def __init__ (self, row_pos, col_pos):
        OutsideRoomError.__init__(self, row_pos, col_pos, "target")

class WallOutsideRoomError(OutsideRoomError):
    """Indicates that there is a wall outside of the perimeter wall."""

    def __init__ (self, row_pos, col_pos):
        OutsideRoomError.__init__(self, row_pos, col_pos, "wall")



if __name__ == "__main__":
    main()

สคริปต์ทุบตีเพื่อแสดงการรายงานข้อผิดพลาดสี:

#!/bin/bash

declare -a TESTS

test() {
    echo -e "\033[1m$1\033[0m"
    tput sgr0
    echo "$2" | ./lasers.py
    echo
}

test \
"no laser" \
"    ##########
    #     x  #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"multiple lasers" \
"    ##########
    #   v x  #
    # /      #
    #       /#
    #   \\  ^ #
    ##########"

test \
"no target" \
"    ##########
    #   v    #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"multiple targets" \
"    ##########
    #   v x  #
    # /      #
    #       /#
    #   \\  x #
    ##########"

test \
"wall not solid" \
"    ##### ####
    #   v x  #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"laser_outside_room" \
"    ##########
 >  #     x  #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"laser before room" \
" >  ##########
    #     x  #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"laser row before room" \
"   >
    ##########
    #     x  #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"laser after room" \
"    ##########
    #     x  #
    # /      #
    #       /#
    #   \\    #
    ##########  >"

test \
"laser row after room" \
"    ##########
    #     x  #
    # /      #
    #       /#
    #   \\    #
    ##########
  > "

test \
"target outside room" \
"    ##########
 x  #   v    #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"target before room" \
" x  ##########
    #   v    #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"target row before room" \
"   x
    ##########
    #   v    #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"target after room" \
"    ##########
    #   v    #
    # /      #
    #       /#
    #   \\    #
    ##########   x"

test \
"target row after room" \
"    ##########
    #   v    #
    # /      #
    #       /#
    #   \\    #
    ##########
  x "

test \
"wall outside room" \
"    ##########
 #  #   v    #
    # /      #
    #       /#
    #   \\  x #
    ##########"

test \
"wall before room" \
" #  ##########
    #   v    #
    # /      #
    #       /#
    #   \\  x #
    ##########"

test \
"wall row before room" \
"    #
    ##########
    #   v    #
    # /      #
    #       /#
    #   \\  x #
    ##########"

test \
"wall after room" \
"    ##########
    #   v    #
    # /      #
    #       /#
    #   \\  x #
    ########## #"

test \
"wall row after room" \
"    ##########
    #   v    #
    # /      #
    #       /#
    #   \\  x #
    ##########
  #"

test \
"mirror outside room positive" \
"    ##########
 /  #   / \\  #
    #        #
    #   \\   x#
    # >   /  #
    ########## "

test \
"mirrors outside room negative" \
"    ##########
 \\  #   v x  #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"mirror before room positive" \
" \\  ##########
    #   / \\  #
    #        #
    #   \\   x#
    # >   /  #
    ########## "

test \
"mirrors before room negative" \
" /  ##########
    #   v x  #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"mirror row before room positive" \
"     \\
    ##########
    #   / \\  #
    #        #
    #   \\   x#
    # >   /  #
    ########## "

test \
"mirrors row before room negative" \
"     \\
    ##########
    #   v x  #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"mirror after row positive" \
"    ##########
    #   / \\  #
    #        #
    #   \\   x#
    # >   /  #
    ########## /  "

test \
"mirrors after row negative" \
"    ##########
    #   v x  #
    # /      #
    #       /#
    #   \\    #
    ##########   /  "

test \
"mirror row after row positive" \
"    ##########
    #   / \\  #
    #        #
    #   \\   x#
    # >   /  #
    ########## 
 /  "

test \
"mirrors row after row negative" \
"    ##########
    #   v x  #
    # /      #
    #       /#
    #   \\    #
    ########## 
 /  "

test \
"laser hitting laser" \
"    ##########
    #   v   \\#
    #        #
    #        #
    #x  \\   /#
    ##########"

test \
"mirrors positive" \
"    ##########
    #   / \\  #
    #        #
    #   \\   x#
    # >   /  #
    ########## "

test \
"mirrors negative" \
"    ##########
    #   v x  #
    # /      #
    #       /#
    #   \\    #
    ##########"

test \
"wall collision" \
"    #############
    #     #     #
    # >   #     #
    #     #     #
    #     #   x #
    #     #     #
    #############"

test \
"extreme example" \
"    ##########
    #/\\/\\/\\  #
    #\\\\//\\\\\\ #
    #//\\/\\/\\\\#
    #\\/\\/\\/x^#
    ##########"

test \
"brian example 1" \
"##########
#   / \\  #
#        #
#/    \\ x#
#\\>   /  #
##########"

test \
"brian example 2" \
"##########
#  /    \\#
# / \\    #
#/    \\ x#
#\\^/\\ /  #
##########"

unittests ที่ใช้ในการพัฒนา:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import unittest

from lasers import *

class TestTileRecognition(unittest.TestCase):
    def test_solid_wall(self):
        self.assertEqual(SOLID_WALL, identify_tile("#"))

    def test_target(self):
        self.assertEqual(TARGET, identify_tile("x"))

    def test_mirror_ne_sw(self):
        self.assertEqual(MIRROR_NE_SW, identify_tile("/"))

    def test_mirror_nw_se(self):
        self.assertEqual(MIRROR_NW_SE, identify_tile("\\"))

    def test_laser_down(self):
        self.assertEqual(LASER_DOWN, identify_tile("v"))

    def test_laser_up(self):
        self.assertEqual(LASER_UP, identify_tile("^"))

    def test_laser_right(self):
        self.assertEqual(LASER_RIGHT, identify_tile(">"))

    def test_laser_left(self):
        self.assertEqual(LASER_LEFT, identify_tile("<"))

    def test_other(self):
        self.assertEqual(None, identify_tile(" "))

class TestReflection(unittest.TestCase):
    def setUp(self):
        self.DIRECTION = LEFT
        self.NOT_DIRECTIO

6
เลเซอร์ฟิสิกส์บอกว่าลำแสงสามารถตัดผ่านได้ ความคิดเห็นด้านบนเป็นการอ้างอิงทางวัฒนธรรมที่สำคัญ
dmckee --- ผู้ดูแลอดีตลูกแมว

5
เต่าและแนวทางกระต่ายกับการตีกอล์ฟ ส่งบางสิ่งบางอย่างที่มีตัวอักษรมากเกินไป (91x มากกว่าผู้ชนะในปัจจุบัน) แต่ให้ความสนใจกับตัวอักษรของสเป็คทุกตัว ช้าและมั่นคงโดยทั่วไปทำให้ฉันได้งานทำสัญญาน้อยลง
Metalshark

คุณอาจไม่เห็นด้วยบางส่วน มันถูกตัดออกที่ "self.NOT_DIRECTIO"
BioGeek

@BioGeek - กดขีดจำกัดความยาวของโพสต์;) นอกจากนี้การทดสอบสไตล์ BASH ก็แสดงให้เห็นถึงการเน้นสี
Metalshark

11

Ruby, 176 ตัวอักษร

x=!0;y=0;e="^v<>#x";b=readlines;b.map{|l|(x||=l=~/[v^<>]/)||y+=1};c=e.index(b[y][x])
loop{c<2&&y+=c*2-1;c>1&&x+=2*c-5;e.index(n=b[y][x])&&(p n==?x;exit);c^='  \/'.index(n)||0}

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

ฉันสงสัยว่ารหัสที่เพิ่มขึ้นxและyอาจทำให้สั้นลง นี่คือส่วนของรหัสที่เพิ่มขึ้น:

c<2&&y+=c*2-1;c>1&&x+=(c-2)*2-1

แก้ไข : ฉันสามารถย่อให้สั้นลงเล็กน้อย:

c<2&&y+=c*2-1;c>1&&x+=2*c-5

ทิศทางปัจจุบันของเลเซอร์cถูกเก็บไว้ดังนี้:

0 => ขึ้น
1 => ลง
2 => เหลือ
3 => ถูกต้อง

รหัสขึ้นอยู่กับข้อเท็จจริงนี้เพื่อเพิ่มxและyตามจำนวนที่ถูกต้อง (0, 1, หรือ -1) ฉันพยายามจัดเรียงตัวเลขที่แมปไปในแต่ละทิศทางโดยมองหาข้อตกลงที่จะให้ฉันใช้การจัดการระดับบิตเพื่อเพิ่มค่าเพราะฉันมีความรู้สึกที่ดุด่าว่ามันจะสั้นกว่าเวอร์ชั่นเลขคณิต


9

C # 3.0

259 ตัวอักษร

bool S(char[]m){var w=Array.FindIndex(m,x=>x<11)+1;var s=Array.FindIndex(m,x=>x>50&x!=92&x<119);var t=m[s];var d=t<61?-1:t<63?1:t<95?-w:w;var u=0;while(0<1){s+=d;u=m[s];if(u>119)return 0<1;if(u==47|u==92)d+=d>0?-w-1:w+1;else if(u!=32)return 0>1;d=u>47?-d:d;}}

อ่านง่ายขึ้นเล็กน้อย:

bool Simulate(char[] m)
{
    var w = Array.FindIndex(m, x => x < 11) + 1;
    var s = Array.FindIndex(m, x => x > 50 & x != 92 & x < 119);
    var t = m[s];
    var d = t < 61 ? -1 : t < 63 ? 1 : t < 95 ? -w : w;
    var u = 0;
    while (0 < 1)
    {
        s += d;
        u = m[s];
        if (u > 119)
            return 0 < 1;
        if (u == 47 | u == 92)
            d += d > 0 ? -w - 1 : w + 1;
        else if (u != 32)
            return 0 > 1;
        d = u > 47 ? -d : d;
    }
}

เศษหลักของตัวอักษรน่าจะอยู่ในการค้นหาความกว้างของแผนที่และตำแหน่งของแหล่งกำเนิดแสงเลเซอร์ แนวคิดใดที่จะทำให้สั้นลงได้


ฉันไม่แน่ใจว่ามันสั้นกว่านี้หรือเปล่า แต่มันเป็นช็อตของฉันที่ค้นหาเลเซอร์และการค้นหาความกว้าง: ใช้ L = List <string>; โดยใช้ P = System.Drawing.Point; ใช้ L = List <string>; L r = new L () {"v", "<", ">", "^"}; P p = new P (); r.ForEach (a => {int c = 0; v.ForEach (s => {c ++) ; ถ้า (s.IndexOf (a)! = - 1) {pX = s.IndexOf (a); pY = c;}});}); int l = v [0]. ความยาว; v คือรายการ <string> ที่มีตารางและจะส่งออกเป็นจุดที่แสดงถึงตำแหน่งเลเซอร์ + ความกว้างที่แสดงถึงความเป็น int
RCIX

ดีกว่า: ใช้ L = รายการ <string>; L l = ใหม่ L (4) {"v", "<", ">", "^"}; var point = new {x = 0, y = 0}; int c = 0; l.ForEach (a => {m.ForEach (s => {ถ้า (s.IndexOf (a)! = - 1) {จุด = ใหม่ {x = s.IndexOf (a), y = c};}}); c ++;}); int w = m [0]. ความยาว;
RCIX

4
ปัญหาถามหาโปรแกรมเต็มรูปแบบไม่ใช่ฟังก์ชั่น
แปลกหน้า

วิธีการเกี่ยวกับ while(1)
SSpoke

9

C + ASCII, 197 ตัวอักษร:

G[999],*p=G,w,z,t,*b;main(){for(;(*p++=t=getchar()^32)>=0;w=w|t-42?w:p-G)z=t^86?t^126?t^28?t^30?z:55:68:56:75,b=z?b:p;for(;t=z^55?z^68?z^56?z^75?0:w:-w:-1:1;z^=*b)b+=t;puts(*b^88?"false":"true");}

โซลูชัน C นี้สมมติว่าชุดอักขระ ASCII ทำให้เราสามารถใช้เคล็ดลับมิเรอร์ XOR ได้ นอกจากนี้ยังเปราะบางอย่างไม่น่าเชื่อเช่นทุกบรรทัดอินพุตจะต้องมีความยาวเท่ากัน

มันแบ่งภายใต้เครื่องหมาย 200 ตัวอักษร - แต่ก็ยังไม่ได้แก้ปัญหา Perl เหล่านั้น!


= O! +1! ขอให้ฉันตี =]
แปลกหน้า

2
การแก้ปัญหาที่ดีที่สุดที่นี่ทำให้สมมติฐาน "ทุกบรรทัดมีความยาวเท่ากัน" ทุกอย่างยุติธรรมในสนามกอล์ฟและสงคราม
hobbs

หากจำเป็นต้องใช้บรรทัดที่ไม่ได้มีความยาวเท่ากันฉันจะเพิ่มกรณีทดสอบให้ แต่ผมบอกว่ามันเห็นได้ชัดว่าเป็นความจงใจ :)
LiraNuna


9

Python - 152

อ่านอินพุตจากไฟล์ชื่อ "L"

A=open("L").read()
W=A.find('\n')+1
D=P=-1
while P<0:D+=1;P=A.find(">^<v"[D])
while D<4:P+=[1,-W,-1,W][D];D=[D,D^3,D^1,4,5][' \/x'.find(A[P])]
print D<5

หากต้องการอ่านจาก stdin ให้แทนที่บรรทัดแรกด้วยสิ่งนี้

import os;A=os.read(0,1e9)

หากคุณต้องการตัวพิมพ์เล็กจริง / เท็จเปลี่ยนบรรทัดสุดท้ายเป็น

print`D<5`.lower()

ต้องใช้ตัวอักษรกี่ตัวเพื่อเปลี่ยนTrueเป็นtrueและFalseเป็นfalseอย่างไร ;-)
ม็อป

คุณไม่สามารถลบ 1 ตัวอักษรโดยเปลี่ยน "พิมพ์D<5" เป็น "พิมพ์ D <5" ได้หรือไม่ หรือมีบางอย่างที่ฉันขาดหายไป?
Ponkadoodle

@ walacoloo แน่นอนสามารถ จำเป็นสำหรับตัวพิมพ์เล็กจริง / เท็จเท่านั้น
John La Rooy

7

JavaScript - 265 ตัวอักษร

Update IV - Odds นี่คือรอบสุดท้ายของการอัพเดทจัดการเพื่อบันทึกตัวละครอีกสองสามตัวโดยเปลี่ยนเป็น do-while วนซ้ำและเขียนสมการการเคลื่อนที่ใหม่

อัปเดต III - ขอบคุณคำแนะนำโดยคนแปลกหน้าเกี่ยวกับการลบ Math.abs () และวางตัวแปรในพื้นที่ชื่อส่วนกลางซึ่งประกอบกับการจัดเรียงตัวแปรการกำหนดค่าใหม่ให้มีความยาว 282 อักขระ

อัปเดต II - การอัปเดตบางอย่างของโค้ดเพิ่มเติมเพื่อลบการใช้! = -1 รวมถึงการใช้ตัวแปรที่ดีกว่าสำหรับการดำเนินการที่ยาวนานขึ้น

อัปเดต - เมื่อผ่านและทำการเปลี่ยนแปลงบางอย่างโดยสร้างการอ้างอิงไปยังฟังก์ชั่น indexOf (ขอบคุณ LiraNuna!) และลบวงเล็บที่ไม่จำเป็น

นี่เป็นครั้งแรกที่ฉันเล่นกอล์ฟรหัสดังนั้นฉันจึงไม่แน่ใจว่าจะทำได้ดีกว่านี้ฟีดแบ็คใด ๆ ที่น่าชื่นชม

เวอร์ชันย่อขนาดเล็กสุด:

a;b;c;d;e;function f(g){a=function(a){return g.indexOf(a)};b=a("\n")+1;a=g[c=e=a("v")>0?e:e=a("^")>0?e:e=a("<")>0?e:a(">")];d=a=="<"?-1:a==">"?1:a=="^"?-b:b;do{e=d==-1|d==1;a=g[c+=d=a=="\\"?e?b*d:d>0?1:-1:a=="/"?e?-b*d:d>0?1:-1:d];e=a=="x"}while(a!="#"^e);return e}

เวอร์ชั่นดั้งเดิมพร้อมความคิดเห็น:

character; length; loc; movement; temp;
function checkMaze(maze) {
        // Use a shorter indexOf function
        character = function(string) { return maze.indexOf(string); }
        // Get the length of the maze
        length = character("\n") + 1;
        // Get the location of the laser in the string
        character = maze[loc = temp = character("v") > 0 ? temp :
                               temp = character("^") > 0 ? temp :
                               temp = character("<") > 0 ? temp : character(">")];
        // Get the intial direction that we should travel
        movement = character == "<" ? -1 :
                   character == ">" ? 1 :
                   character == "^" ? -length : length;
        // Move along until we reach the end
        do {
            // Get the current character
            temp = movement == -1 | movement == 1;
            character = maze[loc += movement = character == "\\" ? temp ? length * movement : movement > 0 ? 1 : -1 :
                                               character == "/" ? temp ? -length * movement : movement > 0 ? 1 : -1 : movement];                                   
            // Have we hit a target?
            temp = character == "x";
            // Have we hit a wall?
        } while (character != "#" ^ temp);
        // temp will be false if we hit the target
        return temp;
    }

หน้าเว็บที่จะทดสอบด้วย:

<html>
  <head>
    <title>Code Golf - Lasers</title>
    <script type="text/javascript">
    a;b;c;d;e;function f(g){a=function(a){return g.indexOf(a)};b=a("\n")+1;a=g[c=e=a("v")>0?e:e=a("^")>0?e:e=a("<")>0?e:a(">")];d=a=="<"?-1:a==">"?1:a=="^"?-b:b;do{e=d==-1|d==1;a=g[c+=d=a=="\\"?e?b*d:d>0?1:-1:a=="/"?e?-b*d:d>0?1:-1:d];e=a=="x"}while(a!="#"^e);return e}
    </script>
  </head>
  <body>
    <textarea id="maze" rows="10" cols="10"></textarea>
    <button id="checkMaze" onclick="alert(f(document.getElementById('maze').value))">Maze</button>
  </body>
</html>

มันใช้อย่างไรเข้า? ฉันต้องการทดสอบและตรวจสอบสิ่งนี้ นอกจากนี้คุณยังสามารถบันทึกจำนวนมากของตัวอักษรถ้าคุณบันทึกเตะเพื่อ a.indexOf
LiraNuna

แทนที่index != -1ด้วยindex > 0โปรด! (หวังว่าจะไม่มีใครใส่ lazer ที่มุมบนซ้ายดังนั้น0จะไม่ถูกส่งกลับมา =]) คุณสามารถโยงvarข้อความหรือกำจัดข้อความทั้งหมดได้ ผมคิดว่าอาจถูกแทนที่ด้วยMath.abs(m)==1 m==-1|m==1สามารถmovement = ...; location += movementปรับให้เหมาะกับlocation += movement =?
แปลกหน้า

@ strager- เพิ่งเห็นความคิดเห็นของคุณดูเหมือนว่าคุณโพสต์ไว้ในขณะที่ฉันกำลังอัปเดตรหัสจนถึง 300 ตัวอักษร ฉันจะดูว่าฉันจะทำอย่างไรกับการกำจัด Math.abs ()
rjzii

function(a){return g.indexOf(a)}สามารถแทนที่ด้วยfunction(a)g.indexOf(a)ในเวอร์ชัน JavaScript ล่าสุด
user1686

6

บ้านของกระจก

ไม่ใช่ความท้าทายที่แท้จริง แต่ฉันเขียนเกมตามแนวคิดนี้ (ไม่นานเกินไป)

มันเขียนใน Scala โอเพนซอร์ซและมีอยู่ที่นี่ :

มันเพิ่มอีกนิด จัดการกับสีและกระจกและอุปกรณ์ประเภทต่าง ๆ แต่รุ่น 0.00001 ทำในสิ่งที่ท้าทายนี้อย่างแท้จริง ฉันทำรุ่นนั้นหายไปและมันก็ไม่เหมาะสำหรับการนับตัวละคร


เป็นไปได้ไหมที่คุณจะอัปโหลดเวอร์ชันที่คอมไพล์ซึ่งทำงานบน Windows โดยไม่ต้องติดตั้ง scala
มิลาน

มีรุ่นที่มีห้องสมุดสกาล่ารวมอยู่ด้วย ดูรายการดาวน์โหลด แต่อย่างไรก็ตามถ้าคุณได้ติดตั้ง Scala โดยขณะนี้ฉันดีใจที่ฉันมีคุณจะทำอย่างนั้น :)
HRJ

6

c (K&R) 339 ตัวละครที่จำเป็นหลังจากคำแนะนำเพิ่มเติมจากคนแปลกหน้า

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

ส่วนที่เหลือของการดำเนินการเป็นไปข้างหน้าตรงไปตรงมาและมีความพยายามมากขึ้นหรือน้อยลงจากก่อนหน้านี้ของฉันพยายามไปข้างหน้า

การบีบอัด:

#define R return
#define C case
#define Z x,y
int c,i,j,m[99][99],Z;s(d,e,Z){for(;;)switch(m[x+=d][y+=e]){C'^':R 1==e;
C'>':R-1==d;C'v':R-1==e;C'<':R 1==d;C'#':C'x':R 0;C 92:e=-e;d=-d;C'/':c=d;
d=-e;e=-c;}}main(){while((c=getchar())>0)c==10?i=0,j++:(c==120?x=i,y=j:
i,m[i++][j]=c);puts(s(1,0,Z)|s(0,1,Z)|s(-1,0,Z)|s(0,-1,Z)?"true":"false");}

ไม่มีการบีบอัด (ish):

#define R return
#define C case
#define Z x,y
int c,i,j,m[99][99],Z;
s(d,e,Z)
{
  for(;;)
    switch(m[x+=d][y+=e]){
    C'^': 
      R 1==e;
    C'>': 
      R-1==d;
    C'v': 
      R-1==e;
    C'<': 
      R 1==d;
    C'#':
    C'x':
      R 0;
    C 92:
      e=-e;
      d=-d;
    C'/':
      c=d;
      d=-e;
      e=-c;
    }
}
main(){
  while((c=getchar())>0)
    c==10?i=0,j++:
      (c==120?x=i,y=j:i,m[i++][j]=c);
  puts(s(1,0,Z)|s(0,1,Z)|s(-1,0,Z)|s(0,-1,Z)?"true":"false");
}

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

ฉันหวังว่าจะมีคนแสดงให้เห็นถึงวิธีที่ละเอียดอ่อนกว่านี้ในการทำงานให้สำเร็จ ไม่มีอะไรผิดปกติกับสิ่งนี้ แต่มันไม่ได้เป็นเวทย์มนตร์ลึก


ไม่จำเป็นต้องใช้=0บน globals เนื่องจากมันถูกกำหนดค่าเริ่มต้นเป็น 0 โดยค่าเริ่มต้น แทนที่ค่าคงที่ของอักขระด้วยค่าเทียบเท่าเป็นทศนิยม ใช้>0แทน!=EOFการตรวจสอบกับ EOF (และ\0) คุณอาจจะสามารถ#defineออกไปบางส่วนของรหัสในcaseเหมือนที่ผมทำกับif's ไม่จำเป็นต้องเสริม\nในputsขณะที่putsต้องพิมพ์ขึ้นบรรทัดใหม่อยู่แล้ว จะสั้นกว่าfor(;;) while(1)หวังว่านี่จะช่วยได้ =]
แปลกหน้า

@strager: ขอบคุณ ฉันมักจะมาในเหล่านี้ซ้ำเพราะผมไม่คิดว่าวิธีการที่ ...
dmckee --- อดีตผู้ดูแลลูกแมว

2
"There is no input validation"- ไม่ควรมีสิ่งใด เพื่อให้ง่ายต่อนักกอล์ฟข้อมูลจะถือว่าเป็น 'สะอาด' เสมอเว้นแต่จะระบุไว้เป็นอย่างอื่น
LiraNuna

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

เว้นแต่ฉันนับผิดโปรแกรมคือ 390 ตัวอักษรไม่ได้ 380
strager


5

PostScript 359 ไบต์

ความพยายามครั้งแรกห้องมากมายสำหรับการปรับปรุง ...

/a[{(%stdin)(r)file 99 string readline not{exit}if}loop]def a{{[(^)(>)(<)(v)]{2
copy search{stop}if pop pop}forall}forall}stopped/r count 7 sub def pop
length/c exch def[(>)0(^)1(<)2(v)3>>exch get/d exch def{/r r[0 -1 0 1]d get
add def/c c[1 0 -1 0]d get add def[32 0 47 1 92 3>>a r get c get .knownget
not{exit}if/d exch d xor def}loop a r get c get 120 eq =

4

Haskell, 395 391 383 361 339 ตัวอักษร (ปรับให้เหมาะสม)

ยังคงใช้เครื่องสถานะทั่วไปมากกว่าสิ่งที่ฉลาด:

k="<>^v"
o(Just x)=x
s y(h:t)=case b of{[]->s(y+1)t;(c:_)->(c,length a,y)}where(a,b)=break(flip elem k)h
r a = f$s 0 a where f(c,x,y)=case i(a!!v!!u)"x /\\"["true",g k,g"v^><",g"^v<>"]of{Just r->r;_->"false"}where{i x y=lookup x.zip y;j=o.i c k;u=j[x-1,x+1,x,x];v=j[y,y,y-1,y+1];g t=f(j t,u,v)}
main=do{z<-getContents;putStrLn$r$lines z}

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

k="<>^v"    -- "key" for direction
o(Just x)=x -- "only" handle successful search
s y(h:t)=case b of  -- find "start" state
  []->s(y+1)t
  (c:_)->(c,length a,y)
 where (a,b)=break(flip elem k)h
r a = f$s 0 a where -- "run" the state machine (iterate with f)
 f(c,x,y)=case i(a!!v!!u)"x /\\"["true",g k,g"v^><",g"^v<>"] of
   Just r->r
   _->"false"
  where
   i x y=lookup x.zip y -- "index" with x using y as key
   j=o.i c k -- use c as index k as key; assume success
   u=j[x-1,x+1,x,x] -- new x coord
   v=j[y,y,y-1,y+1] -- new y coord
   g t=f(j t,u,v) -- recurse; use t for new direction
main=do
 z<-getContents
 putStrLn$r$lines z

3

ฉันเชื่อในการใช้รหัสซ้ำฉันจะใช้รหัสของคุณเป็น API :)

  ทำให้ Board.new.validate (อินพุต)

32 ตัวอักษร \ o / ... wohoooo


6
นั่นคือปิศาจสองเท่า!
Jeff Atwood

3
เอาชนะมัน: p Board.new.validate ป้อน 26 ตัวอักษร \ o /
Alessandra Pereyra

3

C ++: 388ตัวอักษร

#include<iostream>
#include<string>
#include<deque>
#include<cstring>
#define w v[y][x]
using namespace std;size_t y,x,*z[]={&y,&x};int main(){string p="^v<>",s;deque<string>v;
while(getline(cin,s))v.push_back(s);while(x=v[++y].find_first_of(p),!(x+1));int 
i=p.find(w),d=i%2*2-1,r=i/2;do while(*z[r]+=d,w=='/'?d=-d,0:w==' ');while(r=!r,
!strchr("#x<^v>",w));cout<<(w=='x'?"true":"false");}

( 318ไม่มีส่วนหัว)


มันทำงานอย่างไร:

ขั้นแรกให้อ่านทุกบรรทัดแล้วจึงพบเลเซอร์ ต่อไปนี้จะประเมิน0ตราบใดที่ยังไม่พบลูกศรเลเซอร์และในขณะเดียวกันก็กำหนดให้xกับตำแหน่งแนวนอน

x=v[++y].find_first_of(p),!(x+1)

iนั้นเรามาดูสิ่งที่ทิศทางที่เราพบและเก็บไว้ใน แม้แต่ค่าของiคือด้านบน / ซ้าย ("ลดลง") และค่าคี่เป็นด้านล่าง / ขวา ("เพิ่ม") ตามแนวคิดนั้นd("ทิศทาง") และr("การวางแนว") ได้ถูกตั้งค่าไว้ เราทำดัชนีอาเรย์ตัวชี้zพร้อมการวางแนวและเพิ่มทิศทางไปยังจำนวนเต็มที่เราได้รับ ทิศทางจะเปลี่ยนเฉพาะเมื่อเรากดทับในขณะที่ยังคงเหมือนเดิมเมื่อเรากดทับ แน่นอนว่าเมื่อเราชนกระจกเรามักจะเปลี่ยนทิศทาง ( r = !r)


คุณกำลังทำให้ฉันทำโซลูชัน C ++ ของฉันเอง =]
แปลกหน้า

2
@ ผู้สร้างมันน่าเบื่อ ลองทำทางออกที่แสดง "จริง" หรือ "เท็จ" ณ เวลารวบรวม xD
Johannes Schaub - litb

เพิ่มคำอธิบายตั้งแต่ฉันคิดว่าฉันจะเก็บไว้ที่นี้ :)
โยฮันเน Schaub - litb

2

ตัวอักษร Groovy @ 279

m=/[<>^v]/
i={'><v^'.indexOf(it)}
n=['<':{y--},'>':{y++},'^':{x--},'v':{x++}]
a=['x':{1},'\\':{'v^><'[i(d)]},'/':{'^v<>'[i(d)]},'#':{},' ':{d}]
b=[]
System.in.eachLine {b<<it.inject([]) {r,c->if(c==~m){x=b.size;y=r.size;d=c};r<<c}}
while(d==~m){n[d]();d=a[b[x][y]]()}
println !!d

2

ค#

1,020 ตัวอักษร
1,088 ตัวอักษร (เพิ่มข้อมูลจากคอนโซล)
925 ตัวอักษร (ตัวแปร refactored ตัวแปร)
875 ตัวอักษร (ลบ initializer พจนานุกรมซ้ำซ้อน; เปลี่ยนเป็น Binary & โอเปอเรเตอร์)

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

หมายเหตุคลาสที่อ่านได้จะมีวิธีเพิ่มเติมที่จะพิมพ์สนามกีฬาปัจจุบันขณะที่เลเซอร์เคลื่อนที่ไปรอบ ๆ

class L{static void Main(){
A=new Dictionary<Point,string>();
var l=Console.ReadLine();int y=0;
while(l!=""){var a=l.ToCharArray();
for(int x=0;x<a.Count();x++)
A.Add(new Point(x,y),l[x].ToString());
y++;l=Console.ReadLine();}new L();}
static Dictionary<Point,string>A;Point P,O,N,S,W,E;
public L(){N=S=W=E=new Point(0,-1);S.Offset(0,2);
W.Offset(-1,1);E.Offset(1,1);D();
Console.WriteLine(F());}bool F(){
var l=A[P];int m=O.X,n=O.Y,o=P.X,p=P.Y;
bool x=o==m,y=p==n,a=x&p<n,b=x&p>n,c=y&o>m,d=y&o<m;
if(l=="\\"){if(a)T(W);if(b)T(E);if(c)T(S);
if(d)T(N);if(F())return true;}
if(l=="/"){if(a)T(E);if(b)T(W);if(c)T(N);
if(d)T(S);if(F())return true;}return l=="x";}
void T(Point p){O=P;do P.Offset(p);
while(!("\\,/,#,x".Split(',')).Contains(A[P]));}
void D(){P=A.Where(x=>("^,v,>,<".Split(',')).
Contains(x.Value)).First().Key;var c=A[P];
if(c=="^")T(N);if(c=="v")T(S);if(c=="<")T(W);
if(c==">")T(E);}}

เวอร์ชันที่อ่านได้ (ไม่ใช่เวอร์ชันสุดท้ายของกอล์ฟ แต่เป็นเนื้อหาเดียวกัน):

class Laser
{
    private Dictionary<Point, string> Arena;
    private readonly List<string> LaserChars;
    private readonly List<string> OtherChars;

    private Point Position;
    private Point OldPosition;
    private readonly Point North;
    private readonly Point South;
    private readonly Point West;
    private readonly Point East;

    public Laser( List<string> arena )
    {
        SplitArena( arena );
        LaserChars = new List<string> { "^", "v", ">", "<" };
        OtherChars = new List<string> { "\\", "/", "#", "x" };
        North = new Point( 0, -1 );
        South = new Point( 0, 1 );
        West = new Point( -1, 0 );
        East = new Point( 1, 0 );
        FindLaser();
        Console.WriteLine( FindTarget() );
    }

    private void SplitArena( List<string> arena )
    {
        Arena = new Dictionary<Point, string>();
        int y = 0;
        foreach( string str in arena )
        {
            var line = str.ToCharArray();
            for( int x = 0; x < line.Count(); x++ )
            {
                Arena.Add( new Point( x, y ), line[x].ToString() );
            }
            y++;
        }
    }

    private void DrawArena()
    {
        Console.Clear();
        var d = new Dictionary<Point, string>( Arena );

        d[Position] = "*";
        foreach( KeyValuePair<Point, string> p in d )
        {
            if( p.Key.X == 0 )
                Console.WriteLine();

            Console.Write( p.Value );
        }
        System.Threading.Thread.Sleep( 400 );
    }

    private bool FindTarget()
    {
        DrawArena();

        string chr = Arena[Position];

        switch( chr )
        {
            case "\\":
                if( ( Position.X == Position.X ) && ( Position.Y < OldPosition.Y ) )
                {
                    OffSet( West );
                }
                else if( ( Position.X == Position.X ) && ( Position.Y > OldPosition.Y ) )
                {
                    OffSet( East );
                }
                else if( ( Position.Y == Position.Y ) && ( Position.X > OldPosition.X ) )
                {
                    OffSet( South );
                }
                else
                {
                    OffSet( North );
                }
                if( FindTarget() )
                {
                    return true;
                }
                break;
            case "/":
                if( ( Position.X == Position.X ) && ( Position.Y < OldPosition.Y ) )
                {
                    OffSet( East );
                }
                else if( ( Position.X == Position.X ) && ( Position.Y > OldPosition.Y ) )
                {
                    OffSet( West );
                }
                else if( ( Position.Y == Position.Y ) && ( Position.X > OldPosition.X ) )
                {
                    OffSet( North );
                }
                else
                {
                    OffSet( South );
                }
                if( FindTarget() )
                {
                    return true;
                }
                break;
            case "x":
                return true;
            case "#":
                return false;
        }
        return false;
    }

    private void OffSet( Point p )
    {
        OldPosition = Position;
        do
        {
            Position.Offset( p );
        } while( !OtherChars.Contains( Arena[Position] ) );
    }

    private void FindLaser()
    {
        Position = Arena.Where( x => LaserChars.Contains( x.Value ) ).First().Key;

        switch( Arena[Position] )
        {
            case "^":
                OffSet( North );
                break;
            case "v":
                OffSet( South );
                break;
            case "<":
                OffSet( West );
                break;
            case ">":
                OffSet( East );
                break;
        }
    }
}

2
โปรแกรมควรรับอินพุต ส่วนใหญ่มาจาก stdin
LiraNuna

0

Perl 219
รุ่น Perl ของฉันคือ392 342 ตัวอักษร (ผมต้องจัดการกับกรณีของคานตีเลเซอร์):
ปรับปรุงขอบคุณฮอบส์สำหรับการเตือนฉันtr//ก็ตอนนี้ 250 ตัวอักษร:
ปรับปรุงลบmในm//การเปลี่ยนแปลงทั้งสองwhileลูปนำ ประหยัดเล็กน้อย มีเพียงหนึ่งช่องว่างที่จำเป็น
( L:it;goto Lความยาวเท่ากับdo{it;redo}):

@b=map{($y,$x,$s)=($a,$-[0],$&)if/[<>^v]/;$a++;[split//]}<>;L:$_=$s;$x++if/>/;
$x--if/</;$y++if/v/;$y--if/\^/;$_=$b[$y][$x];die"true\n"if/x/;die"false\n"if
/[<>^v#]/;$s=~tr/<>^v/^v<>/if/\\/;$s=~tr/<>^v/v^></if/\//;goto L

ฉันโกนหนวดบางส่วน แต่มันเพิ่งจะแข่งขันกับบางส่วนของพวกเขาแม้ว่าจะช้า
มันดูดีขึ้นเล็กน้อยเป็น:

#!/usr/bin/perl
@b = map {
    ($y, $x, $s) = ($a, $-[0], $&) if /[<>^v]/;
    $a++;
    [split//]
} <>;
L:
    $_ = $s;
    $x++ if />/;
    $x-- if /</;
    $y++ if /v/;
    $y-- if /\^/;
    $_ = $b[$y][$x];
    die "true\n"  if /x/;
    die "false\n" if /[<>^v#]/;
    $s =~ tr/<>^v/^v<>/ if /\\/;
    $s =~ tr/<>^v/v^></ if /\//;
goto L

เอาล่ะ ... จริงๆแล้วมันควรจะอธิบายตัวเองถ้าคุณเข้าใจว่า@bอาเรย์คืออาร์เรย์ของตัวละครในแต่ละบรรทัดและสามารถอ่าน regexp และtrข้อความง่ายๆได้


เคล็ดลับ: คุณสามารถย่อรหัสมิเรอร์ของคุณให้สั้นลงได้ $_=$s;tr/^v<>/<>^v/และ$_=$s;tr/v^<>/<>^v/ตามลำดับ นอกจากนี้คุณไม่จำเป็นต้องใช้ในm m//
hobbs

ขออภัยทำให้คนที่สอง$_=$s;tr/v^></<>^v/;
hobbs

คุณยังมีอีกหลายตัวif m/.../ที่สามารถif/.../บันทึกป๊อปอัพได้สองตัว
hobbs

คุณสามารถใช้y///แทนtr///การบันทึกอักขระสองตัว
ทองคำขาว Azure

0

F # - 454 (หรือราว ๆ นั้น)

มาช้าไปหน่อย แต่ไม่สามารถต้านทานการโพสต์ความพยายาม 2d ของฉัน

อัปเดตการแก้ไขเล็กน้อย ตอนนี้หยุดอย่างถูกต้องหากถูกส่งสัญญาณ ความคิดของตรึง Pin Brian สำหรับ IndexOfAny (ความอัปยศที่บรรทัดนั้น verbose มาก) ฉันไม่ได้จัดการเพื่อหาวิธีที่จะให้ ReadToEnd กลับมาจากคอนโซลดังนั้นฉันจึงเชื่อใจสักหน่อย ...

ฉันพอใจกับคำตอบนี้แม้ว่าจะค่อนข้างสั้น แต่ก็ยังสามารถอ่านได้ค่อนข้างดี

let s=System.Console.In.ReadToEnd()       //(Not sure how to get this to work!)
let w=s.IndexOf('\n')+1                   //width
let h=(s.Length+1)/w                      //height
//wodge into a 2d array
let a=Microsoft.FSharp.Collections.Array2D.init h (w-1)(fun y x -> s.[y*w+x])
let p=s.IndexOfAny[|'^';'<';'>';'v'|]     //get start pos
let (dx,dy)=                              //get initial direction
 match "^<>v".IndexOf(s.[p]) with
 |0->(0,-1)
 |1->(-1,0)
 |2->(1,0)
 |_->(0,1)
let mutable(x,y)=(p%w,p/w)                //translate into x,y coords
let rec f(dx,dy)=
 x<-x+dx;y<-y+dy                          //mutate coords on each call
 match a.[y,x] with
 |' '->f(dx,dy)                           //keep going same direction
 |'/'->f(-dy,-dx)                         //switch dx/dy and change sign
 |'\\'->f(dy,dx)                          //switch dx/dy and keep sign
 |'x'->"true"
 |_->"false"
System.Console.Write(f(dx,dy))

พวกเขากำลังตกแต่ง ตรวจสอบความท้าทายอื่น ๆ ของฉันมันเป็นเพียงการจัดรูปแบบ
LiraNuna

@LiraNuna ตกลงตามที่ปรากฎออกมาย้ำนี้ก็กินพวกเขาต่อไป :)
Benjol

จะเป็นการดีถ้าเปรียบเทียบกับการนำไปใช้แบบ 1 วัน เพียงแค่เพิ่ม / ลบ 1 สำหรับซ้ายและขวาและเพิ่ม / ลบ w สำหรับการขึ้นและลง ฉันคาดหวังว่าคุณจะประหยัดได้ไม่กี่ตัวอักษร
John La Rooy

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