Perl, 147 바이트 (비경쟁, 이동 당 10 초 이상 소요)
에 +4 포함 -0p
프로그램이 재생 X
됩니다. 완벽한 게임을 할 것입니다.
STDIN에 보드를 입력하십시오. 예 :
tictaclatin.pl
-X-O
-X--
X-X-
O--O
^D
ouptut은 모두 같은 보드로 X
교체되며 O
그 반대도 마찬가지입니다. 빈 자리는 X가 그 자리에서 경기 할 경우 결과를 나타내는 숫자로 채워 지며 1
결과는 승리, 2
무승부 및 3
손실입니다. 완성 된 게임은 색상이 반전 된 동일한 위치를 반환합니다.
이 예제에서 출력은 다음과 같습니다.
1O1X
1O33
O3O3
X33X
따라서 X
그가 위와 왼쪽을 따라 3 개의 지점에서 뛰면 위치는 승리입니다 . 다른 모든 움직임은 패배합니다.
이 혼란스러운 결과는 실제로 이동 후 게임이 어떻게 진행되는지 알고 싶다면 실제로 편리합니다. 프로그램이 항상 연극 때문에 X
당신은 교체해야 X
하고 O
의 움직임을보고 O
. 예를 들어 X
왼쪽 상단에서 플레이 하면 이기는 것이 분명 하지만 X
상단을 따라 세 번째 포지션에서 플레이 하는 경우 는 어떻습니까? 출력을 복사하고 O
선택한 이동 위치에 넣고 다른 모든 숫자를 -
다시 바꿉니다.
-OOX
-O--
O-O-
X--X
를 야기하는:
3XXO
3X33
X3X3
O33O
분명히 모든 움직임 O
은 잃어야한다. 그래서 그가 왼쪽 상단에서 뛰면 어떻게 지는가? 다시 O
왼쪽 상단 에 넣고 숫자를 -
다음 과 같이 바꾸십시오 .
OXXO
-X--
X-X-
O--O
기부:
XOOX
1O33
O3O3
X33X
따라서 X는 자신의 승리를 위해 갈 수있는 유일한 방법이 있습니다 :
XOOX
OO--
O-O-
X--X
기부
OXXO
XX33
X3X3
O33O
상황 O
은 절망적이다. 모든 움직임 X
이 즉시 이길 수 있음 을 쉽게 알 수 있습니다 . 최소한 3 O를 연속해서 시도해 봅시다.
OXXO
XX--
X-X-
O-OO
기부:
XOOX
OO13
O3O3
X3XX
X
유일하게이기는 움직임을합니다 (이것은 XXXO
세 번째 열 을 따라 한다는 점에 유의하십시오 :
XOOX
OOO-
O-O-
X-XX
출력은 다음과 같습니다.
OXXO
XXX-
X-X-
O-OO
게임이 이미 완료 되었기 때문입니다. 당신은 세 번째 열에서 승리를 볼 수 있습니다.
실제 프로그램 tictaclatin.pl
:
#!/usr/bin/perl -0p
y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)
빈 보드에 적용하면 내 컴퓨터에서 30Gb 및 41 분이 걸리는 9506699 위치를 평가합니다. 결과는 다음과 같습니다.
2222
2222
2222
2222
따라서 모든 시작 움직임이 그립니다. 따라서 게임은 무승부입니다.
극단적 인 메모리 사용량은 주로를 사용하는 재귀에 의해 발생합니다 do$0
. 일반 기능을 사용하여이 154 바이트 버전을 사용하려면 3Gb 및 11 분이 필요합니다.
#!/usr/bin/perl -0p
sub f{y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+&f%eeg&&(/1/||/2/-1)}f
더 견딜 만합니다 (그러나 여전히 너무 많은 것은 여전히 메모리 누수가 있어야합니다).
여러 가지 속도 향상을 결합하면이 160 바이트 버전 (빈 보드의 경우 5028168 위치, 4 분 및 800M)이됩니다.
#!/usr/bin/perl -0p
sub f{y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/osx;$@<=>0||s%-%$_="$`O$'";$a{$_}//=&f+1or return 1%eeg&&/1/-1}f
마지막 0
으로 승리 (와 혼동하지 마십시오 O
), 1
추첨 및 2
패배에 사용합니다. 이것의 결과도 더 혼란 스럽다. 컬러 스왑없이 승리 한 경우 X의 승리 움직임을 채 웁니다. 그러나 입력 게임이 이미 승리 한 경우 여전히 컬러 스왑을 수행하며 아무 움직임도 채우지 않습니다.
물론 모든 버전은 보드가 가득 차면서 더 빨라지고 더 적은 메모리를 사용합니다. 더 빠른 버전은 2 ~ 3 번 이동하자마자 10 초 이내에 이동을 생성해야합니다.
원칙적으로이 146 바이트 버전도 작동해야합니다.
#!/usr/bin/perl -0p
y/XO/OX/,$@=-$@while/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^/sx,--$|;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)
그러나 내 컴퓨터에서는 펄 버그를 유발하고 코어를 덤프합니다.
6 바이트 위치 캐싱 $$_||=
이 제거되었지만 시간과 메모리가 너무 많이 사용되어 거의 채워진 보드에서만 작동하는 경우 모든 버전은 원칙적으로 여전히 작동합니다 . 그러나 이론적으로는 140 바이트 솔루션이 있습니다.
당신은 넣으면 $\=
바로 전에 (3 바이트 비용) $@<=>0
: 각 출력 보드 전체 보드의 상태에 따라야 할 것입니다 1
에 대한 X
승리, 0
무승부와 -1
손실.
위에서 언급 한 가장 빠른 버전을 기반으로하는 대화식 드라이버는 다음과 같습니다. 드라이버는 게임이 끝나는 시점에 대한 논리가 없으므로 스스로를 중단해야합니다. 골프 코드는 알고 있습니다. 제안 된 움직임 -
이 다른 것으로 대체 되지 않고 돌아 오면 게임이 끝난 것입니다.
#!/usr/bin/perl
sub f{
if ($p++ % 100000 == 0) {
local $| = 1;
print ".";
}
y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/osx;$@<=>0||s%-%$_="$`O$'";$a{$_}//=&f+1or return 1%eeg&&/1/-1}
# Driver
my $tomove = "X";
my $move = 0;
@board = ("----\n") x 4;
while (1) {
print "Current board after move $move ($tomove to move):\n ABCD\n";
for my $i (1..4) {
print "$i $board[$i-1]";
}
print "Enter a move like B4, PASS (not a valid move, just for setup) or just press enter to let the program make suggestions\n";
my $input = <> // exit;
if ($input eq "\n") {
$_ = join "", @board;
tr/OX/XO/ if $tomove eq "O";
$p = 0;
$@="";
%a = ();
my $start = time();
my $result = f;
if ($result == 1) {
tr/OX/XO/ if $tomove eq "O";
tr/012/-/;
} else {
tr/OX/XO/ if $tomove eq "X";
tr/012/123/;
}
$result = -$result if $tomove eq "O";
my $period = time() - $start;
print "\nSuggested moves (evaluated $p positions in $period seconds, predicted result for X: $result):\n$_";
redo;
} elsif ($input =~ /^pass$/i) {
# Do nothing
} elsif (my ($x, $y) = $input =~ /^([A-D])([1-4])$/) {
$x = ord($x) - ord("A");
--$y;
my $ch = substr($board[$y],$x, 1);
if ($ch ne "-") {
print "Position already has $ch. Try again\n";
redo;
}
substr($board[$y],$x, 1) = $tomove;
} else {
print "Cannot parse move. Try again\n";
redo;
}
$tomove =~ tr/OX/XO/;
++$move;
}