/**
 * This file is part of choco-solver, http://choco-solver.org/
 *
 * Copyright (c) 2018, IMT Atlantique. All rights reserved.
 *
 * Licensed under the BSD 4-clause license.
 * See LICENSE file in the project root for full license information.
 */
package org.chocosolver.solver.constraints.binary.element;

import org.chocosolver.solver.constraints.Constraint;
import org.chocosolver.solver.constraints.ConstraintsName;
import org.chocosolver.solver.variables.IntVar;

/**
 * A factory that selects the most adapted element propagator.
 * Created by cprudhom on 29/09/15.
 * Project: choco.
 */
public class ElementFactory {
    private ElementFactory() {
    }

    /**
     * Count the number of time the values in TABLE increase or decrease (ie, count picks and valleys).
     *
     * @param TABLE an array of values
     * @return the number of picks and valleys
     */
    private static int sawtooth(int[] TABLE) {
        int i = 0;
        while (i < TABLE.length - 1 && TABLE[i] == TABLE[i + 1]) {
            i++;
        }
        if (i == TABLE.length - 1) {
            return -1;
        }
        boolean up = TABLE[i] < TABLE[i + 1];
        int c = 0;
        i++;
        while (i < TABLE.length - 1) {
            if (up && TABLE[i] > TABLE[i + 1]) {
                c++;
                up = false;
            } else if (!up && TABLE[i] < TABLE[i + 1]) {
                c++;
                up = true;
            }
            i++;
        }
        return c;
    }

    /**
     * Detect and return the most adapted Element propagator wrt to the values in TABLE
     *
     * @param VALUE  the result variable
     * @param TABLE  the array of values
     * @param INDEX  the index variable
     * @param OFFSET the offset
     * @return an Element constraint
     */
    public static Constraint detect(IntVar VALUE, int[] TABLE, IntVar INDEX, int OFFSET) {
        // first chech the variables match
        int st = sawtooth(TABLE);
        if (st == -1) { // all values from TABLE are the same OR TABLE only contains one value
            assert TABLE[0] == TABLE[TABLE.length - 1];
            VALUE.getModel().member(INDEX, 0, TABLE.length - OFFSET).post();
            return VALUE.getModel().arithm(VALUE, "=", TABLE[0]);
        }
        return new Constraint(ConstraintsName.ELEMENT, new PropElement(VALUE, TABLE, INDEX, OFFSET));
    }
}

@@ -417,16 +417,142 @@
 tsName;%0A
+import org.chocosolver.solver.constraints.unary.PropEqualXC;%0Aimport org.chocosolver.solver.constraints.unary.PropMemberBound;%0A
 import o
@@ -2252,31 +2252,82 @@
     
-VALUE.getModel().member
+return new Constraint(%22FAKE_ELMT%22,%0A                    new PropMemberBound
 (IND
@@ -2359,16 +2359,9 @@
 SET)
-.post();
+,
 %0A   
@@ -2373,50 +2373,38 @@
     
-return VALUE.getModel().arithm
+        new PropEqualXC
 (VALUE,
- %22=%22,
  TAB
@@ -2409,16 +2409,30 @@
 ABLE%5B0%5D)
+%0A            )
 ;%0A      

Fix #600 again