x86 (আইএ -32) মেশিন কোড, 126 বাইট
Hexdump:
60 8b f9 57 33 c0 f2 ae 5e 2b fe 4f 87 fa 8d 1c
12 8b c3 48 f6 e3 c6 04 07 00 48 c6 04 07 20 75
f9 8b ea 4d 53 8d 04 2a 50 53 8b c5 f6 e3 8d 44
68 01 50 53 2b c2 8b c8 50 4b 53 55 53 03 c5 50
f7 d3 53 50 53 95 f6 e2 6b c0 04 50 43 53 51 6a
01 4a 52 6a 01 50 6a ff 51 b0 0a 6a 0b 8b dc 59
8b 6c cb fc 88 04 2f 03 2c cb 89 6c cb fc 83 f9
0a 75 01 ac e2 ea 4a 79 e0 83 c4 58 61 c3
এটি কিছুটা দীর্ঘ, তাই এটি ব্যাখ্যা করতে আমি প্রথমে সি কোডটি দেব:
void doit(const char* s, char out[])
{
int n = strlen(s);
int w = 2 * n;
int h = w - 1;
int m = n - 1;
memset(out, ' ', h * w);
out[h * w] = 0;
int offset1 = n + m;
int offset2 = w * m + 2 * m + 1; // 2 * n * n - 1
int offset3 = offset2 - n; // 2 * n * n - n - 1
int offset4 = 4 * n * m; // 4 * n * n - 4 * n
int offsets[] = {
offset3, -1,
offset4, 1,
m, 1,
offset3, 1 - w,
offset4, -w,
offset2 - 1, -w,
offset2 - 1, w - 1,
m, w - 1,
offset3, w,
offset2, w,
offset1, w,
};
do
{
char c = *s++;
for (int i = 0; i < 11; ++i)
{
if (i == 9)
c = '\n';
int offset = offsets[i * 2];
assert(offset > 0 && offset < w * h);
out[offset] = c;
offsets[i * 2] += offsets[i * 2 + 1];
}
} while (--n);
}
এখানে n
ইনপুট স্ট্রিংয়ের দৈর্ঘ্য ।
আউটপুট ক্ষেত্রের মাত্রা (উচ্চতা) 2n
দ্বারা 2n-1
( প্রস্থ )। প্রথমত, এটি শূন্যস্থান দিয়ে সমস্ত কিছু পূরণ করে (এবং একটি টার্মিনেটিং নাল বাইট যুক্ত করে)। তারপরে, এটি আউটপুট অঞ্চলে 11 টি সরল রেখা বরাবর ভ্রমণ করে এবং এগুলি পাঠ্য দিয়ে পূর্ণ করে:
- 2 টি লাইন শেষ-লাইন বাইট দ্বারা ভরাট হয় (= 10)
- 9 লাইন ইনপুট স্ট্রিংয়ের একটানা বাইট দ্বারা পূর্ণ হয়
প্রতিটি লাইন দুটি সংখ্যার দ্বারা উপস্থাপিত হয়, একটি সূচনা অফসেট এবং একটি স্ট্রাইড। offsets
অ্যাক্সেসকে "সহজ" করার জন্য আমি তাদের উভয়কে অ্যারেতে স্টাফ করেছি ।
আকর্ষণীয় অংশ অ্যারে পূরণ করা হয়। অ্যারেতে প্রবেশের ক্রমটির জন্য খুব কম গুরুত্ব রয়েছে; আমি তাদের পুনরায় সাজানোর চেষ্টা করেছি নিবন্ধের বিবাদগুলির সংখ্যা হ্রাস করতে। তদুপরি, চতুর্ভুজ সূত্র গণনার উপায় চয়ন করার ক্ষেত্রে কিছুটা স্বাধীনতা অর্জন করে; আমি বিয়োগের সংখ্যা হ্রাস করার চেষ্টা করেছি (কারণ সংযোজনগুলি নমনীয় দ্বারা প্রয়োগ করা যেতে পারেLEA
নির্দেশের )।
সমাবেশ উত্স:
pushad;
; // Calculate the length of the input string
mov edi, ecx;
push edi;
xor eax, eax;
repne scasb;
pop esi; // esi = input string
sub edi, esi;
dec edi;
; // Calculate the size of the output area
xchg edi, edx; // edx = n
// edi = output string
lea ebx, [edx + edx]; // ebx = w
mov eax, ebx;
dec eax; // eax = h
mul bl; // eax = w * h
; // Fill the output string with spaces and zero terminate it
mov byte ptr [edi + eax], 0;
myfill:
dec eax;
mov byte ptr [edi + eax], ' ';
jnz myfill;
mov ebp, edx;
dec ebp; // ebp = m
; // Fill the array of offsets
push ebx; // w
lea eax, [edx + ebp];
push eax; // offset1
push ebx; // w
mov eax, ebp;
mul bl;
lea eax, [eax + 2 * ebp + 1];
push eax; // offset2
push ebx; // w
sub eax, edx;
mov ecx, eax; // ecx = offset3
push eax; // offset3
dec ebx;
push ebx; // w - 1
push ebp; // m
push ebx; // w - 1
add eax, ebp;
push eax; // offset2 - 1
not ebx;
push ebx; // -w
push eax; // offset2 - 1
push ebx; // -w
xchg eax, ebp; // eax = m
mul dl;
imul eax, eax, 4;
push eax; // offset4
inc ebx;
push ebx; // 1 - w
push ecx; // offset3
push 1;
dec edx; // edx = n - 1
push edx;
push 1;
push eax;
push -1;
push ecx;
; // Use the array of offsets to write stuff to output
myout:
mov al, '\n';
push 11;
mov ebx, esp;
pop ecx;
myloop:
mov ebp, [ebx + ecx * 8 - 4];
mov [edi + ebp], al;
add ebp, [ebx + ecx * 8];
mov [ebx + ecx * 8 - 4], ebp;
cmp ecx, 10;
jne skip_read;
lodsb;
skip_read:
loop myloop;
dec edx;
jns myout;
add esp, 11 * 8;
popad;
ret;
আমি এখানে বাইট গুণগুলি ব্যবহার করেছি, ইনপুট স্ট্রিংয়ের দৈর্ঘ্য 127 এ সীমাবদ্ধ করে রেখেছি the এটি রেজিস্টারে ক্লোবারিং এড়ায় । পরিবর্তে edx
পণ্যটি গণনা করা ax
হয়।
একটি ছোটখাট ত্রুটি: অ্যারে পূরণ করার পরে, স্ট্রিংয়ের দৈর্ঘ্য 1 হ্রাস পায় So সুতরাং আমি লুপের প্রস্থান শর্তটি সামঞ্জস্য করেছি:
jns myout
এটি নিচে -1 এ গণনা করা হয়।