Skip to content

Instantly share code, notes, and snippets.

@easyaspi314
Last active October 4, 2018 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save easyaspi314/636e80f100cef313aef947903e832966 to your computer and use it in GitHub Desktop.
Save easyaspi314/636e80f100cef313aef947903e832966 to your computer and use it in GitHub Desktop.
Overcomplicated ShowNum assignment

ShowNum

A completely overcomplicated way to do my homework assignment.

The assignment

Write a Java class (called ShowNum) that displays the same number of asterisks (row and columns) as is input in 2 numbers. 
Your class should have a default constructor (number1 is 0, number2 is 0) and 
another constructor that inputs 2 numbers (integers). 
You'll need accessor methods for the numbers and a display method that displays as follows:

Input:   2, 7     
*******
*******
Demo the class in a client (called ShowNumClient) that allows the user to run the program as many times as they want (enter number and use display method). 
The user will signal with a sentinel (-1), when they want to terminate the client. 
Make sure that each number entered in the client is between 1 and 30. 

License

 The MIT License
 Copyright (c) 2018 easyaspi314

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.

StringCompat.java is copied from the JDK and is released under the GPLv2, inline in the comment.

/*
* Copyright (C) 2018 easyaspi314
* MIT license
*/
// filename must be ShowNum.java
public class ShowNum {
private int mRows;
private int mCols;
/**
* Constructs a new ShowNum object with the rows and columns specified.
*
* @see setRows
* @see setCols
*
* @param rows The number of rows
* @param cols The number of columns
* @throws IllegalArgumentException If either {@code rows} or {@code cols}
* are < 1 or > 30, thrown by {@code setRows}/{@code setCols}.
*/
public ShowNum(int rows, int cols) throws IllegalArgumentException {
setRows(rows);
setCols(cols);
} // end ShowNum ctor (int, int)
/**
* Empty constructor. Sets both values to zero.
*/
public ShowNum() {
// We don't check the range in the empty ctor.
mRows = 0;
mCols = 0;
} // end ShowNum ctor ()
/**
* Sets the number of rows.
*
* @param rows The new value to set
* @throws IllegalArgumentException if rows is < 1 or > 30
*/
public final void setRows(int rows) throws IllegalArgumentException {
if (rows < 1 || rows > 30) {
throw new IllegalArgumentException("rows out of range");
}
mRows = rows;
} // end setRows method
/**
* Sets the number of columns.
*
* @param cols The new value to set
*/
public final void setCols(int cols) throws IllegalArgumentException {
if (cols < 1 || cols > 30) {
throw new IllegalArgumentException("cols out of range");
}
mCols = cols;
} // end setCols method
/**
* Displays the grid of asterisks.
*/
public void display() {
System.out.printf("Input: %d %d\n", mRows, mCols);
String str = StringCompat.repeat("*", mCols);
for (int i = 0; i < mRows; i++) {
System.out.println(str);
}
}
} // end class ShowNum
/*
* Copyright (C) 2018 easyaspi314
* MIT license
*/
import java.util.Scanner;
// Filename must be ShowNumClient.java
public class ShowNumClient {
private Scanner mScanner;
private Reader<Integer> mRowsReader;
private Reader<Integer> mColsReader;
private ShowNum mShowNum;
/**
* Creates a ShowNumClient instance.
*/
public ShowNumClient() {
mScanner = new Scanner(System.in);
mRowsReader = createIntReader("How many rows (-1 to exit): ");
mColsReader = createIntReader("How many columns (-1 to exit): ");
mShowNum = null;
} // end ShowNumClient ctor
/**
* A callback for Reader&lt;T&gt;.
*
* @param T: The type to return
*/
private static interface ReaderCallback<T> {
/**
* Displays a prompt message.
*/
public void prompt();
/**
* Validates an input. Return null on an error, or the valid input on
* success.
*
* @param value The value to parse.
* @return T The parsed value, or null to indicate failure.
*/
public T validateInput(String value);
/**
* Displays an invalid input message.
*
* @param input The input given, or an empty string for empty input.
*/
public void invalidInput(String input);
} // end ReaderCallback interface
/**
* A callback to read input from the reader, using ReaderCallback to
* validate.
*
* @param <T> The type to return
*/
private static class Reader<T> {
private Scanner mScanner;
private ReaderCallback<T> mCallback;
/**
* Don't use this
*/
private Reader() {
throw new UnsupportedOperationException("Use Reader(ReaderCallback<T>) instead.");
} // end Reader ctor ()
/**
* Constructs a new Reader object.
*
* @param callback A {
* @see ReaderCallback} to handle the input
*/
public Reader(Scanner scanner, ReaderCallback<T> callback) {
mScanner = scanner;
mCallback = callback;
} // end Reader ctor (ReaderCallback<T>)
/**
* Reads a value and validates it, using mCallback to validate and
* prompt.
*
* This will repeat itself until a correct input is found, calling
* invalidInput.
*
* @return T, a non-null value.
*/
public T read() {
String input;
T ret = null;
// Loop until validateInput sets ret to a non-null value
while (ret == null) {
// Prompt the user
mCallback.prompt();
// Read a line of input
input = mScanner.nextLine();
// Empty input calls invalidInput with an empty String.
if (input == null || input.isEmpty()) {
mCallback.invalidInput("");
}
// Validate the input.
ret = mCallback.validateInput(input);
// Call invalidInput if ret failed.
if (ret == null) {
mCallback.invalidInput(input);
}
}
return ret;
} // end read method
} // end class Reader
/**
* Creates a new Reader&lt;Integer&gt; which validates input for ShowNum and
* exits on -1.
*
* @param prompt The prompt message to show.
* @return A Reader with the correct prompt.
*/
final Reader<Integer> createIntReader(final String prompt) {
return new Reader<>(mScanner, new ReaderCallback<Integer>() {
/**
* Prompts the user to enter a number with the message prompt.
*/
@Override
public void prompt() {
System.out.print(prompt);
} // end prompt method
/**
* Validates an input from 1 to 30, or -1.
*
* @param value The String to parse.
* @return The correct value, or null
*/
@Override
public Integer validateInput(String value) {
if (value.isEmpty()) {
return null;
}
try {
// Parse the integer
Integer i = Integer.parseInt(value);
// -1 exits but is still valid
if (i != -1 && (i < 1 || i > 30)) {
return null;
}
return i;
} catch (NumberFormatException unused) {
// from Integer.parseInt if value isn't a number.
// We don't care about the exception itself.
return null;
}
} // end validateInput method
/**
* Prints an invalid message.
*
* @param input Unused.
*/
@Override
public void invalidInput(String input) {
System.out.println("Please enter a number between 1 and 30, or -1 to exit.");
} // end invalidInput method
}); // end ReaderCallback implementation
}// end createReader method
/**
* Runs the loop, prompting the user and displaying.
*
* @return true, or false if the user wants to exit.
*/
public boolean run() {
int rows = mRowsReader.read();
if (rows == -1) {
return false;
}
int cols = mColsReader.read();
if (cols == -1) {
return false;
}
// Note: We already checked for ShowNum's bounds so we don't need to catch anything.
if (mShowNum == null) {
// If mShowNum is null, create it once with rows, cols.
mShowNum = new ShowNum(rows, cols);
} else {
// Otherwise, set the rows on an existing instance
mShowNum.setRows(rows);
mShowNum.setCols(cols);
}
// Display the asterisks.
mShowNum.display();
return true;
} // end run method
/**
* The main method. Loops run() until it returns false, in which it exits.
*
* @param args the command line arguments
*/
public static void main(String[] args) {
ShowNumClient client = new ShowNumClient();
while (client.run()) {
// loop forever
}
} // end main method
} // end class ShowNumClient
/*
* Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.Arrays;
/**
* A direct backport of String.repeat because apparently we don't have this
* logical method until Java 11.
* http://hg.openjdk.java.net/jdk/jdk/file/default/src/java.base/share/classes/java/lang/String.java
*/
// filename must be StringCompat.java
public class StringCompat {
/**
* Returns a string whose value is the concatenation of this string repeated
* {@code count} times.
*
* If this string is empty or count is zero then the empty string is
* returned.
*
* @param str The string to repeat
* @param count number of times to repeat
*
* @return A string composed of this string repeated {@code count} times or
* the empty string if this string is empty or count is zero
*
* @throws IllegalArgumentException if the {@code count} is negative.
*
* @since 11
*/
public static String repeat(final String str, int count) {
// because we can't get String's private members
final byte[] value = str.getBytes();
if (count < 0) {
throw new IllegalArgumentException("count is negative: " + count);
}
if (count == 1) {
return str;
}
final int len = value.length;
if (len == 0 || count == 0) {
return "";
}
if (len == 1) {
final byte[] single = new byte[count];
Arrays.fill(single, value[0]);
return new String(single);
}
if (Integer.MAX_VALUE / count < len) {
throw new OutOfMemoryError("Repeating " + len + " bytes String " + count
+ " times will produce a String exceeding maximum size.");
}
final int limit = len * count;
final byte[] multiple = new byte[limit];
System.arraycopy(value, 0, multiple, 0, len);
int copied = len;
for (int next = copied << 1; next < limit && 0 < next; next = next << 1) {
System.arraycopy(multiple, 0, multiple, copied, copied);
copied = next;
}
System.arraycopy(multiple, 0, multiple, copied, limit - copied);
return new String(multiple);
} // end String_repeat method
} // end class StringCompat
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment