Loading...

Във форума е въведено ограничение, което позволява на потребителите единствено да разглеждат публикуваните въпроси.

mar0der avatar mar0der 191 Точки

[Exam] PHP Basics - 12 Януари 2015 - решения, впечатления, резултати

Здравейте,

веднъж и аз да стартирам такава тема :) Моето лично мнение е, че на поправителни / повишителни изпити, особено като са струпани в 4 дни един след друг е хубаво, ако не с една идея по - лесни то в никакъв случай по - трудни задачи от тези на редовната сесия. Мнението ми може да се потвърди и от 50% нулеви резултати на днешния изпит а бих казал, че имаше подобно леко "изхъвляне" в една от задачките на JS също. Идеята ми е че с подобен тип задачи хората който са на кантар да се откажат .. биват отказвани, а това е лоши и за тах и за Софтуни.

Ето мойте решения GitHub

Ще се радвам да прочета мненията ви за днешния изпит.

PP: Ако някой може сам да измисли алгоритъм за пълнене на спираловидна матрица в рамките на час и нещо, без да е решавал нещо подобно до момента лично ще му стисна ръката и ще го черпя бира. Ма наистина сам да я измисли, не да "преведе" алгоритъма от джава или C# 

Тагове:
5
PHP Web Development Basics 12/01/2015 23:58:03
nikola.m.nikolov avatar nikola.m.nikolov 830 Точки

Аз лично този изпит го започнах доста зле...

Започнах с 1-ва задача. След редовния изпит по PHP вече имам обеца на ухото, че дати се генерират само с DateTime. Да ама в случая ако DateTime не успее да генерира дата judge връща runtime error. Какво ли не търсих, но в крайна сметка се оказа, че DateTime конструктора няма как да върне false ако не успее да генерира дата. Успях да взема само 37 точки.

След 1 час борба с първа задача минах на 2-ра. Тук набързо направих някакъв regex и взех 50 точки. След малко корекции стигнах до 75 и реших да зарежа и тази задача и да минавам на следващата. Поне не отделих много време да се боря и с тази задача.

Минах на 3-та. Веднага си погледнах решението на спиралната матрица от C# Basics домашното. Все пак тук имаше и допълнителни условия и трябваше малко повече логика да се добави. След няколко submit-a и тук взех 100 точки.

Реших да се върна на 1-ва. При strtotime хубавото е, че ако не успее връща false. Накрая измислих някакво тъпо решение като комбинация между strtotime и DateTime. Проверявам с if дали strtotime може да генерира дата и ако да то с DateTime генерирам дата. По този начин 1 тест не минаваше и имах 87 точки. Пак я зарязах.

Стигнах най-накрая и до 4-та. Тя беше много идентична с Computer Shop от изпита на 5 Септември. Директно си копирах решението и го преработих малко. В началото имах дребни грешни но след няколко submit-а взех 100 точки.

Върнах се отново на първа и за 20 минути успях да я реша.

Накрая ми останаха да преодолея последните два теста на втора. След като ми светна в зелено последния тест, на който повечето хора са се мъчили остана да гадая каква ли тъпа грешка съм направил, за да не ми мине 7-ми. Оказа се, че в regex-a след началната главна буква търся само малки букви, а трябва да търся и големи.

Така за 4 часа и малко успях да се преборя с всички задачи. Фактът, че само Filkolev беше решил всички задачи, когато си тръгвах говори достатъчно за изпита :). 

mar0der, след като реши всички задачи без трета очаквах да станеш готов доста преди мен с изпита.

 

Ето и моите решения на задачите (преработени):

GitHub

 

P.S. ако някой има желание мога да му обясня логиката на пълнене на спиралната матрица.

3
13/01/2015 13:16:25
mar0der avatar mar0der 191 Точки

значи аз имах голям късмет с датата че открих решение на твоето затруднение почти моментално. Ако ползваш ООП синтаксиса когато не успее да генерира дата дава грешка трика тук е че ако ползваш процедурния синтаксис date_create то той ако не успее да направи дата връща false което решава задачата доста лесно. (справка виж моето решение). А иначе явно някъде съм пропуснал тая задача с спираловидната матрица в c# щото после забелязах че маса народ са я ярешили със 100 точки а са се затруднили на предните задачки. Та както казах не е лесно да измислиш алгоритъм за пълнене на спираловидна матрица под напрежение за час и нещо. Аз лично намеих код в интернет и го преведох на php това ми отне 2 часа (не намирах работещ код) останалото решение с палиндроми ( или както им е там името ) ми отне 15 мин. Аз лично бях потресен от скоростта на filkolev тои имасше 387 точки в 11 и нещо :) Явно възраста ми си казва думата и затъпявам :)

1
Filkolev avatar Filkolev 4482 Точки

За задачи с дати се бях подготвил още от редовния изпит, където разучих подробно DateTime, пак за 1-ва задача. Спирална матрица решавах за последния курс по C#, една за подготовка и една, която дадохме на изпит. 4-та беше много стандартна и като цяло по-лесна от предишни такива, давани на PHP. На това отдавам краткото време, за което ги направих тези трите.

Иначе статистиката: в 11:44 - 350 т., в 12:30 - 387 т., 13:36 - 400 т. Да кажем от 3:30 мин общо, 2 часа ми заминаха да мъча 2-ра, от тях 1 час борба конкретно с тест 8. 

Виждам, че са качили материалите от изпита, интересно ми е да го видя въпросния тест и защо ми беше толкова трудно да го хвана.

1
nikola.m.nikolov avatar nikola.m.nikolov 830 Точки

mar0der, прав си за date_create. Промених си малко решението на първа задача в github. Доста кратка и лесна логически стана. И на мен ще ми е интересно защо на втора толкова време се мъчих с последния тест. Хубавото в случая беше, че като пуснах един submit само с принтиране на No matches видях, че на два теста вземам точки и единия беше именно 8-ми. Това доста помогна.

За regex-a на втора не е нужно да се използва lookahead, а вместо това може да се сложи само \d. Моят regex така съм го направил, че ако махна това \d вземам само 50 точки.

2
13/01/2015 15:25:03
mar0der avatar mar0der 191 Точки

Filkolev при мен разликата между тоя тест последния да не работи и да работи е само лукахеда

0
mar0der avatar mar0der 191 Точки

nikola.m.nikolov прав си май кат се замисля и /d ще свърши работа.

1
velio84 avatar velio84 241 Точки

"P.S. ако някой има желание мога да му обясня логиката на пълнене на спиралната матрица."

 

Аз имам желание :)

Така и не ги реших тия задачи, още от C# Basics

0
nikola.m.nikolov avatar nikola.m.nikolov 830 Точки

Velio, ами използвам 6 променливи специално за пълнене на матрицата.

$direction = 1;
$x = 0;
$y = $length - 1;
$xCount = $rows - 1;
$yCount = $length - 1;
$char = 0;

$x и $y ги използвам за определяне на индекса на двумерната матрица и съответстват на редове и колони.

$xCount ми служи да определя колко цикъла по x трябва да направя (за да пълня на даден ред), преди да сменя посоката и да пълня по колони. $yCount е аналогично, като с него пълно по колони. 

$char е лесно - това е индекса на стринга, от който взимам символите и пълня с тези символи спиралата

$direction служи да определя посоката на пълнене на спиралата -  ако е 1 тогава пълня първо надолу по редовете, след което започвам да пълня наляво по колоните. Ако е -1 започвам да пълня нагоре по редовете, след което започвам да пълня надясно по колоните.

В конкретната задача от ред 13 до ред 16 създавам масив от еднакви по дължина стрингове, съставени само от *. Това се явява първоначално празната спирала. 

Съществената част за пълнене на спиралата е от ред 18 до 40. 

Създавам for цикъл, който върти от първия до последния ред на спиралата. В него имам веднага вложен цикъл, който върти по колони. Ако сме на нулевия ред то го пълня с първите символи от стринга. Ако спиралата има 7 колони то взимам първите 7 символа от стринга. Ако е с 4 колони, то взимам първите 4 символа от стринга със символите. При всяко завъртане на цикъла увеличавам char++. 

Ако обърнеш внимание при инициализирането $x съм го задал да е 0, защото започваме от нулевия ред да пълним спиралата. $y нарочно не съм го инициализирал с 0, а директно с $lenght - 1. Все пак е ясно, че като запълни първия ред $y винаги ще стигне до $lenght - 1. $lenght e броя колони. Можеше и да инициализирам $y = 0 и при пълненето на първия ред на спиралата да увеличавам $y++ на всеки цикъл.

След като напълня първия ред идва момента с $direction. Както казах за $direction - при 1 пълня надолу и след това наляво, а при -1 пълня нагоре и след това надясно. Тези две пълнения ги правя с последните 2 цикъла. С първия пълня по редове, затова променям само стойността на $x. За да определя дали $x да намалява или да се увеличава използва $direction. Ако $direction = 1, следователно трябва да пълня надолу по редовете, т.е. $x трябва да се увеличава. Така се получава следната формула $x = $x + 1 * $direction. Ако $direction = 1 имаме $x = $x + 1 * 1, т.е. $x ще се увеличи. Ако $direction = -1 следователно $x  = $x + 1 * -1 т.е. ще се намали. Като свършат двата цикъла за пълнене по $x и $y обръщам $direction с  $direction *= -1.

$xCount и $yCount ги използвам за да определя колко пъти да въртя най-вътрешните 2 цикъла, с които пълня спиралата. Ако имаме матрица с 5 реда и 5 колони я пълня по следния начин - първо запълвам целия първи ред и стигам до края. След това пълня 4 реда надолу и 4 реда наляво и намалявам с 1. После пълня 3 реда нагоре и 3 реда надясно и пак намалявам с 1. Така пълно докато $xCount и $yCount не станат 0-ли. Когато матрицата е квадратна то може да се ползва само 1 променлива. Когато обаче е правоъгълна се налага да се използват $xCount и $yCount.

 

 

3
15/01/2015 00:08:02
velio84 avatar velio84 241 Точки

Благодаря за подробното обяснение :)

Схванах каква е логиката, утре ще ти дебъгна и решението да разгледам как работи.

1
Filkolev avatar Filkolev 4482 Точки

Не съм вече в състояние в такъв час да обмислям обяснението на Никола, но ще го прочета на свежа глава утре.

Да споделя все пак и аз логиката на пълнене с while цикли.

В случая използвам факта, че трябва да напълним точно N*N елемента. Инициализирам матрицата, като задавам на всяка клетка стойност false, това показва, че дадената клетка все още не е била запълнена. В типизираните езици може да се подходи по друг начин, примерно да се сложи стойност, която да я ясно, че няма да бъде добавена впоследствие в матрицата, или пък да се направи отделна матрица с булеви стойности, която единствено да следи кои клетки от основната матрица са вече запълнени.

Имам променлива, която изпълнява две функции едновременно - 1) следи кой индекс от стринга трябва да хвана, за да добавя символа в дадената клетка; 2) брои попълнените вече клетки. Главният цикъл приключва, когато са запълнени N*N клекти.

В главния цикъл има 4 вложени while цикъла, като всеки от тях пълни матрицата в определена посока, в случая първият пълни по колони надясно, вторият надолу по редове и т.н. Т.е. започвайки от кой да е ъгъл на матрицата аз мога доста лесно да променя начина на пълнене като разменя поредността на циклите.

Имам две променливи, които следят текущия ред и текущата колона. На всяко завъртане на вътрешен цикъл увеличавам съответната променлива, т.е. цикълът, който върви надясно, увеличава колоните, цикълът, който върви в посока нагоре, намалява редовете и т.н.

Всеки от тези 4 цикъла се върти докато: 1) не стигне границите на матрицата или 2) не стигне до стойност, която вече е била запълнена. При което този цикъл приключва и започва следващият, който сменя посоката.

След всеки един цикъл трябва да се обновят стойностите на реда и колоната, така че новата позиция да е клетката, която трябва да бъде напълнена първа от следващия цикъл. С чисто визуален пример много лесно се вижда кое как да се коригира; например, след приключване на цикъла, който върви надясно, трябва на увеличим реда, за да слезем на следващия (следващата посока е надолу) и да намалим колоната, понеже сме излезли от рамките на матрицата или сме отишли в ред, който е вече запълнен.

Както споделих малко по-горе, доста ми е интуитивна тази логика и много лесно се намират грешки ако има такива. Аз допуснах 1-2 на изпита, трябваха ми не повече от 5 минути да ги оправя, защото всяка една стъпка ми е пределно ясна и разбираема.

3
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.