Skip to content

Instantly share code, notes, and snippets.

@kevinkirkup
Last active February 12, 2021 13:55
Show Gist options
  • Save kevinkirkup/3cce2fe2bd33b0531a454049e561b531 to your computer and use it in GitHub Desktop.
Save kevinkirkup/3cce2fe2bd33b0531a454049e561b531 to your computer and use it in GitHub Desktop.
Search exercise
@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
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