No description, website, or topics provided.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
config
lib
test
README.md
mix.exs

README.md

Информация

Задачата е за промяна на точките от малкия проект в курса по Elixir, проведен през лятната сесия 2017/2018 Тя носи общо 30 точки:

  • 20 за имплементация и защита
  • 10 за тестове

Освен имплементацията на задачата, вие ще трябва да напишете и смислени тестове към нея.

По време на изпитването ще Ви бъдат задавани въпроси, свързани с имплементацията и познаване на езика. Неразбиране на написаният от Вас код ще доведе до отнемане на точки.

Задачата няма краен срок - тя ще бъде оценена на място при провеждането на поправителния изпит на 25.08.2018г от 13:00 в зала 305.

Table

Задачата ви е да направите модул Table, който да подържа работа с таблици.

Какво представлява една таблица

Всяка таблица е правоъгълна и с произволен брой редове и колони. Всяка клетка съдържа число, стринг или нищо (nil).

Интерфейса за работа с таблици

Table.new()

Създава празна таблица.

Table.new(list)

Създава таблица от списък от редове на таблицата, които на свой ред също са списъци.

Table.new([[1, 2, 3],
           ["a", "b", "c"]])

Таблица, създадена по горния начин, съответства на:

1 2 3
a b c
Table.new([[2],
           ["a",  "b", "c"],
           ["ba", "ba"]])
2
a b c
ba ba
iex> Table.new([]) == Table.new()
true

Table.size(table)

Тази функция връща наредена двойка {rows, columns}, съответно броят на редовете и броят на колоните в таблицата.

Table.to_list(table)

Тази функция трябва да връща списък от списъци, където всеки вътрешен списък представлява ред в таблицата.

Ако table има следния вид:

1 2
3 4 5
6
iex> Table.to_list(table)
[[1, 2, nil], [3, 4, 5], [nil, 6, nil]]

Ако таблицата е празна, функцията трябва да върне празен списък.

Table.insert_row(table, row \\ [], position \\ :last)

Създава нова таблица с добавен нов ред row, като реда е вмъкнат на позиция position

  • row е списък с елементи. Ако новият ред има повече елементи от броя на колоните на таблицата, то колоните трябва да бъдат увеличени така, че да може да се запише целия нов ред.
  • position е цяло число или атома :last
    • ако е зададено число редът се вмиква на съответната позиция
    • ако числото е по-малко или равно на 1, редът бива вмъкнат в началото на таблицата
    • ако числото е по-голямо от досегашния брой редове, или e atoma :last, новият ред се вмъква в края на таблицата

За следващите няколко примера таблицата table, която ще изпозваме като входна за функцията, има следния вид:

1 2
3 4
Table.insert_row(table)

Този код създава следната таблица:

1 2
3 4
Table.insert_row(table, [5,6])

Table.insert_row(table, [5,6], :last)

Table.insert_row(table, [5,6], 6)

Тези три извиквания на функцията са еквивалентни и "произвеждат" следната таблица:

1 2
3 4
5 6
Table.insert_row(table, [5,6], -10)

Table.insert_row(table, [5,6], 1)
5 6
1 2
3 4
Table.insert_row(table, [5,6], 2)
1 2
5 6
3 4

Функцията може да бъде извикана с по-голям или по-малък ред от досегашната големина на таблицата и тогава поведението е следното:

Table.insert_row(table, [5,6,7])
1 2
3 4
5 6 7
Table.insert_row(table, [5])
1 2
3 4
5

Table.insert_column(table, column \\ [], positon \\ :last)

Поведението на insert_column е аналогично на това на insert_row, но за колони.

Table.delete_row(table, positon \\ :last)

Премахва ред от таблицата на позиция position, като връща наредена двойка {new_table, deleted_row}, съответно новата таблица и изтрития ред като списък.

  • position e цяло число или атома :last
    • ако е подаденo число, което не отговаря на никой ред тогава функцията трябва да върне старата таблица и празен списък.
    • ако е подаден атомът :last, трябва да бъде изтрит последният ред.

За следващите няколко примера таблицата (table), която ще изпозваме като входна за функцията има следния вид:

1 2
3 4 5
6
iex> {new_table, row} = Table.delete(table); row
[nil, 6, nil]
iex> {new_table, row} = Table.delete_row(table, 3); row
[nil, 6, nil]
iex> {new_table, row} = Table.delete_row(table, :last); row
[nil, 6, nil]

Таблицата new_table трябва да има следния вид и след извикването и на трите функции:

1 2
3 4 5
iex> {new_table, row} = Table.delete(table, 2); row
[3, 4, 5]

new_table е:

1 2
6
iex> {^table, row} = Table.delete(table, 0); row
[]
iex> {^table, row} = Table.delete(table, 10); row
[]

Table.delete_column(table, positon \\ :last)

Поведението на delete_column е аналогично на това на delete_row, но за колони.

Table.cell(table, {row, column})

Връща стойността в клетката, съответстваща на ред row и колона column (и двете трябва да са цели числа). Ако клетката е извън текущия размер на таблицата се връща nil.

Table.overwrite_cell(table, {row, column}, value \\ nil)

Презаписва се стойността на клетката, съответстваща на ред row и колона column (и двете трябва да са цели числа). Ако такава клетка не съществува, тогава се връща старата таблица.

  • value е стринг, число, nil или функция
    • ако е стринг, число или nil, то това е новата стойност на клетката.
    • ако е функция то стойността ѝ се изчислява и това е новата стойност на клетката (ако тя е валидна такава).

Експортиране на таблица

Вашата таблица трябва да може да бъде "записана" в 3 различни формата: CSV, HTML и Markdown. За това ще се грижи функцията Table.format_as(table, format). Функцията връща IOList -format е един от атомите: :md, :html или :csv

Експортиране в CSV формат

CSV(Comma-separated values) форматът може да се използва за да се представи таблица. В този формат всеки ред от таблицата е изобразен в ред от файла, а отделните клетки в даден ред са отделени със запетаи. Например следната таблица:

1 2.0 three
Are you counting?

би изглеждала така във csv формат

1,2.0,three
Are,you,counting?

Важно е да се отбележи, че в csv формата има 3 специални символа: ", , и \n. Ако искаме някоя клетка да съдържа тези символи, то информацията за тази клетка трябва да започва и да завършва със ", а всички срещания на " вътре в клетката да бъдат заменени с "". Клетка също може да бъде празна. Например:

1, 2.0, three
"Are you counting?"
He said

би изглеждала така:

"1, 2.0, three",
,"""Are,you,counting?""
He said"

Експортиране в HTML формат.

Всички знаем какво е HTML. Затова направо към примера.

1 2.0 three
Are you counting?

би изглеждала така във HTML формат:

<table>
  <tr>
    <td>1</td>
    <td>2.0</td>
    <td>three</td>
  </tr>
  <tr>
    <td>Are</td>
    <td>you</td>
    <td>counting?</td>
  </tr>
</table>

Може да не отделяте отделяте време на форматиране. Вариант, в който всичко е представено на един ред също върши работа - важното е да е валидна HTML таблица.

Във HTML също има символи, които трябва да бъдат представени по друг начин:

  • < става &lt;
  • > става &gt;
  • & става &amp;

Експортиране в MD формат.

Последният вариант за форматиране на таблица е Markdown. Нека да видим как изглежда една таблица в MD:

1 2.0 three
Are you counting?
Yes No Maybe

Би изглеждало така:

|1|2.0|three|
|-|-|-|
|Are|you|counting?|
|Yes|No|Maybe|

Трябва да забележим, че втория ред винаги се състои от | разделени с -.

В MD трябва да замените същите неща, както в HTML:

  • < става &lt;
  • > става &gt;
  • & става &amp;

Също така всеки от символите: \ * _ { } | [ ] ( ) # + - . и ! трябва да пъде предшестван от \. Например:

a > b || (arr[4] & 1) == 0 && p - 7
Are those some magic incantations?

Ще изглежда така като стринг:

|a&gt;b|\|\||\(arr\[4\]&amp;1\)==0|&amp;&amp;|p\-7|
|-|-|-|-|-|
|Are|those|some|magic|incantations?|