przemyxe0p

przemyxe0p

What do you do if you’ve done an exercise, it works, it’s not very inefficient and seems concise, then you go to the community solutions, sort by highest-rated user and see this?

defmodule Sublist do
  @doc """
  Returns whether the first list is a sublist or a superlist of the second list
  and if not whether it is equal or unequal to the second list.
  """
  def compare(a, b) when is_list(a) and is_list(b) do
    case {contains?(a, b), contains?(b,a)} do
      {true, true} -> :equal
      {true, false} -> :superlist
      {false, true} -> :sublist
      {false, false} -> :unequal
    end
  end

  # determines if list a contains list b. restore_a is needed to restore
  # already "eaten" members of a, when b couldn't be matched completely
  defp contains?(a, b, current_b \\ :initial, restore_a \\ nil)
  defp contains?(a, b, :initial, nil), do: contains?(a, b, b, nil)
  defp contains?(_, _, [], _), do: true
  defp contains?([], _, _, _), do: false
  defp contains?([x | a], b, [x | c], nil), do: contains?(a, b, c, a)
  defp contains?([x | a], b, [x | c], restore_a), do: contains?(a, b, c, restore_a)
  defp contains?([_ | a], b, _, nil), do: contains?(a, b, b, nil)
  defp contains?(_, b, _, restore_a), do: contains?(restore_a, b, b, nil)
end

To clarify I enjoy creating solutions, and having to think, and play, but there is border.

Showing Posts 1 to 8

mudasobwa

mudasobwa

Creator of Cure

Create your own wrapper my_contains?/4 which would print the intermediate results and run it for several different inputs.

  def compare(a, b) when is_list(a) and is_list(b) do
    case {my_contains?(a, b), my_contains?(b,a)} do
      {true, true} -> :equal
      {true, false} -> :superlist
      {false, true} -> :sublist
      {false, false} -> :unequal
    end
  end

  defp my_contains?(a, b, current_b \\ :initial, restore_a \\ nil) do
    IO.inspect(a: a, b: b, current_b: current_b, restore_a: restore_a)
    contains?(a, b, current_b, restore_a)
  end

  defp contains?(a, b, current_b \\ :initial, restore_a \\ nil)
  defp contains?(a, b, :initial, nil), do: my_contains?(a, b, b, nil)
  defp contains?(_, _, [], _), do: true
  defp contains?([], _, _, _), do: false
  defp contains?([x | a], b, [x | c], nil), do: my_contains?(a, b, c, a)
  defp contains?([x | a], b, [x | c], restore_a), do: my_contains?(a, b, c, restore_a)
  defp contains?([_ | a], b, _, nil), do: my_contains?(a, b, b, nil)
  defp contains?(_, b, _, restore_a), do: my_contains?(restore_a, b, b, nil)```
derek-zhou

derek-zhou

The code you cited seems fine to me, pretty clever use of tail recursion. I am not sure what do you mean. do you mean:

  • You don’t like this code. Of course you can have a opinion and choose to use your own code. or:
  • You like this code but wish some one to explain to you in digestible pieces. Then you did not say which part you do not understand. Or:
  • You don’t care about this code at all, all you care is to win the competition to provide the best solution. Then it is a matter of skill issue, right?
przemyxe0p

przemyxe0p OP

It’s just too hard for me. I got overwhelmed
So, I’ve been getting better at reading community solutions, but still I don’t know in what order to read function clauses to understand it. Now sometimes i get it right away how sth works like i jump through lines with correct order to understand it fast. But How should you approach reading this kind of multiclause functions?

derek-zhou

derek-zhou

The correct reading order is from the top to bottom. If you want to improve your skill on tail recursion, write with it. Can you implement the enumerating functions in Enum, starting with Enum.reverse/1, with tail recursion? If you can write comfortably in tail recursion, it will click for you.

przemyxe0p

przemyxe0p OP

Yes i did it many times, implementing Enum.reverse/1 is easy for me.
for example right now i wrote function to flatten list:

  defp fl(list, acc \\ [])

  defp fl([], acc), do: acc

  defp fl([el | tail], acc) when is_list(el),
    do: fl(el, acc) |> then(&fl(tail, &1))

  defp fl([el | tail], acc) when not is_list(el),
    do: fl(tail, [el | acc])
end

The problem is 5 minutes later when i look at the code i want to add something, e.x ommiting some values, i cannot comprehand what is happening
XD

przemyxe0p

przemyxe0p OP

Reading from top to bottom is not always the way (for me) to understand how function will behave.

derek-zhou

derek-zhou

nitpick, can’t help it.

defp fl([], acc), do: Enum.reverse(acc)
przemyxe0p

przemyxe0p OP

  @spec flatten(list) :: list
  def flatten(list), do: fl(list) |> Enum.reverse()

  defp fl(list, acc \\ [])

  defp fl([], acc), do: acc

  defp fl([[_|_] = el | tail], acc), do: fl(el, acc) |> then(&fl(tail, &1))
  defp fl([nil | tail], acc), do: fl(tail, acc)
  defp fl([el | tail], acc),do: fl(tail, [el | acc])

I guess we should reverse at the end, not on intermediate states, and your suggestion would not work (I tested it).

How to tell if my above solution is proper tail-call recursion?

— All posts loaded —

Where Next? Top

Trending in Challenges Top

Other Trending Topics Top

webofbits
I’ve released the first beta of Draught, a coding-agent CLI and runtime built with Elixir. Draught can run agentic coding tasks using Ol...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews