Neue choice() Methoden

This commit is contained in:
ngb
2022-07-27 13:55:11 +02:00
parent 687d7d35b7
commit 03d37222bf
2 changed files with 171 additions and 8 deletions

View File

@@ -8,16 +8,17 @@ import java.awt.Cursor;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Random; import java.util.Random;
import java.util.function.DoubleUnaryOperator; import java.util.function.DoubleUnaryOperator;
/** /**
* Basisklasse für die meisten Objekte der Zeichemaschine, die von Nutzern * Basisklasse für die meisten Objekte der Zeichenmaschine, die von Nutzern
* erweitert werden können. * erweitert werden können.
* <p> * <p>
* Die Konstanten stellen viele Funktionen zur einfachen Programmierung bereit * Die Konstanten stellen viele Funktionen zur einfachen Programmierung bereit
* und enthält auch einige dynamische Werte, die von der Zeichenmaschine laufend * und enthält auch einige dynamische Werte, die von der Zeichenmaschine laufend
* aktuell gehalten werden (beispielsweise {@link #runtime}. * aktuell gehalten werden (beispielsweise {@link #runtime}).
* <p> * <p>
* Für die Implementierung eigener Klassen ist es oft hilfreich von * Für die Implementierung eigener Klassen ist es oft hilfreich von
* {@code Constants} zu erben, um die Methoden und Konstanten einfach im * {@code Constants} zu erben, um die Methoden und Konstanten einfach im
@@ -64,13 +65,49 @@ public class Constants {
/** /**
* Patchversion der Zeichenmaschine. * Patchversion der Zeichenmaschine.
*/ */
public static final int APP_VERSION_REV = 22; public static final int APP_VERSION_REV = 31;
/** /**
* Version der Zeichenmaschine als Text-String. * Version der Zeichenmaschine als Text-String.
*/ */
public static final String APP_VERSION = APP_VERSION_MAJ + "." + APP_VERSION_MIN + "." + APP_VERSION_REV; public static final String APP_VERSION = APP_VERSION_MAJ + "." + APP_VERSION_MIN + "." + APP_VERSION_REV;
/**
* Gibt an, ob die Zeichenmaschine unter macOS gestartet wurde.
*/
public static final boolean MACOS;
/**
* Gibt an, ob die Zeichenmaschine unter Windows gestartet wurde.
*/
public static final boolean WINDOWS;
/**
* Gibt an, ob die Zeichenmaschine unter Linux gestartet wurde.
*/
public static final boolean LINUX;
static {
final String name = System.getProperty("os.name");
if( name.contains("Mac") ) {
MACOS = true;
WINDOWS = false;
LINUX = false;
} else if( name.contains("Windows") ) {
MACOS = false;
WINDOWS = true;
LINUX = false;
} else if( name.equals("Linux") ) { // true for the ibm vm
MACOS = false;
WINDOWS = false;
LINUX = true;
} else {
MACOS = false;
WINDOWS = false;
LINUX = false;
}
}
/** /**
* Standardbreite eines Zeichenfensters. * Standardbreite eines Zeichenfensters.
@@ -1280,6 +1317,26 @@ public class Constants {
return getRandom().nextGaussian(); return getRandom().nextGaussian();
} }
/**
* Wählt ein zufälliges Element aus dem Array aus.
*
* @param values Ein Array mit Werten, die zur Auswahl stehen.
* @return Ein zufälliges Element aus dem Array.
*/
public static final int choice( int[] values ) {
return values[random(0, values.length - 1)];
}
/**
* Wählt ein zufälliges Element aus dem Array aus.
*
* @param values Ein Array mit Werten, die zur Auswahl stehen.
* @return Ein zufälliges Element aus dem Array.
*/
public static final double choice( double[] values ) {
return values[random(0, values.length - 1)];
}
/** /**
* Wählt ein zufälliges Element aus dem Array aus. * Wählt ein zufälliges Element aus dem Array aus.
* *
@@ -1291,6 +1348,69 @@ public class Constants {
return values[random(0, values.length - 1)]; return values[random(0, values.length - 1)];
} }
/**
* Wählt die angegebene Anzahl Elemente aus dem Array aus.
*
* @param values Ein Array mit Werten, die zur Auswahl stehen.
* @param n Anzahl der auszuwählenden Elemente.
* @param unique Bei {@code true} werden Elemente im Array nur maximal
* einmal ausgewählt (Ziehen ohne Zurücklegen).
* @return Ein zufälliges Element aus dem Array.
* @throws IllegalArgumentException Wenn {@code unique == true} und
* {@code values.length < n}, also nicht
* genug Werte zur Wahl stehen.
*/
public static final int[] choice( int[] values, int n, boolean unique ) {
if( unique && values.length < n )
throw new IllegalArgumentException(
String.format("Need at least <%d> values to choose <%d> unique values (<%d> given).", n, n, values.length)
);
int[] result = new int[n];
int[] valuesCopy = Arrays.copyOf(values, values.length);
for( int i = 0; i < n; i++ ) {
int j = random(0, valuesCopy.length-1);
int l = valuesCopy.length-1;
result[i] = valuesCopy[j];
valuesCopy[j] = valuesCopy[l];
valuesCopy[l] = result[i];
if( unique )
valuesCopy = Arrays.copyOf(valuesCopy, l);
}
return result;
}
/**
* Wählt die angegebene Anzahl Elemente aus dem Array aus.
*
* @param values Ein Array mit Werten, die zur Auswahl stehen.
* @param n Anzahl der auszuwählenden Elemente.
* @return Ein zufälliges Element aus dem Array.
*/
public static final double[] choice( double[] values, int n, boolean unique ) {
if( unique && values.length < n )
throw new IllegalArgumentException(
String.format("Need at least <%d> values to choose <%d> unique values (<%d> given).", n, n, values.length)
);
double[] result = new double[n];
double[] valuesCopy = Arrays.copyOf(values, values.length);
for( int i = 0; i < n; i++ ) {
int j = random(0, valuesCopy.length-1);
int l = valuesCopy.length-1;
result[i] = valuesCopy[j];
valuesCopy[j] = valuesCopy[l];
valuesCopy[l] = result[i];
if( unique )
valuesCopy = Arrays.copyOf(valuesCopy, l);
}
return result;
}
/** /**
* Wählt die angegebene Anzahl Elemente aus dem Array aus. * Wählt die angegebene Anzahl Elemente aus dem Array aus.
* *
@@ -1299,12 +1419,26 @@ public class Constants {
* @param <T> Datentyp der Elemente. * @param <T> Datentyp der Elemente.
* @return Ein zufälliges Element aus dem Array. * @return Ein zufälliges Element aus dem Array.
*/ */
public static final <T> T[] choice( T[] values, int n ) { public static final <T> T[] choice( T[] values, int n, boolean unique ) {
Object[] result = new Object[n]; if( unique && values.length < n )
throw new IllegalArgumentException(
String.format("Need at least <%d> values to choose <%d> unique values (<%d> given).", n, n, values.length)
);
T[] result = Arrays.copyOf(values, n);
T[] valuesCopy = Arrays.copyOf(values, values.length);
for( int i = 0; i < n; i++ ) { for( int i = 0; i < n; i++ ) {
result[i] = choice(values); int last = valuesCopy.length-1;
int j = random(0, last);
result[i] = valuesCopy[j];
valuesCopy[j] = valuesCopy[last];
valuesCopy[last] = result[i];
if( unique )
valuesCopy = Arrays.copyOf(valuesCopy, last);
} }
return (T[]) result; return result;
} }
/** /**
@@ -1474,7 +1608,7 @@ public class Constants {
} }
public static final double asDouble( char value ) { public static final double asDouble( char value ) {
return (double) value; return value;
} }
public static final double asDouble( byte value ) { public static final double asDouble( byte value ) {

View File

@@ -2,6 +2,9 @@ package schule.ngb.zm;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.stream.IntStream;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
class ConstantsTest { class ConstantsTest {
@@ -169,4 +172,30 @@ class ConstantsTest {
assertTrue(0.0 <= d && 1.0 >= d, "Noise should be in Range 0 to 1. Was <" + d + ">."); assertTrue(0.0 <= d && 1.0 >= d, "Noise should be in Range 0 to 1. Was <" + d + ">.");
} }
@Test
void choice() {
int[] values = IntStream.range(0,1000).toArray();
int[] choosen = Constants.choice(values, 1, false);
assertEquals(1, choosen.length);
assertTrue(Arrays.stream(values).anyMatch((i) -> i == choosen[0]));
int[] choosen4 = Constants.choice(values, 2000, false);
assertEquals(2000, choosen4.length);
int[] choosen2 = Constants.choice(values, 400, false);
assertEquals(400, choosen2.length);
assertTrue(Arrays.stream(choosen2).allMatch((i) -> Arrays.binarySearch(values, i)>=0 ));
int[] choosen3 = Constants.choice(values, 999, true);
assertEquals(999, choosen3.length);
assertTrue(Arrays.stream(choosen3).allMatch((i) -> Arrays.binarySearch(values, i)>=0 ));
for( int i = 0; i < choosen3.length; i++ ) {
for( int j = i+1; j < choosen3.length; j++ ) {
assertNotEquals(choosen3[i], choosen3[j], "Item "+i+" also found at index "+j);
}
}
assertThrows(IllegalArgumentException.class, () -> Constants.choice(values, 2000, true));
}
} }