I have a batch of sprites (textured OpenGL ES 2.0 Quads) which I loop through to move. Here is a simplified version of my code:
//'sprite' & other values have been are assumed to exist for the purpose of the question
public void moveQuadBatch(){
//Loop for as many sprites as there are to draw
for (loop = 0; loop < sprite.number; loop++){
moveQuadNumber(loop); //this method will move the sprite that corresponds to the number loops so we can move through the entire batch and move each individual sprite
}
}
Now, for some batches, there is a countdown timer, or some other condition (and there isn't for others, like above). Therefore, I've created a similar method for these objects like so:
public void moveQuadBatchWithCheck(){
//Loop for as many sprites as there are to draw
for (loop = 0; loop < sprite.number; loop++){
//Only do this if the particular sprite's countdown/delay counter has reached 0 (counting down from another method not seen here)
if (sprite.delay[loop]<0){
moveQuadNumber(loop); //this method will move the sprite that corresponds to the number loops so we can move through the entire batch and move each individual sprite
}
}
}
However, I'm not entirely happy about this as there is a lot of code duplication. Instead of having these 2 methods is there any way I can use the first one and somehow 'slipstream' the additional check into the for loop? Or otherwise cut down on the duplication that I have here? This is a simple example, there are others and currently I have multiple methods which are all very similar.
Edit
As mentioned, the above is somewhat simplified. I could have some for loops which check another value (other than delay for example), and some could check 2 conditions.
public void moveQuadBatch(bool checkDelay) {
for (loop = 0; loop < sprite.number; loop++){
if (!checkDelay || sprite.delay[loop] < 0) {
moveQuadNumber(loop);
}
}
}
Now moveQuadBatch(false) is your first function and moveQuadBatch(true) is your second one.
As to "inserting extra code", you're basically talking about functions. In Python an elegant approach would be to pass a function in and offload all logic to the function, e.g:
def moveQuadBatch(predicate=None):
for loop, sprite in enumerate(self.sprites):
if not predicate or predicate(loop, sprite):
self.moveQuadNumber(loop)
Then you would use it as such:
inst.moveQuadBatch()
inst.moveQuadBatch(lambda loop, sprite: sprite.delay[loop] < 0)
inst.moveQuadBatch(lambda loop, sprite: sprite.doesItBlend(loop))
You can do this same thing in Java but not quite as neatly: you have to define a predicate class and instances of it. This is the approach B.J. Smegma was advocating.
public interface QuadBatchPredicate {
public boolean shouldMove(int loop, Sprite sprite);
}
Your function would look like this:
public void moveQuadBatch(QuadBatchPredicate pred) {
for (loop = 0; loop < sprite.number; loop++){
if (pred == null || pred(loop, sprite)) {
moveQuadNumber(loop);
}
}
}
public void moveQuadBatch() {
moveQuadBatch(null);
}
Then you can use anonymous classes to define the predicates:
moveQuadBatch();
moveQuadBatch(new QuadBatchPredicate() {
public boolean shouldMove(int loop, Sprite sprite) {
return sprite.delay[loop] < 0;
}
});
moveQuadBatch(new QuadBatchPredicate() {
public boolean shouldMove(int loop, Sprite sprite) {
return sprite.doesItBlend();
}
});
A bit cruftier than the Python solution, but it gets the point across. Now you can "insert code" into the function by defining the predicate, in-line, to be whatever you want it to be. Plus you can save often-used ones so you don't repeat them all over the place:
QuadBatchPredicate checkBlends = new QuadBatchPredicate() {
public boolean shouldMove(int loop, Sprite sprite) {
return sprite.doesItBlend();
}
};
Make an interface as so:
public interface MyInteface {
void do_something(int loop);
}
Make different implementations of that interface depending on your needs e.g.
public class MyInterfaceImpl {
public void do_something(int loop) {
if (!checkDelay || sprite.delay[loop] < 0) {
moveQuadNumber(loop);
}
}
Then your method could look simple as this:
public void moveQuadBatch(MyInterface interface) {
for (int loop = 0; loop < sprite.number; loop++){
interface.do_something(loop)
}
}
You could add "effects" to your sprites.
public class Sprite {
private boolean active = true;
private ArrayList<Effect> effects = new ArrayList<>();
public void update(int time) {
for(Effect e: effects) {
e.update(this, time);
}
}
public void addEffect(Effect effect) {
effects.add(effect);
}
public void setActive(boolean active) {
this.active = active;
}
}
public interface Effect {
void update(Sprite sprite, int time);
}
public class Delay implements Effect {
private int delay;
public Delay(int delay) {
this.delay = delay;
}
public void update(Sprite sprite, int time) {
delay -= time;
if(delay > 0) sprite.setActive(false);
else sprite.setActive(true);
}
}
I would create a seperate method for the delay check and change your method like this:
public void moveQuadBatchWithCheck(bool check){
for (loop = 0; loop < sprite.number; loop++){
if(check){
if (sprite.delay[loop]<0){
moveQuadNumber(loop);
}
}
else{
moveQuadNumber(loop);
}
}
Then when you want to check call the method with true
in the parameter.
Not sure if this is what you're looking for though, but I hope it helps.
Related
I wanted to make some kind of sorting algorithms visualisation is java swing but I am stuck on quicksort since I need to stop the partition loop every iteration so the array can redraw. That's how I wanted to do it but without any success
public int partition(int lowIndex, int highIndex,int i)
{
int pivot = highIndex;
for(int j=lowIndex; j<highIndex; j++)
{
if(isBigger(j,pivot))
{
i++;
swap(i,j);
return i;
}
}
swap(i+1,pivot);
return i+1;
}
Didn't find any good solution to keep track on i as well. I'm just clueless
Google for "Java swing visualize sorting algorithms" and you'll find many hits.
For example:
Code Review: sorting algorithm visualization program
Key points:
You need to modify your "sort" code to trigger some kind of "event" at each step (e.g. every time you swap elements):
EXAMPLE:
public class BubbleSort implements SortingAlgorithm {
...
#Override
public void doSort(int[] nums) {
...
SortingAlgorithm.setCurrentBar(j+1);
SortingAlgorithm.sleepFor(delay);
The "event handler" will redraw the array (or, more accurately, request the Event Dispatcher thread (EDT) to repaint).
Consequently, the event handler needs to "know about" the array, and the current index
EXAMPLE:
public abstract interface SortingAlgorithm {
...
public abstract void doSort(int[] nums);
public abstract void changeDelay(int delay);
public static void setCurrentBar(int currentBarIndex) {
PaintSurface.currentBarIndex = currentBarIndex;
}
...
There also needs to be some kind of "delay" between each step
This example uses SwingUtilities.invokeLater(). The example camickr suggests SwingWorker.
I hope that gives you a few ideas, and points you in the right direction!
Instead of calling partition from other class I implemented partition() and sort() methods in an anonymous SwingWorker class and after every swap in partition() method I called publish(array). Uploading source code if anyone would like to see how I solved this problem or would need help himself. Any feedback is really appreciate since it's my first "bigger" project
private void startThread()
{
SwingWorker sw1 = new SwingWorker() {
public int partition(int lowIndex, int highIndex) {
int pivot = highIndex;
int i = lowIndex - 1;
for (int j = lowIndex; j < highIndex; j++) {
if (sorter.isBigger(pivot, j)) {
i++;
sorter.swap(i, j);
try {
Thread.sleep(100);
}
catch(Exception e)
{
// not implemented yet
}
publish(sorter.getArray());
}
}
sorter.swap(i+1,pivot);
publish(sorter.getArray());
return i+1;
}
public void sort(int lowIndex, int highIndex)
{
if(lowIndex < highIndex)
{
int i = partition(lowIndex,highIndex);
try{
sort(lowIndex,i-1) ;
}
finally {
sort(i+1, highIndex);
}
}
}
#Override
protected int[] doInBackground() throws Exception {
sorter.setArray(drafter.getArray());
while (!sorter.isArraySorted()) {
//Thread.sleep(10);
sort(0,sorter.getLength()-1);
}
return sorter.getArray();
}
protected void process(List chunks)
{
int[] val = (int[]) chunks.get(chunks.size()-1);
drafter.ChangeArray(val);
//drafter.repaint();
}
};
sw1.execute();
}
So let's say I have a main class with a while loop:
public class Main {
public static void main(String[] args) throws InterruptedException {
int one = 1;
int counter = 0;
while (one<100){
Thread.sleep(1000);
counter += 1;
Function.Move();
one++;
}
The counter variable in this loop is counting each second elapsed.
There is a separate class called Function:
public class Function {
public static int Move (int result){
result = 1 + counter;
return result;
}
}
So as you can see, inside the Function class's Move method, I want to be able to use the counter variable's new value, which increases with each passing second, to calculate the value of a different variable which will then be returned to the main method.
The problem is that I can't figure out how to pass the value of counter to the Move method inside the Function class to begin with.
I'm not shure if i understand what you want to do correctly, depending on where exactly you will need that result variable later i think your coude should look something like this:
public class Main {
int counter;
public static void main(String[] args) throws InterruptedException {
int one = 1;
counter = 0;
while (one<100){
Thread.sleep(1000);
counter += 1;
one++;
}
}
public int getCounter() {
return counter;
}
}
public class Function {
public static int move (int result, Main main){
result = 1 + main.getCounter();
return result;
}
}
You can use Function.move() anywhere you need it's value in your Programm now.
Beware, though, that you will need your code using the Function.move() to run in a different Thread as the Main Thread. Otherwise it will always return 101 or 1, as the while loop will always be running before or after your call to Function.move(), depending on where you call it (except if you call it from within the while loop, but then you counld just use counter++ without the need to have an extra class)
I have a homework assignment where I need to make an array of lightbulb objects. Then add a method to "turn them on". I need to have a nested loop to have an imaginary person turn on every bulb then pull the string on every other bulb then every 3rd and so on until its every 20 bulbs. This is the code I have. It compiles but when I run it, it just goes forever. PLEASE HELP
public class LightBulb
{
public boolean isTurnedOn;
public LightBulb()
{
isTurnedOn = false;
}
public boolean isOn()
{
if(isTurnedOn==false)
return false;
return true;
}
public void pullString()
{
if(isTurnedOn==true){
isTurnedOn=false;
}
isTurnedOn=true;
}
}
public class LightDriver
{
public static void main(String[]arg)
{
int numOn=0;
LightBulb[]Bulb=new LightBulb[100];
for(int a=0;a<100;a++){
Bulb[a]=new LightBulb();
}
for(int b=0;b<=19;b++){
for(int c=0;c<=100;c=b+1){
Bulb[c].pullString();
}
}
for(int d=0;d<100;d++){
if(Bulb[d].isTurnedOn==true){
numOn++;
}
}
System.out.println(numOn+" lightbulbs are on");
}
}
This is causing the problem:
for(int b=0;b<=19;b++){
for(int c=0;c<=100;c=b+1){
Bulb[c].pullString();
}
}
For every iteration of the inner for loop, you are setting c = b + 1 which means that c is not changing, since b is not changing.
I think what you want is this:
for(int b=1; b <= 20; b++){
for(int c=0; c < 100; c = c + b){
Bulb[c].pullString();
}
}
Also, your pullString method sets isTurnedOn to true no matter what it originally was. I think this is what you want instead:
public void pullString()
{
if (isTurnedOn)
{
isTurnedOn = false;
}
else
{
isTurnedOn = true;
}
}
Your problem is in this loop
for(int b=0;b<=19;b++){
for(int c=0;c<=100;c=b+1){
Bulb[c].pullString();
}
}
your value of c never increases, as it is always set to b+1 which - within a single iteration of the b loop - never changes. As such, you never reach the termination condition of the loop. Here is a fix
for(int b=0;b<=19;b++){
int c = b+1; //assign initial value outside of inner loop
for(;c<=100;c++){ //increment value inside of inner loop
Bulb[c].pullString();
}
}
I was experimenting with this question today, from Euler Problems:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
I thought about it and it can of course be done with for-loops, however I want to use Java 8 as it opens up new options.
However first of all, I do not know how to generate an IntStream that produces such elements, so I still ended up using normal for-loops:
public class Problem4 extends Problem<Integer> {
private final int digitsCount;
private int min;
private int max;
public Problem4(final int digitsCount) {
this.digitsCount = digitsCount;
}
#Override
public void run() {
List<Integer> list = new ArrayList<>();
min = (int)Math.pow(10, digitsCount - 1);
max = min * 10;
for (int i = min; i < max; i++) {
for (int j = min; j < max; j++) {
int sum = i * j;
if (isPalindrome(sum)) {
list.add(sum);
}
}
}
result = list.stream().mapToInt(i -> i).max().getAsInt();
}
private boolean isPalindrome(final int number) {
String numberString = String.valueOf(number);
String reversed = new StringBuilder(numberString).reverse().toString();
return (numberString.equals(reversed));
}
#Override
public String getName() {
return "Problem 4";
}
}
As you can see I might be a bit lazy, bit really the IntStream::max is a very nice method and I think it is better to use that, as to write it yourself.
Here comes the issue though, I need to have a list now to be able to obtain the maximum in this manner, which means I need to store data, where I really should not do so.
So, the question now, would it be possible to implement this in Java 8?
for (int i = min; i < max; i++) {
for (int j = min; j < max; j++) {
yield i * j;
}
}
And then out of that method create an PrimitiveIterator.OfInt (unboxes version of Iterator<Integer>, or create an IntStream directly?
Then getting the answer with streamFromYield.filter(this::isPalindrome).max().getAsInt() would be really easy to implement.
Lastly, I know this question has been asked before, however the last time is already quite a bit ago and now Java 8 is going to happen very soon, where they have added as big concept Stream<T> and the new language construct, called lambdas.
So making such code may be very different now than when people were making it for Java 6 or 7.
Well, I think we've gotten carried away using the Streams API from the "outside," using flatMap, optimizing the palindrome-finding algorithm, etc. See answers from Boris the Spider and assylias. However, we've sidestepped the original question of how to write a generator function using something like Python's yield statement. (I think the OP's nested-for example with yield was using Python.)
One of the problems with using flatMap is that parallel splitting can only occur on the outermost stream. The inner streams (returned from flatMap) are processed sequentially. We could try to make the inner streams also parallel, but they'd possibly compete with the outer ones. I suppose nested splitting could work, but I'm not too confident.
One approach is to use the Stream.generate or (like assylias' answer) the Stream.iterate functions. These create infinite streams, though, so an external limit must be supplied to terminate the stream.
It would be nice if we could create a finite but "flattened" stream so that the entire stream of values is subject to splitting. Unfortunately creating a stream is not nearly as convenient as Python's generator functions. It can be done without too much trouble, though. Here's an example that uses the StreamSupport and AbstractSpliterator classes:
class Generator extends Spliterators.AbstractIntSpliterator {
final int min;
final int max;
int i;
int j;
public Generator(int min, int max) {
super((max - min) * (max - min), 0);
this.min = min;
this.max = max;
i = min;
j = min;
}
public boolean tryAdvance(IntConsumer ic) {
if (i == max) {
return false;
}
ic.accept(i * j);
j++;
if (j == max) {
i++;
j = min;
}
return true;
}
}
public static void main(String[] args) {
Generator gen = new Generator(100, 1000);
System.out.println(
StreamSupport.intStream(gen, false)
.filter(i -> isPalindrome(i))
.max()
.getAsInt());
}
Instead of having the iteration variables be on the stack (as in the nested-for with yield approach) we have to make them fields of an object and have the tryAdvance increment them until the iteration is complete. Now, this is the simplest form of a spliterator and it doesn't necessarily parallelize well. With additional work one could implement the trySplit method to do better splitting, which in turn would enable better parallelism.
The forEachRemaining method could be overridden, and it would look almost like the nested-for-loop-with-yield example, calling the IntConsumer instead of yield. Unfortunately tryAdvance is abstract and therefore must be implemented, so it's still necessary to have the iteration variables be fields of an object.
How about looking at it from another direction:
You want a Stream of [100,1000), and for each element of that Stream you want another Stream of that element multiplied by each of [100, 1000). This is what flatMap is for:
public static void main(final String[] args) throws Exception {
OptionalInt max = IntStream.range(100, 1000).
flatMap((i) -> IntStream.range(i, 1000).map((j) -> i * j)).
unordered().
parallel().
filter((i) -> {
String forward = Integer.toString(i);
String backward = new StringBuilder(forward).reverse().toString();
return forward.equals(backward);
}).
max();
System.out.println(max);
}
Not sure if getting a String and then the reverse is the most efficient way to detect palindromes, off the top of my head this would seem to be faster:
final String asString = Integer.toString(i);
for (int j = 0, k = asString.length() - 1; j < k; j++, k--) {
if (asString.charAt(j) != asString.charAt(k)) {
return false;
}
}
return true;
It gives the same answer but I haven't put it under an rigorous testing... Seems to be about 100ms faster on my machine.
Also not sure this problem is big enough for unordered().parallel() - removing that gives a little boost to speed too.
Was just trying to demonstrate the capabilities of the Stream API.
EDIT
As #Stuart points out in the comments, as multiplication is commutative, we only need to IntStream.range(i, 1000) in the sub-stream. This is because once we check a x b we don't need to check b x a. I have updated the answer.
There always have been ways to emulate that overrated yield feature, even without Java 8. Basically it is about storing the state of an execution, i.e. the stack frame(s), which can be done by a thread. A very simple implementation could look like this:
import java.util.Iterator;
import java.util.NoSuchElementException;
public abstract class Yield<E> implements Iterable<E> {
protected interface Flow<T> { void yield(T item); }
private final class State implements Runnable, Iterator<E>, Flow<E> {
private E nextValue;
private boolean finished, value;
public synchronized boolean hasNext() {
while(!(value|finished)) try { wait(); } catch(InterruptedException ex){}
return value;
}
public synchronized E next() {
while(!(value|finished)) try { wait(); } catch(InterruptedException ex){}
if(!value) throw new NoSuchElementException();
final E next = nextValue;
value=false;
notify();
return next;
}
public void remove() { throw new UnsupportedOperationException(); }
public void run() {
try { produce(this); }
finally {
synchronized(this) {
finished=true;
notify();
}
}
}
public synchronized void yield(E next) {
while(value) try { wait(); } catch(InterruptedException ex){}
nextValue=next;
value=true;
notify();
}
}
protected abstract void produce(Flow<E> f);
public Iterator<E> iterator() {
final State state = new State();
new Thread(state).start();
return state;
}
}
Once you have such a helper class, the use case will look straight-forward:
// implement a logic the yield-style
Iterable<Integer> y=new Yield<Integer>() {
protected void produce(Flow<Integer> f) {
for (int i = min; i < max; i++) {
for (int j = min; j < max; j++) {
f.yield(i * j);
}
}
}
};
// use the Iterable, e.g. in a for-each loop
int maxPalindrome=0;
for(int i:y) if(isPalindrome(i) && i>maxPalindrome) maxPalindrome=i;
System.out.println(maxPalindrome);
The previous code didn’t use any Java 8 features. But it will allow using them without the need for any change:
// the Java 8 way
StreamSupport.stream(y.spliterator(), false).filter(i->isPalindrome(i))
.max(Integer::compare).ifPresent(System.out::println);
Note that the Yield support class above is not the most efficient implementation and it doesn’t handle the case if an iteration is not completed but the Iterator abandoned. But it shows that such a logic is indeed possible to implement in Java (while the other answers convincingly show that such a yield logic is not necessary to solve such a problem).
I'll give it a go. Version with a loop then with a stream. Although I start from the other end so it's easier because I can limit(1).
public class Problem0004 {
public static void main(String[] args) {
int maxNumber = 999 * 999;
//with a loop
for (int i = maxNumber; i > 0; i--) {
if (isPalindrome(i) && has3DigitsFactors(i)) {
System.out.println(i);
break;
}
}
//with a stream
IntStream.iterate(maxNumber, i -> i - 1)
.parallel()
.filter(i -> isPalindrome(i) && has3DigitsFactors(i))
.limit(1)
.forEach(System.out::println);
}
private static boolean isPalindrome(int n) {
StringBuilder numbers = new StringBuilder(String.valueOf(n));
return numbers.toString().equals(numbers.reverse().toString());
}
private static boolean has3DigitsFactors(int n) {
for (int i = 999; i > 0; i--) {
if (n % i == 0 && n / i < 1000) {
return true;
}
}
return false;
}
}
I am using Google javaparser to parse the java file, when I try to count the "If" statement, it seems like I can not get the number of "else-if" statement.
For example, I want to parse the following code:
if(i>1){
i++;
}else if(i>2){
i++;
}else if(i>3){
i++;
}else{
i++;
}
I want to get the Cyclomatic complexity so that I need to count the number of "if" and "else-if".
When I use Visitor pattern, I can only visit the "IfStmt" defined in the API, the code looks like:
private static class IfStmtVisitor extends VoidVisitorAdapter<Void> {
int i = 0;
#Override
public void visit(IfStmt n, Void arg) {
//visit a if statement, add 1
i++;
if (n.getElseStmt() != null) {
i++;
}
}
public int getNumber() {
return i;
}
}
There is no way to get "else-if" but the Visitor pattern with "IfStmt" treats the whole code block as one "if" Statement.So, I expect the number to be 4, but it is 2.
Anyone have some idea?
A if-statement only contains one "then Statement" and one "else Statement". The else Statement can be a hidden if statement. So there is a recursivity. To track your needed complexity the following recursive method may help:
private static class IfStmtVisitor extends VoidVisitorAdapter<Void> {
int i = 0;
#Override
public void visit(IfStmt n, Void arg)
{
cyclomaticCount(n);
}
private void cyclomaticCount(IfStmt n)
{
// one for the if-then
i++;
Statement elseStmt = n.getElseStmt();
if (elseStmt != null)
{
if ( IfStmt.class.isAssignableFrom(elseStmt.getClass()))
{
cyclomaticCount((IfStmt) elseStmt);
}
else
{
// another for the else
i++;
}
}
}
public int getNumber() {
return i;
}
}
Hope that helps.