PDA

Просмотр полной версии : [Вопрос] Оптимизация?



vovandolg
14.01.2016, 05:43
Возможно ли подобный код оптимизировать?

if(memberrs == 1 && rankk >= 14 || memberrs == 3 && rankk >= 14 || memberrs == 10 && rankk >= 14
|| memberrs == 19 && rankk >= 14 || memberrs == 21 && rankk >= 14 || memberrs == 2 && rankk >= 9
|| memberrs == 26 && rankk >= 9 || memberrs == 4 && rankk >= 9 || memberrs == 5 && rankk >= 9
|| memberrs == 6 && rankk >= 9 || memberrs == 11 && rankk >= 9 || memberrs == 12 && rankk >= 9
|| memberrs == 13 && rankk >= 9 || memberrs == 14 && rankk >= 9 || memberrs == 15 && rankk >= 9
|| memberrs == 17 && rankk >= 9

DeimoS
14.01.2016, 07:56
Тут оптимизировать нечего. Можно, разве что, сократить.

if(((memberrs == 1 || memberrs == 3 || memberrs == 10 || memberrs == 19 || memberrs == 21) && rankk >= 14)
|| ((memberrs == 2 || memberrs == 26 || memberrs == 4 || memberrs == 5 || memberrs == 6 || memberrs == 11 || memberrs == 12
|| memberrs == 13 || memberrs == 14 || memberrs == 15 || memberrs == 17) && rankk >= 9))

Daniel_Cortez
14.01.2016, 17:43
Тут оптимизировать нечего. Можно, разве что, сократить.

if(((memberrs == 1 || memberrs == 3 || memberrs == 10 || memberrs == 19 || memberrs == 21) && rankk >= 14)
|| ((memberrs == 2 || memberrs == 26 || memberrs == 4 || memberrs == 5 || memberrs == 6 || memberrs == 11 || memberrs == 12
|| memberrs == 13 || memberrs == 14 || memberrs == 15 || memberrs == 17) && rankk >= 9))
Да почему же нечего? Можно юзануть switch, эта конструкция как раз создана для случаев с несколькими вариантами значений одной переменной.
Ещё можно вынести все требования к рангам в массив, где индекс элемента будет обозначать ID фракции, а значение - требуемый ранг.


// 1-й элемент массива означает номер ранга для 1-й фракции, 2-й элемент - для второй фракции и т.д.
// Для фракций, которых не было в условии, я поставил в массиве 0 (см. проверку далее).
// Полный список составляйте сами, раз уж так старательно перепутали ID фракций в условии.
static const rank_requirements[] = { 0, 14, 9, 14, 9, 9, 9, 0, 0, 0, 14, /* ... */ };
new required_rank;
// Не выносите присваивание в required_rank за пределы условия - сначала должна выполниться
// проверка на правильность ID фракции, иначе можно словить выход за пределы массива.
if (!(1 <= memberrs <= 26) || ((required_rank = rank_requirements[memberrs]) == 0)
return SendClientMessage(playerid, -1, "Неправильный ID фракции."); // Можно просто вернуть 1/0, без SCM.
if (rand >= required_rank)
{
/* Ваши действия. */
}

vovandolg
14.01.2016, 20:01
if (rand >= required_rank)
Что такое rand? Ранг который на данный момент у пипла?

DeimoS
14.01.2016, 20:12
Да почему же нечего? Можно юзануть switch, эта конструкция как раз создана для случаев с несколькими вариантами значений одной переменной.
Ещё можно вынести все требования к рангам в массив, где индекс элемента будет обозначать ID фракции, а значение - требуемый ранг.


// 1-й элемент массива означает номер ранга для 1-й фракции, 2-й элемент - для второй фракции и т.д.
// Для фракций, которых не было в условии, я поставил в массиве 0 (см. проверку далее).
// Полный список составляйте сами, раз уж так старательно перепутали ID фракций в условии.
static const rank_requirements[] = { 0, 14, 9, 14, 9, 9, 9, 0, 0, 0, 14, /* ... */ };
new required_rank;
// Не выносите присваивание в required_rank за пределы условия - сначала должна выполниться
// проверка на правильность ID фракции, иначе можно словить выход за пределы массива.
if (!(1 <= memberrs <= 26) || ((required_rank = rank_requirements[memberrs]) == 0)
return SendClientMessage(playerid, -1, "Неправильный ID фракции."); // Можно просто вернуть 1/0, без SCM.
if (rand >= required_rank)
{
/* Ваши действия. */
}


Только какая существенная польза от такой оптимизации? :) Если уж на то пошло, то давайте сразу на байт-коде всё строчить, ведь на компиляцию тратится время (да и компилятор, глупенький, не умеет впитывать в себя современные методы оптимизации кода). А чего бы и нет? *Погоня за наносекундами*

Daniel_Cortez
14.01.2016, 20:54
if (rand >= required_rank)
Что такое rand? Ранг который на данный момент у пипла?
rank, отвечал с планшета.



Только какая существенная польза от такой оптимизации? :) Если уж на то пошло, то давайте сразу на байт-коде всё строчить, ведь на компиляцию тратится время (да и компилятор, глупенький, не умеет впитывать в себя современные методы оптимизации кода). А чего бы и нет? *Погоня за наносекундами*
Я и не заставляю пользоваться тем способом - вариант со switch вполне прокатил бы. Приведённая мной оптимизация с вытаскиванием значения из массива имеет смысл только в коде, критичном ко времени выполнения - в OnPlayerUpdate или каком-нибудь таймере со с циклом по всем игрокам, например. Собственно, описал я здесь этот способ только потому, что не видел, чтобы кто-то разъяснял его где-то ещё. Пользоваться им или нет - зависит только от умений скриптера и поставленных перед ним задач.

vovandolg
15.01.2016, 07:45
А как тут со switch переплетать если у меня 2 переменной связываются друг с дружкой и у каждого значения memberrs своё значение rankk
Да допустим я сделаю как мне примерно нужно:


switch(memb)
{
case 8:
{}
case 16:
{}
case 23:
{}
case 29,30:
{}
case 7,27,28:
{}
case 1,3,10,19,21:
{}
case 2,4..6,11..15,17,18,22,24..26:
{}
}

Или начать с рангов та же лабуда:


switch(rank)
{
case 4,5: //это типо (rank >= 4) и так далее
{}
case 5,6:
{}
case 6,7:
{}
case 9,10:
{}
case 11,12:
{}
case 12,13:
{}
case 14,15:
{}
}
И в итоге получается что из одного куска кода мне надо будет скопировать и сделать 7 кусков кода.. Мне кажется или switch не поможет уже тут?

DeimoS
15.01.2016, 08:59
Возможно он имел ввиду что-то подобное:

switch(memberrs)
{
case 1, 3, 10, 19, 21:
{
if(rankk >= 14)
{

}
}
case 2, 4..6, 11..15, 17, 26:
{
if(rankk >= 9)
{
//Действие
}
}
}
И да, не будем забывать, что switch/case не всегда будет быстрее if/else =) Хотя в этом случае должно быть быстрее. Но существенная разница будет заметна либо в лютых скриптах на десятки тысяч итераций, либо где-нибудь в OnPlayerUpdate. Во всех остальных случаях это больше попахивает извращением, чем чем-то действительно полезным. Особенно если в обоих условиях выполняется одинаковый код.

vovandolg
15.01.2016, 09:03
DeimoS, Это только 2 ранга, а у меня их на 7 выйдет, если даже сделать на 7 рангов будет лучше чем вообще без switch?

DeimoS
15.01.2016, 09:07
DeimoS, Это только 2 ранга, а у меня их на 7 выйдет, если даже сделать на 7 рангов будет лучше чем вообще без switch?

Зависит от конкретной ситуации. Как именно будет всё реализовано и какие действия будут происходить после условия? Как уже сказал, switch/case не всегда работает быстрее, да и не везде он уместен. Нужно под конкретную ситуацию смотреть

Daniel_Cortez
15.01.2016, 10:08
DeimoS, Это только 2 ранга, а у меня их на 7 выйдет, если даже сделать на 7 рангов будет лучше чем вообще без switch?
Выложите полный код команды, или хотя бы тот, в котором определяются требования к ID организации и рангу. Из ваших слов вообще ничего не понятно.

vovandolg
15.01.2016, 10:31
if(strcmp(cmd, "/giverank", true) == 0)
{
new memb = PlayerInfo[playerid][pMember];
new rank = PlayerInfo[playerid][pRank];

if(memb == 1 && rank >= 14 || memb == 3 && rank >= 14 || memb == 10 && rank >= 14 || memb == 19 && rank >= 14
|| memb == 21 && rank >= 14 || memb == 2 && rank >= 9 || memb == 26 && rank >= 9 || memb == 4 && rank >= 9
|| memb == 5 && rank >= 9 || memb == 6 && rank >= 9 || memb == 11 && rank >= 9 || memb == 12 && rank >= 9
|| memb == 13 && rank >= 9 || memb == 14 && rank >= 9 || memb == 15 && rank >= 9 || memb == 17 && rank >= 9
|| memb == 18 && rank >= 9 || memb == 22 && rank >= 9 || memb == 24 && rank >= 9 || memb == 25 && rank >= 9
|| memb == 9 && rank >= 13 || memb == 16 && rank >= 13 || memb == 20 && rank >= 13 || memb == 7 && rank >= 5
|| memb == 27 && rank >= 5 || memb == 8 && rank >= 5 || memb == 28 && rank >= 5 || memb == 29 && rank >= 6
|| memb == 23 && rank >= 11 || memb == 30 && rank >= 6)
{
tmp = strcharsplit(cmdtext, idx);
if(!strlen(tmp))
return SendClientMessage(playerid, COLOR_WHITE, "Наберите: /giverank [id] [ðàíã]");
new para1 = ReturnUser(tmp);
tmp = strcharsplit(cmdtext, idx);
new level = strval(tmp);
switch(memb)
{
case 8: if(level > 4 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 4!");
case 7,27,28: if(level > 5 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 5!");
case 29,30: if(level > 6 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 6!");
case 2,4..6,11..15,17,18,22,24..26: if(level > 9 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 9!");
case 23: if(level > 11 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 11!");
case 16: if(level > 12 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 12!");
case 1,3,10,19,21: if(level > 14 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 14!");
}
if(!IsPlayerConnected(para1) || para1 == INVALID_PLAYER_ID || para1 == playerid) return true;
if (PlayerInfo[para1][pLeader] >= 1) return SendClientMessage(playerid, COLOR_GREY, "Он лидер!");
if(memb != PlayerInfo[para1][pMember]) return SendClientMessage(playerid, COLOR_GREY, "Он не в вашей фраке!");
if(memb > 0 && rank <= level) return SendClientMessage(playerid,COLOR_GREY,"Îøèáêà");
if(PlayerInfo[playerid][pLeader] <= 0 && rank <= PlayerInfo[para1][pRank]) return SendClientMessage(playerid, COLOR_GREY, "Ошибка");
format(stringer, sizeof(stringer), "Вас повысил/понизил %s до %d ранга",level, PlayerInfo[playerid][pNames]);
SendClientMessage(para1, 0x6BB3FFAA, stringer);
format(stringer, sizeof(stringer), "Вы повысили %s до %d ранга.", PlayerInfo[para1][pNames],level);
SendClientMessage(playerid, 0x6BB3FFAA, stringer);
PlayerInfo[para1][pRank] = level;
return true;
}
else return SendClientMessage(playerid,COLOR_GREY,"Вам не доступна команда");
}
Вот допустим)

NewGreen
15.01.2016, 12:55
if(strcmp(cmd, "/giverank", true) == 0)
{
new memb = PlayerInfo[playerid][pMember];
new rank = PlayerInfo[playerid][pRank];

if(memb == 1 && rank >= 14 || memb == 3 && rank >= 14 || memb == 10 && rank >= 14 || memb == 19 && rank >= 14
|| memb == 21 && rank >= 14 || memb == 2 && rank >= 9 || memb == 26 && rank >= 9 || memb == 4 && rank >= 9
|| memb == 5 && rank >= 9 || memb == 6 && rank >= 9 || memb == 11 && rank >= 9 || memb == 12 && rank >= 9
|| memb == 13 && rank >= 9 || memb == 14 && rank >= 9 || memb == 15 && rank >= 9 || memb == 17 && rank >= 9
|| memb == 18 && rank >= 9 || memb == 22 && rank >= 9 || memb == 24 && rank >= 9 || memb == 25 && rank >= 9
|| memb == 9 && rank >= 13 || memb == 16 && rank >= 13 || memb == 20 && rank >= 13 || memb == 7 && rank >= 5
|| memb == 27 && rank >= 5 || memb == 8 && rank >= 5 || memb == 28 && rank >= 5 || memb == 29 && rank >= 6
|| memb == 23 && rank >= 11 || memb == 30 && rank >= 6)
{
tmp = strcharsplit(cmdtext, idx);
if(!strlen(tmp))
return SendClientMessage(playerid, COLOR_WHITE, "Наберите: /giverank [id] [ðàíã]");
new para1 = ReturnUser(tmp);
tmp = strcharsplit(cmdtext, idx);
new level = strval(tmp);
switch(memb)
{
case 8: if(level > 4 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 4!");
case 7,27,28: if(level > 5 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 5!");
case 29,30: if(level > 6 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 6!");
case 2,4..6,11..15,17,18,22,24..26: if(level > 9 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 9!");
case 23: if(level > 11 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 11!");
case 16: if(level > 12 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 12!");
case 1,3,10,19,21: if(level > 14 || level < 1) return SendClientMessage(playerid, COLOR_GREY, "С 1 по 14!");
}
if(!IsPlayerConnected(para1) || para1 == INVALID_PLAYER_ID || para1 == playerid) return true;
if (PlayerInfo[para1][pLeader] >= 1) return SendClientMessage(playerid, COLOR_GREY, "Он лидер!");
if(memb != PlayerInfo[para1][pMember]) return SendClientMessage(playerid, COLOR_GREY, "Он не в вашей фраке!");
if(memb > 0 && rank <= level) return SendClientMessage(playerid,COLOR_GREY,"Îøèáêà");
if(PlayerInfo[playerid][pLeader] <= 0 && rank <= PlayerInfo[para1][pRank]) return SendClientMessage(playerid, COLOR_GREY, "Ошибка");
format(stringer, sizeof(stringer), "Вас повысил/понизил %s до %d ранга",level, PlayerInfo[playerid][pNames]);
SendClientMessage(para1, 0x6BB3FFAA, stringer);
format(stringer, sizeof(stringer), "Вы повысили %s до %d ранга.", PlayerInfo[para1][pNames],level);
SendClientMessage(playerid, 0x6BB3FFAA, stringer);
PlayerInfo[para1][pRank] = level;
return true;
}
else return SendClientMessage(playerid,COLOR_GREY,"Вам не доступна команда");
}
Вот допустим)


if(strcmp(cmd, "/giverank", true) == 0)
{
new memb = PlayerInfo[playerid][pMember];
new rank = PlayerInfo[playerid][pRank];

if(memb > 0 && rank > 0)
{
// ... продолжение кода

p.s. переменные memb и rank лишние, можно напрямую обращаться к массиву PlayerInfo

vovandolg
15.01.2016, 14:47
А не чего что я овер9000 строк превратил в пару строк?
так для себя скажем) чтобы не листать не искать и проще было:king:

VVWVV
15.01.2016, 15:53
if(strcmp(cmd, "/giverank", true) == 0)
{
new memb = PlayerInfo[playerid][pMember];
new rank = PlayerInfo[playerid][pRank];

if(memb > 0 && rank > 0)
{
// ... продолжение кода

p.s. переменные memb и rank лишние, можно напрямую обращаться к массиву PlayerInfo

Для того, чтобы двадцать раз не обращаться к массиву, сделан буфер (две переменные), который хранит в себе одно значение. Убедится в этом вы можете, посмотрев листинг ассемблера.

NewGreen
15.01.2016, 16:12
Для того, чтобы двадцать раз не обращаться к массиву, сделан буфер (две переменные), который хранит в себе одно значение. Убедится в этом вы можете, посмотрев листинг ассемблера.

Раздаю вредные советы :good: