如何在Elixir中重写Erlang组合算法?

时间:2015-06-02 01:00:48

标签: functional-programming erlang elixir

过去几周我一直在修补Elixir。我刚刚遇到了这个简洁的combinations algorithm in Erlang,我尝试在Elixir中重写但是卡住了。

Erlang版本:

comb(0,_) ->
  [[]];
comb(_,[]) ->
  [];
comb(N,[H|T]) ->
  [[H|L] || L <- comb(N-1,T)]++comb(N,T).

Elixir版本我想出了这个,但它不正确:

def combination(0, _), do: [[]]
def combination(_, []), do: []
def combination(n, [x|xs]) do
  for y <- combination(n - 1, xs), do: [x|y] ++ combination(n, xs)
end

使用示例,结果不正确:

iex> combination(2, [1,2,3])
[[1, 2, [3], [2, 3]]]

关于我做错了什么的指示?

谢谢!
肖恩

1 个答案:

答案 0 :(得分:14)

您需要将for表达式包装在括号中,如Erlang代码。

iex(1)> defmodule Foo do
...(1)>   def combination(0, _), do: [[]]
...(1)>   def combination(_, []), do: []
...(1)>   def combination(n, [x|xs]) do
...(1)>     (for y <- combination(n - 1, xs), do: [x|y]) ++ combination(n, xs)
...(1)>   end
...(1)> end
{:module, Foo,
 <<70, 79, 82, 49, 0, 0, 6, 100, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 137, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 2, 104, 2, ...>>,
 {:combination, 2}}
iex(2)> Foo.combination 2, [1, 2, 3]
[[1, 2], [1, 3], [2, 3]]

演示:

@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
  getWindow().getDecorView().setSystemUiVisibility(View.GONE);
return true;    
}
return super.onTouchEvent(event);
}

private void onLeftSwipe() {

     finish();  
    overridePendingTransition  (R.anim.left_in,R.anim.left_out);
 }

private void onRightSwipe() {
  // Do something
    finish();   
    overridePendingTransition  (R.anim.right_out , R.anim.right_in);
}
    // Private class for gestures


public class SwipeGestureDetector extends SimpleOnGestureListener {
  // Swipe properties, you can change it to make the swipe 
  // longer or shorter and speed
  private static final int SWIPE_MIN_DISTANCE = 120;
  private static final int SWIPE_MAX_OFF_PATH = 200;
  private static final int SWIPE_THRESHOLD_VELOCITY = 200;

  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2,
                       float velocityX, float velocityY) {
    try {
      float diffAbs = Math.abs(e1.getY() - e2.getY());
      float diff = e1.getX() - e2.getX();

      if (diffAbs > SWIPE_MAX_OFF_PATH)
        return false;

      // Left swipe
      if (diff > SWIPE_MIN_DISTANCE && Math.abs(velocityX) >     SWIPE_THRESHOLD_VELOCITY) {
    shake_or_swipe.this.onLeftSwipe();

  // Right swipe
  } else if (-diff > SWIPE_MIN_DISTANCE && Math.abs(velocityX) >     SWIPE_THRESHOLD_VELOCITY) {
    shake_or_swipe.this.onRightSwipe();
  }
} catch (Exception e) {
  Log.e("Shake Activity", "Error on gestures");
}
return false;
  }
}