Last active
February 12, 2021 13:55
-
-
Save kevinkirkup/3cce2fe2bd33b0531a454049e561b531 to your computer and use it in GitHub Desktop.
Search exercise
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@doc """ | |
Parse data for a single line of the text file | |
""" | |
def parse_line(line, _num, index) do | |
String.downcase(line) | |
|> String.to_charlist() | |
|> Enum.with_index() | |
|> Enum.chunk_while( | |
{[], 0}, | |
fn {c, i}, {word, column} -> | |
if c == ' ' do | |
{:cont, {word, column}, {"", i}} | |
else | |
{:cont, {[word | c], column}} | |
end | |
end, | |
fn | |
[] -> {:cont, []} | |
acc -> {:cont, Enum.reverse(acc), []} | |
end | |
) | |
|> IO.inspect() | |
|> Enum.reduce(index, fn {word, column}, acc -> | |
Map.update( | |
acc, | |
word, | |
[%Searchy.IndexEntry{line: line, column: column}], | |
&(&1 ++ [%Searchy.IndexEntry{line: line, column: column}]) | |
) | |
end) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Searchy do | |
@moduledoc """ | |
Documentation for `Searchy`. | |
""" | |
require IO | |
defmodule IndexEntry do | |
@moduledoc """ | |
An entry in the search index. | |
""" | |
defstruct line: "", column: 0 | |
end | |
@doc """ | |
Open the specified file and index all of the words | |
""" | |
def build_index!(file) do | |
File.open!(file) | |
|> IO.stream(:line) | |
|> Enum.map(&remove_punctuation(&1)) | |
|> Enum.with_index() | |
|> Enum.reduce(%{}, &process_line(&1, &2)) | |
end | |
@doc """ | |
Filter invalid characters from the provided line of text | |
""" | |
def remove_punctuation(line) do | |
String.replace(line, [".", ",", ";"], " ") | |
end | |
@doc """ | |
Process a line of text from the file | |
""" | |
def process_line({line, num}, index), do: parse_line(line, num, index) | |
@doc """ | |
Parse data for a single line of the text file | |
""" | |
def parse_line(line, line_number, index) do | |
String.downcase(line) | |
|> String.split() | |
|> Enum.reduce({index, 0}, fn word, {index, column} -> | |
{Map.update( | |
index, | |
word, | |
[%Searchy.IndexEntry{line: line_number, column: column}], | |
&(&1 ++ [%Searchy.IndexEntry{line: line_number, column: column}]) | |
), column + String.length(word) + 1} | |
end) | |
|> elem(0) | |
end | |
@doc """ | |
Search the index for the occurrences of word. | |
""" | |
def search(index, word) do | |
{:ok, Map.get(index, String.downcase(word), [])} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment