"repeat" structure in Java - java

I'm teaching programming to beginners (starting at 12-15 years old) and one of the choices we made (because it was natural in Python) was to teach the notion of "repeating an action" before the notion of variables.
We warted in Python with
for loop in range(10):
without speaking about variables of arrays and in C++ with
#define repeat(nb) for(int _loop = 0 ; _loop < (nb) ; _loop++)
The idea was to hide the complexity of a classical loop in order to insist on the "repeat" part. We are not hiding from the students the fact that "repeat(10)" is not a part of C++,
it's just a way to simplify the learning.
In Pascal we can't do much more than
for loop := 1 to 10 do
but that's ok because its's not that difficult to remember.
I was looking for something similar in Java and I found that :
import java.util.List;
import java.util.AbstractList;
class Range {
public static List<Integer> size(final int end) {
return new AbstractList<Integer>() {
#Override
public Integer get(int index) {
return 0 + index;
}
#Override
public int size() {
return end;
}
};
};
}
public class Main {
public static void main(String[] argv) {
for (int loop : Range.size(10)) {
System.out.println("xx");
}
}
}
The
for (int loop : Range.size(10))
is still easier to remember than
for(int loop = 0 ; loop < 10 ; loop++)
but there is two problems :
two variables are needed for imbricated for loops : I dont think we can do much about that
we are having warnings because the variable loop is not used
Do you see a better solution that what we have ?
Once again, we only want to provide some "tool" at the beginning phase in order for the students to "repeat" actions, before knowing anything about "variables". We are not hiding from them that's is not in the langage and after a few exercises (~80-100) we are asking them to use the real syntax.
We have approximately 20 exercices before introducing variables : some about printing texts but mostly we are providing one library with objects you can manipulate (hence the variables are hidden in the object state). You can think of the "logo-turtle" for example. This way the notion of "loop" can be manipulated and "seen" before introducing explicit variables and you can have interresting exercises really fast.
One example, in Python, where you want to visit every case of a 10x10 table once and only once and then be back at your starting point (lower-left corner) :
from robot import *
top()
for loop in range(4):
for loop in range(8):
top()
right()
for loop in range(8):
bottom()
right()
for loop in range(8):
top()
right()
for loop in range(9):
bottom()
for loop in range(9):
left()
This exercise is not that easy but the syntax is really simple and allow the student to concentrate on the "algorithmic" part and not the "langage" part.
After a few exercises the students are getting interrested and we can introduce more syntax and more difficult concepts like the variables.

Do you really need to use Java for those exercises? If other languages works for you then why not to use them? You can always move to Java when you students know basics like variables.
I agree that variables can be quite confusing from beginners - especially that their value can change all the time, it is not something people are used from algebra where values don't change once "assigned".
If you want to use Java, you could use while loop which seems to fit better. One dirty trick how to avoid use of variable is following code - it use StackTraceElement instead of variable.
It prints
Hello A
Hello B
Hello C
Hello C
Hello C
Hello B
Hello C
Hello C
Hello C
Hello A
Hello B
Hello C
Hello C
Hello C
Hello B
Hello C
Hello C
Hello C
Hello A
Hello B
Hello C
Hello C
Hello C
Hello B
Hello C
Hello C
Hello C
Here is full source. main(Strinng[] args) method is code with loops, rest is supporting code.
import java.util.HashMap;
import java.util.Map;
public class Repeater {
public static void main(String[] args) {
while(range(3)) {
System.out.println("Hello A");
while (range(2)) {
System.out.println("Hello B");
while (range(3)) {
System.out.println("Hello C");
}
}
}
}
public static boolean range(int size) {
return Range.range(size);
}
public static class Range {
static Map<StackTraceElement, RangePosition> ranges = new HashMap<StackTraceElement, RangePosition>();
public static boolean range(int size) {
final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
//System.out.println(stackTraceElement);
RangePosition position = ranges.get(stackTraceElement);
if (position == null) {
position = new RangePosition();
position.size = size;
ranges.put(stackTraceElement, position);
}
final boolean next = position.next();
if (!next) {
ranges.remove(stackTraceElement);
}
return next;
}
}
public static class RangePosition {
int current,size;
boolean next() {
current++;
return current <= size;
}
}
}
But I'd prefer to use some language which supports this naturally.

I would always introduce variables first. What are you going to do inside the loop without knowledge about variables ?
Apart from that maybe it would be easier to use a while loop. The head of a while loop is much easier and doesn't require variable definitions.
This is very simple to understand:
while (do_the_loop){
//this is repeated
}

Java really is not suitable for this kind of task because it does not allow for functions to be passed.
The only way I can think of doing this without variables would be with an interface:
private static void repeat(int times, DoStuff what) {
for (int i = 0; i < times; i++) {
what.doIt();
}
}
private interface DoStuff {
public void doIt();
}
And then use it this way:
repeat(5, new DoStuff() { public void doIt() {
System.out.println("xx"); // whatever needs to be done
}});
Which would be without variables but quite confusing at the beginning.

This is not really what you are searching for, but here is my opinion and how I would teach it. (Beware, I'm not a teacher at all :D)
Aren't there two different courses for this: Algorithms and Programming? In programming, you really should start off by teaching them the variables. It's not difficult at all. And I don't think that 20 exercises about algorithms are going to be that interesting for them. I think they will be more attracted to the power of computing something than either writing for loops inside each other. Writing a simple program that computes some summations and multiplications et cetera will do to introduce the idea of primitive variables. Then I would introduce the for loop. Demonstrate by printing 10 times some text in combination with the variable used in the for loop:
for (int i = 0; i < 10; ++i)
// Tell them that the 'i' is a variable as you explained before.
{
System.out.println("This is line " + i);
}
Then writing an application that computes the factorial of a hardcoded number will be interesting, I think. This way, most of them will hopefully get the idea of working with variables. Then try to explain scopes.
int number = 5;
int factorial = 1;
for (int i = 1; i <= number; ++i)
{
factorial = factorial * i;
}
System.out.println(number + "! = " + factorial);

if you have a limit defined you have to use a while structure
while(myval < mylimit){
//do something
myval++;
}
but when the limit is unknow then you should use for or for each
for (int i =0; i< list.size();i++)
{
}
of by objects
for each (String myString : myStringArray){
}
Saludos

Related

Shortest concise readable syntax to iterate over consecutive numbers from given range

In groovy I can iterate through numbers using that simple syntax:
(1..10).each {
do_domething it
}
What is the shortest syntax to do that in Java? I am now exploring streams and I came up with such an idea:
IntStream.range(0, 10)
.forEach(do_domething());
It is even longer than the traditional way (below), but seems to be more concise.
for (int i = 0; i < 10; i++)
do_domething()
I am just curious if there is shorter and readable way of doing it. I don't know everything about Java so I am just asking, probably there is no such thing, but I would like to make sure.
If you need to use IntStream.range repeatedly in one class, you can reduce verbosity by using a static import:
import static java.util.stream.IntStream.range;
Then the syntax becomes
range(0, 10).forEach(...)
Beyond that, there's not much else I can suggest. In my view it is a bit ridiculous that we have to write for(int i = 0; i < n; i++) repeatedly, but at least it has the advantage of being instantly recognisable.
There are some major differences between those two that do not make them drop in replacements of each other.
A return from a regular for-loop will return from your method, but for the stream/lambda version it returns from the lambda function. See below.
for (int i = 0; i < 10; i++) {
if (i == 5) {
return;//returns from the whole method
}
}
IntStream.range(0, 10).forEach((i -> {
if (i == 5) {
return; //returns only from the lambda
}
}));
Another major difference is how the two code blocks interact with variables. For lambdas to interact with variables that our outside its scope, they need to be final. So the stream/lambda code below won't compile.
String x = "";
for (int i = 0; i < 10; i++) {
if (i == 5) {
x = "5";
}
}
IntStream.range(0, 10).forEach((i -> {
if (i == 5) {
x = "5"; //wont compile
}
}));
There might be other differences between the two. But for me that last one has caused problems that has lead me to continue using the regular for-loop.
If you want concise you can use a helper method.
public static void each(int start, int end, IntConsumer consumer) {
IntStream.range(start, end).forEach(consumer);
}
and then you can write
import static java.lang.System.out;
each(0, 10, out::println);
If "each" is a bit verbose you could use a connector character like
public static void ⁀(int start, int end, IntConsumer consumer) {
IntStream.range(start, end).forEach(consumer);
}
public static void main(String... args) {
⁀(0, 10, out::println);
}
prints
0
1
2
3
4
5
6
7
8
9
You could create a helper function to create an array
public static int[] range(final int length){
return IntStream.range(0, length).toArray();
}
Then using a foreach loop all you need to write is:
for(int i : range(10)) {
do_domething();
}
You can use the so-called "Facetious Arrow" operator (it looks like an arrow "-->") to write the loop slightly more briefly. [Pro Tip: It's not really an arrow]
for (int i=10;i-->0;)doSomething();
For example:
for (int i=10;i-->0;)System.out.println(i);
Prints:
9
8
7
6
5
4
3
2
1
0

Obtain the largest number in an array of numbers [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
This is my first time doing java and I am am trying to get the largest number from an array of x numbers using a method called bigNum(). Can anyone tell me why this doesn't work?
class project3
{
public static void main(String args[])
{
int total =0;
int b;
System.out.println("How many numbers do you want in the array");
int maxItems = EasyIn.getInt();
int[] numbers = new int[maxItems];
for (int i=0; i < maxItems; i++)
{
b = EasyIn.getInt();
}
bigNum(b);
}
public static void bigNum(int maxItems)
{
for (int i = 1; i >= maxItems; i++)
{
if (bigNum(b) >= maxItems)
bigNum(b) = maxItems;
}
return bigNum(b);
}
}
You're probably getting compiler errors at this point due to unmatched braces. You want your program to have matched braces, and you also want to avoid having methods inside of other methods.
You want to have something that has the following form
class project3
{
public static void main(String args[])
{
...
}
public static int bigNum(int maxItems[])
{
...
return someInt;
}
}
// capital letter for the class (convention)
public class Project3 {
public static void main(String args[]) {
//int total = 0; // you never used this number
System.out.println("How many numbers do you want in the array");
int maxItems = EasyIn.getInt();
int[] numbers = new int[maxItems];
for(int i = 0; i < maxItems; ++i) {
int newNumber = EasyIn.getInt();
/* you want to put the numbers into an array,
so don't call "bigNum" but put them there: */
numbers[i] = newNumber;
}
// now find the big number:
int bigNumber = bigNum(numbers);
System.out.println("The biggest number: " + bigNumber);
}
// first: change the return type to get the biggest number
// second: pass the reference to the array, not a single number
// public static void bigNum(int maxItems) {
public static int bigNum(int[] items) {
// create big number, assume it's very small:
int bigNumber = Integer.MIN_VALUE;
// this for loop will never run, change it a bit:
//for(int i = 1; i >= maxItems; i++) {
for(int i = 0; i < items.length; i++) {
// your idea is correct, but you can not use the
// method here, see explanations below
// Also don't check for the number of Items, but for
if(items[i] > bigNumber) {
bigNumber = items[i];
}
}
return bigNumber;
}
}
Explanations and further readings
Class name: Java has lots of different naming conventions, but the most common rules are: ClassNames/Types in CamelCase with a Capital at the beginning, variableNames following a similar convention but with a leading small letter. This makes it much easier to read code.
Indentation: Try to use a more consistent indentation. Also supports readability. Actually some other programming languages even rely on correct indentation.
Try to understand what variables and what methods are and how to use them (and return from them, you can not assign values to a method in Java. While you read the latter tutorial focus on return types and how to call methods correctly, you can not return an int when your method is of type void. Also the parameters need to be exactly defined.
Apart from that try to compile your code before you post it. As your code went, it should have thrown lots of compile errors, e.g. bigNum(b) = maxItems; should tell you that the left-hand side of an assignment needs to be a variable. This can help you a lot while tracking down mistakes.
Another error is that for most people EasyIn will not be defined (as it is for me, so the code I posted above might actually not be working, I didn't try). I suppose it's a learning library (we had our AlgoTools back in our first Java lectures). Still it would be nice to tell us what it is and what other imports you use (common mistake when I let my IDE decide my imports for me: java.util.Date and java.sql.Date).
Also try to make clear to yourself what you want to achieve with your program and how. Your algorithm actually looks like you didn't think too much about it: You try to find a biggest number and always check "a big number" against the number of expected items, which then might become "the big number" as well. Or something like that.
Programming is being concise and exact, so make a plan before. If it's too hard for you to think about a solution directly, you can maybe draw it on paper.
And if you then have problems, after compiling, asking your program, asking google, asking stack overflow: provide us with as many details as you can and we will be able to help you without just posting some code.
Good luck!

proper way to store large numbers in a variable

I would like to play around with numbers and however elementary, Ive been writing algorithms for the fibonacci sequence and a brute force path for finding prime numbers!
Im not a programmer, just a math guy.
However, a problem I run into quiet often is that a long long, double and floats often run out of room.
If I wanted to continue to work in JAVA, in what way can I create my own data type so that I dont run out of room.
Conceptually, I thought to put 3 doubles together like so,
public class run {
static double a = 0;
static double b = 0;
//static double c = 0;
static void bignumber(boolean x) {
if (x == true && a < 999999999) {
++a;
} else if (x == true && a == 999999999) {
++b;
a = 0;
}
System.out.print(b + "." + a + " \n");
}
public static void main(String[] args) {
while(true) {
bignumber(true);
}
}
}
is there a better way to do this,
I would like to one day be able to say
mydataType X = 18476997032117414743068356202001644030185493386634
10171471785774910651696711161249859337684305435744
58561606154457179405222971773252466096064694607124
96237204420222697567566873784275623895087646784409
33285157496578843415088475528298186726451339863364
93190808467199043187438128336350279547028265329780
29349161558118810498449083195450098483937752272570
52578591944993870073695755688436933812779613089230
39256969525326162082367649031603655137144791393234
7169566988069
or any other number found on this site
I have also tried
package main;
import java.math.BigInteger;
public class run {
BigDecimal a = 184769970321174147430683562020019566988069;
public static void main(String[] args) {
}
}
But it still seems to be out of range
Use BigDecimal (instead of double), and BigInteger (instead of int, long) for that purpose, But you can only work with them by their methods. No operators, can be used.
Used like this:
BigInteger big = new BigInteger("4019832895734985478385764387592") // Strings...
big.add(new BigInteger("452872468924972568924762458767527");
Same with BigDecimal
BigDecimal is the class used in java where you need to represent very large or very small numbers, and maintain precision. The drawbacks are that it is not a primitive, so you can't use the normal math operators (+/-/*/etc), and that it can be a little processor/memory intensive.
You can store large numbers like this:
length
digits[]
and implement your math for them. This is not very complicated. As a hint, to make everything more simple you can store the digits in reverse order. This will make your math simpler to implement - you always add nr[k] with nr[k] and have room for transport for any length numbers, just remember to fill with 0 the shorter one.
In Knuth Seminumeric Algorithms book you can find a very nice implementation for all operations.

Java exercise for checkout

I'm trying some Java recently and look for some review of my style. If You like to look at this exercise placed in the image, and tell me if my style is good enought? Or maybe it is not good enought, so You can tell me on what aspect I should work more, so You can help me to improve it?
exercise for my question
/*
* File: MathQuiz.java
*
* This program produces Math Quiz.
*/
import acm.program.*;
import acm.util.*;
public class MathQuiz extends ConsoleProgram {
/* Class constants for Quiz settings. */
private static final int CHANCES = 3;
private static final int QUESTIONS = 5;
private static final int MIN = 0;
private static final int MAX = 20;
/* Start program. Number of questions to ask is assigned here. */
public void run() {
println("Welcome to Math Quiz");
while(answered != QUESTIONS) {
produceNumbers();
askForAnswer();
}
println("End of program.");
}
/* Ask for answer, and check them. Number of chances includes
* first one, where user is asked for reply. */
private void askForAnswer() {
int answer = -1;
if(type)
answer = readInt("What is " + x + "+" + y + "?");
else
answer = readInt("What is " + x + "-" + y + "?");
for(int i = 1; i < CHANCES+1; i++) {
if(answer != solution) {
if(i == CHANCES) {
println("No. The answer is " + solution + ".");
break;
}
answer = readInt("That's incorrect - try a different answer: ");
} else {
println("That's the answer!");
break;
}
}
answered++;
}
/* Produces type and two numbers until they qualify. */
private void produceNumbers() {
produceType();
produceFirst();
produceSecond();
if(type)
while(x+y >= MAX) {
produceFirst();
produceSecond();
}
else
while(x-y <= MIN) {
produceFirst();
produceSecond();
}
calculateSolution();
}
/* Calculates equation solution. */
private void calculateSolution() {
if(type) solution = x + y;
else solution = x - y;
}
/* Type of the equation. True is from plus, false is for minus. */
private void produceType() {
type = rgen.nextBoolean();
}
/* Produces first number. */
private void produceFirst() {
x = rgen.nextInt(0, 20);
}
/* Produces second number. */
private void produceSecond() {
y = rgen.nextInt(0, 20);
}
/* Class variables for numbers and type of the equation. */
private static boolean type;
private static int x;
private static int y;
/* Class variables for equation solution. */
private static int solution;
/* Class variable counting number of answered equations,
* so if it reaches number of provided questions, it ends */
private static int answered = 0;
/* Random generator constructor. */
RandomGenerator rgen = new RandomGenerator();
}
One thing I noticed was that all of your methods take no parameters and return void.
I think it would be clearer if you use method parameters and return values to show the flow of data through your program instead of using the object's state to store everything.
There are a few things you should do differently, and a couple you could do differently.
The things you should do differently:
Keep all fields together.
static fields should always be in THIS_FORM
you've used the static modifier for what clearly look like instance fields. (type,x,y,solution, answered). This means you can only ever run one MathsQuiz at a time per JVM. Not a big deal in this case, but will cause problems for more complex programs.
produceFirst and produceSecond use hardcoded parameters to nextInt rather than using MAX and MIN as provided by the class
There is no apparent need for answered to be a field. It could easily be a local variable in run.
Things you should do differently:
There is a small possibility (however tiny), that produceNumbers might not end. Instead of producing two random numbers and hoping they work. Produce one random number and then constrain the second so that a solution will always be formed. eg. say we are doing and addition and x is 6 and max is 20. We know that y cannot be larger than 14. So instead of trying nextInt(0,20), you could do nextInt(0,14) and be assured that you would get a feasible question.
For loop isn't really the right construct for askForAnswer as the desired behaviour is to ask for an answer CHANCES number of times or until a correct answer is received, whichever comes first. A for loop is usually used when you wish to do something a set number of times. Indeed the while loop in run is a good candidate for a for loop. A sample while loop might look like:
int i = 1;
boolean correct = (solution == readInt("What is " + x + "+" + y + "?"));
while (i < CHANCES && !correct) {
correct = (solution == readInt("Wrong, try again."));
i++;
}
if (correct) {
println("Well done!");
} else {
println("Nope, the answer is: "+solution);
}
Looks like a very clean program style. I would move all variables to the top instead of having some at the bottom, but other than that it is very readable.
Here is something I'd improve: the boolean type that is used to indicate whether we have an addition or subtraction:
private void produceType() {
type = rgen.nextBoolean();
}
produceType tells, that something is generated and I'd expect something to be returned. And I'd define enums to represent the type of the quiz. Here's my suggestion:
private QuizType produceType() {
boolean type = rgen.nextBoolean();
if (type == true)
return QuizType.PLUS;
else
return QuizType.MINUS;
}
The enum is defined like this:
public enum QuizType { PLUS, MINUS }
Almost good I have only a few improvements:
variables moves to the top
Inside produceNumbers and your while you have small repeat. I recommend refactor this
Small advice: Code should be like books - easy readable - in your run() method firstly you call produceNumber and then askForAnswer. So it will be better if in your code you will have the same order in definitions, so implementation askForAnswer before produceNumber. But it isn't necessary
Pay attention to have small methods. A method shouldn't have much to do - I think that askForAnswer you could split to two methods

Very simple code for number search gives me infinite loop

I am a newbie Computer Science high school student and I have trouble with a small snippet of code. Basically, my code should perform a basic CLI search in an array of integers. However, what happens is I get what appears to be an infinite loop (BlueJ, the compiler I'm using, gets stuck and I have to reset the machine). I have set break points but I still don't quite get the problem...(I don't even understand most of the things that it tells me)
Here's the offending code (assume that "ArrayUtil" works, because it does):
import java.util.Scanner;
public class intSearch
{
public static void main(String[] args)
{
search();
}
public static void search()
{
int[] randomArray = ArrayUtil.randomIntArray(20, 100);
Scanner searchInput = new Scanner(System.in);
int searchInt = searchInput.nextInt();
if (findNumber(randomArray, searchInt) == -1)
{
System.out.println("Error");
}else System.out.println("Searched Number: " + findNumber(randomArray, searchInt));
}
private static int findNumber(int[] searchedArray, int searchTerm)
{
for (int i = 0; searchedArray[i] == searchTerm && i < searchedArray.length; i++)
{
return i;
}
return -1;
}
}
This has been bugging me for some time now...please help me identify the problem!
I don't know about the infinite loop but the following code is not going to work as you intended. The i++ can never be reached so i will always have the value 0.
for (int i = 0; searchedArray[i] == searchTerm && i < searchedArray.length; i++)
{
return i;
}
return -1;
You probably mean this:
for (int i = 0; i < searchedArray.length; i++)
{
if (searchedArray[i] == searchTerm)
{
return i;
}
}
return -1;
I don't know what is the class ArrayUtil (I can not import is using my Netbeans). When I try to change that line with the line int[] randomArray = {1 , 2, 3, 5, 7, 10, 1 , 5}; It works perfectly.
And you should change the loop condition. I will not tell you why but try with my array and you will see the bug soon. After you see it, you can fix it:)
There are 4 basic issues here.
1. Putting searchedArray[i] == searchTerm before i < searchedArray.length can result in an out-of-bounds exception. You must always prevent that kind of code.
2. Your intention seems to be the opposite of your code. Your method name implies finding a search term. But, your code implies that you want to continue your loop scan until the search term is not found, although your loop won't do that either. Think of "for (; this ;) { that } " as "while this do that".
3. Place a break point at the beginning of "search". Then, with a small array, step through the code line by line with the debugger and watch the variables. They don't lie. They will tell you exactly what's happening.
4. Please use a standard IDE and compiler, such as Eclipse and Sun's JDK 6 or 7. Eclipse with JDK 7 is a serious combination that doesn't exhibit a strange "infinite loop" as you describe above.

Categories

Resources