I was wondering if you can create a custom base with your own symbols instead of the one Java applies to you with Integer.parseInt (0-9 and A-P.)
I was thinking of something like this:
public class Base {
private String symbols;
public Base(String symbols) {
this.symbols = symbols;
}
// for example: new Base("0123456789"); would represent base 10
public static String convertBases(Base from, Base to, String toConvert) {
// Takes toConvert which is encoded in base "from" and converts it to base "to"
}
}
I am not sure how to implement this. Does anyone have the code for this?
To do this, you need to first parse the input text in the from base, then format the value in the to base, exactly like you'd need to do if using standard base "alphabet".
public static String convertBases(int fromRadix, int toRadix, String text) {
int value = Integer.parseInt(text, fromRadix);
return Integer.toString(value, toRadix);
}
So, first you implement parse and toString, then implementing convertTo is easy:
public class Base {
private final String symbols;
private final BigInteger radix;
private final Map<Character, Integer> symbolIndex;
public Base(String symbols) {
if (symbols.length() <= 1)
throw new IllegalArgumentException("Must provide at least 2 symbols: length=" + symbols.length());
this.symbols = symbols;
this.radix = BigInteger.valueOf(symbols.length());
this.symbolIndex = new HashMap<>(symbols.length() * 4 / 3 + 1);
for (int i = 0; i < symbols.length(); i++) {
Integer prevIndex = this.symbolIndex.putIfAbsent(symbols.charAt(i), i);
if (prevIndex != null)
throw new IllegalArgumentException("Duplicate symbol at index " + prevIndex +
" and " + i + ": " + symbols.charAt(i));
}
}
public BigInteger parse(String text) {
BigInteger value = BigInteger.ZERO;
for (int i = 0; i < text.length(); i++) {
Integer index = this.symbolIndex.get(text.charAt(i));
if (index == null)
throw new IllegalArgumentException("Not a valid number: " + text);
value = value.multiply(this.radix).add(BigInteger.valueOf(index));
}
return value;
}
public String toString(BigInteger value) {
if (value.signum() < 0)
throw new IllegalArgumentException("Negative value not allowed: " + value);
if (value.signum() == 0)
return this.symbols.substring(0, 1);
StringBuilder buf = new StringBuilder();
for (BigInteger v = value; v.signum() != 0; v = v.divide(this.radix))
buf.append(this.symbols.charAt(v.mod(this.radix).intValue()));
return buf.reverse().toString();
}
public String convertTo(Base newBase, String text) {
return newBase.toString(parse(text));
}
}
Test
Base base3 = new Base("012");
Base base6alpha = new Base("ABCDEF");
System.out.println(base3.convertTo(base6alpha, "0")); // 0 -> A
System.out.println(base3.convertTo(base6alpha, "2")); // 2 -> C
System.out.println(base3.convertTo(base6alpha, "10")); // 3 -> D
System.out.println(base3.convertTo(base6alpha, "200")); // 18 -> DA
Output
A
C
D
DA
Test 2
Base obscure = new Base("^JsdloYF9%");
Base base64 = new Base("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
BigInteger value = new BigInteger("123456789012345678901234567890"); // Too large for int and long
String obscureValue = obscure.toString(value);
String base64Value = base64.toString(value);
System.out.println(obscureValue);
System.out.println(base64Value);
System.out.println(base64.convertTo(obscure, base64Value));
System.out.println(obscure.convertTo(base64, obscureValue));
Output
JsdloYF9%^JsdloYF9%^JsdloYF9%^
BjukP9sNz4O5OPwrS
JsdloYF9%^JsdloYF9%^JsdloYF9%^
BjukP9sNz4O5OPwrS
Let's start with a value type. It holds a string representation and a Base object. (i.e., it has a string representation and a something like a decoder). Why? because we don't want to pass around Strings which we need to look at and "guess" what base they are.
public class CustomNumber {
private final String stringRepresentation;
private final Base base;
public CustomNumber(String stringRepresentation, Base base) {
super();
this.stringRepresentation = stringRepresentation;
this.base = base;
}
public long decimalValue() {
return base.toDecimal(stringRepresentation);
}
public CustomNumber toBase(Base newBase) {
long decimalValue = this.decimalValue();
String stringRep = newBase.fromDecimal(decimalValue);
return new CustomNumber(stringRep, newBase);
}
}
Then we need to define an interface which is broad enough to handle any regular or custom-symbol base. We will later build concrete implementations on top.
public interface Base {
public long toDecimal(String stringRepresentation);
public String fromDecimal(long decimalValue);
}
We are all set. Lets do an example implementation to support the standard decimal number format before going to custom string symbols:
public class StandardBaseLong implements Base{
public long toDecimal(String stringRepresentation) {
return Long.parseLong(stringRepresentation);
}
public String fromDecimal(long decimalValue) {
return Long.toString(decimalValue);
}
}
Now finally, coming to the custom string base:
public class CustomBase implements Base{
private String digits;
public CustomBase(String digits) {
this.digits = digits;
}
public long toDecimal(String stringRepresentation) {
//Write logic to interpret that string as your base
return 0L;
}
public String fromDecimal(long decimalValue) {
//Write logic to generate string output in your base format
return null;
}
}
Now you have a framework to work with various custom and standard bases.
Of course, there could be more customisations and improved features (more convenience constructors, hashCode and equals implementations and arithmetic). But, they are beyond the scope of this answer.
Related
I have an array of versions such as ["1.0.0.0","1.5.0.0","1.5.0.1","1.5.0.2","1.5.0.3","1.5.0.4","1.5.0.7","1.6.0.0","1.6.0.1","1.13.0.0","1.13.1.0","1.13.1.1","1.13.1.2","1.13.1.3","1.13.1.4","1.22.0.0","1.22.1.0","1.22.1.1"]
I need to map it into tree like
1.0.0.0
|1.5.0.0
||1.5.0.1
||1.5.0.2
||1.5.0.3
||1.5.0.4
||1.5.0.7
|1.6.0.0
||1.6.0.1
|1.13.0.0
||1.13.1.0
||1.13.1.1
||1.13.1.2
|1.22.0.0
||1.22.1.0
||1.22.1.1
Can any one help with this using Java
What do you want to achieve? This looks like you either want to print every version or to check versions.
For first case, iterate trough array and print it like:
System.out.println("your item")
In second case, you can simply check if your array contains version you are checking.
I assume that you would like to insert the input version into a Binary Search Tree (BST)
It will allow you to find requested versions in O(log(n)) time
These are the main steps to achieve your goal:
1) Use a java BST implementation.
2) Implement String Comparator, in order to determine which version is bigger.
3) Add elements to the tree.
4) Print elements in your favorite format.
1) I've used this implementation: https://www.cs.cmu.edu/~adamchik/15-121/lectures/Trees/code/BST.java
2) I've implemented a comparator that maps version strings to integers.
It allows me to compare the encoded numeric values of the versions
public class VersionsComparator implements Comparator {
#Override
public int compare(String s1, String s2) {
String versionPattern = "(\\d+)[.](\\d+)[.](\\d+)[.](\\d+)";
final int numOfMatchers = 2;
Pattern pattern = Pattern.compile(versionPattern);
Matcher[] matchers = new Matcher[numOfMatchers];
matchers[0] = pattern.matcher(s1);
matchers[1] = pattern.matcher(s2);
for (Matcher matcher : matchers) {
if(!matcher.matches()) {
throw new RuntimeException("Invalid version format");
}
}
int version1 = parseVersion(s1, matchers[0]);
int version2 = parseVersion(s2, matchers[1]);
return version2 - version1;
}
private int parseVersion(String version, Matcher matcher) {
int length = matcher.groupCount();
int[] v = new int[length];
int parsedVersion = 0;
for (int i = 0; i < length; i++) {
v[i] = Integer.parseInt(matcher.group(length - i));
parsedVersion += Math.pow(10, i) * v[i];
}
return parsedVersion;
}
}
3) Adding all of the strings to the tree:
private static BST getBST(String[] strArr) {
BST<String> bst = new BST<String>();
Arrays.asList(strArr).stream().forEach(str -> bst.insert(str));
return bst;
}
4) Printing the tree elements:
I've added my own printing style, by adding 2 methods to the BST class:
public void inOrderTraversalWithHierarchy() {
inOrderWithHierarchyHelper(root, 0);
}
private void inOrderWithHierarchyHelper(Node r, int level) {
if (r != null) {
inOrderWithHierarchyHelper(r.left, level + 1);
for (int i = 0; i < level; System.out.print("|"), i++);
System.out.println(r);
inOrderWithHierarchyHelper(r.right, level + 1);
}
}
This is the code of the client class:
public class CodeToMakeTreeStructureFromVersionNames {
public class VersionsComparator implements Comparator<String>{
#Override
public int compare(String s1, String s2) {
String versionPattern = "(\\d+)[.](\\d+)[.](\\d+)[.](\\d+)";
final int numOfMatchers = 2;
Pattern pattern = Pattern.compile(versionPattern);
Matcher[] matchers = new Matcher[numOfMatchers];
matchers[0] = pattern.matcher(s1);
matchers[1] = pattern.matcher(s2);
for (Matcher matcher : matchers) {
if(!matcher.matches()) {
throw new RuntimeException("Invalid version format");
}
}
int version1 = parseVersion(s1, matchers[0]);
int version2 = parseVersion(s2, matchers[1]);
return version2 - version1;
}
private int parseVersion(String version, Matcher matcher) {
int length = matcher.groupCount();
int[] v = new int[length];
int parsedVersion = 0;
for (int i = 0; i < length; i++) {
v[i] = Integer.parseInt(matcher.group(length - i));
parsedVersion += Math.pow(10, i) * v[i];
}
return parsedVersion;
}
}
public static void main(String[] args) {
String[] versions = {"1.0.0.0","1.5.0.0","1.5.0.1","1.5.0.2","1.5.0.3","1.5.0.4","1.5.0.7","1.6.0.0","1.6.0.1","1.13.0.0","1.13.1.0","1.13.1.1","1.13.1.2","1.13.1.3","1.13.1.4","1.22.0.0","1.22.1.0","1.22.1.1"};
printBST(getBST(versions));
}
private static BST<String> getBST(String[] strArr) {
BST<String> bst = new BST<String>();
Arrays.asList(strArr).stream().forEach(str -> bst.insert(str));
return bst;
}
private static void printBST(BST bst) {
bst.inOrderTraversalWithHierarchy();
}
}
I have a repository class that uses text files(a requirement), meaning that I have to read strings and cast them in order to instantiate objects. The problem is that I want my repository class as general as I can make it, in order to use it to manipulate different object types.
So, is there a (more elegant) way to dynamically cast strings to whatever field (primitive) type it needs at runtime, while avoiding lots of
try-catch structures with numerous ifs/switches?
As a short simplified version, I want objectA.txt to contain only objectA's information, similarly for objectB.txt, and my Repository code to handle both:
Repository repoA = new Repository("objectA.txt", < list of Types for A >); TypeA a=repoA.getOne();
Repository repoB = new Repository("objectB.txt", < list of Types for B >); TypeB b=repoB.getOne();
What I have:
public class FileRepository extends InMemoryRepository{
private String fileName;
private List<Class> types;
public FileRepository(String fileName, List<Class> types) {
//#param types
// - list containing the Class to be instantiated followed by it's field types
super();
this.fileName = fileName;
this.types=types;
loadData();
}
private void loadData() {
Path path = Paths.get(fileName);
try {
Files.lines(path).forEach(line -> {
List<String> items = Arrays.asList(line.split(","));
//create Class array for calling the correct constructor
Class[] cls=new Class[types.size()-1];
for (int i=1; i<types.size(); i++){
cls[i-1]=types.get(i);
}
Constructor constr=null;
try {
//get the needed constructor
constr = types.get(0).getConstructor(cls);
} catch (NoSuchMethodException e) {
//do something
e.printStackTrace();
}
//here is where the fun begins
//#arg0 ... #argn are the primitives that need to be casted from string
//something like:
//*(type.get(1))* arg0=*(cast to types.get(1))* items.get(0);
//*(type.get(2))* arg1=*(cast to types.get(2))* items.get(1);
//...
Object obj= (Object) constr.newInstance(#arg0 ... #argn);
});
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
P.S.: I'm a JAVA newbie, so please keep the explanations as simple as possible.
No IDE on hand, so I hope this makes sense:
private static final Map<Class, Function<String, ?>> parsers = new HashMap<>();
static {
parsers.put(Long.class, Long::parseLong);
parsers.put(Integer.class, Integer::parseInt);
parsers.put(String.class, String::toString);
parsers.put(Double.class, Double::parseDouble);
parsers.put(Float.class, Float::parseFloat);
// add your own types here.
}
public <T> T parse(Class<T> klass, String value) {
// add some null-handling logic here? and empty values.
return (T)parsers.get(klass).apply(value);
}
Then when you need to create the parameters for your constructor:
parameters =
IntStream
.range(0, cls.size-1)
.map(i -> (Object)parse(types.get(i), items.get(i)))
.toArray(Object[]::new);
I think you can make use of auto-boxing and auto-unboxing coupled with the observation that all wrapper classes provide a method named valueOf that accepts a String and returns an instance of the respective (wrapper) type such that the given string represents the legal value of that type.
The following is an attempt of a type-safe implementation that suits your needs:
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.Consumer;
/**
* Created by kmhaswade on 3/18/16.
*/
//#ThreadUnsafe
public class NonStreamingGenericPrimitiveDataRepo<T> implements Iterable<T> {
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
#Override
public boolean hasNext() {
return theIterator.hasNext();
}
#Override
public T next() {
String next = theIterator.next();
try {
Method m = theType.getDeclaredMethod("valueOf", String.class);
return (T) m.invoke(null, next);
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new RuntimeException("This is impossible!");
} catch (InvocationTargetException e) {
throw new RuntimeException("data: " + next + " does not represent type: " + theType);
}
}
};
}
#Override
public void forEach(Consumer<? super T> action) {
throw new RuntimeException("left as an exercise :-) ");
}
private final ArrayList<String> theCache;
private final Iterator<String> theIterator;
private final Class<T> theType;
public NonStreamingGenericPrimitiveDataRepo(Reader reader, Class<T> theType) throws IOException {
Objects.requireNonNull(reader);
Objects.requireNonNull(theType);
if (Integer.class.equals(theType)
|| Long.class.equals(theType)
|| Float.class.equals(theType)
|| Double.class.equals(theType)
|| Boolean.class.equals(theType)
|| String.class.equals(theType)) {
theCache = new ArrayList<>();
try (BufferedReader br = new BufferedReader(reader)) {
String line;
while ((line = br.readLine()) != null)
theCache.add(line);
}
theIterator = theCache.iterator();
this.theType = theType;
} else {
throw new IllegalArgumentException("Not a wrapper type: " + theType);
}
}
public static void main(String[] args) throws IOException {
for (int i : new NonStreamingGenericPrimitiveDataRepo<>(ints(), Integer.class))
System.out.println("read an int: " + i);
for (float f : new NonStreamingGenericPrimitiveDataRepo<>(floats(), Float.class))
System.out.println("read a float: " + f);
for (boolean b: new NonStreamingGenericPrimitiveDataRepo<>(booleans(), Boolean.class))
System.out.println("read a boolean: " + b);
}
static StringReader ints() {
return new StringReader("1.w\n2\n-3\n4\n");
}
static StringReader floats() {
return new StringReader("1.0f\n3.25f\n-3.33f\n4.44f\n");
}
static StringReader booleans() {
return new StringReader("false \ntrue\n");
}
}
If you want to identify the type of primitive data type from a String, you can use the following:
public class Test {
final static String LONG_PATTERN = "[-+]?\\d+";
final static String DOUBLE_PATTERN = "[-+]?(\\d*[.])?\\d+";
final static String BOOLEAN_PATTERN = "(true|false)";
final static String CHAR_PATTERN = "[abcdefghijklmnopqrstuvwxyz]";
public static void main(String[] args) {
String[] xList= {
"1", //int
"111111111111", //long
"1.1", //float
"1111111111111111111111111111111111111111111111111111.1", //double
"c", //char
"true", //boolean
"end" //String
};
for (String x: xList){
if(x.matches(LONG_PATTERN)){
long temp = Long.parseLong(x);
if (temp >= Integer.MIN_VALUE && temp <= Integer.MAX_VALUE){
System.out.println( x + " is int use downcast");
} else {
System.out.println( x + " is long");
}
} else if(x.matches(DOUBLE_PATTERN)){
double temp = Double.parseDouble(x);
if (temp >= Float.MIN_VALUE && temp <= Float.MAX_VALUE){
System.out.println( x + " is float use downcast");
} else {
System.out.println( x + " is Double");
}
} else if (x.toLowerCase().matches(BOOLEAN_PATTERN)){
boolean temp = x.toLowerCase().equals("true");
System.out.println(x + " is Boolean");
} else if(x.length() == 1){
System.out.println(x + " is char");
}else {
System.out.println( x + " is String");
}
}
}
}
Output:
1 is int use downcast
111111111111 is long
1.1 is float use downcast
1111111111111111111111111111111111111111111111111111.1 is Double
c is char
true is Boolean
end is String
The above code categorizes your String in 4 major parts long integer, double, boolean and if none matches then String. As java states, primitive data types fall in two categories:
Integers
byte
char (represented as a character)
short
int
long
Floating point numbers
float
double
Boolean
boolean
This way you will be able to identify the types in which your String lies. You can modify the code to check the range and type cast the numbers accordingly in byte and short as well.
I have a hashmap containing Key and Value <String, String>.
i.e. mapValue:
mapValue.put("A","B-7");
mapValue.put("B","START+18");
mapValue.put("C","A+25");
Now I want to evaluate expression for 'C'. So for C, the expression would be
replaced by (((START+18)-7)+25).
So if anymethod, I will pass the string C, it should return string
"(((START+18)-7)+25)" and also I want to evaluate it as per the priority.
Thanks
generally logic of such function (assuming, you know possible operations and syntax is strict) may as follows:
public String eval(HashMap<String, String> mapValue, String variable) {
//get expression to be evaluated
String tmp = mapValue.get(variable);
// For each knwon operation
for (String op : OPERATIONS) {
// split expression in operators in Array
String[] vars = tmp.split("\\" + op);
// for each Element of splitted expr. Array
for (int i = 0; i < vars.length; i++) {
//Check if Element is a valid key in HashMap
if (mapValue.containsKey(vars[i])) {
//if it is replace element with result of iteration
vars[i] = eval(mapValue, vars[i]); // DO ITERATION
}
//if Element is not a valid key in has do nothing
}
//Join splitted string with proper operator
tmp = join(vars, op);
}
//return in parenthesis
return "(" + tmp + ")";
}
The result of 'eval(mapValue,"C")' would be:
(((START+18)-7)+25)
Some short join function may be implemented as follows:
public String join(String[] arr, String d) {
String result = arr[0];
int i = 1;
while (i < arr.length) {
result += d + arr[i];
i++;
}
return result;
}
All code provided above is more to illustrate logic, as some exception handling, better operations with string etc should be used.
Hope it helps
Cheers!
As mentioned in the comments I would not recommend recursion - it can lead to stackoverflow-Exceptions, if the recursion gets too deep.
Also I would recommend not to use String equations. Strings are slow to parse and can lead to unexpected results (as mentioned by #rtruszk "START" contains variable "A").
I created an example as my recommendation:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class X {
static interface Expression {
}
static class Combination implements Expression {
Expression[] values;
public Combination(Expression... values) {
this.values = values;
}
#Override
public String toString() {
return "?";
}
}
static class Reference implements Expression {
private String reference;
public Reference(String reference) {
this.reference = reference;
}
#Override
public String toString() {
return reference;
}
}
static class Number implements Expression {
private int value;
public Number(int value) {
this.value = value;
}
#Override
public String toString() {
return ""+value;
}
}
public static void main(String[] args) {
Map<String, Expression> mapValue = new HashMap<>();
mapValue.put("START", new Number(42));
String x = "C";
mapValue.put("A", new Combination( new Reference("B"), new Number(-7)));
mapValue.put("B", new Combination(new Reference("START"), new Number(+18)));
mapValue.put("C", new Combination( new Reference("A"), new Number(+25)));
int result = 0;
ArrayList<Expression> parts = new ArrayList<>();
parts.add(mapValue.get(x));
while (!parts.isEmpty()) {
debuggingOutput(x, result, parts);
Expression expression = parts.remove(0);
if (expression instanceof Combination)
parts.addAll(Arrays.asList(((Combination) expression).values));
else if (expression instanceof Reference)
parts.add(mapValue.get(((Reference) expression).reference));
else if (expression instanceof Number)
result += ((Number) expression).value;
}
System.out.println(result);
}
private static void debuggingOutput(String x, int result, ArrayList<Expression> parts) {
System.out.print(x);
System.out.print(" = ");
System.out.print(result);
for (Expression part : parts) {
System.out.print(" + ");
System.out.print(part);
}
System.out.println();
}
}
Im having a class Woning (house) and a subclass KoopWoning (buyable House) and a subclass HuurWoning (rentable House). KoopWoning and Huurwoning extend Woning. HuurWoning is just a Woning, whereas KoopWoning has an extra variable energylevel. KoopWoning has also a function getEnergylevel, which returns the energylevel of the KoopWoning. I also have a class Portefeuille which has an arraylist of Woningen.
Im reading all Woningen in a Portefeuille from a textfile. In a 5th class, I want to be able to sort the ArrayList of Woningen of Portefeuille (from the textfile). I have a function woningenTot(int maxprijs) which returns an ArrayList with all the Woningen that fullfil the requirement (having a price below maxprijs). These Woningen I want to print on the screen.
The problem is as follows:
It can be possible that there is also a KoopWoning in the file. In that case I also want to be able to sort on energylevel. However, I can't sort on the energylevels. I can't call the function getEnergylevel because it's an ArrayList, and Woning doesn't contain the function getEnergylevel.
So how can I solve this? If it's too vague, I could include the code, however it's quite big :O
Any help is appreciated; i have spent a couple of hours on this program, from which at least 1.5 hours on this problem alone :(
EDIT: Here is the code for class KoopWoning
public class KoopWoning extends Woning implements EnergiepeilWoning {
private char energiepeil;
public KoopWoning (Adres adres, int kamers, int vraagPrijs, char energiepeil) {
super(adres, kamers, vraagPrijs);
this.energiepeil = energiepeil;
}
public char getEnergiepeil () {
return energiepeil;
}
public boolean compareEnergiepeil (Object other) {
boolean res = false;
if (other instanceof KoopWoning) {
KoopWoning that = (KoopWoning) other;
res = (this.getEnergiepeil() == that.getEnergiepeil());
}
return res;
}
public String toString () {
String res = adres + ", " + kamers + " kamers, prijs " + prijs + ", energiepeil " + energiepeil;
return res;
}
And here is the code for class Woning
public class Woning {
protected int kamers;
protected int prijs;
protected Adres adres;
protected String tag;
public Woning (Adres adres, int kamers, int prijs) {
this.adres = adres;
this.kamers = kamers;
this.prijs = prijs;
}
public String toString () {
String res = adres + ", " + kamers + " kamers, prijs " + prijs;
return res;
}
public void setTag (String tag) {
this.tag = tag;
}
public String getTag () {
return tag;
}
public boolean kostHooguit (int maxprijs) {
return (prijs <= maxprijs);
}
public boolean equals (Object other) {
boolean res = false;
if (other instanceof Woning) {
Woning that = (Woning) other;
if (this.adres.equals(that.adres))
res = true;
}
return res;
}
public static Woning read (Scanner sc) {
try {
Adres adress = Adres.read(sc);
int kamer = sc.nextInt();
sc.next();
sc.next();
int prijs = sc.nextInt();
String check = sc.next();
if (check.equals("energiepeil")) {
char peil = sc.next().charAt(0);
KoopWoning kwoning = new KoopWoning (adress, kamer, prijs, peil);
return kwoning;
}
else {
Woning woning = new Woning (adress, kamer, prijs);
return woning;
}
}
catch (Exception e) {
System.out.println("Woning: Exception is caught");
System.out.println(e.getMessage());
Adres adress = new Adres ("", "", "", "");
Woning woning = new Woning (adress, 0, 0);
return woning;
}
}
}
And lastly, the code for the class Portefeuille
public class Portefeuille {
private ArrayList<Woning> woninglijst;
public Portefeuille () {
woninglijst = new ArrayList<Woning>();
}
public void voegToe (Woning woning) {
if (!woninglijst.contains(woning))
woninglijst.add(woning);
}
public ArrayList<Woning> woningenTot (int maxprijs) {
ArrayList<Woning> woninglijst2 = new ArrayList<Woning>();
for (int i = 0; i < woninglijst.size(); i++) {
if(woninglijst.get(i).kostHooguit(maxprijs))
woninglijst2.add(woninglijst.get(i));
}
return woninglijst2;
}
public String toStringExt () {
String res = "[";
for (int i = 0; i < woninglijst.size(); i++)
res = res + woninglijst.get(i).toString() + "; ";
if (woninglijst.size() != 0)
res = res.substring (0, res.length() - 2);
res = res + "]";
return res;
}
public String toString () {
String res = "";
for (int i = 0; i < woninglijst.size(); i++)
res = woninglijst.get(i).toString2();
return res;
}
public boolean equals (Object other) {
boolean res = false;
if (other instanceof Portefeuille) {
Portefeuille that = (Portefeuille) other;
if (this.woninglijst.size() == that.woninglijst.size()) {
int i = 0;
while (i < this.woninglijst.size() && this.woninglijst.get(i).equals(that.woninglijst.get(i)))
i = i + 1;
res = (i == this.woninglijst.size());
}
}
return res;
}
public static Portefeuille read (String infile) {
try {
Scanner sc = new Scanner (new File(infile));
ArrayList<Woning> wlijst = new ArrayList<Woning>();
Portefeuille p = new Portefeuille();
int woningen = sc.nextInt();
int i = 0;
while (i < woningen) {
sc.nextLine();
String tag = sc.nextLine();
wlijst.add(Woning.read(sc));
p.voegToe(wlijst.get(i));
i++;
}
sc.close();
return p;
}
catch (Exception e) {
System.out.println("Portefeuille: Exception is caught");
Portefeuille p = new Portefeuille();
return p;
}
}
}
EDIT
I fixed it myself. Thanks for answering you all :)
You could define, on the top-level class, a method like getSortableValue(), and implement it to return a default field (you didn't mention the field you need to sort on for Woningen). In the KoopWoning you override this method to return the energyLevel instead. Then you always sort on the value returned by getSortableValue().
You can let the them implement Comparable, so like Woning implements Comparable<Woning>. This will let you implement the (required) method:
#override
public int compareTo(Woning other) {
int result = Integer.compareto(maxPrijs, other.maxPrijs);
if (result != 0) return result;
result = Integer.compareto(someField, other.someField);
if (result != 0) return result;
// etc...
return 0;
}
The subclass KoopWoning extends Woning implements Comparable<KoopWoning> can have a method like this:
#override
public int compareTo(KoopWoning other) {
int result = Integer.compareto(energylevel, other.energylevel);
if (result != 0) return result;
return super.compareTo(other);
}
Then all you need to do is load all the Woning instances in a list and execute
Collections.sort(list);
Having subclasses inherit Comparable is optional, so HuurWoning will just sort like Woning.
You could define a Comparator on Woning that determines the relative ordering of two Woning. You could do this either by having a method that looks at the actual types of the two arguments and then acts appropriately, or, better, by having an overrideable method of Woning that returns some value that you can use for sorting purposes.
If, for instance, you decide that anything with an energy level should come after anything without one, then you can have KoopWoning return something with the energy level in the high order bits of a long, so that it always comes out higher than anything without one (essentially you'd be setting a default energy level of zero).
Then, you can use
Collections.sort(arrayList, myComparator);
to sort the list based on the Comparator you've created.
There are some nice classes in the Guava library that help with Comparator building on multiple keys, but if your case is fairly simple, you probably won't need them.
Any help or advice would be greatly appreciated. I'm trying to create a simple game which generates ten different, random questions. The questions can contain 2, 3 or 4 integers. So something like this: 55 2 − 4 − 101, 102/3/3, 589 − 281, 123 + 5 6 + 2.
The question will be displayed in a textview and then the user can take a guess, entering values into an edittext and then upon clicking a key on a custom keypad I have created it will check the answer, and then display the next question in the sequence of 10.
I know how to create random numbers, just struggling to work out how to create a whole question with random operators (+, -, /, *).
Big thank you to anyone who has the time to construct a reply.
A little of spare time produced a complete example for your case. Create new RandomMathQuestionGenerator.java file and it is cooked for compilation.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class RandomMathQuestionGenerator {
private static final int NUMBER_OF_QUESTIONS = 10;
private static final int MIN_QUESTION_ELEMENTS = 2;
private static final int MAX_QUESTION_ELEMENTS = 4;
private static final int MIN_QUESTION_ELEMENT_VALUE = 1;
private static final int MAX_QUESTION_ELEMENT_VALUE = 100;
private final Random randomGenerator = new Random();
public static void main(String[] args) {
RandomMathQuestionGenerator questionGenerator = new RandomMathQuestionGenerator();
List<Question> randomQuestions = questionGenerator.getGeneratedRandomQuestions();
for (Question question : randomQuestions) {
System.out.println(question);
}
}
public List<Question> getGeneratedRandomQuestions() {
List<Question> randomQuestions = new ArrayList<Question>(NUMBER_OF_QUESTIONS);
for (int i = 0; i < NUMBER_OF_QUESTIONS; i++) {
int randomQuestionElementsCapacity = getRandomQuestionElementsCapacity();
Question question = new Question(randomQuestionElementsCapacity);
for (int j = 0; j < randomQuestionElementsCapacity; j++) {
boolean isLastIteration = j + 1 == randomQuestionElementsCapacity;
QuestionElement questionElement = new QuestionElement();
questionElement.setValue(getRandomQuestionElementValue());
questionElement.setOperator(isLastIteration ? null
: Operator.values()[randomGenerator.nextInt(Operator.values().length)]);
question.addElement(questionElement);
}
randomQuestions.add(question);
}
return randomQuestions;
}
private int getRandomQuestionElementsCapacity() {
return getRandomIntegerFromRange(MIN_QUESTION_ELEMENTS, MAX_QUESTION_ELEMENTS);
}
private int getRandomQuestionElementValue() {
return getRandomIntegerFromRange(MIN_QUESTION_ELEMENT_VALUE, MAX_QUESTION_ELEMENT_VALUE);
}
private int getRandomIntegerFromRange(int min, int max) {
return randomGenerator.nextInt(max - min + 1) + min;
}
}
class Question {
private List<QuestionElement> questionElements;
public Question(int sizeOfQuestionElemets) {
questionElements = new ArrayList<QuestionElement>(sizeOfQuestionElemets);
}
public void addElement(QuestionElement questionElement) {
questionElements.add(questionElement);
}
public List<QuestionElement> getElements() {
return questionElements;
}
public int size() {
return questionElements.size();
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (QuestionElement questionElement : questionElements) {
sb.append(questionElement);
}
return sb.toString().trim();
}
}
class QuestionElement {
private int value;
private Operator operator;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Operator getOperator() {
return operator;
}
public void setOperator(Operator operator) {
this.operator = operator;
}
#Override
public String toString() {
return value + (operator == null ? "" : " " + operator.getDisplayValue()) + " ";
}
}
enum Operator {
PLUS("+"), MINUS("-"), MULTIPLIER("*"), DIVIDER("/");
private String displayValue;
private Operator(String displayValue) {
this.displayValue = displayValue;
}
public String getDisplayValue() {
return displayValue;
}
}
Run and preview. Hope this helps.
Thanks to:
Generating random number in
range
Retrieving random
element from array
Create an array char[] ops = { '+', '-', '/', '*' } and create a random int i in range [0,3], and chose ops[i]
You will need to take care that you do not generate a divide by zero question.
You can make it even more generic by creating an interface MathOp and creating 4 classes that implement it: Divide, Sum , ... and create an array: MathOp[] ops instead of the char[]
Using this, it will also give you much easier time to check the result later on...
Put your operators in an array (4 elements), generate a random integer from 0 to 3, and pick the operator that is at this index in the array.
Do that each time you need to have a random operator, i.e. after every number of your question except the last one.
Make an array that has one entry for each of the operators. Then generate a random number between 0 and the length of the array minus 1.
So since each operation is binary you can just worry about figuring out the base case and then building up your expressions from there.
An easy way would just to select a random number an correlate that which operation will be used.
int displayAnswer(int leftSide, int rightSide, int operation {
int answer;
string operation;
switch(operation) {
case 1:
operation = "+";
answer = leftSide + rightSide;
break;
case 2:
operation = "-";
answer = leftSide - rightSide;
break;
case 3:
operation = "*";
answer = leftSide * rightSide;
break;
case 4:
operation = "/";
answer = leftSide / rightSide:
break;
}
textView.setText(leftSide + operation + rightSide);
return answer;
}