Skip to content

Instantly share code, notes, and snippets.

@Mazuh
Created April 22, 2024 16:15
Show Gist options
  • Select an option

  • Save Mazuh/f9c4bb150ee969dda6ba4e72d90a184e to your computer and use it in GitHub Desktop.

Select an option

Save Mazuh/f9c4bb150ee969dda6ba4e72d90a184e to your computer and use it in GitHub Desktop.

Revisions

  1. Mazuh created this gist Apr 22, 2024.
    54 changes: 54 additions & 0 deletions balanced_octopus.ex
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    defmodule BalancedOctopus do
    @opening_to_closing %{"(" => ")", "[" => "]", "{" => "}"}
    @closing_to_opening %{")" => "(", "]" => "[", "}" => "{"}

    def balanced?(text, stack \\ [])
    def balanced?("", []), do: true
    def balanced?(_text, :error), do: false
    def balanced?("", _pending_stack), do: false

    def balanced?(text, stack) do
    {current_char, next_text} = String.split_at(text, 1)
    updated_stack = maybe_stack(stack, current_char)
    balanced?(next_text, updated_stack)
    end

    defp maybe_stack(stack, char) do
    cond do
    Map.has_key?(@opening_to_closing, char) ->
    stack_push(stack, char)

    Map.has_key?(@closing_to_opening, char) ->
    {last_opening, rest} = stack_pop(stack)
    required_last_opening = @closing_to_opening[char]
    if last_opening == required_last_opening, do: rest, else: :error

    true ->
    stack
    end
    end

    defp stack_push(stack, inserting), do: [inserting | stack]

    defp stack_pop([]), do: {nil, []}
    defp stack_pop([popped | rest] = _stack), do: {popped, rest}
    end

    [
    ["abcd", true],
    ["(abcd", false],
    ["(abcd)", true],
    ["(ab[cd)ef]", false],
    ["(abc[%def])", true],
    ["$(abc[de]fg{hi}jk)%//", true],
    ["(({abc})", false]
    ]
    |> Enum.each(fn [text, expectation] ->
    IO.write("Testing #{text} as #{expectation}... ")

    if BalancedOctopus.balanced?(text) == expectation do
    IO.puts("✅")
    else
    IO.puts("🔴")
    end
    end)