লোকেরা দুঃখিত, এবার কোনও হেক্সাগনি নেই ...
বাইট গণনাটি আইএসও 8859-1 এনকোডিং ধরেছে।
.+¶
$.'$*_¶$&
^_¶
¶
((^_|\2_)*)_\1{5}_+
$2_
^_*
$.&$*×_$&$&$.&$*×
M!&m`(?<=(?=×*(_)+)\A.*)(?<-1>.)+(?(1)!)|^.*$
O$`(_)|.(?=.*$)
$1
G-2`
T`d`À-É
m`\A(\D*)(?(_)\D*¶.|(.)\D*¶\2)((.)(?<=(?<4>_)\D+)?((?<=(?<1>\1.)\4\D*)|(?<=(?<1>\D*)\4(?<=\1)\D*)|(?<=\1(.(.)*¶\D*))((?<=(?<1>\D*)\4(?>(?<-7>.)*)¶.*\6)|(?<=(?<1>\D*)(?=\4)(?>(?<-7>.)+)¶.*\6))|(?<=(×)*¶.*)((?<=(?<1>\1.(?>(?<-9>¶.*)*))^\4\D*)|(?<=(?<1>\D*)\4(?>(?<-9>¶.*)*)(?<=\1)^\D*)|(?<=(?<1>\1\b.*(?(9)!)(?<-9>¶.*)*)\4×*¶\D*)|(?<=(?<1>\D*\b)\4.*(?(9)!)(?<-9>¶.*)*(?<=\1.)\b\D*))|(?<=(?<1>\1.(?>(?<-11>.)*)¶.*)\4(.)*¶\D*)|(?<=(?<1>\1(?>(?<-12>.)*)¶.*)\4(.)*¶\D*)|(?<=(?<1>\1.(?>(?<-13>.)*¶\D*))\4(\w)*\W+.+)|(?<=(?<1>.*)\4(?>(?<-14>.)*¶\D*)(?<=\1.)(\w)*\W+.+))(?<=\1(\D*).+)(?<!\1\15.*(?<-1>.)+))*\Z
প্রথম লাইনে লক্ষ্য স্ট্রিং এবং ইনপুটটির দ্বিতীয় লাইনে ষড়ভুজ আশা করে। মুদ্রণ 0
বা 1
তদনুসারে।
এটি অনলাইন চেষ্টা করুন! (প্রথম লাইন একটি টেস্ট স্যুট সক্ষম করে, যেখানে প্রতিটি লাইন একটি টেস্ট কেস থাকে, ¦
লাইনফিডের পরিবর্তে পৃথকীকরণের জন্য ব্যবহার করে ))
এই চ্যালেঞ্জটি সমাধানের যথাযথ উপায়টি অবশ্যই একটি রেগেক্সের সাথে। ;) এবং যদি এই সত্য না হয় যে এই চ্যালেঞ্জটি হেক্সাগনটির উদ্ঘাটিত পদ্ধতিও জড়িত , এই উত্তরটিতে আসলে একটি একক ~ 600-বাইট দীর্ঘ রেজেক্স ছাড়া কিছুই থাকবে না nothing
এটি এখনও পুরোপুরি গল্ফ হয়নি, তবে ফলাফলটি নিয়ে আমি বেশ খুশি (আমার প্রথম কার্যকরী সংস্করণ, নামকরণ করা গোষ্ঠীগুলি এবং স্যানিটির জন্য প্রয়োজনীয় অন্যান্য জিনিসগুলি সরিয়ে দেওয়ার পরে, এটি ছিল প্রায় 1000 বাইট)। আমি মনে করি আমি স্ট্রিং এবং হেক্সাগনের ক্রমটি অদলবদল করে প্রায় 10 বাইট সঞ্চয় করতে পেরেছিলাম তবে এটির শেষে পুরোটা পুনরায় লেখার প্রয়োজন হবে, যা আমি এখনই অনুভব করছি না। G
মঞ্চ বাদ দিয়ে একটি 2-বাইট সাশ্রয়ও রয়েছে , তবে এটি সমাধানটি যথেষ্ট গতি কমিয়ে দেয়, তাই আমি যতক্ষণ না নিশ্চিত হয়েছি যে আমি এটি গল্ফ করেছি ততক্ষণ আমি এই পরিবর্তনটি নিয়ে অপেক্ষা করব।
ব্যাখ্যা
এই সমাধানের মূল অংশটি ভারসাম্যপূর্ণ গোষ্ঠীগুলির ব্যাপক ব্যবহার করে , তাই আমি তাদের পড়ার পরামর্শ দিই, যদি আপনি বুঝতে চান যে এটি কীভাবে বিশদভাবে কাজ করে (যদি আপনি না করেন তবে আমি আপনাকে দোষ দেব না) ...
সমাধানের প্রথম অংশটি (যেমন শেষ দুটি লাইন ব্যতীত সমস্ত কিছুই) হেক্সাগনি উত্স কোডটি ফোল্ড করাতে আমার উত্তরটির একটি পরিবর্তিত সংস্করণ । লক্ষ্যবস্তুটি এঁটে দেওয়া ছাড়াকালীন এটি ষড়ভুজটি তৈরি করে (এবং এটি আসলে লক্ষ্যযুক্ত স্ট্রিংয়ের আগে ষড়ভুজটি তৈরি করে)। বাইটস সংরক্ষণ করতে আমি আগের কোডটিতে কিছু পরিবর্তন করেছি:
- পটভূমি চরিত্রটি
×
কোনও জায়গার পরিবর্তে যাতে ইনপুটটিতে সম্ভাব্য স্থানগুলির সাথে বিরোধ না করে।
_
পরিবর্তে কোনও অপ / ওয়াইল্ডকার্ড অক্ষর .
, যাতে গ্রিড ঘরগুলি নির্ভরযোগ্যভাবে শব্দের অক্ষর হিসাবে চিহ্নিত করা যায়।
- ষড়ভুজটি প্রথম নির্মিত হওয়ার পরে আমি কোনও স্পেস বা ইন্ডেন্টেশন প্রবেশ করিনা। এটি আমাকে একটি তির্যক ষড়ভুজ দেয়, তবে এটি আসলে কাজ করা আরও অনেক সুবিধাজনক এবং সংলগ্ন নিয়মগুলি মোটামুটি সহজ।
এখানে একটি উদাহরণ। নিম্নলিখিত পরীক্ষার ক্ষেত্রে:
ja
abcdefghij
আমরা পেতে:
××abc
×defg
hij__
____×
___××
ja
ষড়ভুজটির স্বাভাবিক বিন্যাসের সাথে এটির তুলনা করুন:
a b c
d e f g
h i j _ _
_ _ _ _
_ _ _
আমরা দেখতে পাচ্ছি যে প্রতিবেশীরা এখন উত্তর-পশ্চিম এবং দক্ষিণ-পূর্ব প্রতিবেশী ব্যতীত সাধারণ 8 মুর-প্রতিবেশীদের সবাই। সুতরাং আমাদের অনুভূমিক, উল্লম্ব এবং দক্ষিণ-পশ্চিম / উত্তর-পূর্ব সংলগ্নতা (ভাল এবং তারপরে মোড়ানোর প্রান্তগুলি রয়েছে) পরীক্ষা করতে হবে। এই আরও কমপ্যাক্ট লেআউটটি ব্যবহার করার সাথে সাথে বোনাসও রয়েছে যা আমরা ××
যখন প্রয়োজন তখন উড়তে ষড়ভুজ আকারের নির্ধারণ করতে শেষগুলি ব্যবহার করতে সক্ষম হব ।
এই ফর্মটি তৈরি হওয়ার পরে, আমরা পুরো স্ট্রিংয়ে আরও একটি পরিবর্তন করব:
T`d`À-É
এটি বর্ধিত ASCII অক্ষরের সাথে অঙ্কগুলি প্রতিস্থাপন করে
ÀÁÂÃÄÅÆÇÈÉ
যেহেতু তারা ষড়ভুজ এবং লক্ষ্য স্ট্রিংয়ে উভয় প্রতিস্থাপন করা হয়েছে এটি স্ট্রিংটি মিলছে কিনা তা প্রভাব ফেলবে না। এছাড়াও, যেহেতু তারা অক্ষর \w
এবং \b
এখনও তাদের ষড়ভুজ কোষ হিসাবে সনাক্ত করে। এই প্রতিস্থাপনটি করার সুবিধাটি হ'ল আমরা এখন \D
আসন্ন রেজেক্সে যে কোনও চরিত্রের (বিশেষত, লাইনফিডগুলি পাশাপাশি নন-লাইনফিড অক্ষরগুলি) মেলে ব্যবহার করতে পারি । আমরা এটিটি s
সম্পাদন করতে বিকল্পটি ব্যবহার করতে পারি না , কারণ আমাদের .
বেশ কয়েকটি জায়গায় নন-লাইনফিড অক্ষরগুলির সাথে মিল রাখতে হবে ।
এখন শেষ বিট: কোনও পাথ আমাদের প্রদত্ত স্ট্রিংয়ের সাথে মেলে কিনা তা নির্ধারণ করে। এটি একটি একক রাক্ষসী রেজেক্সের সাহায্যে করা হয়। আপনি নিজেকে জিজ্ঞাসা করতে পারেন কেন কেন?!?! ঠিক আছে, এটি মূলত ব্যাকট্র্যাকিংয়ের সমস্যা: আপনি কোথাও শুরু করেন এবং স্ট্রিংয়ের সাথে মেলে ততক্ষণ কোনও পথ চেষ্টা করেন এবং একবার এটি ব্যাকট্র্যাক না করে শেষ চরিত্রের থেকে আলাদা প্রতিবেশীর চেষ্টা করে যা কাজ করে। এক জিনিসরেগেক্সের সাথে কাজ করার সময় আপনি বিনা পয়সায় ব্যাকট্র্যাকিং করছেন। আক্ষরিকভাবেই কেবলমাত্র রেজেক্স ইঞ্জিনটি করে। সুতরাং যদি আমরা কেবলমাত্র একটি বৈধ পথ (যা এই ধরণের সমস্যার পক্ষে যথেষ্ট জটিল, তবে ভারসাম্যপূর্ণ দলগুলির মধ্যে অবশ্যই সম্ভব) বর্ণনা করার একটি উপায় খুঁজে পাই, তবে রেইজেক্স ইঞ্জিনটি আমাদের জন্য সম্ভাব্য সকলের মধ্যে সেই পথটি সন্ধান করবে। একাধিক পর্যায় ( এবং আমি অতীতেও এটি করেছি ) দিয়ে ম্যানুয়ালি অনুসন্ধানটি কার্যকর করা সম্ভব হবে , তবে আমি সন্দেহ করি যে এই বিশেষ ক্ষেত্রে এটি আরও কম হবে be
একটি রেজেক্সের সাথে এটি বাস্তবায়নের একটি সমস্যা হ'ল ব্যাকট্র্যাকিংয়ের সময় আমরা ইচ্ছামত রেজেক্স ইঞ্জিনের কার্সারটিকে পিছনে পিছনে বুনতে পারি না (যা আমাদের প্রয়োজন যেহেতু পথটি উপরে বা নীচে যেতে পারে)। সুতরাং পরিবর্তে, আমরা একটি ক্যাপচারিং গ্রুপে আমাদের নিজস্ব "কার্সার" ট্র্যাক করি এবং আপডেট করি প্রতিটি পদক্ষেপে (আমরা অস্থায়ীভাবে একটি বর্ণনীর সাহায্যে কার্সারের অবস্থানে যেতে পারি)। এটি আমাদের পূর্ববর্তী সমস্ত অবস্থানগুলি সঞ্চয় করতে সক্ষম করে যা আমরা ইতিমধ্যে বর্তমান অবস্থানটি পরিদর্শন করি নি তা পরীক্ষা করে ব্যবহার করব।
সুতরাং আসুন এটি পেতে। এখানে নামী গোষ্ঠীগুলি, ইনডেন্টেশন, প্রতিবেশীদের কম এলোমেলো ক্রম এবং কিছু মন্তব্য সহ রেজেক্সের একটি সামান্য স্যানার সংস্করণ এখানে রয়েছে:
\A
# Store initial cursor position in <pos>
(?<pos>\D*)
(?(_)
# If we start on a wildcard, just skip to the first character of the target.
\D*¶.
|
# Otherwise, make sure that the target starts with this character.
(?<first>.)\D*¶\k<first>
)
(?:
# Match 0 or more subsequent characters by moving the cursor along the path.
# First, we store the character to be matched in <next>.
(?<next>.)
# Now we optionally push an underscore on top (if one exists in the string).
# Depending on whether this done or not (both of which are attempted by
# the engine's backtracking), either the exact character, or an underscore
# will respond to the match. So when we now use the backreference \k<next>
# further down, it will automatically handle wildcards correctly.
(?<=(?<next>_)\D+)?
# This alternation now simply covers all 6 possible neighbours as well as
# all 6 possible wrapped edges.
# Each option needs to go into a separate lookbehind, because otherwise
# the engine would not backtrack through all possible neighbours once it
# has found a valid one (lookarounds are atomic).
# In any case, if the new character is found in the given direction, <pos>
# will have been updated with the new cursor position.
(?:
# Try moving east.
(?<=(?<pos>\k<pos>.)\k<next>\D*)
|
# Try moving west.
(?<=(?<pos>\D*)\k<next>(?<=\k<pos>)\D*)
|
# Store the horizontal position of the cursor in <x> and remember where
# it is (because we'll need this for the next two options).
(?<=\k<pos>(?<skip>.(?<x>.)*¶\D*))
(?:
# Try moving north.
(?<=(?<pos>\D*)\k<next>(?>(?<-x>.)*)¶.*\k<skip>)
|
# Try moving north-east.
(?<=(?<pos>\D*)(?=\k<next>)(?>(?<-x>.)+)¶.*\k<skip>)
)
|
# Try moving south.
(?<=(?<pos>\k<pos>.(?>(?<-x>.)*)¶.*)\k<next>(?<x>.)*¶\D*)
|
# Try moving south-east.
(?<=(?<pos>\k<pos>(?>(?<-x>.)*)¶.*)\k<next>(?<x>.)*¶\D*)
|
# Store the number of '×' at the end in <w>, which is one less than the
# the side-length of the hexagon. This happens to be the number of lines
# we need to skip when wrapping around certain edges.
(?<=(?<w>×)*¶.*)
(?:
# Try wrapping around the east edge.
(?<=(?<pos>\k<pos>.(?>(?<-w>¶.*)*))^\k<next>\D*)
|
# Try wrapping around the west edge.
(?<=(?<pos>\D*)\k<next>(?>(?<-w>¶.*)*)(?<=\k<pos>)^\D*)
|
# Try wrapping around the south-east edge.
(?<=(?<pos>\k<pos>\b.*(?(w)!)(?<-w>¶.*)*)\k<next>×*¶\D*)
|
# Try wrapping around the north-west edge.
(?<=(?<pos>\D*\b)\k<next>.*(?(w)!)(?<-w>¶.*)*(?<=\k<pos>.)\b\D*)
)
|
# Try wrapping around the south edge.
(?<=(?<pos>\k<pos>.(?>(?<-x>.)*¶\D*))\k<next>(?<x>\w)*\W+.+)
|
# Try wrapping around the north edge.
(?<=(?<pos>.*)\k<next>(?>(?<-x>.)*¶\D*)(?<=\k<pos>.)(?<x>\w)*\W+.+)
)
# Copy the current cursor position into <current>.
(?<=\k<pos>(?<current>\D*).+)
# Make sure that no matter how many strings we pop from our stack of previous
# cursor positions, none are equal to the current one (to ensure that we use
# each cell at most once).
(?<!\k<pos>\k<current>.*(?<-pos>.)+)
)*
# Finally make sure that we've reached the end of the string, so that we've
# successfully matched all characters in the target string.
\Z
আমি আশা করি যে এ থেকে সাধারণ ধারণাটি মোটামুটি পরিষ্কার। সেই পথগুলির মধ্যে যে কোনও একটি চলাচল কীভাবে কাজ করে তার উদাহরণ হিসাবে, আসুন সেই বিটটি দেখি যা কার্সারকে দক্ষিণে নিয়ে যায়:
(?<=(?<pos>\k<pos>.(?>(?<-x>.)*)¶.*)\k<next>(?<x>.)*¶\D*)
মনে রাখবেন যে লুকবাইন্ডগুলি ডান থেকে বামে (বা নীচে থেকে উপরে) পড়তে হবে, কারণ এটি সেই ক্রম যা তাদের সম্পাদন করা হয়:
(?<=
(?<pos>
\k<pos> # Check that this is the old cursor position.
. # Match the character directly on top of the new one.
(?>(?<-x>.)*) # Match the same amount of characters as before.
¶.* # Skip to the next line (the line, the old cursor is on).
) # We will store everything left of here as the new
# cursor position.
\k<next> # ...up to a match of our current target character.
(?<x>.)* # Count how many characters there are...
¶\D* # Skip to the end of some line (this will be the line below
# the current cursor, which the regex engine's backtracking
# will determine for us).
)
মনে রাখবেন যে এটি \k<pos>
আসলে স্ট্রিংয়ের শুরুতে পৌঁছেছে তা নিশ্চিত করার জন্য সামনে অ্যাঙ্কর স্থাপন করা প্রয়োজন নয় । <pos>
সর্বদা ×
যে পরিমাণ থেকে শুরু হয় অন্য কোথাও খুঁজে পাওয়া যায় না, সুতরাং এটি ইতিমধ্যে অন্তর্নিহিত অ্যাঙ্কর হিসাবে কাজ করে।
আমি এই পোস্টটি প্রয়োজনের চেয়ে বেশি ফুলে উঠতে চাই না, তাই আমি অন্য 11 টি মামলায় বিস্তারিতভাবে যাব না, তবে নীতিগতভাবে তারা সবাই একইভাবে কাজ করে। আমরা যাচাই করেছি যে <next>
ভারসাম্যপূর্ণ গোষ্ঠীর সাহায্যে পুরানো কার্সার অবস্থান থেকে কিছু নির্দিষ্ট (গ্রহণযোগ্য) দিক খুঁজে পাওয়া যায় এবং তারপরে আমরা সেই ম্যাচের স্ট্রিংটিকে নতুন কার্সারের অবস্থান হিসাবে সংরক্ষণ করি <pos>
।