Programing

코드 골프 : 레이저

lottogame 2020. 6. 9. 07:36
반응형

코드 골프 : 레이저


도전

문자별로 가장 짧은 코드는 보드의 2D 표현을 입력하고 입력에 따라 'true'또는 'false' 를 출력 합니다.

보드는 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 ^ #
    ##########
산출:
    진실

코드 카운트에는 입 / 출력 (전체 프로그램)이 포함됩니다.


펄, 166160

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보드 i 의 열 i , 열 j$t{99*i+j} 에서 문자를 보유하는 보드의 테이블에 로드합니다 . 그때,

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

그것의 요소를 검색 %t문자에 대한 것과 일치 > ^ <하거나 v, 동시에 세트 $d레이저 빔의 초기 방향을 나타내고 0에서 3 사이의 값이.

메인 루프에서 각 반복이 시작될 $d때 빔이 현재 미러에 있는지 업데이트 합니다. 3에 의한 XOR'ing은 \미러에 대한 올바른 동작을 제공하고 1에 의한 XOR'ing 미러에 대한 올바른 동작을 제공합니다 /.

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

다음으로 현재 위치에 따라 현재 위치 $r가 업데이트됩니다.

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

$_매치 연산자를 편리하게 사용할 수 있도록 현재 위치에 문자를 할당합니다 .

/[\/\\ ]/ && redo

우리가 빈 공간이나 거울에 있다면 계속하십시오. 그렇지 않으면 true목표에 도달 하면 종료 됩니다 ( $_ =~ /x/) false.

제한 : 99 개 이상의 열이있는 문제에서는 작동하지 않을 수 있습니다. 이 제한은 3 자 이상의 비용으로 제거 할 수 있습니다.


펄, 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부작용 이 약간 줄었 습니다. 골프 코드에서 tr은 y'''백 슬래시 하나의 백 슬래시를 건너 뛸 수 있는 형식으로 작성되었습니다 .

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

목표물이나 벽에 부딪 치면 올바른 메시지로 종료하십시오.

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

레이저 앞에 빈 공간이 있으면 앞으로 이동하십시오. 레이저 앞에 거울이 있으면 앞으로 이동하여 빔을 회전하십시오. 두 경우 모두 "저장된 심볼"을 이전 빔 위치에 다시 넣고 방금 덮어 쓴 것을 저장된 심볼에 넣습니다.

redo;

종료 할 때까지 반복하십시오. {...;redo}2 자 미만 for(;;){...}및 3 자 미만 while(1){...}입니다.


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)

가능하면 위에 언급 된 매크로를 사용하여 레이저를 정의하십시오. -11대응에 바로 각각 왼쪽과 -ww상하.

        !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)

    );
}

나는 사람들이 LOOOOONG 시간 동안 이것을 기다리고있을 것입니다. (도전이 끝났고 아무도 더 이상 신경 쓰지 않습니까?)

보라 ... 나는 여기에 해결책을 제시한다.

Befunge-93!

무려 973 개의 문자를 사용합니다 (또는 공백을 무시할 정도로 자선 가능한 경우 688 입니다. 서식 지정에만 사용되며 실제 코드에서는 아무 것도 수행하지 않습니다).

주의 사항 : 나는 얼마 전에 Perl에 자신의 Befunge-93 통역사를 썼습니다. 불행히도 이것이 실제로 테스트 할 시간이 있었던 전부입니다. 나는 일반적으로 정확성에 대해 확신하지만 EOF와 관련하여 이상한 제한이있을 수 있습니다 : Perl의 <>연산자는 파일 끝에서 undef를 반환 하기 때문에 숫자 컨텍스트에서 0으로 처리됩니다. EOF가 다른 값 (-1) 인 C 기반 구현의 경우이 코드가 작동하지 않을 수 있습니다.

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 좌표를 저장하는 곳입니다. 다음 2 개의 열은 레이저 빔 소스가 발견 될 때 레이저 빔 소스의 x 및 y 좌표를 저장하기위한 것이며; 그리고 마지막 열 ( 'a'문자가있는)은 현재 빔 방향을 포함하도록 덮어 쓰여집니다. 이는 빔의 경로가 추적됨에 따라 분명히 변합니다.

프로그램은 (0,27)을 초기 커서 위치로 지정하여 시작합니다. 그런 다음 입력을 한 번에 한 문자 씩 읽고 커서 위치에 놓습니다. 개행은 실제 캐리지 리턴과 같이 y 좌표 만 증가시키고 x 좌표는 0으로 되돌아갑니다. 결국 인터프리터는 undef를 읽으며 입력의 끝을 알리고 레이저 반복 단계로 넘어 가기 위해 0 문자 값이 사용됩니다. 레이저 문자 [<> ^ v]를 읽으면 메모리 저장소 ( 'a'문자 위)에도 복사되고 좌표는 왼쪽 열에 복사됩니다.

이 모든 것의 최종 결과는 전체 파일이 기본적으로 Befunge 코드로 복사되어 실제 코드보다 약간 작은 방법으로 복사된다는 것입니다.

이후 빔 위치가 커서 위치로 다시 복사되고 다음 반복이 수행됩니다.

  • 현재 빔 방향을 확인하고 커서 좌표를 적절하게 늘리거나 줄입니다. (나는 첫 번째 움직임에서 레이저 빔의 코너 케이스를 다루지 않아도되도록 이것을 먼저 수행합니다.)
  • 해당 위치의 문자를 읽습니다.
  • 문자가 "#"이면 줄 바꿈과 "false"를 스택에 넣고 인쇄하고 끝냅니다.
  • 모든 빔 문자와 비교하십시오 [<> ^ v]; 일치하는 경우 "false \ n"도 인쇄하고 종료하십시오.
  • 문자가 공백이면 스택을 비우고 계속하십시오.
  • 캐릭터가 슬래시 인 경우 빔 방향을 스택으로 가져와 각 방향 캐릭터와 차례로 비교합니다. 하나를 찾으면 새로운 방향이 코드의 동일한 지점에 저장되고 루프가 반복됩니다.
  • 문자가 백 슬래시 인 경우 기본적으로 위와 동일한 작업을 수행하십시오 (백 슬래시에 대한 적절한 맵핑 제외).
  • 캐릭터가 'x'이면 목표물에 부딪힌 것입니다. "true \ n"을 인쇄하고 종료하십시오.
  • 해당 문자가 없으면 "error \ n"을 인쇄하고 종료하십시오.

수요가 충분하면 코드 에서이 모든 것이 달성되는 곳을 정확하게 지적하려고 노력할 것입니다.


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

Golfscript-83 자 (내와 스트 레이저의 매쉬업)

줄 바꿈은 포장을 위해 여기 있습니다.

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

골프 스크립트-107 자

개행은 명확성을 위해 거기에 있습니다

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

작동 방식

첫 번째 줄은 초기 위치와 방향을 계산합니다.
두 번째 라인은 레이저가 거울에 닿을 때마다 회전하는 단계입니다.


루비 353 자 :

314 277 자!

좋아, 루비에는 256자가 있고 이제 끝났다. 멋진 라운드 번호. :)

247 자 멈출 수 없어

223 개 203 루비 201 문자

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

약간 리팩토링 :

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

파이썬

바꿈을 포함하여 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

나는 파이썬조차도 옵션 세미콜론을 가지고 있다는 것을 잊었다.

작동 원리

이 코드의 핵심은 복잡한 숫자를 사용하여 위치와 방향을 나타내는 것입니다. 행은 가상 축이며 아래쪽으로 증가합니다. 열은 실제 축이며 오른쪽으로 증가합니다.

l='>v<^';레이저 기호 목록. 순서는 레이저 방향 문자의 인덱스가 sqrt (-1)의 거듭 제곱과 일치하도록 선택됩니다.

x={'/':'^<v>','\\':'v>^<',' ':l};빔이 다른 타일을 떠날 때 방향이 어떻게 변하는지를 결정하는 변환 테이블. 타일이 핵심이며 새로운 방향은 값입니다.

b=[1];보드를 보유합니다. while 루프가 최소한 한 번 실행되도록 첫 번째 요소는 1입니다 (true로 평가됨).

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: space는 방향 기호보다 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로 인쇄합니다.


되어 있었다 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 to Objects 코드로 대체되었습니다.

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

F #, 255 자 (그리고 여전히 읽을 수 있습니다!) :

좋아, 밤의 휴식 후, 나는 이것을 많이 개선했다.

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])

한 줄씩 살펴 보겠습니다.

먼저, 모든 입력을 큰 1 차원 배열로 처리하십시오 (2D 배열은 코드 골프에 좋지 않을 수 있습니다. 1D 배열을 사용하고 한 행의 너비를 인덱스에 더하거나 빼서 한 줄 위 / 아래로 이동하십시오).

다음으로 입력 행의 너비 'w'와 시작 위치 인 'c'를 배열로 인덱싱하여 계산합니다.

이제 현재 위치 'c'와 위쪽, 왼쪽, 오른쪽, 아래쪽에 대해 0,1,2,3 인 방향 'd'를 취하는 '다음'기능 'n'을 정의 해 봅시다.

인덱스 엡실론 'e'와 슬래시 '무엇에 대한 새로운 방향'은 테이블로 계산됩니다. 예를 들어, 현재 방향 'd'가 0 (위쪽) 인 경우 테이블의 첫 번째 요소에 "-w, 2"가 표시됩니다. 이는 인덱스를 w 씩 줄이며 슬래시를 칠 경우 새 방향은 2입니다. (권리).

이제 우리는 (1) 다음 인덱스 ( "c + e"-현재 플러스 엡실론)와 (2) 새로운 방향을 사용하여 다음 함수 'n'으로 되풀이합니다. 그 다음 세포. lookahead char가 슬래시 인 경우 새 방향은 's'입니다. 백 슬래시 인 경우 새로운 방향은 3 초입니다 (인코딩 0123을 선택하면이 효과가 나타납니다). 그것이 공간이라면, 우리는 계속 같은 방향 'd'로 진행합니다. 그리고 다른 캐릭터 'c'라면 게임이 종료되고 char가 'x'이면 'true'를 인쇄하고 그렇지 않으면 false를 인쇄합니다.

시작하기 위해 초기 위치 'c'와 시작 방향 (0123으로 방향의 초기 인코딩을 수행)과 함께 재귀 함수 'n'을 호출합니다.

나는 아마 여전히 더 많은 캐릭터를 면도 할 수 있다고 생각하지만, 이것처럼 꽤 기뻐합니다 (255는 좋은 숫자입니다).


18203 자 무게는 다음을 수행 할 수있는 Python 솔루션입니다.

  • '방'밖에서 거울에 대처
  • 2D 제한에 따라 '방'이 없을 때 궤적 계산
  • 오류보고

여전히 약간의 정리가 필요하며 2D 물리학이 빔이 스스로 교차 할 수 없다는 것을 알 수 있는지 모르겠습니다 ...

#!/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()

색상 오류보고를 보여주는 bash 스크립트 :

#!/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#
#\\^/\\ /  #
##########"

개발에 사용 된 단위 테스트 :

#!/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

루비, 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}

나는 대부분의 포스터와 같은 간단한 상태 머신을 사용했지만 아무 것도 화려하지 않았습니다. 나는 생각할 수있는 모든 트릭을 사용하여 계속 엉망이되었습니다. 방향을 변경하는 데 사용 된 비트 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). 나는 숫자가 각 방향으로 매핑되는 것을 재 배열하려고 시도했는데, 그것은 산술 버전보다 짧을 것이라는 잔소리가 있기 때문에 값을 증가시키기 위해 약간의 비트 조작을 할 수있는 배열을 찾았습니다.


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

문자의 주요 낭비는 맵의 너비와 레이저 소스의 위치를 ​​찾는 것 같습니다. 이것을 단축하는 방법에 대한 아이디어가 있습니까?


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 솔루션을 이길 수는 없습니다!


골프 스크립트 (83 자)

안녕하세요, ibble 블러!

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

파이썬-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)

소문자 true / false가 필요한 경우 마지막 행을 다음으로 변경하십시오.

print`D<5`.lower()

자바 스크립트-265 자

업데이트 IV- 승률은 마지막 업데이트 라운드이며, do-while 루프로 전환하고 이동 방정식을 다시 작성하여 두 문자를 더 절약 할 수 있습니다.

업데이트 III -Math.abs ()를 제거하고 전역 네임 스페이스에 변수를 배치하는 것과 관련하여 strager의 제안 덕분에 변수 할당의 재배 열과 함께 코드가 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>

거울의 집

도전에 대한 실제 입장은 아니지만이 개념을 기반으로 게임을 작성했습니다 (너무 오래되지 않았습니다).

Scala로 작성되었으며 오픈 소스이며 여기에서 사용할 수 있습니다 .

조금 더합니다; 색상 및 다양한 유형의 미러 및 장치를 다루지 만 버전 0.00001은이 문제가 요구하는대로 정확하게 수행했습니다. 나는 그 버전을 잃어 버렸고 어쨌든 문자 수에 최적화되지 않았습니다.


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 x 99 이하의 입력에서 올바르게 작동합니다. 헤더를 포함하지 않고 표준 라이브러리를 링크하는 컴파일러가 필요합니다. 그리고 나는 내가 끝났다고 생각한다. 스 트래 거는 그의 도움으로도 상당히 스트레치했다.

오히려 누군가가 작업을 수행하는 더 미묘한 방법을 보여주기를 바랍니다. 이것에는 아무런 문제가 없지만 깊은 마술은 아닙니다.


루비-146 문자

A=$<.read
W=A.index('
')+1
until
q=A.index(">^<v"[d=d ?d+1:0])
end
while d<4
d=[d,d^3,d^1,4,5][(' \/x'.index(A[q+=[1,-W,-1,W][d]])or 4)]
end
p 5>d

포스트 스크립트 , 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 =

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

코드 재사용을 믿고 코드 중 하나를 API로 사용합니다. :).

  Board.new.validate (입력)를 넣습니다.

32 자 \ o / ... wohoooo


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)이 바뀝니다 .


그루비 @ 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

씨#

1020 자
1088 자 (콘솔에서 추가 된 입력)
925 자 (리팩터링 된 변수)
875 자 (중복 사전 이니셜 라이저 제거, 이진 및 연산자로 변경)

게시하기 전에 다른 사람을 보지 않도록 포인트를 만들었습니다. 나는 그것이 약간 LINQ 될 수 있다고 확신합니다. 그리고 읽기 가능한 버전의 전체 FindLaser 메소드는 나에게 비린 것처럼 보입니다. 그러나 작동하고 늦었습니다 :)

읽기 가능한 클래스에는 레이저가 움직일 때 현재 Arena를 인쇄하는 추가 메소드가 포함되어 있습니다.

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

Perl 219
My perl version is 392 342 characters long (I had to handle the case of the beam hitting the laser):
Update, thanks Hobbs for reminding me of tr//, it's now 250 characters:
Update, removing the m in m//, changing the two while loops brought a few savings; there's now only one space required.
(L:it;goto L is the same length as 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

I shaved some, but it barely just competes with some of these, albeit late.
It looks a little better as:

#!/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

Well... Honestly this should be self explanatory if you understand that the @b is an array arrays of characters in each line, and can read the simple regexp and tr statements.


F# - 454 (or thereabouts)

Bit late to the game, but can't resist posting my 2d attempt.

Update modified slightly. Now stops correctly if transmitter is hit. Pinched Brian's idea for IndexOfAny (shame that line is so verbose). I haven't actually managed to work out how to get ReadToEnd to return from the Console, so I'm taking that bit on trust...

I'm pleased with this answer, as though it is quite short, it is still fairly readable.

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

참고URL : https://stackoverflow.com/questions/1480023/code-golf-lasers

반응형