Професионална програма
Loading...
+ Нов въпрос
g.stoyanov avatar g.stoyanov 776 Точки

Ръководство за решаване на задачи с рисуване на конзолата.

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

Първо да спомена за един основен принцип (поне при мен е така) при решаването на тези задачки – Откриването на повторяеми последователности от символи и опростяването им - привеждането им във вид който на нас ни е удобен.

Второ, задължително се запознайте със конструктора на string просто си нямате на представа колко помага при този тип задачи: new string(‘*’, 3) = “***” готино нали J

За да ми е по лесно направо ще започна с примери които са от софтуерната академия:

П.С.: Ще пускам обясненията на задачите веднага като успея да ги напиша!

50
Programming Basics
mmddimitrova avatar mmddimitrova 433 Точки
Best Answer

Здравей,

Би било добре да поместиш и кода на съответните задачи.

Поздрави за инициативата и +1 от мен!

1
g.stoyanov avatar g.stoyanov 776 Точки
Ще ги добавям вече :)
0
g.stoyanov avatar g.stoyanov 776 Точки

1.  Forest Road

Samples

4

*...

.*..

..*.

...*

..*.

.*..

*...

5

*....

.*...

..*..

...*.

....*

...*.

..*..

.*...

*....

 

Да погледнем какво трябва да изобразим на конзолата… Почваме ред по ред с първия пример:

  1.        *... тук виждаме два символа които се повтарят различен брой пъти, а именно [*.] повтарящи се съответно [1, 3]
  2.        .*.. тук са три символа (ВАЖНО: Еднаквите символи които са разделени трябва да ги смятаме като различни, освен при някои случаи ;)) [.*.][1, 1, 2]
  3.        ..*. [.*.][2, 1, 1]
  4.        ...* тук пак са два [.*][3, 1]
  5.        ..*. отново почват по три[.*.][2, 1, 1]
  6.        .*.. [.*.][1, 1, 2]
  7.        *... и накрая отново два символа които се повтарят определен брой пъти [*.] [1, 3]

Така какво имаме три броя патърни [*.][.*.][.*], все още ми се струва че е сложничко а на вас как ви се струва? Нека го опростим, какво ще кажете ако за първия ред приемем че патърна и повторенията са съответно [.*.][0, 1, 3] вярно е нали. Същото да направим с 4 и 7 ред съответно [.*.][3, 1, 0] и [.*.][0, 1, 3]. Поне от към патърните опростихме нещата имаме само един а именно [.*.]. Сега да погледнем повторенията:

[ .     *     . ]

[0, 1, 3]

[1, 1, 2]

[2, 1, 1]

[3, 1, 0]

[2, 1, 1]

[1, 1, 2]

[0, 1, 3]

Вече можем да забележим че имаме доста ясна картинка за това което трябва да направим. Така да започваме от двата примера виждаме че височината ни е равна на инпута (широчината) умножен по две, минус едно (ВАЖНО: винаги е добре да проверим твърдението си и с други примерни входни данни!). Нека се придържаме към първия пример. Понеже ще отпечатваме ред по ред означава че цикъла ни ще бъде до (4 х 2) – 1, а именно 7. Забелязваме също че в оптимизирания патърн има един символ който не се променя – нито местоположението нито бройката, това е *, заради това в момента не я взимаме под внимание. Остават два символа които са еднакви но на всеки ред имат различни стойности. Ако не беше така щяхме да ги смятаме за един просто щяхме да го поставяме на различни места :). Нека да ги именуваме leftDots и rightDots. Така почваме с цикъла и виждаме друг проблем :) ще имаме следните числа: 0, 1, 2, 3, 4, 5 и 6 как на всяка итерация да получим нужните ни на нас а именно: 0-3, 1-2, 2-1, 3-0, 2-1, 1-2 и 0-3. Тук вече идва рутината. Просто сега като ви споделя как може пълноценно да използвате цикъла ще осмислите и вие колко мощен може да бъде един цикъл! Така пуснем нашия цикъл от 3 до -3 (по-голямо от -4), по този начин ще имаме числата: 3, 2, 1, 0, -1, -2, -3. Някои ще кажат с какво ни помага това? Тук идва на помощ Math.Abs() след като го приложим на всички итерации получаваме: 3, 2, 1, 0, 1, 2, 3 :) получихме стойностите за rightDots: rightDots = Math.Abs(i). Дотук добре ами leftDots… какво ще стане ако изваждаме Math.Abs(i) от 3 (да тази идея идва от практика и като видим подобни решения именно за това трябва да си споделяме знанията), получаваме 0, 1, 2, 3, 2, 1, 0 готово имаме стойностите и на leftDots. Сега остава в цикъла да напишем:

Console.WriteLine(“{0}*{1}”, new string(‘.’,  (инпута - 1) - Math.Abs(i)), new string(‘.’,  Math.Abs(i)));

Както виждате символа * няма нужда да го обработваме просто го хардкодваме и задачата е готова.

Забравих да кажа че цикъла трябва да е от инпута - 1 до -(инпута - 1). Логично :)

Code

7
g.stoyanov avatar g.stoyanov 776 Точки

      2. Trapezoid

Examples

5

 

.....*****

....*....*

...*.....*

..*......*

.*.......*

**********

10

 

..........**********

.........*.........*

........*..........*

.......*...........*

......*............*

.....*.............*

....*..............*

...*...............*

..*................*

.*.................*

********************

Ето и втория пример, продължаваме по същата логика (символи - повторения):

[.*] [5, 5]

[.*.*] [4, 1, 4, 1]

[.*.*] [3, 1, 5, 1]

[.*.*] [2, 1, 6, 1]

[.*.*] [1, 1, 7, 1]

[*] [10]

Тук сигурно ще кажете логиката от предишния пример не сработва не можем да приведем патърните към един! Да така е но в този случаи можем да забележим че това са първия и последния… съответно можем да ги отпечатим преди и след цикъла, това означава че всъщност имаме абсолютно същия метод за решаване, разбира се ако може да се каже така с минимални промени. Забравете за момент първия и последния ред, те са ясни –

1-ви : Console.WriteLine(“{0}{1}”, new string(‘.’,  инпута), new string(‘*’, инпута));

Последен : Console.WriteLine(“{0}”, new string(‘*’,  инпута * 2));

 

Сега да видим… нека го наречем мап-а :

[ .  *  .  * ]

[4, 1, 4, 1]

[3, 1, 5, 1]

[2, 1, 6, 1]

[1, 1, 7, 1]

Както видяхме от първия пример забравяме за символите *, нито се местят нито си променят стойността. Така че имаме мап за символите .(точка):

[4, 4]

[3, 5]

[2, 6]

[1, 7]

Така как да направим цикъла??? Имаме пак сходни като стойност промени но различни като знак… Ето какво виждам аз трябва ми цикъл със стойности 0, 1 ,2 , 3 . Извода ми за тези стойности идва от това че и двете бройки на точките се променят с еднакви стойности (именно тези) в положителна и отрицателна стойност. Поради това правя цикъла от 0 до по – малко от инпут - 1. Така вече мога да вадя и… да добавям стойността на i. Остава да напиша следния ред в цикъла:

 

Console.WriteLine(“{0}*{1}*”, new string(‘.’,  (инпут - 1) - i), new string(‘.’ (инпут - 1) + i));

 

Code

3
g.stoyanov avatar g.stoyanov 776 Точки

3. Fir Tree

Examples

5

...*...

..***..

.*****.

*******

...*...

9

.......*.......

......***......

.....*****.....

....*******....

...*********...

..***********..

.*************.

***************

.......*.......

 

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

[.*.] [3, 1, 3]

[.*.] [2, 3, 2]

[.*.] [1, 5, 1]

[.*.] [0, 7, 0]

[.*.] [3, 1, 3]

До тук виждаме че имаме нарастваща последователност с изключение на последния ред. Вече знаем че може да го (проблемият ред) отпечатим отделно – извън цикъла. Параметрите на цикъла можем лесно да сметнем, а именно от (входа – 2) до 0. Виждаме че звездичката има нарастваща константна последователност но тя е от 1 до 7 със стъпка 2. Проблема лесно се решава ако си декларираме една променлива звезда с начална стойност 1 извън цикъла и след това в тялото на цикъла напишем следните редове:

Console.WriteLine(“{0}{1}{0}”, new string(‘.’,  i), new string(‘.’(звезда)));

звезда += 2;

Както забелязахте тук имаме еднакъв символ с еднакви стойности за това ползваме в печатния формат само стойности 0 и 1 тъй като спокойно си ползваме параметъра 0 на двете места. И за тези които не са разбрали последния ред на кода (пънчето на елхичката) извън цикъла е:

Console.WriteLine(string.Format("{0}*{0}", new string('.', входа - 2)));

 

Code

1
g.stoyanov avatar g.stoyanov 776 Точки

4. Sand-glass

Examples

5

 

 

*****

.***.

..*..

.***.

*****

7

*******

.*****.

..***..

...*...

..***..

.*****.

*******

 

1
g.stoyanov avatar g.stoyanov 776 Точки

5. Carpets

Examples


6

../\..

./  \.

/ /\ \

\ \/ /

.\  /.

..\/..

 

 

12

...../\.....

..../  \....

.../ /\ \...

../ /  \ \..

./ / /\ \ \.

/ / /  \ \ \

\ \ \  / / /

.\ \ \/ / /.

..\ \  / /..

...\ \/ /...

....\  /....

.....\/.....


 

0
g.stoyanov avatar g.stoyanov 776 Точки

6. Telerik Logo

Examples


3

 

.*...*.

*.*.*.*

...*...

..*.*..

.*...*.

..*.*..

...*...

 

 5

..*.......*..

.*.*.....*.*.

*...*...*...*

.....*.*.....

......*......

.....*.*.....

....*...*....

...*.....*...

..*.......*..

...*.....*...

....*...*....

.....*.*.....

......*......


0
g.stoyanov avatar g.stoyanov 776 Точки

7. UK Flag

Examples


5

\.|./

.\|/.

--*--

./|\.

/.|.\

 

 9

\...|.../

.\..|../.

..\.|./..

...\|/...

----*----

.../|\...

../.|.\..

./..|..\.

/...|...\

 

0
NorthMania avatar NorthMania 22 Точки

Колега благодаря ти за положения труд!

Много бих се радвал и ти също така много би помогнал на други започващи курсисти ако обясниш решенията на задачите UK flag, Carpets , Telerik Logo.

Благодаря за ръководството много ми помогна !

0
HPetrov avatar HPetrov 822 Точки

Някои от задачите са доста елементарни и решението ти е вече в главата само като видиш картинката, но някои като логото на Телерик са малко по кофти и искат малко повече въображение и знания да можеш да ги докараш. Мога да предоставя моите решения на повечето от тези задачи от bgcoder но мисля, че е твърде рано за голяма част от хората да се мъчат на такива задачи без да са написали няколко conditional statements и 10-15 цикли или да ги съчетаят даже :P Но с удоволствие ще дам насоки вече като минат още 2-3 лекции и наближи времето за подготовка за изпит :)

Но за нетърпеливите ще им дам един много важен hint - на всяка задача за принтиране на изображение има 1 или няколко съотношения, които трябва да се намерят. Намерите ли ги, половината ви задача е решена ;)

2
g.stoyanov avatar g.stoyanov 776 Точки
Килимчето и Телерик логото са по сложни, използвам други подходи ;) ще ги обясня и тях. Иначе докато успея да напиша ръководства за всички задачи ще стане време точно за изпита така че не е рано, пък и може да има хора на по-високо ниво.
1
g.stoyanov avatar g.stoyanov 776 Точки

Пуснах метода ми за втория пример - Trapezoid. Мисля следващият да е от по-сложните за да задоволим желанието на всички ;). Ако има някакви въпроси спокойно може да питате тук.

1