What is the best way to do minimum_swaping in Elixir.

Hello Everyone. Thanks for your help in advance.
I am trying to do a minimum swap with the script below.

Script:
def minimum_swaps(list) when is_list(list) do
t = minimum_swaps_iter(list)
if t == list, do: t, else: minimum_swaps(t)
end

def minimum_swaps_iter([y, x | t]) when y <x, do: [x | minimum_swaps_iter([y | t])]
def minimum_swaps_iter([y, x | t]), do: [y | minimum_swaps_iter([x | t])]
def minimum_swaps_iter(list), do: list

Below is my sample test:

use ExUnit.Case
import Challenge, only: [minimum_swaps: 1]

test “should handle single swap” do
assert minimum_swaps([3, 1, 2]) == 1
end

test “should handle multiple swaps” do
assert minimum_swaps([3, 1, 2, 4]) == 2
end

Results: Failed: Test Results: MinimumSwaps
test should handle single swap

  1. test should handle single swap (MinimumSwaps)
    test/solution_test.exs:5
    Assertion with == failed
    code: assert minimum_swaps([3, 1, 2]) == 1
    left: [3, 2, 1]
    right: 1
    stacktrace:
    test/solution_test.exs:6: (test)
    Completed in 2.9350ms
    test should handle multiple swaps
  2. test should handle multiple swaps (MinimumSwaps)
    test/solution_test.exs:9
    Assertion with == failed
    code: assert minimum_swaps([3, 1, 2, 4]) == 2
    left: [4, 3, 2, 1]
    right: 2
    stacktrace:
    test/solution_test.exs:10: (test)
    Completed in 0.0160ms Completed in 2.9510ms

Please , where / what exactly is wrong with my script.?

:wave:

You are returning a sorted list from minimum_swaps instead of the count of times it ran. This makes the test fail.

You can maintain a counter and increment it each time you call minimum_swaps:

def minimum_swaps(list) when is_list(list) do
  minimum_swaps(list, 0)
end

defp minimum_swaps(list, counter) do
  t = minimum_swaps_iter(list)
  if t == list, do: counter, else: minimum_swaps(t, counter + 1)
end

That would probably make the tests pass.

This is exactly what I was about to suggest, except when you run it one of the tests still fails.

  1) test should handle multiple swaps (ChallengeTest)
     test/challenge_test.exs:9
     Assertion with == failed
     code:  assert minimum_swaps([3, 1, 2, 4]) == 2
     left:  3
     right: 2
     stacktrace:
       test/challenge_test.exs:10: (test)

@millinkan you might need to explain exactly what you expect the code to do if this test is expected to pass

1 Like

I want the swapping to be done once/twice to give an output in the descending order.
[3, 1, 2] → [3, 2, 1] . —> 1 onces
[3, 1, 2, 4] → [3, 4, 2, 1] → [4, 3, 2, 1] . —> twice 2.

I don’t want to use Enum.reverse().

For the second list your algorithm produces:

         y  x               y  x               y  x
iter 1: [3, 1, 2, 4] -> [3, 2, 1, 4] -> [3, 2, 4, 1]
iter 2: [3, 2, 4, 1] -> [3, 2, 4, 1] -> [3, 4, 2, 1]
iter 3: [3, 4, 2, 1] -> [4, 3, 2, 1] -> [4, 3, 2, 1]

So it takes three steps. It needs at least 3 steps to move 4 from right to left.

1 Like

Hmmm…
Thanks Ruslandoga, can you help with a solution that will use the minimum number of swaps.?
So for the second list, 2 steps will be ok, in order to pass the test and then 1 step for the first list.