Умнотии


От няколко месеца, плюс останалите задачи, се опитвам да попрочитам и написаното в един форум.
То и регистрация се изисква, ама и нерегистрираните могат да прочетат онова, което ще цитирам днес с любезното съгласие на автора:

Та – за да почнете да се оправяте по-смело и добре, смятам да ви напиша следния инструктаж, който да описва стъпка по стъпка какво да правим когато хванем задача:

1. прочитаме я
2. маркираме си наум всичките простотии (предистории/смешки/али-бали) и не ги гледаме повече
3. прочитаме няколкократно всички конкретни факти (формат на вход/изхода, ограничения, пояснения, някакви страни условия)
Особено много трябва да внимавате за някви гадни малки изреченийца скрити сред спама. [тук направих съкращение на цитата – ЕН]
Ми хууву, като си изчетете задачата, следващата стъпка е да
4. вникнете в задачата. Това дали някой е вникнал в задачата много добре се познава от мен на школите – пускам програмата тествам я и викам „кефи ли ви как работи?“ Когато чуя случаен отговор – явно тоя човек дори не е вникнал в условието. Когато съм на школа, трябва със съжаление да отбележа, че много от вас не достигат до етапа „вникване“. Друга проява е, когато след 1-2 часа стигнем до въпроса „а ква беше задачата“. Посланието ми е – недейте да продължавате със следващи стъпки, преди напълно да сте вникнали.
5. Задачите от Е група, често не заслужават етап 5. Той е- „да измислим някъф алгоритъм“. Все пак, има изключения, в които дори да има очевидно решение, то обикновено е прекалено трудно за написване, а трябва да се сетим за хитрото. В по- горните групи, ако има очевидно решение, то явно то ще е проблемно. Свикнете с идеята да отделяте поне по 15 минути на стъпка 5.
6. Време е да започнем да мислим как би се справял алгоритъма, който измислихме на предната стъпка. Дали няма да е прекалено бавен/паметозаемащ/труден за писане/неработещ в някои случаи? Тук е въпрос и на време/стратегия… Дали имаме шанса да измислим и впоследствие напишем нещо по-добро за оставащото време. Свикнете с мисълта, че обикновено първата ни хрумка за алгоритъм ще е куца, и често ще трябва да се връщаме на стъпка 5 за по-добра хрумка.

Всъщност въпроса „как да измислям добрия алгоритъм“ е единственото нещо, за което не мога да ви дам някви прости малоумни правилца, инструктаж или нещо друго тъпо. Просто ви казвам да му обърнете много старание. В групи A, B, C победителите се определят точно от този етап. В действителност, това колко сме досетливи, е въпрос на повече практика, опит, късмет, бодрост, а според някои идиоти – и на талант (всъщност такова нещо като талант няма, всичко си зависи от подготовката ви). За това и школата ми е насочена не към задълбаване в езика С++ (което задълбаване е нещо лесно и неособено вълнуващо), ами към сблъскването с различни алгоритми все повече и повече. Скоро ще осъзнаете, че много задачи, в които други хора биха имали нужда от няколкократно повтаряне на стъпки 5-6 и биха се въртяли в кръг, за вас са очевидни, познати или тривиални.
7. Когато сме готови с измислянето на реализируем алгоритъм, за който вярваме, че ще се справя достатъчно добре (но не преди да сме измислили такъв), е време да се захванем с програмирането. Една от първите задачи е да си измислим добри имена на променливите. Още на тоя етап много хора се обричат на 7 години нещастия. Добри имена на променливите, наричам такива които не могат да се сбърка за кво са и не могат да се объркат помежду си.
8. По време на програмирането на самата програма е добре да си поставяме коментари, които да ни напомнят кой код за какво ни е служел. Разбирам ви, да не виждате смисъла от такива коментари в проста програма, но в програма заплетена поне колкото bfs, сме мъртви без тях. Еднакво лошо е да се питаш „за кво ми беше променливата f” или да се питаш „за кво ми бяха тия 14 реда код“.
9. Когато сме написали програмата си, започваме да я тестваме/дебъгваме. Трябва да направите тези проверки в този ред:
-избирате си единствен малък тестов пример (защо не дадения ви в условието)
-оправяте компилационни грешки
-оправяте още компилационни грешки
-програмата ви тръгва
-въвеждате тестовия си пример
-програмата ви гърми
-намирате защо е гърмяла но тя продължава да гърми
-зяпате защо гърми
-не намирате защо гърми
-почвате да бухате тестови отпечатвания
-достигате до момента в който има ред на който пише
cout<<”do tuk dostigam”;
a=5/0;
cout<<”tuk ne dostigam”;
осъзнавате, че програмата ви е гърмяла на реда а=5/0; обглеждате го отвсякъде и ме повиквате да ми кажете, че компютърът ви е развален, излушвате ме къде ви е грешката, и си я оправяте, евентуално повтаряме тая сценка няколко пъти, накрая програмата ви не гърми, но е прекалено бавна, викате ме, да ми покажете, че компютърът ви е забил, почваме да слагаме нови тестови cout-и докато стигнем до следното:
for(p=0;p<5;j=p+1){
cout<<”toq red se vika do bezkrai”;
}
cout<<”toq red izobshto ne s izvikva”;
след което дописваме cout<<p; за да видим що така тва p не нараства
-отново се държите изненадано.
-оправяте си го
-програмата ви вече започва да завършва, ама извежда грешни неща
-този път най-накрая решавате сами да тествате и бухате тестови cout-и докато не стигнете до реда a=а+3; след който сте очаквали а да се увеличи с 2, което не разбирате що не става…
-накрая тестовият пример ви бачка.
С времето ще се радвам да ставате все по-смели и да се оправяте по-самостоятелно с такива бъгове..
10. Веднъж открили, че даден наш код работи с даден малък пример, не е време да разкараме тестовите cout-и и да обявим програмата ни за успешно изтествана. Вместо това трябва да тестваме програмата с:
-още няколко малки, но разнообразни примери.
-един средно голям, за който също да сме преценили очаквания отговор, за да го сравним
-няколко разнообразни огромни (колкото дават ограниченията) тестови входа. Дори да не знаем, дали програмата ни е извела правилния отговор (който би било невъзможно да получим на ръка), ще знаем дали тя завършва бързо, може би ще знаем дали и е стигнала паметта и други подобни.
-няколко примера в интересни частни случаи. Най-често това са: прости числа, частни случаи, равенства и други ситуации, които може нашия скрит бъг да се издаде.
Ако сме открили, че понякога нашата програма работи грешно, то най-вероятно трябва да повторим тестванията от стъпка 9. Има и по-неприятен случай – на този късен етап да открием, че сме избрали безнадеждно тъп алгоритъм (или такъв, който работи вярно, но много рядко). В този случай при ограничено оставащо време, може би добро решение ще е няква форма на тъпотия, която да хване незаслужени точици.
Състезанията в групи D и Е се определят от това кой до колко успява да си дебъгне програмите.
11. Ако сме направили голям брой разнообразни успешни тестове, е време да си прочетем условието отново. Цялото. Дори и маркираните отначало като ала-бала неща. В тях или другаде може да се е скрил някой пропуснат детайл.
12. Последната стъпка е да разкараме тестовите cout-и и да поогледаме кода си за пропуснати нови редове, излишни интервали и тем подобни тъпотии. Компилирайте си го отново, може и да го тествате пак.
13. Ако сте на състезание с онлайн система – предавайки кода си, веднага ще получите отговор, дали успешно е протекъл тестовият пример. Това може да ви сигнализира за пропуснат нов ред, или пък че не сте забелязали някой бъг, който под линукс изревава например. Ясно, че в тоя случай се връщаме на 10. Това, че тестовият пример на системата е проработил НЕ ни замества тестването с разнообразни примери – винаги си правете и стъпка 10!

Уау… отново написах адски много текст. Да не сте останали с впечетлението, че нищо не казах?
Основното ми послание беше: Търсете си грешките обилно и разнообразно. Недейте да вкарвате емоции, когато се окаже, че нещата не ви вървят, ами спокойно и търпеливо си намерете грешките. Това ще ви е по- лесно, ако в началото сте си помислили хубаво как кода ви е да е прост и ясен.

Моето поумняване се свежда до:
три седмици умуване като как не ми излиза точно един тест на една „баламска“ задачка? (такава, която не се нуждае от инструкция 5).
Вероятността да намеря причината – открих поне с колко греша на изхода.
Предположих къде се получава грешката.
Огледах тестовия пример.
Не видях причина да се случва разминаването.
Пак се чудих на тестовия пример. Пак не ми се видя нищо непредвидено в теста, което кодът ми да не проверява.
Пак си огледах сорса. Пак си го харесах.
Пак огледах теста.
Взех суперважно решение – да си направя свой тест с точно избрани начални входни данни, които ще проверяват само един случай – съмнителния от трудния тестов пример на автора.
Този път уцелих – и в моя прост, единичен пример, се получи грешен резултат.
Наблъсках си малко допълнителни изходни проследявания, докато „хванах“ причината за грешката.
Тя беше супер тъпа: На един ред присвоявам стойност на променлива, на следващия си мисля, че смятам не с текущата, а с по-предишната стойност на въпросната променлива.
Кой ми е крив, че не премислих всичко това наум от позицията на машината???
Известна ми е такава грешка при всяка една начинаеща група, всяка година си имам поне две групи, на които дори тихичко се радвам, като направи някой от групата подобна грешка.
Учениците ми изучават информатика общо 2 години, общо за 72 учебни часа.
А на мене ми отне три или четири седмици да си видя своята заблуда.
Направо си е за хвалба!
И даже се похвалих, че съм напреднала с решението!
И даже го нарекох – алгоритъм с пълно изчерпване.
И – голяма радост си беше то!
А днес – избрах нова задачка. Тя си е малко по-алгоритмична.
Засилих се аз да измислям хитро решение. Ама все ми се изплъзва от мислите. 🙂 😦
Рекох си – не, няма да се откажа, ще направя най-наивното решение, все ще хвана някоя „незаслужена“ точица.
Речено-сторено:
Направих си кода. Пратих го на системата.
Изкарах два верни теста, два грешни, другото – tl.
Хайде, че има недостиг на време, добре.
Че има и грешене отговор, бива, ама грешен още от първия тест, дали пък направих пълно изчерпване на ситуациите???
Отворих файла с тестовете на авторите, видях първия пример – о, срамота! – най-невзрачното начално състояние, с най-невзрачни входни данни, съм го забравила. И съм почнала смело от отговор, който избирам за най-малка възможна стойност на отговор!!!
Е-е-ех, защо ли съм съобразителна колкото половин ученик???
И, като се засилих да си оправям пропуска, изведнъж се сетих, че този частен случай можеше да не е само при този първи тестов пример.
Че то… това мило отговорче, можеше да се получи и при друга ситуация…
Пък аз – вече ги изброих всичките, откога си ги анализирах всички възможности, уж пак – пълно изчерпване, е-е-ех!!!
Този път се стегнах, оправих сорса като за всеки подобен случай… с тайната надеждичка наистина и другата грешка от системата да ми е заради този мой пропуск.
Не би!
Няма друг верен резултат – останах си с три верни, един грешен и шест с недостиг на време изходи.
Вероятно, грешният отговор на един от тестовете се дължи на препълване на променливата, което изобщо не можах да измъдря като как да предотватя.
Задачката си има алгоритмично решение, до което още ми е далечно да се размисля. 🙂
По този въпрос ще си дам още време за размисъл и поумняване, а с всеки изминал ден се убеждавам в правотата и необходимостта на точно този стил, с който първоначално форумът на Яшу ме стресна:

Отдавна ми прави впечатление, че не програмирате като спокойни уверени люде, ами като случайни келяви убитняци.

Това си има негативните последствия- често почвате да пишете нещо което е абсурдно да работи, защото алгоритъма му е тъп. В други случай алгоритъма ви е ок, но като тръгнете да го пишете произвеждате нещо мошно кат релефа (ето за тоз говоря: http://www.vbox7.com/play:3afc39c4 ), който както се досещате му е много оплетена логиката и няма шанс да се оправи. Дори в алгоритъма ви да има логика и дори да сте я написали кратко просто и ясно, често допускате 1-2 бъгчета, което е нормално за всеки програмист, но вие го възприемате като повод да ме извикате да ви го търся аз, а когато сте на състезание… всъщност кво точно случвате, когато сте на състезание?

Обещавам пак да пиша, докато не се увери целят свят (ако случайно някой досега се е съмнявал), че и аз съм от келявите убитняци… 🙂 😦

Advertisements

Вашият коментар

Попълнете полетата по-долу или кликнете върху икона, за да влезете:

WordPress.com лого

You are commenting using your WordPress.com account. Log Out / Промяна )

Twitter picture

You are commenting using your Twitter account. Log Out / Промяна )

Facebook photo

You are commenting using your Facebook account. Log Out / Промяна )

Google+ photo

You are commenting using your Google+ account. Log Out / Промяна )

Connecting to %s