পার্ল, 147 বাইট (প্রতিযোগিতামূলক নয়, প্রতি চালের চেয়ে 10 সেকেন্ডের বেশি সময় নেয়)
জন্য +4 অন্তর্ভুক্ত -0p
প্রোগ্রামটি বাজায় X
। এটি একটি নিখুঁত খেলা খেলবে।
এসটিডিনে বোর্ডটি ইনপুট করুন, যেমন:
tictaclatin.pl
-X-O
-X--
X-X-
O--O
^D
আউটপুটটি একই বোর্ডে X
প্রতিস্থাপিত O
এবং তদ্বিপরীতগুলির সাথে একই হবে । খালি দাগগুলি এমন একটি সংখ্যার সাথে পূরণ করা হবে যাতে এক্সটি সেখানে খেললে 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
সুতরাং এক্সের কাছে তার জয়ের একটাই উপায় রয়েছে:
XOOX
OO--
O-O-
X--X
দান
OXXO
XX33
X3X3
O33O
এর জন্য পরিস্থিতি O
হতাশ remains এখনই সহজে দেখা যায় যে প্রতিটি পদক্ষেপ X
তাত্ক্ষণিকভাবে জিততে দেয়। আসুন কমপক্ষে একটানা 3 টি এর জন্য যাওয়ার চেষ্টা করুন:
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)
খালি বোর্ডে প্রয়োগ করা এটি 9506699 পজিশনের মূল্যায়ন করে যা আমার কম্পিউটারে 30 জিবি এবং 41 মিনিট সময় নেয়। ফলাফল হলো:
2222
2222
2222
2222
সুতরাং প্রতিটি শুরু করার পদক্ষেপ অঙ্কন করে। সুতরাং খেলা একটি ড্র।
চরম স্মৃতি ব্যবহার বেশিরভাগ ক্ষেত্রে পুনরাবৃত্তি ব্যবহারের কারণে ঘটে do$0
। প্লেইন ফাংশনটি ব্যবহার করে এই 154 বাইট সংস্করণটি ব্যবহার করতে 3 জিবি এবং 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 মিনিট এবং 800 এম শূন্য বোর্ডের জন্য) বাড়ে:
#!/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
হারের জন্য। এটির আউটপুটটি আরও বিভ্রান্তিকর। এটি রঙের অদলবদল ছাড়াই জয়ের ক্ষেত্রে এক্সের জন্য বিজয়ী পদক্ষেপে পূরণ করে, তবে যদি ইনপুট গেমটি ইতিমধ্যে জিতে থাকে তবে এটি রঙের অদলবদল করে এবং কোনও পদক্ষেপ পূরণ করে না।
বোর্ডের ভরাট হওয়ার সাথে সাথে সমস্ত সংস্করণ অবশ্যই দ্রুততর হয় এবং কম মেমরি ব্যবহার করে। দ্রুত সংস্করণগুলি 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;
}