All Downloads are FREE. Search and download functionalities are using the official Maven repository.

squidpony.ArrayTools Maven / Gradle / Ivy

Go to download

SquidLib platform-independent logic and utility code. Please refer to https://github.com/SquidPony/SquidLib .

There is a newer version: 3.0.6
Show newest version
package squidpony;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * Static methods for various frequently-used operations on 1D and 2D arrays. Has methods for copying, inserting, and
 * filling 2D arrays of primitive types (char, int, double, and boolean). Has a few mehods for creating ranges of ints
 * or chars easily as 1D arrays. Also contains certain methods for working with orderings, which can be naturally used
 * with {@link squidpony.squidmath.OrderedMap}, {@link squidpony.squidmath.OrderedSet}, {@link squidpony.squidmath.K2},
 * and similar ordered collections plus ArrayList using {@link #reorder(ArrayList, int...)} in this class.
 * Created by Tommy Ettinger on 11/17/2016.
 */
public class ArrayTools {

    static final char[] letters = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a',
            'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'À', 'Á',
            'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý',
            'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù',
            'ú', 'û', 'ü', 'ý', 'þ', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ',
            'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į',
            'İ', 'ı', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'ĸ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ',
            'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ',
            'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'Ǿ', 'ǿ', 'Ș', 'ș', 'Ț', 'ț',
            'Γ', 'Δ', 'Θ', 'Λ', 'Ξ', 'Π', 'Σ', 'Φ', 'Ψ', 'Ω', 'α', 'β', 'γ'};
    static final char[] empty = new char[0];

    /**
     * Stupidly simple convenience method that produces a range from 0 to end, not including end, as an int array.
     *
     * @param end the exclusive upper bound on the range
     * @return the range of ints as an int array
     */
    public static int[] range(int end) {
        if (end <= 0)
            return new int[0];
        int[] r = new int[end];
        for (int i = 0; i < end; i++) {
            r[i] = i;
        }
        return r;
    }

    /**
     * Stupidly simple convenience method that produces a range from start to end, not including end, as an int array.
     *
     * @param start the inclusive lower bound on the range
     * @param end   the exclusive upper bound on the range
     * @return the range of ints as an int array
     */
    public static int[] range(int start, int end) {
        if (end - start <= 0)
            return new int[0];
        int[] r = new int[end - start];
        for (int i = 0, n = start; n < end; i++, n++) {
            r[i] = n;
        }
        return r;
    }

    /**
     * Stupidly simple convenience method that produces a char range from start to end, including end, as a char array.
     *
     * @param start the inclusive lower bound on the range, such as 'a'
     * @param end   the inclusive upper bound on the range, such as 'z'
     * @return the range of chars as a char array
     */
    public static char[] charSpan(char start, char end) {
        if (end - start <= 0)
            return empty;
        if (end == 0xffff) {

            char[] r = new char[0x10000 - start];
            for (char i = 0, n = start; n < end; i++, n++) {
                r[i] = n;
            }
            r[0xffff - start] = 0xffff;
            return r;
        }
        char[] r = new char[end - start + 1];
        for (char i = 0, n = start; n <= end; i++, n++) {
            r[i] = n;
        }
        return r;
    }

    /**
     * Stupidly simple convenience method that produces a char array containing only letters that can be reasonably
     * displayed (with SquidLib's default text display assets, at least). The letters are copied from a single source
     * of 256 chars; if you need more chars or you don't need pure letters, you can use {@link #charSpan(char, char)}.
     * This set does not contain "visual duplicate" letters, such as Latin alphabet capital letter 'A' and Greek
     * alphabet capital letter alpha, 'Α'; it does contain many accented Latin letters and the visually-distinct Greek
     * letters, up to a point.
     * @param charCount the number of letters to return in an array; the maximum this will produce is 256
     * @return the range of letters as a char array
     */
    public static char[] letterSpan(int charCount) {
        if (charCount <= 0)
            return empty;
        char[] r = new char[Math.min(charCount, 256)];
        System.arraycopy(letters, 0, r, 0, r.length);
        return r;
    }

    /**
     * Gets the nth letter from the set that SquidLib is likely to support; from index 0 (returning 'A') to 255
     * (returning the Greek lower-case letter gamma, 'γ') and wrapping around if given negative numbers or numbers
     * larger than 255. This set does not contain "visual duplicate" letters, such as Latin alphabet capital letter 'A'
     * and Greek alphabet capital letter alpha, 'Α'; it does contain many accented Latin letters and the
     * visually-distinct Greek letters, up to a point.
     * @param index typically from 0 to 255, but all ints are allowed and will produce letters
     * @return the letter at the given index in a 256-element portion of the letters SquidLib usually supports
     */
    public static char letterAt(int index)
    {
        return letters[index & 255];
    }

    /**
     * Gets a copy of the 2D char array, source, that has the same data but shares no references with source.
     *
     * @param source a 2D char array
     * @return a copy of source, or null if source is null
     */
    public static char[][] copy(char[][] source) {
        if (source == null)
            return null;
        if (source.length < 1)
            return new char[0][0];
        char[][] target = new char[source.length][];
        for (int i = 0; i < source.length; i++) {
            target[i] = new char[source[i].length];
            System.arraycopy(source[i], 0, target[i], 0, source[i].length);
        }
        return target;
    }

    /**
     * Gets a copy of the 2D double array, source, that has the same data but shares no references with source.
     *
     * @param source a 2D double array
     * @return a copy of source, or null if source is null
     */
    public static double[][] copy(double[][] source) {
        if (source == null)
            return null;
        if (source.length < 1)
            return new double[0][0];
        double[][] target = new double[source.length][];
        for (int i = 0; i < source.length; i++) {
            target[i] = new double[source[i].length];
            System.arraycopy(source[i], 0, target[i], 0, source[i].length);
        }
        return target;
    }

    /**
     * Gets a copy of the 2D int array, source, that has the same data but shares no references with source.
     *
     * @param source a 2D int array
     * @return a copy of source, or null if source is null
     */
    public static int[][] copy(int[][] source) {
        if (source == null)
            return null;
        if (source.length < 1)
            return new int[0][0];
        int[][] target = new int[source.length][];
        for (int i = 0; i < source.length; i++) {
            target[i] = new int[source[i].length];
            System.arraycopy(source[i], 0, target[i], 0, source[i].length);
        }
        return target;
    }

    /**
     * Gets a copy of the 2D boolean array, source, that has the same data but shares no references with source.
     *
     * @param source a 2D boolean array
     * @return a copy of source, or null if source is null
     */
    public static boolean[][] copy(boolean[][] source) {
        if (source == null)
            return null;
        if (source.length < 1)
            return new boolean[0][0];
        boolean[][] target = new boolean[source.length][];
        for (int i = 0; i < source.length; i++) {
            target[i] = new boolean[source[i].length];
            System.arraycopy(source[i], 0, target[i], 0, source[i].length);
        }
        return target;
    }

    /**
     * Inserts as much of source into target at the given x,y position as target can hold or source can supply.
     * Modifies target in-place and also returns target for chaining.
     * Used primarily to place a smaller array into a different position in a larger array, often freshly allocated.
     *
     * @param source a 2D char array that will be copied and inserted into target
     * @param target a 2D char array that will be modified by receiving as much of source as it can hold
     * @param x      the x position in target to receive the items from the first cell in source
     * @param y      the y position in target to receive the items from the first cell in source
     * @return target, modified, with source inserted into it at the given position
     */
    public static char[][] insert(char[][] source, char[][] target, int x, int y) {
        if (source == null || target == null)
            return target;
        if (source.length < 1 || source[0].length < 1)
            return copy(target);
        for (int i = 0; i < source.length && x + i < target.length; i++) {
            System.arraycopy(source[i], 0, target[x + i], y, Math.min(source[i].length, target[x + i].length - y));
        }
        return target;
    }

    /**
     * Inserts as much of source into target at the given x,y position as target can hold or source can supply.
     * Modifies target in-place and also returns target for chaining.
     * Used primarily to place a smaller array into a different position in a larger array, often freshly allocated.
     *
     * @param source a 2D double array that will be copied and inserted into target
     * @param target a 2D double array that will be modified by receiving as much of source as it can hold
     * @param x      the x position in target to receive the items from the first cell in source
     * @param y      the y position in target to receive the items from the first cell in source
     * @return target, modified, with source inserted into it at the given position
     */
    public static double[][] insert(double[][] source, double[][] target, int x, int y) {
        if (source == null || target == null)
            return target;
        if (source.length < 1 || source[0].length < 1)
            return copy(target);
        for (int i = 0; i < source.length && x + i < target.length; i++) {
            System.arraycopy(source[i], 0, target[x + i], y, Math.min(source[i].length, target[x + i].length - y));
        }
        return target;
    }

    /**
     * Inserts as much of source into target at the given x,y position as target can hold or source can supply.
     * Modifies target in-place and also returns target for chaining.
     * Used primarily to place a smaller array into a different position in a larger array, often freshly allocated.
     *
     * @param source a 2D int array that will be copied and inserted into target
     * @param target a 2D int array that will be modified by receiving as much of source as it can hold
     * @param x      the x position in target to receive the items from the first cell in source
     * @param y      the y position in target to receive the items from the first cell in source
     * @return target, modified, with source inserted into it at the given position
     */
    public static int[][] insert(int[][] source, int[][] target, int x, int y) {
        if (source == null || target == null)
            return target;
        if (source.length < 1 || source[0].length < 1)
            return copy(target);
        for (int i = 0; i < source.length && x + i < target.length; i++) {
            System.arraycopy(source[i], 0, target[x + i], y, Math.min(source[i].length, target[x + i].length - y));
        }
        return target;
    }

    /**
     * Inserts as much of source into target at the given x,y position as target can hold or source can supply.
     * Modifies target in-place and also returns target for chaining.
     * Used primarily to place a smaller array into a different position in a larger array, often freshly allocated.
     *
     * @param source a 2D boolean array that will be copied and inserted into target
     * @param target a 2D boolean array that will be modified by receiving as much of source as it can hold
     * @param x      the x position in target to receive the items from the first cell in source
     * @param y      the y position in target to receive the items from the first cell in source
     * @return target, modified, with source inserted into it at the given position
     */
    public static boolean[][] insert(boolean[][] source, boolean[][] target, int x, int y) {
        if (source == null || target == null)
            return target;
        if (source.length < 1 || source[0].length < 1)
            return copy(target);
        for (int i = 0; i < source.length && x + i < target.length; i++) {
            System.arraycopy(source[i], 0, target[x + i], y, Math.min(source[i].length, target[x + i].length - y));
        }
        return target;
    }

    /**
     * Creates a 2D array of the given width and height, filled with entirely with the value contents.
     * You may want to use {@link #fill(char[][], char)} to modify an existing 2D array instead.
     * @param contents the value to fill the array with
     * @param width    the desired width
     * @param height   the desired height
     * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents
     */
    public static char[][] fill(char contents, int width, int height) {
        char[][] next = new char[width][height];
        for (int x = 0; x < width; x++) {
            Arrays.fill(next[x], contents);
        }
        return next;
    }

    /**
     * Creates a 2D array of the given width and height, filled with entirely with the value contents.
     * You may want to use {@link #fill(float[][], float)} to modify an existing 2D array instead.
     * @param contents the value to fill the array with
     * @param width    the desired width
     * @param height   the desired height
     * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents
     */
    public static float[][] fill(float contents, int width, int height) {
        float[][] next = new float[width][height];
        for (int x = 0; x < width; x++) {
            Arrays.fill(next[x], contents);
        }
        return next;
    }

    /**
     * Creates a 2D array of the given width and height, filled with entirely with the value contents.
     * You may want to use {@link #fill(double[][], double)} to modify an existing 2D array instead.
     * @param contents the value to fill the array with
     * @param width    the desired width
     * @param height   the desired height
     * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents
     */
    public static double[][] fill(double contents, int width, int height) {
        double[][] next = new double[width][height];
        for (int x = 0; x < width; x++) {
            Arrays.fill(next[x], contents);
        }
        return next;
    }

    /**
     * Creates a 2D array of the given width and height, filled with entirely with the value contents.
     * You may want to use {@link #fill(int[][], int)} to modify an existing 2D array instead.
     * @param contents the value to fill the array with
     * @param width    the desired width
     * @param height   the desired height
     * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents
     */
    public static int[][] fill(int contents, int width, int height) {
        int[][] next = new int[width][height];
        for (int x = 0; x < width; x++) {
            Arrays.fill(next[x], contents);
        }
        return next;
    }

    /**
     * Creates a 2D array of the given width and height, filled with entirely with the value contents.
     * You may want to use {@link #fill(byte[][], byte)} to modify an existing 2D array instead.
     * @param contents the value to fill the array with
     * @param width    the desired width
     * @param height   the desired height
     * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents
     */
    public static byte[][] fill(byte contents, int width, int height) {
        byte[][] next = new byte[width][height];
        for (int x = 0; x < width; x++) {
            Arrays.fill(next[x], contents);
        }
        return next;
    }

    /**
     * Creates a 2D array of the given width and height, filled with entirely with the value contents.
     * You may want to use {@link #fill(boolean[][], boolean)} to modify an existing 2D array instead.
     * @param contents the value to fill the array with
     * @param width    the desired width
     * @param height   the desired height
     * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents
     */
    public static boolean[][] fill(boolean contents, int width, int height) {
        boolean[][] next = new boolean[width][height];
        if (contents) {
            for (int x = 0; x < width; x++) {
                Arrays.fill(next[x], true);
            }
        }
        return next;
    }
    /**
     * Fills {@code array2d} with {@code value}.
     * Not to be confused with {@link #fill(boolean, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     */
    public static void fill(boolean[][] array2d, boolean value) {
        final int width = array2d.length;
        for (int i = 0; i < width; i++) {
            Arrays.fill(array2d[i], value);
        }
//        final int width = array2d.length;
//        final int height = width == 0 ? 0 : array2d[0].length;
//        if(width > 0) {
//            for (int i = 0; i < height; i++) {
//                array2d[0][i] = value;
//            }
//        }
//        for (int x = 1; x < width; x++) {
//            System.arraycopy(array2d[0], 0, array2d[x], 0, height);
//        }
    }

    /**
     * Fills {@code array2d} with {@code value}.
     * Not to be confused with {@link #fill(char, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     */
    public static void fill(char[][] array2d, char value) {
        final int width = array2d.length;
        for (int i = 0; i < width; i++) {
            Arrays.fill(array2d[i], value);
        }
//        final int width = array2d.length;
//        final int height = width == 0 ? 0 : array2d[0].length;
//        if(width > 0) {
//            for (int i = 0; i < height; i++) {
//                array2d[0][i] = value;
//            }
//        }
//        for (int x = 1; x < width; x++) {
//            System.arraycopy(array2d[0], 0, array2d[x], 0, height);
//        }
    }

    /**
     * Fills {@code array2d} with {@code value}.
     * Not to be confused with {@link #fill(float, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     */
    public static void fill(float[][] array2d, float value) {
        final int width = array2d.length;
        for (int i = 0; i < width; i++) {
            Arrays.fill(array2d[i], value);
        }
//        final int width = array2d.length;
//        final int height = width == 0 ? 0 : array2d[0].length;
//        if(width > 0) {
//            for (int i = 0; i < height; i++) {
//                array2d[0][i] = value;
//            }
//        }
//        for (int x = 1; x < width; x++) {
//            System.arraycopy(array2d[0], 0, array2d[x], 0, height);
//        }
    }


    /**
     * Fills {@code array2d} with {@code value}.
     * Not to be confused with {@link #fill(double, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     */
    public static void fill(double[][] array2d, double value) {
        final int width = array2d.length;
        for (int i = 0; i < width; i++) {
            Arrays.fill(array2d[i], value);
        }
//        final int height = width == 0 ? 0 : array2d[0].length;
//        if(width > 0) {
//            for (int i = 0; i < height; i++) {
//                array2d[0][i] = value;
//            }
//        }
//        for (int x = 1; x < width; x++) {
//            System.arraycopy(array2d[0], 0, array2d[x], 0, height);
//        }
    }

    /**
     * Fills {@code array3d} with {@code value}.
     * Not to be confused with {@link #fill(double[][], double)}, which fills a 2D array instead of a 3D one, or with
     * {@link #fill(double, int, int)}, which makes a new 2D array.
     * @param array3d a 3D array that will be modified in-place
     * @param value the value to fill all of array3d with
     */
    public static void fill(double[][][] array3d, double value) {
        final int depth = array3d.length;
        final int width = depth == 0 ? 0 : array3d[0].length;
        final int height = width == 0 ? 0 : array3d[0][0].length;
        if(depth > 0 && width > 0) {
            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    Arrays.fill(array3d[i][j], value);
                }
            }
        }
    }

    /**
     * Fills {@code array2d} with {@code value}.
     * Not to be confused with {@link #fill(int, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     */
    public static void fill(int[][] array2d, int value) {
        final int width = array2d.length;
        for (int i = 0; i < width; i++) {
            Arrays.fill(array2d[i], value);
        }

//        final int width = array2d.length;
//        final int height = width == 0 ? 0 : array2d[0].length;
//        if(width > 0) {
//            for (int i = 0; i < height; i++) {
//                array2d[0][i] = value;
//            }
//        }
//        for (int x = 1; x < width; x++) {
//            System.arraycopy(array2d[0], 0, array2d[x], 0, height);
//        }
    }

    /**
     * Fills {@code array2d} with {@code value}.
     * Not to be confused with {@link #fill(byte, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     */
    public static void fill(byte[][] array2d, byte value) {
        final int width = array2d.length;
        for (int i = 0; i < width; i++) {
            Arrays.fill(array2d[i], value);
        }
//        final int width = array2d.length;
//        final int height = width == 0 ? 0 : array2d[0].length;
//        if(width > 0) {
//            for (int i = 0; i < height; i++) {
//                array2d[0][i] = value;
//            }
//        }
//        for (int x = 1; x < width; x++) {
//            System.arraycopy(array2d[0], 0, array2d[x], 0, height);
//        }
    }


    /**
     * Fills a sub-section of {@code array2d} with {@code value}, with the section defined by start/end x/y.
     * Not to be confused with {@link #fill(boolean, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     * @param startX the first x position to fill (inclusive)
     * @param startY the first y position to fill (inclusive)
     * @param endX the last x position to fill (inclusive)
     * @param endY the last y position to fill (inclusive)
     */
    public static void fill(boolean[][] array2d, boolean value, int startX, int startY, int endX, int endY) {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        for (int x = startX; x <= endX && x < width; x++) {
            for (int y = startY; y <= endY && y < height; y++) {
                array2d[x][y] = value;
            }
        }
    }

    /**
     * Fills a sub-section of {@code array2d} with {@code value}, with the section defined by start/end x/y.
     * Not to be confused with {@link #fill(char, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     * @param startX the first x position to fill (inclusive)
     * @param startY the first y position to fill (inclusive)
     * @param endX the last x position to fill (inclusive)
     * @param endY the last y position to fill (inclusive)
     */
    public static void fill(char[][] array2d, char value, int startX, int startY, int endX, int endY) {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        for (int x = startX; x <= endX && x < width; x++) {
            for (int y = startY; y <= endY && y < height; y++) {
                array2d[x][y] = value;
            }
        }
    }

    /**
     * Fills a sub-section of {@code array2d} with {@code value}, with the section defined by start/end x/y.
     * Not to be confused with {@link #fill(float, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     * @param startX the first x position to fill (inclusive)
     * @param startY the first y position to fill (inclusive)
     * @param endX the last x position to fill (inclusive)
     * @param endY the last y position to fill (inclusive)
     */
    public static void fill(float[][] array2d, float value, int startX, int startY, int endX, int endY) {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        for (int x = startX; x <= endX && x < width; x++) {
            for (int y = startY; y <= endY && y < height; y++) {
                array2d[x][y] = value;
            }
        }
    }

    /**
     * Fills a sub-section of {@code array2d} with {@code value}, with the section defined by start/end x/y.
     * Not to be confused with {@link #fill(double, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     * @param startX the first x position to fill (inclusive)
     * @param startY the first y position to fill (inclusive)
     * @param endX the last x position to fill (inclusive)
     * @param endY the last y position to fill (inclusive)
     */
    public static void fill(double[][] array2d, double value, int startX, int startY, int endX, int endY) {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        for (int x = startX; x <= endX && x < width; x++) {
            for (int y = startY; y <= endY && y < height; y++) {
                array2d[x][y] = value;
            }
        }
    }

    /**
     * Fills a sub-section of {@code array2d} with {@code value}, with the section defined by start/end x/y.
     * Not to be confused with {@link #fill(int, int, int)}, which makes a new 2D array.
     * @param array2d a 2D array that will be modified in-place
     * @param value the value to fill all of array2D with
     * @param startX the first x position to fill (inclusive)
     * @param startY the first y position to fill (inclusive)
     * @param endX the last x position to fill (inclusive)
     * @param endY the last y position to fill (inclusive)
     */
    public static void fill(int[][] array2d, int value, int startX, int startY, int endX, int endY) {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        for (int x = startX; x <= endX && x < width; x++) {
            for (int y = startY; y <= endY && y < height; y++) {
                array2d[x][y] = value;
            }
        }
    }

    /**
     * Randomly fills all of {@code array2d} with random values generated from {@code seed}; can fill an element with
     * any long, positive or negative.
     * Fairly efficient; uses a fast random number generation algorithm that can avoid some unnecessary work in this
     * context, and improves quality by seeding each column differently. Generates {@code (height + 1) * width} random
     * values to fill the {@code height * width} elements in array2d.
     * @param array2d a 2D array that will be modified in-place
     * @param seed the seed for the random values, as a long
     */
    public static void randomFill(long[][] array2d, final long seed)
    {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        long r0 = seed, z;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                z = r0 ^ (((r0 >>> 23) ^ (r0 += 0xA99635D5B8597AE5L)) * 0xAD5DE9A61A9C3D95L);
                array2d[x][y] = z ^ (z >>> 29);
            }
        }
    }
    /**
     * Randomly fills all of {@code array2d} with random values generated from {@code seed}; can fill an element with
     * any int, positive or negative.
     * Fairly efficient; uses a fast random number generation algorithm that can avoid some unnecessary work in this
     * context, and improves quality by seeding each column differently. Generates {@code (height + 1) * width} random
     * values to fill the {@code height * width} elements in array2d.
     * @param array2d a 2D array that will be modified in-place
     * @param seed the seed for the random values, as a long
     */
    public static void randomFill(int[][] array2d, final long seed)
    {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        long r0 = seed, z;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                z = r0 ^ (((r0 >>> 23) ^ (r0 += 0xA99635D5B8597AE5L)) * 0xAD5DE9A61A9C3D95L);
                array2d[x][y] = (int)(z ^ (z >>> 29));
            }
        }
    }
    /**
     * Randomly fills all of {@code array2d} with random values generated from {@code seed}, limiting results to between
     * 0 and {@code bound}, exclusive.
     * Fairly efficient; uses a fast random number generation algorithm that can avoid some unnecessary work in this
     * context, and improves quality by seeding each column differently. Generates {@code (height + 1) * width} random
     * values to fill the {@code height * width} elements in array2d.
     * @param array2d a 2D array that will be modified in-place
     * @param bound the upper exclusive limit for the ints this can produce
     * @param seed the seed for the random values, as a long
     */
    public static void randomFill(int[][] array2d, final int bound, final long seed)
    {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        long r0 = seed, z;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                z = r0 ^ (((r0 >>> 23) ^ (r0 += 0xA99635D5B8597AE5L)) * 0xAD5DE9A61A9C3D95L);
                array2d[x][y] = (int) ((bound * ((z ^ (z >>> 29)) & 0xFFFFFFFFL)) >> 32);
            }
        }
    }
    /**
     * Randomly fills all of {@code array2d} with random values generated from {@code seed}, choosing chars to place in
     * the given 2D array by selecting them at random from the given 1D char array {@code values}.
     * Fairly efficient; uses a fast random number generation algorithm that can avoid some unnecessary work in this
     * context, and improves quality by seeding each column differently. Generates {@code (height + 1) * width} random
     * values to fill the {@code height * width} elements in array2d.
     * @param array2d a 2D array that will be modified in-place
     * @param values a 1D char array containing the possible char values that can be chosen to fill array2d
     * @param seed the seed for the random values, as a long
     */
    public static void randomFill(char[][] array2d, final char[] values, final long seed)
    {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        final int bound = values.length;
        long r0 = seed + bound, z;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                z = r0 ^ (((r0 >>> 23) ^ (r0 += 0xA99635D5B8597AE5L)) * 0xAD5DE9A61A9C3D95L);
                array2d[x][y] = values[(int) ((bound * ((z ^ (z >>> 29)) & 0xFFFFFFFFL)) >>> 32)];
            }
        }
    }

    /**
     * Randomly fills all of {@code array2d} with random values generated from {@code seed}, choosing chars to place in
     * the given 2D array by selecting them at random from the given 1D char array {@code values}.
     * Fairly efficient; uses a fast random number generation algorithm that can avoid some unnecessary work in this
     * context, and improves quality by seeding each column differently. Generates {@code (height + 1) * width} random
     * values to fill the {@code height * width} elements in array2d.
     * @param array2d a 2D array that will be modified in-place
     * @param values a 1D char array containing the possible char values that can be chosen to fill array2d
     * @param seed the seed for the random values, as a long
     */
    public static void randomFill(char[][] array2d, final CharSequence values, final long seed)
    {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        final int bound = values.length();
        long r0 = seed + bound, z;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                z = r0 ^ (((r0 >>> 23) ^ (r0 += 0xA99635D5B8597AE5L)) * 0xAD5DE9A61A9C3D95L);
                array2d[x][y] = values.charAt((int) ((bound * ((z ^ (z >>> 29)) & 0xFFFFFFFFL)) >>> 32));
            }
        }
    }

    /**
     * Randomly fills all of {@code array2d} with random values generated from {@code seed}; can fill an element with
     * any float between 0.0 inclusive and 1.0 exclusive.
     * Fairly efficient; uses a fast random number generation algorithm that can avoid some unnecessary work in this
     * context, and improves quality by seeding each column differently. Generates {@code (height + 1) * width} random
     * values to fill the {@code height * width} elements in array2d.
     * @param array2d a 2D array that will be modified in-place
     * @param seed the seed for the random values, as a long
     */
    public static void randomFill(float[][] array2d, final long seed)
    {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        long r0 = seed, z;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                z = r0 ^ (((r0 >>> 23) ^ (r0 += 0xA99635D5B8597AE5L)) * 0xAD5DE9A61A9C3D95L);
                array2d[x][y] = ((z ^ (z >>> 29)) & 0xFFFFFFL) * 0x1p-24f;
            }
        }
    }
    /**
     * Randomly fills all of {@code array2d} with random values generated from {@code seed}, limiting results to between
     * 0 and {@code bound}, exclusive.
     * Fairly efficient; uses a fast random number generation algorithm that can avoid some unnecessary work in this
     * context, and improves quality by seeding each column differently. Generates {@code (height + 1) * width} random
     * values to fill the {@code height * width} elements in array2d.
     * @param array2d a 2D array that will be modified in-place
     * @param bound the upper exclusive limit for the floats this can produce
     * @param seed the seed for the random values, as a long
     */
    public static void randomFill(float[][] array2d, final float bound, final long seed) {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        long r0 = seed, z;
        final float mul = 0x1p-24f * bound;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                z = r0 ^ (((r0 >>> 23) ^ (r0 += 0xA99635D5B8597AE5L)) * 0xAD5DE9A61A9C3D95L);
                array2d[x][y] = ((z ^ (z >>> 29)) & 0xFFFFFFL) * mul;
            }
        }
    }

    /**
     * Randomly fills all of {@code array2d} with random values generated from {@code seed}; can fill an element with
     * any double between 0.0 inclusive and 1.0 exclusive.
     * Fairly efficient; uses a fast random number generation algorithm that can avoid some unnecessary work in this
     * context, and improves quality by seeding each column differently. Generates {@code (height + 1) * width} random
     * values to fill the {@code height * width} elements in array2d.
     * @param array2d a 2D array that will be modified in-place
     * @param seed the seed for the random values, as a long
     */
    public static void randomFill(double[][] array2d, final long seed)
    {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        long r0 = seed, z;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                z = r0 ^ (((r0 >>> 23) ^ (r0 += 0xA99635D5B8597AE5L)) * 0xAD5DE9A61A9C3D95L);
                array2d[x][y] = ((z ^ (z >>> 29)) & 0x1FFFFFFFFFFFFFL) * 0x1p-53;
            }
        }
    }
    /**
     * Randomly fills all of {@code array2d} with random values generated from {@code seed}, limiting results to between
     * 0 and {@code bound}, exclusive.
     * Fairly efficient; uses a fast random number generation algorithm that can avoid some unnecessary work in this
     * context, and improves quality by seeding each column differently. Generates {@code (height + 1) * width} random
     * values to fill the {@code height * width} elements in array2d.
     * @param array2d a 2D array that will be modified in-place
     * @param bound the upper exclusive limit for the doubles this can produce
     * @param seed the seed for the random values, as a long
     */
    public static void randomFill(double[][] array2d, final double bound, final long seed)
    {
        final int width = array2d.length;
        final int height = width == 0 ? 0 : array2d[0].length;
        long r0 = seed, z;
        final double mul = 0x1p-53 * bound;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                z = r0 ^ (((r0 >>> 23) ^ (r0 += 0xA99635D5B8597AE5L)) * 0xAD5DE9A61A9C3D95L);
                array2d[x][y] = ((z ^ (z >>> 29)) & 0x1FFFFFFFFFFFFFL) * mul;
            }
        }

    }

    /**
     * Rearranges an ArrayList to use the given ordering, returning a copy; random orderings can be produced with
     * {@link squidpony.squidmath.RNG#randomOrdering(int)} or
     * {@link squidpony.squidmath.RNG#randomOrdering(int, int[])}. These orderings will never repeat an earlier element,
     * and the returned ArrayList may be shorter than the original if {@code ordering} isn't as long as {@code list}.
     * Using a random ordering is like shuffling, but allows you to repeat the shuffle exactly on other collections of
     * the same size. A reordering can also be inverted with {@link #invertOrdering(int[])} or
     * {@link #invertOrdering(int[], int[])}, getting the change that will undo another ordering.
     *
     * @param list     an ArrayList that you want a reordered version of; will not be modified.
     * @param ordering an ordering, typically produced by one of RNG's randomOrdering methods.
     * @param       any generic type
     * @return a modified copy of {@code list} with its ordering changed to match {@code ordering}.
     */
    public static  ArrayList reorder(ArrayList list, int... ordering) {
        int ol;
        if (list == null || ordering == null || (ol = Math.min(list.size(), ordering.length)) == 0)
            return list;
        ArrayList alt = new ArrayList(ol);
        for (int i = 0; i < ol; i++) {
            alt.add(list.get((ordering[i] % ol + ol) % ol));
        }
        return alt;
    }

    /**
     * Given an ordering such as one produced by {@link squidpony.squidmath.RNG#randomOrdering(int, int[])}, this finds
     * its inverse, able to reverse the reordering and vice versa.
     *
     * @param ordering the ordering to find the inverse for
     * @return the inverse of ordering
     */
    public static int[] invertOrdering(int[] ordering) {
        int ol = 0;
        if (ordering == null || (ol = ordering.length) == 0) return ordering;
        int[] next = new int[ol];
        for (int i = 0; i < ol; i++) {
            if (ordering[i] < 0 || ordering[i] >= ol) return next;
            next[ordering[i]] = i;
        }
        return next;
    }

    /**
     * Given an ordering such as one produced by {@link squidpony.squidmath.RNG#randomOrdering(int, int[])}, this finds
     * its inverse, able to reverse the reordering and vice versa. This overload doesn't allocate a new int
     * array, and instead relies on having an int array of the same size as ordering passed to it as an
     * additional argument.
     *
     * @param ordering the ordering to find the inverse for
     * @param dest     the int array to put the inverse reordering into; should have the same length as ordering
     * @return the inverse of ordering; will have the same value as dest
     */
    public static int[] invertOrdering(int[] ordering, int[] dest) {
        int ol = 0;
        if (ordering == null || dest == null || (ol = Math.min(ordering.length, dest.length)) == 0)
            return ordering;
        for (int i = 0; i < ol; i++) {
            if (ordering[i] < 0 || ordering[i] >= ol) return dest;
            dest[ordering[i]] = i;
        }
        return dest;
    }

    /**
     * Reverses the array given as a parameter, in-place, and returns the modified original.
     * @param data an array that will be reversed in-place
     * @return the array passed in, after reversal
     */
    public static boolean[] reverse(boolean[] data)
    {
        int sz;
        if(data == null || (sz = data.length) <= 0) return data;
        boolean t;
        for (int i = 0, j = sz - 1; i < j; i++, j--) {
            t = data[j];
            data[j] = data[i];
            data[i] = t;
        }
        return data;
    }

    /**
     * Reverses the array given as a parameter, in-place, and returns the modified original.
     * @param data an array that will be reversed in-place
     * @return the array passed in, after reversal
     */
    public static char[] reverse(char[] data)
    {
        int sz;
        if(data == null || (sz = data.length) <= 0) return data;
        char t;
        for (int i = 0, j = sz - 1; i < j; i++, j--) {
            t = data[j];
            data[j] = data[i];
            data[i] = t;
        }
        return data;
    }

    /**
     * Reverses the array given as a parameter, in-place, and returns the modified original.
     * @param data an array that will be reversed in-place
     * @return the array passed in, after reversal
     */
    public static float[] reverse(float[] data)
    {
        int sz;
        if(data == null || (sz = data.length) <= 0) return data;
        float t;
        for (int i = 0, j = sz - 1; i < j; i++, j--) {
            t = data[j];
            data[j] = data[i];
            data[i] = t;
        }
        return data;
    }

    /**
     * Reverses the array given as a parameter, in-place, and returns the modified original.
     * @param data an array that will be reversed in-place
     * @return the array passed in, after reversal
     */
    public static double[] reverse(double[] data)
    {
        int sz;
        if(data == null || (sz = data.length) <= 0) return data;
        double t;
        for (int i = 0, j = sz - 1; i < j; i++, j--) {
            t = data[j];
            data[j] = data[i];
            data[i] = t;
        }
        return data;
    }

    /**
     * Reverses the array given as a parameter, in-place, and returns the modified original.
     * @param data an array that will be reversed in-place
     * @return the array passed in, after reversal
     */
    public static int[] reverse(int[] data)
    {
        int sz;
        if(data == null || (sz = data.length) <= 0) return data;
        int t;
        for (int i = 0, j = sz - 1; i < j; i++, j--) {
            t = data[j];
            data[j] = data[i];
            data[i] = t;
        }
        return data;
    }

    /**
     * Reverses the array given as a parameter, in-place, and returns the modified original.
     * @param data an array that will be reversed in-place
     * @return the array passed in, after reversal
     */
    public static byte[] reverse(byte[] data)
    {
        int sz;
        if(data == null || (sz = data.length) <= 0) return data;
        byte t;
        for (int i = 0, j = sz - 1; i < j; i++, j--) {
            t = data[j];
            data[j] = data[i];
            data[i] = t;
        }
        return data;
    }
    /**
     * Reverses the array given as a parameter, in-place, and returns the modified original.
     * @param data an array that will be reversed in-place
     * @return the array passed in, after reversal
     */
    public static T[] reverse(T[] data)
    {
        int sz;
        if(data == null || (sz = data.length) <= 0) return data;
        T t;
        for (int i = 0, j = sz - 1; i < j; i++, j--) {
            t = data[j];
            data[j] = data[i];
            data[i] = t;
        }
        return data;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy