Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix backtics and other improvements #122

Merged
merged 6 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/10-basics/20-modules/description.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ theory: |

Modules are defined with a special contstruct _defmodule/do/end_:

```
```elixir
# use CamelCase for name
defmodule HexletBasics do
# Here goes module contains
Expand Down
14 changes: 6 additions & 8 deletions modules/10-basics/30-strings/description.ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ theory: |

Функция `String.upcase(str, mode)` работает в трех разных режимах. В режиме `:default` она переводит в верхний регистр все символы, для которых это возможно. В режиме `:ascii` она переводит только символы латинского алфавита:

```
```elixir
String.upcase("hello мир!", :default) # "HELLO МИР!"
String.upcase("hello мир!", :ascii) # "HELLO мир!"
```
Expand All @@ -31,14 +31,12 @@ instructions: |

Реализуйте функцию `concate_and_upcase`, которая принимает две строки, соединяет их вместе, удаляет пробелы в начале и в конце, и переводит в верхний регистр только символы латинского алфавита.

```
defmodule Solution do
def concate_and_upcase(str1, str2) do
# TODO реализация
end
end
```elixir
Solution.concate_and_upcase(" привет ", "world!")
# => "привет WORLD!"

IO.puts(Solution.concate_and_upcase("привет ", "world!"))
Solution.concate_and_upcase("hello ", "мир! ")
# => "HELLO мир!"
```

tips:
Expand Down
20 changes: 11 additions & 9 deletions modules/10-basics/40-numbers/description.ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ theory: |
```

Для больших чисел можно использовать символ подчеркивания между разрядами для удобства чтения:

```elixir
100_500
1_000_000
Expand Down Expand Up @@ -66,14 +66,16 @@ instructions: |

Каждый результат выводится на отдельной строке.

```
defmodule Solution do

def do_math(a, b) do
# TODO реализация
end

end
```elixir
Solution.do_math(10, 10)
# => 2.0
# => 1
# => 0

Solution.do_math(42, 3)
# => 15.0
# => 14
# => 3
```


Expand Down
27 changes: 12 additions & 15 deletions modules/20-data-types/20-lists/description.ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,22 @@ theory: |

Зачем нужны такие странные операции? На них основана итерация по элементам списка. А на итерации основана вообще любая работа со списками и с другими коллекциями. Это станет понятно позже, когда мы начнем изучать рекурсию и основы функционального программирования.


instructions: |

Реализовать функцию, которая возвращает сумму первого и второго элементов списка.
instructions: |

Внимательный слушатель спросит: "а что функция должна сделать, если в списке только один элемент, или список вообще пустой?". На этот вопрос мы ответим в следующем модуле, где будем изучать ветвления в коде и сопоставление с образцом. Пока будем считать, что функция всегда вызывается со списком, содержащим два или больше элементов.

```elixir
defmodule Solution do
Реализуйте функцию `get_second_item`, которая возвращает сумму первого и второго элементов списка.

def get_second_item(list) do
# TODO реализация
end
Внимательный читатель спросит: "а что функция должна сделать, если в списке только один элемент, или список вообще пустой?". На этот вопрос мы ответим в следующем модуле, где будем изучать ветвления в коде и сопоставление с образцом. Пока будем считать, что функция всегда вызывается со списком, содержащим два или больше элементов.

end
```elixir
Solution.get_second_item([20, 22, 24])
# => 42
Solution.get_second_item([1, 2, 3, 4])
# => 3
```

Еще более внимательный слушатель спросит: "а что, если список содержит элементы такого типа, для которого не определена операция суммирования?". В этом случае возникнет исключение. Исключения и обработку ошибок мы, конечно, тоже изучим.


tips: []
Еще более внимательный читатель спросит: "а что, если список содержит элементы такого типа, для которого не определена операция суммирования?". В этом случае возникнет исключение. Исключения и обработку ошибок изучим в соответствующем модуле.

tips:
- |
[Официальная документация](https://hexdocs.pm/elixir/List.html)
65 changes: 39 additions & 26 deletions modules/20-data-types/30-maps/description.ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ theory: |
```

Часто в качестве ключей используют атомы:

```elixir
other_map = %{:a => 1, :b => 2}
other_map[:a] # 1
other_map[:b] # 2
```

Для ключей атомов (и только в этом случае) можно использовать синтаксический сахар:

```elixir
other_map = %{a: 1, b: 2}
other_map = %{a: 1, b: 2}
other_map.a # 1
other_map.b # 2
```
Expand All @@ -37,7 +37,7 @@ theory: |
```

Как видим, в первом случае возвращается значение `nil`, а во втором случае генерируется исключение.

Функция `Map.get` работает так же, как обращение через квадратные скобки. Но она позволяет указать дефолтное значение для отсутствующего ключа:

```elixir
Expand Down Expand Up @@ -71,7 +71,7 @@ theory: |
Такой синтаксис удобен тем, что позволяет изменять несколько ключей сразу.

А добавить новый ключ этот синтаксис не позволяет:

```elixir
%{other_map | :c => 42} # ** (KeyError) key :c not found in: %{a: 1, b: 2}
```
Expand All @@ -82,34 +82,47 @@ theory: |
Map.delete(other_map, :a) # %{b: 2}
```


instructions: |

Реализовать функцию `keys_sum`, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает сумму значений. Если ключа в словаре нет, то соответствующее значение не учитывается.

Реализовать функцию `keys_product`, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает произведение значений. Если ключа в словаре нет, то соответствующее значение не учитывается.

Реализовать функцию `copy_key`, которая принимает два словаря, ключ, и значение по умолчанию. По ключу нужно извлечь значение из первого словаря и вставить во второй словарь. Если в первом словаре нет такого ключа, то во второй словарь нужно вставить значение по умолчанию. Если во втором словаре уже есть такой ключ, то его значение меняется.

```elixir
defmodule Solution do
instructions: |

def keys_sum(map, key1, key2) do
# TODO реализация
end
Реализуйте функцию `keys_sum`, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает сумму значений. Если ключа в словаре нет, то соответствующее значение не учитывается.

def keys_product(map, key1, key2) do
# TODO реализация
end
Реализуйте функцию `keys_product`, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает произведение значений. Если ключа в словаре нет, то соответствующее значение не учитывается.

def copy_key(from_map, to_map, key, default_value) do
# TODO реализация
end
Реализуйте функцию `copy_key`, которая принимает два словаря, ключ, и значение по умолчанию. По ключу нужно извлечь значение из первого словаря и вставить во второй словарь. Если в первом словаре нет такого ключа, то во второй словарь нужно вставить значение по умолчанию. Если во втором словаре уже есть такой ключ, то его значение меняется.

end
```elixir
map = %{a: 1, b: 2, c: 42}
Solution.keys_sum(map, :a, :b)
# => 3
Solution.keys_sum(map, :a, :c)
# => 43
Solution.keys_sum(map, :c, :b)
# => 44

map = %{one: 1, five: 5, ten: 10}
Solution.keys_product(map, :one, :five)
# => 5
Solution.keys_product(map, :five, :ten)
# => 50
Solution.keys_product(map, :two, :ten)
# => 10

map1 = %{a: 1, b: 2}
map2 = %{c: 3, d: 4}

Solution.copy_key(map1, map2, :a, 42)
# => %{c: 3, d: 4, a: 1}
Solution.copy_key(map1, map2, :b, 42)
# => %{c: 3, d: 4, b: 2}

Solution.copy_key(map2, map1, :d, 42)
# => %{a: 1, b: 2, d: 4}
Solution.copy_key(map2, map1, :e, 42)
# => %{a: 1, b: 2, e: 42}
```


tips:
- |
[Официальная документация](https://hexdocs.pm/elixir/Map.html)
35 changes: 17 additions & 18 deletions modules/30-flow/10-pattern-matching/description.ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ theory: |
IO.puts(age) # => 25
```

Первая строка опять выглядит как присваивание. Только значение более сложное -- кортеж из трех элементов. А вот вторая строка уже интереснее.
Первая строка опять выглядит как присваивание. Только значение более сложное -- кортеж из трех элементов. А вот вторая строка уже интереснее.

Слева от оператора `=` шаблон, который ограничивает множество значений. Этот шаблон может совпасть только с такими значениями, которые являются кортежами из трех элементов, первым элементом обязательно должен быть атом `:user`, а второй и третий элемент могут быть любыми.
Слева от оператора `=` шаблон, который ограничивает множество значений. Этот шаблон может совпасть только с такими значениями, которые являются кортежами из трех элементов, первым элементом обязательно должен быть атом `:user`, а второй и третий элемент могут быть любыми.

Справа от оператора `=` находится значение, которое мы сравниваем с шаблоном. В данном случае значение извлекается из переменной `user`, но оно может быть и результатом вызова функции или литералом.

Expand Down Expand Up @@ -69,7 +69,7 @@ theory: |

Обратите внимания на символ подчеркивания. Он совпадает с любым значением, и применяется, когда это значение не нужно, мы не хотим сохранять его в переменную.

Если переменная встречается два раза, то значения в этих местах должны быть одинаковыми:
Если переменная встречается два раза, то значения в этих местах должны быть одинаковыми:

```elixir
{a, a, 42} = {10, 10, 42} # match
Expand All @@ -78,7 +78,7 @@ theory: |
```

Но это не касается символа подчеркивания:

```elixir
{_, _, 42} = {10, 10, 42} # match
{_, _, 42} = {20, 20, 42} # match
Expand All @@ -90,7 +90,7 @@ theory: |
```elixir
[pattern] = [value]
```

Шаблон может включать:
- литералы
- переменные
Expand All @@ -107,30 +107,29 @@ theory: |
- конструкция case
- клозы функций (clause)
- обработка исключений (rescue, catch)
- чтение сообщений из mailbox процесса (receive)
- чтение сообщений из mailbox процесса (receive)

Конструкции case и function clause рассмотрим в следующей теме. Обработка исключений и чтение сообщений будут позже в курсе.

instructions: |

Реализовать функцию `get_age(user)`, которая принимает объект `user`, представленный в виде кортежа `{:user, name, age}`, и возвращает возраст (age).
Реализуйте функцию `get_age(user)`, которая принимает объект `user`, представленный в виде кортежа `{:user, name, age}`, и возвращает возраст (age).

Реализовать функцию `get_names(users)`, которая принимает список из трёх объектов `user`, представленных такими же кортежами, и возвращает список из трёх имен.
Реализуйте функцию `get_names(users)`, которая принимает список из трёх объектов `user`, представленных такими же кортежами, и возвращает список из трёх имен.

```elixir
defmodule Solution do
bob = {:user, "Bob", 42}
helen = {:user, "Helen", 20}
kate = {:user, "Kate", 22}

def get_age(user) do
# TODO реализация
end
Solution.get_age(bob) # => 42
Solution.get_age(helen) # => 20
Solution.get_age(kate) # => 22

def get_names(users) do
# TODO реализация
end

end
Solution.get_names([bob, helen, kate])
# => ["Bob", "Helen", "Kate"]
```

tips:
- |
[Про pattern matching](https://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D0%BF%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D1%81_%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D1%86%D0%BE%D0%BC)
20 changes: 10 additions & 10 deletions modules/30-flow/30-cond/description.ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
name: Конструкция cond
theory: |

Если из конструкции *case* убрать шаблоны, но оставить охранные выражения, то получится конструкция *cond*.
Если из конструкции *case* убрать шаблоны, но оставить охранные выражения, то получится конструкция *cond*.

Было:

```elixir
case Expr do
Pattern1 [when GuardSequence1] ->
Expand All @@ -18,7 +18,7 @@ theory: |
```

Стало:

```elixir
cond do
GuardSequence1 ->
Expand All @@ -30,7 +30,7 @@ theory: |
```

В принципе, это эквивалент цепочки `if...else if`, которая нередко встречается в императивных языках. Python, например:

```python
a = int(input())
if a < -5:
Expand Down Expand Up @@ -59,7 +59,7 @@ theory: |
## Конструкция if

В Эликсир есть привычная всем конструкция *if*:

```elixir
def gcd(a, b) do
if rem(a, b) == 0 do
Expand All @@ -70,10 +70,10 @@ theory: |
end
```

Только это не настоящая конструкция языка, а макрос. Впрочем, в Эликсир очень многое является макросами. В некоторых случаях это важно знать, в некоторых не важно.
Только это не настоящая конструкция языка, а макрос. Впрочем, в Эликсир очень многое является макросами. В некоторых случаях это важно знать, в некоторых не важно.

Есть и конструкция *unless*, тоже макрос:

```elixir
def gcd(a, b) do
unless rem(a, b) != 0 do
Expand All @@ -85,7 +85,7 @@ theory: |
```

Есть важное отличие от императивных языков -- в функциональных языках *if* всегда возвращает какое-то значение.

```elixir
> a = 5
> b = 10
Expand All @@ -109,10 +109,10 @@ theory: |
instructions: |

Реализовать функцию `single_win?(a_win, b_win)`, которая принимает 2 булевых параметра: `a_win` -- победил ли игрок A, и `b_win` -- победил ли игрок B. Функция возвращает `true` если победил только один из двоих игроков, иначе возвращает `false`.

Реализовать функцию `double_win?(a_win, b_win, c_win)`, которая принимает 3 булевых параметра для трех игроков. Если победили игроки A и B, то функция возвращает атом `:ab`. Если победили игроки A и C, то функция возвращает атом `:ac`, если победили игроки B и C, то функция возвращает атом `:bc`. Во всех остальных случаях функция возвращает `false`.

```
```elixir
defmodule Solution do

def single_win?(a_win, b_win) do
Expand Down