Elixir Plagiarism Check
defmodule PlagiarismCheck do
def plagiarism_check(code1, code2) do
c1 = Enum.join(code1, " ")
c2 = Enum.join(code2, " ")
if c1 == c2 do
false
else
words1 = ~r/\w+/ |> Regex.scan(c1) |> List.flatten()
words2 = ~r/\w+/ |> Regex.scan(c2) |> List.flatten()
candidates =
words1
|> Enum.zip(words2)
|> Enum.reduce(%{}, fn {w1, w2}, acc ->
if w1 != w2 and not numeric?(w1), do: Map.put(acc, w1, w2), else: acc
end)
c1_placeheld =
Enum.reduce(candidates, c1, fn {orig, _repl}, acc ->
replace_word(acc, orig, "PLACEHOLDER" <> orig)
end)
c1_final =
Enum.reduce(candidates, c1_placeheld, fn {orig, repl}, acc ->
replace_word(acc, "PLACEHOLDER" <> orig, repl)
end)
c1_final == c2
end
end
defp numeric?(w) do
case Integer.parse(w) do
{_n, ""} -> true
_ -> false
end
end
defp replace_word(text, target, replacement) do
escaped = Regex.escape(target)
text
|> String.replace(~r/(\W)#{escaped}(\W)/, "\\1#{replacement}\\2")
|> String.replace(~r/(\W)#{escaped}/, "\\1#{replacement}")
end
end
This flattens both snippets, tries consistent identifier replacements, and checks whether the rewritten code matches.