Use Livebook to open this notebook and explore new ideas.
It is easy to get started, on your machine or the cloud.
# Document Tools
```elixir
Mix.install([
{:jason, "~> 1.4"},
{:kino, "~> 0.9", override: true},
{:youtube, github: "brooklinjazz/youtube"},
{:hidden_cell, github: "brooklinjazz/hidden_cell"}
])
```
## Navigation
<div style="display: flex; align-items: center; width: 100%; justify-content: space-between; font-size: 1rem; color: #61758a; background-color: #f0f5f9; height: 4rem; padding: 0 1rem; border-radius: 1rem;">
<div style="display: flex;">
<i class="ri-home-fill"></i>
<a style="display: flex; color: #61758a; margin-left: 1rem;" href="../start.livemd">Home</a>
</div>
<div style="display: flex;">
<i class="ri-bug-fill"></i>
<a style="display: flex; color: #61758a; margin-left: 1rem;" href="https://github.com/DockYard-Academy/curriculum/issues/new?assignees=&labels=&template=issue.md&title=Document Tools">Report An Issue</a>
</div>
<div style="display: flex;">
<i class="ri-arrow-left-fill"></i>
<a style="display: flex; color: #61758a; margin-left: 1rem;" href="../exercises/file_system_todo_app.livemd">File System Todo</a>
</div>
<div style="display: flex;">
<a style="display: flex; color: #61758a; margin-right: 1rem;" href="../exercises/file_search.livemd">File Search</a>
<i class="ri-arrow-right-fill"></i>
</div>
</div>
## Document Tools
You're going to create a `Document` module which provides some convenient function for working with text files.
Once you have a working solution, consider how you can optimize it to reduce how much of a file you load into memory.
<details style="background-color: lightgreen; padding: 1rem; margin: 1rem 0;">
<summary>Example Solution</summary>
```elixir
defmodule Document do
def word_count(file_name) do
File.stream!(file_name)
|> Stream.map(fn line ->
line |> String.split(" ", trim: true) |> Enum.count()
end)
|> Enum.sum()
end
def line_count(file_name) do
file = File.open!(file_name)
count = count_lines(file)
File.close(file)
count
end
defp count_lines(file, count \\ 0) do
case IO.read(file, :line) do
:eof -> count
_ -> count_lines(file, count + 1)
end
end
def add_line_numbers(file_name) do
lined_content =
File.stream!(file_name)
|> Stream.with_index()
|> Stream.map(fn {line, index} -> "#{index + 1}. #{line}" end)
|> Enum.join("")
File.write!(file_name, lined_content)
end
end
```
</details>
```elixir
defmodule Document do
@moduledoc """
Documentation for `Document` module.
"""
@doc ~S"""
Count the number of words in a document.
## Examples
Any sequence of characters separated by a space will be considered a word.
iex> File.write("word_count.txt", "one two three")
iex> Document.word_count("word_count.txt")
3
Ensure your solution ignores newline characters.
iex> File.write("word_count.txt", "one\ntwo\nthree")
iex> Document.word_count("word_count.txt")
3
"""
def word_count(file_name) do
end
@doc ~S"""
Count the number of words in a document.
## Examples
iex> File.write("line_count.txt", "line1\nline2\nline3\n")
iex> Document.line_count("line_count.txt")
3
"""
def line_count(file_name) do
end
@doc ~S"""
Add line numbers formatted as "X. rest of line" to an existing file.
## Examples
iex> File.write("add_line_numbers.txt", "one\ntwo\nthree")
iex> Document.add_line_numbers("add_line_numbers.txt")
iex> File.read!("add_line_numbers.txt")
"1. one\n2. two\n3. three"
"""
def add_line_numbers(file_name) do
end
end
```
## Commit Your Progress
DockYard Academy now recommends you use the latest [Release](https://github.com/DockYard-Academy/curriculum/releases) rather than forking or cloning our repository.
Run `git status` to ensure there are no undesirable changes.
Then run the following in your command line from the `curriculum` folder to commit your progress.
```
$ git add .
$ git commit -m "finish Document Tools exercise"
$ git push
```
We're proud to offer our open-source curriculum free of charge for anyone to learn from at their own pace.
We also offer a paid course where you can learn from an instructor alongside a cohort of your peers.
We will accept applications for the June-August 2023 cohort soon.
## Navigation
<div style="display: flex; align-items: center; width: 100%; justify-content: space-between; font-size: 1rem; color: #61758a; background-color: #f0f5f9; height: 4rem; padding: 0 1rem; border-radius: 1rem;">
<div style="display: flex;">
<i class="ri-home-fill"></i>
<a style="display: flex; color: #61758a; margin-left: 1rem;" href="../start.livemd">Home</a>
</div>
<div style="display: flex;">
<i class="ri-bug-fill"></i>
<a style="display: flex; color: #61758a; margin-left: 1rem;" href="https://github.com/DockYard-Academy/curriculum/issues/new?assignees=&labels=&template=issue.md&title=Document Tools">Report An Issue</a>
</div>
<div style="display: flex;">
<i class="ri-arrow-left-fill"></i>
<a style="display: flex; color: #61758a; margin-left: 1rem;" href="../exercises/file_system_todo_app.livemd">File System Todo</a>
</div>
<div style="display: flex;">
<a style="display: flex; color: #61758a; margin-right: 1rem;" href="../exercises/file_search.livemd">File Search</a>
<i class="ri-arrow-right-fill"></i>
</div>
</div>
See source