পার্ল, 137 টি অক্ষর
($x,$y)=<>;while($x=~s/.. *//s){$e=hex$&;$i=0;$s=$r[$i]+=$e*hex,$r[$i]&=255,$r[++$i]+=$s>>8 for$y=~/.. */gs;$y="00$y"}printf'%02x 'x@r,@r
আদেশ সহকারে
- কখনও কখনও
00
ফলাফলের শেষে একটি অতিরিক্ত বাইট প্রিন্ট করে। অবশ্যই ফলাফলটি অতিরিক্ত সেই অতিরিক্ত বাইট দিয়েও সঠিক।
- ফলাফলের শেষ হেক্স বাইটের পরে একটি অতিরিক্ত স্থান মুদ্রণ করে।
ব্যাখ্যা
ব্যাখ্যাটি কিছুটা দীর্ঘ হতে চলেছে, তবে আমি মনে করি এখানকার বেশিরভাগ মানুষ এটি আকর্ষণীয় বলে মনে করবে।
প্রথমত, যখন আমি 10 বছর বয়সী ছিলাম, আমাকে নীচের ছোট্ট কৌশলটি শেখানো হয়েছিল। আপনি এটি দিয়ে যে কোনও দুটি ধনাত্মক সংখ্যাকে গুণ করতে পারেন। আমি 13 × 47 উদাহরণ আপনিই প্রথম সংখ্যা, 13 লেখা, এবং শুরু ব্যবহার করে এই বর্ণনা করবে বিভাজক 2 দ্বারা এটি (প্রতিটি সময় নিচে রাউন্ড) যতক্ষণ না আপনি 1 পৌঁছানোর:
13
6
3
1
এখন, 13 পরবর্তী আপনি অন্যান্য নম্বর, 47 লিখুন, এবং রাখা গুন 2 দ্বারা এটি সময়ের একই সংখ্যা:
13 47
6 94
3 188
1 376
এখন আপনি সমস্ত রেখাটি অতিক্রম করেছেন যেখানে বাম সংখ্যাটি সমান । এই ক্ষেত্রে এটি কেবল only. (আমি কোডে স্ট্রাইক-মাধ্যমে করতে পারি না, তাই আমি কেবল এটি সরিয়ে ফেলব)) অবশেষে, আপনি বাকী সমস্ত সংখ্যা ডানদিকে যুক্ত করুন:
13 47
3 188
1 376
----
611
এবং এটি সঠিক উত্তর। 13 × 47 = 611।
এখন, যেহেতু আপনি সব কম্পিউটার Geeks, আপনি বুঝতে পেরেছি করবে কি আমরা আসলে বাম এবং ডান কলামে করছেন x >> 1
এবং y << 1
যথাক্রমে। তদ্ব্যতীত, আমরা y
কেবল যোগ যদি x & 1 == 1
। এটি সরাসরি একটি অ্যালগরিদমে অনুবাদ করে, যা আমি এখানে সিউডোকোডে লিখব:
input x, y
result = 0
while x > 0:
if x & 1 == 1:
result = result + y
x = x >> 1
y = y << 1
print result
if
একটি গুণটি ব্যবহার করতে আমরা আবার লিখতে পারি এবং তারপরে আমরা সহজেই এটিকে পরিবর্তন করতে পারি যাতে এটি বিট-বাই-বিটের পরিবর্তে বাইট-বাই-বাইট ভিত্তিতে কাজ করে:
input x, y
result = 0
while x > 0:
result = result + (y * (x & 255))
x = x >> 8
y = y << 8
print result
এটি এখনও এর সাথে একটি গুণ রয়েছে y
যা নির্বিচারে আকারের, তাই আমাদের এটিকে একটি লুপেও পরিবর্তন করতে হবে to আমরা পার্লে এটি করব।
এখন পার্লকে সবকিছু অনুবাদ করুন:
$x
এবং $y
হেক্স ফর্ম্যাটের ইনপুটগুলি হ'ল তাই তাদের মধ্যে প্রথমে কমপক্ষে উল্লেখযোগ্য বাইট রয়েছে ।
সুতরাং, পরিবর্তে x >> 8
আমি না $x =~ s/.. *//s
। আমার স্পেস + স্টার লাগবে কারণ শেষ বাইটে এটির জায়গা নাও থাকতে পারে (স্পেস + ব্যবহার করতে পারে ?
)। এটি স্বয়ংক্রিয়ভাবে সরানো বাইট ( x & 255
) এ প্রবেশ করে $&
।
y << 8
সহজভাবে $y = "00$y"
।
result
আসলে একটি সংখ্যাসূচক অ্যারে @r
। শেষে, প্রতিটি উপাদানের @r
উত্তরের একটি বাইট থাকে তবে গণনার অর্ধেক অংশে এটিতে একাধিক বাইট থাকতে পারে। আমি নীচে আপনাকে প্রমাণ করব যে প্রতিটি মান কখনই দুটি বাইট (16 বিট) এর বেশি হয় না এবং ফলাফলটি সর্বদা শেষে একটি বাইট হয়।
সুতরাং এখানে পার্ল কোডটি নিচু করা হয়েছে এবং মন্তব্য করা হয়েছে:
# Input x and y
($x, $y) = <>;
# Do the equivalent of $& = x & 255, x = x >> 8
while ($x =~ s/.. *//s)
{
# Let e = x & 255
$e = hex $&;
# For every byte in y... (notice this sets $_ to each byte)
$i = 0;
for ($y =~ /.. */gs)
{
# Do the multiplication of two single-byte values.
$s = $r[$i] += $e*hex,
# Truncate the value in $r[$i] to one byte. The rest of it is still in $s
$r[$i] &= 255,
# Move to the next array item and add the carry there.
$r[++$i] += $s >> 8
}
# Do the equivalent of y = y << 8
$y = "00$y"
}
# Output the result in hex format.
printf '%02x ' x @r, @r
এখন প্রমাণের জন্য যে এটি সর্বদা বাইট আউটপুট করে এবং গণনা কখনই দুটি বাইটের চেয়ে বেশি মান উৎপন্ন করে না । আমি এটি while
লুপের মাধ্যমে অন্তর্ভুক্ত করে প্রমাণ করব :
খালি @r
(কারণ এটা সব এটা কোন মান আছে) শুরুতে পরিষ্কারভাবে এটা 0xFF চেয়ে মান বেশি। এটি বেস কেস সমাপ্ত করে।
এখন, @r
প্রতিটি while
পুনরাবৃত্তির শুরুতে কেবলমাত্র একক বাইট রয়েছে :
for
লুপ স্পষ্টভাবে &=
255 সঙ্গে ফলাফলের অ্যারের মধ্যে সব মান গুলি গত এক ছাড়া তাই আমরা শুধু তাই গত এক তাকান প্রয়োজন।
আমরা জানি যে আমরা সর্বদা থেকে কেবলমাত্র একটি বাইট অপসারণ করি $x
এবং $y
:
সুতরাং, $e*hex
দুটি একক-বাইট মানগুলির একটি গুণ, যার অর্থ এটি সীমার মধ্যে 0 — 0xFE01
।
ইন্ডাকটিভ হাইপোথিসিস দ্বারা, $r[$i]
একটি বাইট হয়; সুতরাং, $s = $r[$i] += $e*hex
পরিসীমা মধ্যে 0 — 0xFF00
।
অতএব, $s >> 8
সর্বদা একটি বাইট হয়।
$y
লুপের 00
প্রতিটি পুনরাবৃত্তিতে একটি বাড়তি বাড়ায় while
:
অতএব, while
লুপের প্রতিটি পুনরাবৃত্তিতে , অভ্যন্তরীণ for
লুপটি আগের while
পুনরাবৃত্তির চেয়ে আরও একটি পুনরাবৃত্তির জন্য চালিত হয় ।
অতএব, লুপের $r[++$i] += $s >> 8
সর্বশেষ পুনরাবৃত্তিতে for
সর্বদা যুক্ত $s >> 8
হয় 0
এবং আমরা ইতিমধ্যে $s >> 8
এটি সর্বদা একটি বাইট হিসাবে প্রতিষ্ঠিত করেছি ।
অতএব, লুপের @r
শেষে সঞ্চিত সর্বশেষ for
মানটিও একটি একক বাইট।
এটি একটি দুর্দান্ত এবং উত্তেজনাপূর্ণ চ্যালেঞ্জ শেষ করে। এটি পোস্ট করার জন্য অনেক ধন্যবাদ!