Codewars – Pick peaks – DEV Community

سلام.
من چالش های Codewars و روند فکرم را در این مجموعه پست می کنم. من در صورت امکان از JS و Node 18 استفاده می کنم. فقط برای شفافیت، من از آنها استفاده منصفانه می کنم.
استراحت کردم و الان برگشتم. با این حال، بدون ارسال راه حل در اینجا، برخی از چالش ها را انجام داد. بیایید به یک چالش آسان نزدیک شویم.
پیک پیک ها سرگرم کننده است. شما باید حداکثر محلی را طبق تعریف ریاضی آن پیدا کنید. از GFG:
از نظر ریاضی، f (a) ≥ f (a -h) و f (a) ≥ f (a + h) که در آن h > 0 باشد، سپس a حداکثر نقطه محلی نامیده می شود.
در اصل، ما باید ببینیم که کدام مقادیر از نزدیکترین همسایگانش بزرگتر هستند. اگر همسایهای گم شده است، نمیتوانیم بررسی کنیم که آیا حداکثر محلی است یا خیر. بنابراین ما مرزهای آرایه را بررسی نمی کنیم.
راه حل زیر بهینه نیست. باید یک پاس باشد. علاوه بر این، به من آموزش داده شد که از مصرف خودداری کنم break
و continue
. اما این کار را انجام می دهد.
ابتدا قوانین را تعیین می کنیم:
- اگر آرایه خالی است، آرایه های خالی را برگردانید.
[] => {pos:[], peaks:[]}
- اگر مقداری کمتر یا مساوی با مقدار قبلی باشد، بهطور خودکار کنار گذاشته میشود (پلاتوها در قانون دیگری بررسی میشوند).
(array[i] <= array[i-1]) ? discard
- اگر یک مقدار توسط قانون قبلی کنار گذاشته نشود، و از مقدار بعدی بزرگتر باشد، حداکثر است.
(array[i] > array[i+1]) ? maximum
- اگر مقداری با قاعده فوق الذکر نادیده گرفته نشود، و با مقدار بعدی برابر باشد، نیاز به رفتار خاصی دارد. این را بعداً حل خواهیم کرد.
دوم، به یک مقدار بازگشتی خاص نیاز دارد: {pos:[], peaks:[]}
این چالش موقعیت و ارزش حداکثر را می خواهد.
سوم، باید یک حلقه برای آرایه تنظیم کنیم:for (let i = 1 ; i < arr.length -1 ; i++)
ما از مقدار اول و آخر صرف نظر می کنیم زیرا آنها هرگز طبق تعریف ماکزیمم نخواهند بود.
چهارم، ما قوانین را اجرا می کنیم:
for (let i = 1 ; i < arr.length -1 ; i++){
if (arr[i] <= arr[i-1]){
continue;
}
if (arr[i] > arr[i+1]){
cache.pos.push(i);
cache.peaks.push(arr[i]);
}
if (arr[i] == arr[i+1]){
// TO DO
}
}
ما باید قسمت آخر را اصلاح کنیم. این برخورد ویژه ای است که در بالا ذکر شد در هنگام تنظیم قوانین. این فقط یک حلقه دیگر است که به عنوان یک فرآیند فرعی عمل می کند:
if (arr[i] == arr[i+1]){
for (let j=i +1 ; j< arr.length - 1; j++){
if (arr[j] == arr[j+1]){
continue;
}
if (arr[j] < arr[j+1]){
break;
}
if (arr[j] > arr[j+1]){
cache.pos.push(i);
cache.peaks.push(arr[i]);
}
}
}
مجموع همه اینها این است:
function pickPeaks(arr){
let cache = {pos:[], peaks:[]};
if (arr == false) {
return cache;
}
for (let i = 1 ; i < arr.length -1 ; i++){
if (arr[i] <= arr[i-1]){
continue;
}
if (arr[i] > arr[i+1]){
cache.pos.push(i);
cache.peaks.push(arr[i]);
}
if (arr[i] == arr[i+1]){
for (let j=i +1 ; j< arr.length - 1; j++){
if (arr[j] == arr[j+1]){
continue;
}
if (arr[j] < arr[j+1]){
break;
}
if (arr[j] > arr[j+1]){
cache.pos.push(i);
cache.peaks.push(arr[i]);
}
}
}
}
return cache;
}
و حالا بیایید آن را آزمایش کنیم … بله! گذشت! بیایید ارسال کنیم و …
اوه نه. چی؟؟؟
این تست خاص: pickPeaks([1,2,5,4,3,2,3,6,4,1,2,3,3,4,5,3,2,1,2,3,5,5,4,3])
این باید برگردد: {pos:[2,7,14,20], peaks:[5,6,5,5]}
برمیگرداند: {pos:[2,7,14,20,20], peaks:[5,6,5,5,5]}
اما چرا؟ منطق منطقی است. و هر حلقه درست است… اوهوم… صبر کنید… تکراری می شود. موقعیت 20، مقدار 5. دو بار آنجاست. اینجا مشکلی وجود دارد:
if (arr[i] == arr[i+1]){
for (let j=i +1 ; j< arr.length - 1; j++){
if (arr[j] == arr[j+1]){
continue;
}
if (arr[j] < arr[j+1]){
break;
}
if (arr[j] > arr[j+1]){
cache.pos.push(i);
cache.peaks.push(arr[i]);
}
}
}
بعد از مقداری اشکال زدایی با Dev Tools، آن را پیدا کردم. مشکل اینجاست:
if (arr[j] > arr[j+1]){
cache.pos.push(i);
cache.peaks.push(arr[i]);
}
از دست رفته است break
بیانیه [...3,5,5,4,3]
مقدار دوم را کپی می کند زیرا تنها زمانی از حلقه داخلی خارج می شود که دنباله ای را پیدا کند که در آن شرایط خروج اتفاق می افتد:
if (arr[j] < arr[j+1]){
break;
}
وگرنه ادامه میده معلوم شد زمانی که حداکثر را پیدا کرد باید خارج شود:
if (arr[j] > arr[j+1]){
cache.pos.push(i);
cache.peaks.push(arr[i]);
break; // <------------ EXTREMELY IMPORTANT
}
ثابت شد:
function pickPeaks(arr){
let cache = {pos:[], peaks:[]};
if (arr == false) {
return cache;
}
for (let i = 1 ; i < arr.length -1 ; i++){
if (arr[i] <= arr[i-1]){
continue;
}
if (arr[i] > arr[i+1]){
cache.pos.push(i);
cache.peaks.push(arr[i]);
}
if (arr[i] == arr[i+1]){
for (let j=i +1 ; j< arr.length - 1; j++){
if (arr[j] == arr[j+1]){
continue;
}
if (arr[j] < arr[j+1]){
break;
}
if (arr[j] > arr[j+1]){
cache.pos.push(i);
cache.peaks.push(arr[i]);
break; // if you don't break, situations like this: 3,5,5,4,3
// can duplicate a value..
}
}
}
}
return cache;
}
ناکارآمد، اما موثر.
مراقب باشید. آب بنوشید 💧💧💧 .
قبلی