Package org.drools.verifier.misc

Source Code of org.drools.verifier.misc.FindMissingNumber

/**
* Copyright 2010 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.drools.verifier.misc;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;

import org.drools.verifier.components.NumberRestriction;

public class FindMissingNumber {

    public static final int MIN_NUMBER_OF_RESTRICTIONS = 4;

    /**
     * Test if the values in constraints are in pattern.
     *
     * @param restrictions
     * @return false if can't find a pattern or constraints list is null or size
     *         of the list is under 3.
     */
    public static Number testForPattern(Collection<NumberRestriction> restrictions) {

        if ( restrictions == null || restrictions.size() < MIN_NUMBER_OF_RESTRICTIONS ) {
            return null;
        }

        BigDecimal[] numbers = new BigDecimal[restrictions.size()];

        int index = 0;
        for ( NumberRestriction restriction : restrictions ) {
            if ( restriction.isInt() ) {
                numbers[index++] = BigDecimal.valueOf( restriction.getValue().intValue() );
            } else {
                numbers[index++] = BigDecimal.valueOf( restriction.getValue().doubleValue() );
            }
        }

        Arrays.sort( numbers );

        Number missingNumber = findSumPattern( numbers );
        if ( missingNumber != null ) {
            return missingNumber;
        } else {
            missingNumber = findMultiplicationPattern( numbers );
            if ( missingNumber != null ) {
                return missingNumber;
            }
        }

        return null;
    }

    /**
     * Looks for sum pattern, on each step x is added or removed. -x is the same
     * as +(-x) so this works for both.
     *
     * @param numbers
     * @return true if pattern is found.
     */
    protected static Number findSumPattern(BigDecimal[] numbers) {
        if ( numbers == null || numbers.length < MIN_NUMBER_OF_RESTRICTIONS ) {
            return null;
        }
        BigDecimal gap = null;
        Number missingNumber = null;

        BigDecimal a = numbers[0];
        BigDecimal b = numbers[1];
        BigDecimal c = numbers[2];
        BigDecimal d = numbers[3];

        // Uses first four numbers to check if there is a pattern and to
        // calculate the gap between them. One missing value is allowed.
        if ( b.subtract( a ).equals( c.subtract( b ) ) ) {
            gap = b.subtract( a );
        } else if ( c.subtract( b ).equals( d.subtract( c ) ) ) {
            gap = c.subtract( b );
        } else if ( b.subtract( a ).equals( d.subtract( c ) ) ) {
            gap = b.subtract( a );
        } else {
            // No pattern found.
            return null;
        }

        for ( int i = 0; i < (numbers.length - 1); i++ ) {
            BigDecimal first = numbers[i];
            BigDecimal second = numbers[i + 1];

            if ( missingNumber == null && !second.subtract( first ).equals( gap ) ) {
                missingNumber = second.subtract( gap );
            } else if ( !second.subtract( first ).equals( gap ) && missingNumber != null ) {
                // Happends if there is no pattern found, or more than 1
                // missing number.
                return null;
            }
        }

        return missingNumber;
    }

    /**
     * Looks for multiplication pattern, on each step x multiplied or divided.
     * *x is the same as *(1/x) so this works for both.
     *
     * @param numbers
     * @return true if pattern is found.
     */
    protected static Number findMultiplicationPattern(BigDecimal[] numbers) {
        if ( numbers == null || numbers.length < MIN_NUMBER_OF_RESTRICTIONS ) {
            return null;
        }
        try {

            BigDecimal gap = null;
            Number missingNumber = null;

            BigDecimal a = numbers[0];
            BigDecimal b = numbers[1];
            BigDecimal c = numbers[2];
            BigDecimal d = numbers[3];

            // Uses first four numbers to check if there is a pattern and to
            // calculate the gap between them. One missing value is allowed.
            if ( b.divide( a ).equals( c.divide( b ) ) ) {
                gap = b.divide( a );
            } else if ( c.divide( b ).equals( d.divide( c ) ) ) {
                gap = c.divide( b );
            } else if ( b.divide( a ).equals( d.divide( c ) ) ) {
                gap = b.divide( a );
            } else {
                // No pattern found.
                return null;
            }

            BigDecimal first = null;
            BigDecimal second = null;
            for ( int i = 0; i < (numbers.length - 1); i++ ) {
                first = numbers[i];
                second = numbers[i + 1];

                if ( missingNumber == null && !second.divide( first ).equals( gap ) ) {
                    missingNumber = first.multiply( gap );
                } else if ( !second.divide( first ).equals( gap ) && missingNumber != null ) {
                    // Happends if there is no pattern found, or more than 1
                    // missing number.
                    return null;
                }
            }
            return missingNumber;
        } catch ( Exception e ) {
            return null;
        }
    }
}
TOP

Related Classes of org.drools.verifier.misc.FindMissingNumber

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.