The task is to:
Part one:
Write a program which prints the integers from 1 to a number given by the user.
Sample output part 1
Part two:
Ask the user for the starting point as well.
Sample output part 2
My code:
import java.util.Scanner;
import javax.swing.plaf.synth.SynthOptionPaneUI;
public class FromWhereToWhere {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// part one
System.out.println("Where to?");
int end = Integer.valueOf(scanner.nextLine());
for (int i = 1; i < end + 1; i++) {
System.out.println(i);
}
// part two
System.out.println("Where to?");
end = Integer.valueOf(scanner.nextLine());
System.out.println("Where from?");
int start = Integer.valueOf(scanner.nextLine());
for (int i = start; i < end + 1; i++) {
System.out.println(i);
}
}
}
It works as intended my terminal
But I get an error in TMC saying
FAIL:
WhereFromTest test
NoSuchElementException: No line found
The code for testing:
import fi.helsinki.cs.tmc.edutestutils.MockStdio;
import fi.helsinki.cs.tmc.edutestutils.Points;
import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.*;
import static org.junit.Assert.*;
#Points("02-16.2")
public class WhereFromTest {
#Rule
public MockStdio io = new MockStdio();
#Test
public void test() {
int[][] pairs = {{1, 1}, {12, 8}, {50, 100}, {-2,2}};
for (int[] pair : pairs) {
test(pair);
}
}
private void test(int[] pair) {
io.setSysIn(pair[0] + "\n" + pair[1] + "\n");
int len = io.getSysOut().length();
ReflectionUtils.newInstanceOfClass(FromWhereToWhere.class);
FromWhereToWhere.main(new String[0]);
String output = io.getSysOut().substring(len);
output = output.replaceAll("[^-\\d]+", " ").trim();
String[] lines = output.split("\\s+");
int linesInOutput = (lines.length == 1 && lines[0].isEmpty()) ? 0 : lines.length;
int linesCount;
if(pair[0] < pair[1]) {
linesCount = 0;
} else {
linesCount = pair[0] - pair[1] + 1;
}
if (linesCount != linesInOutput) {
String numbersCount = (linesCount == 1) ? "number": "numbers";
fail("With the input " + pair[0] + ", " + pair[1] + " output should contain " + linesCount + " " + numbersCount + ", now it contained " + linesInOutput);
}
if(linesCount == 0) {
return;
}
int firstNumber = Integer.valueOf(lines[0]);
if(firstNumber != pair[1]) {
fail("With the input " + pair[0] + ", " + pair[1] + " the first printed number should be " + pair[1] + ", now it was " + firstNumber);
}
int lastNumber = getLastNumber(output);
if(lastNumber != pair[0]) {
fail("With the input " + pair[0] + ", " + pair[1] + " the last printed number should be " + pair[0] + ", now it was " + lastNumber);
}
}
private static int getLastNumber(String inputStr) {
String patternStr = "(?s).*?(-?\\d+)\\s*$";
Matcher matcher = Pattern.compile(patternStr).matcher(inputStr);
assertTrue("The output should be a number.", matcher.find());
int number = Integer.valueOf(matcher.group(1));
return number;
}
}
I don't see the issue or how to input the message. The full error that I keep getting is below. I can't see any problems with the code and I can't find a way to a message into the code.
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of ran
ge: 30
at java.base/java.lang.StringLatin1.charAt (String.java:47)
at java.base/java.lang.String.charAt (String.java:693
at Main.main (Main.java:15)
import java.util.Scanner;
public class Main
{
public static void main( String[] args )
{
Scanner kb = new Scanner(System.in);
System.out.println("What is your message? ");
String message ="" + "\n";
System.out.println("\nYour message is " + " characters long.");
System.out.println("The first character is at position 0 and is '" + "'.");
int lastpos = 30;
System.out.println("The last character is at position " + lastpos + " and is '" + message.charAt(lastpos) + "'.");
System.out.println("\nHere are all the characters, one at a time:\n");
for ( int i=0; i<message.length(); i++ )
{
System.out.println("\t" + i + " - '" + message.charAt(i) + "'");
}
int a_count = 0;
for ( int i=0; i<message.length(); i++ )
{
char letter = message.charAt(i);
if ( letter == 'a' || letter == 'A' );
{
a_count++;
}
}
System.out.println("\nYour message contains the letter 'a' " + a_count + " times. Isn't that interesting?");
}
}
You never actually capture a message from the scanner - something like this:
message = kb.nextLine();
In addition, if you're trying to get the last index/position of the message, you'd want to do something like this:
int lastpos = message.length();
OR
int lastpos = message.length()-1;
The difference between the two being that the first gives you the size of the string, and the second gives you the last index of the string (for example, "abcdefg", lastpos 1 would be 7, and lastpos 2 would be 6).
Finally, keep in mind, you can do something like
message.charAt(0);
to get the first index character of the string.
I have made 3 changes from the code that you have written. They are the following:
Read the message using kb.nextLine(); instead of "" + "\n";
The first character of the message is message.charAt(0) instead of "'."
To count the number of characters, you have given semicolon after the if condition. Remove that. The semicolon after if is not needed.
Check the snippet below for better understanding.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
System.out.println("What is your message? ");
String message = kb.nextLine();
System.out.println("\nYour message is " + " characters long.");
System.out.println("The first character is at position 0 and is '" + message.charAt(0));
int lastpos = 30;
System.out.println("The last character is at position " + lastpos + " and is '" + message.charAt(lastpos) + "'.");
System.out.println("\nHere are all the characters, one at a time:\n");
for (int i = 0; i < message.length(); i++) {
System.out.println("\t" + i + " - '" + message.charAt(i) + "'");
}
int a_count = 0;
for (int i = 0; i < message.length(); i++) {
char letter = message.charAt(i);
if (letter == 'a' || letter == 'A') {
a_count++;
}
}
System.out.println("\nYour message contains the letter 'a' " + a_count + " times. Isn't that interesting?");
}
}
I wasn't able to figure this one out since I don't know how to calculate "inserting" an underscore. I included my attempt at solving this problem.
Given a string, do not let the same character repeat for n positions. If it does repeat, insert an underscore to push
it X positions down. The final output needed is just the total number of characters.
Example 1) Input "QQ",2 becomes "Q__Q", the return value is 4.
Example 2) Input "ABCA",2 becomes "ABCA" (no spaces needed), total characters is 4.
Example 3) Input "DEDEE", 1 becomes "DEDE_E", total chars is 6.
Example 4) Input "JKJK", 2 becomes "JK_JK", total characters is 5 (The toughest example).
import java.lang.Math;
import java.util.HashMap;
import java.util.ArrayList;
public class Spacer {
public static void main (String args[]) {
System.out.println("QQ,2 = " + spacey("QQ", 2) + ", expected 4");
System.out.println("ABCA,2 = " + spacey("ABCA",2) + ", expected 4");
System.out.println("DEDEE,1 = " + spacey("DEDEE", 1) + ", expected 6");
System.out.println("JKJK,2 = " + spacey("JKJK", 2) + ", expected 5");
}
private static int spacey(String word, int spaces) {
// int shift = 0;
HashMap<Character, Integer> hm = new HashMap<>();
for (int i=0; i<word.length(); i++) {
char letter = word.charAt(i);
System.out.println(i + "=" + letter + " last saw " + hm.get(word.charAt(i)));
if (hm.get(letter) == null) {
hm.put(letter, i);
} else {
System.out.println(i + "-" + hm.get(letter) + "<=" + spaces);
if (i - hm.get(word.charAt(i)) <= spaces) {
// System.out.println("add " + (spaces + 1 - (i - hm.get(letter))));
// shift += (spaces + 1) - (i - hm.get(letter));
word = word.substring(0, i) + "_" + word.substring(i);
System.out.println(i + " word=" + word);
}
hm.put(letter, i); // update the hashmap with the last seen again
}
}
return word.length();
}
}
Your question is (mainly) about inserting underscores. A key insight that can help move forward is that the input and output strings are different, so it would be cleaner to treat them as such, using a StringBuilder for example. Additionally, it doesn't hurt at this stage to use temporary variables to capture concepts such as distance between characters. Leveraging these two ideas, you can have more self-explanatory code, for example:
public static String space(String input, int spaces) {
HashMap<Character, Integer> map = new HashMap<>();
StringBuilder result = new StringBuilder();
for( char symbol : input.toCharArray() ) {
int position = result.length();
int lastPosition = map.getOrDefault(symbol, position-spaces-1);
int distance = position - lastPosition -1;
for( int j = 0; j < Math.max( spaces - distance, 0) ; j++ ) {
result.append('_');
}
result.append(symbol);
map.put(symbol, result.length()-1);
}
return result.toString();
}
(and once this is mastered and digested, it's of course possible to in-line the temps)
The requirement doesn't ask you to display the constructed string so we need to only do calculations. The regex (.+)\1 will match any repetition of 1 or more chars and countPattern returns how many times that pattern was found.
public static void main(String[] args) {
System.out.println("QQ,2 = " + spacey("QQ", 2) + ", expected 4");
System.out.println("ABCA,2 = " + spacey("ABCA",2) + ", expected 4");
System.out.println("DEDEE,1 = " + spacey("DEDEE", 1) + ", expected 6");
System.out.println("JKJK,2 = " + spacey("JKJK", 2) + ", expected 6"); //in becomes JK__JK, ie. 4 + 2x'_'
}
private static int spacey(String word, int spaces) {
if(spaces<0){
throw new IllegalArgumentException("should be positive value");
}
if(word==null){
return 0;
}
if(spaces==0){
return word.length();
}
final Pattern repeatedCharRegex = Pattern.compile("(.+)\\1");
final int repetitions = countPattern(word, repeatedCharRegex);
return word.length() + repetitions*spaces;
}
public static int countPattern(String references, Pattern referencePattern) {
Matcher matcher = referencePattern.matcher(references);
int count = 0;
while (matcher.find()){
count++;
}
return count;
}
First of all you have an error in one of your test cases. Assuming you want to reproduce the cases in the quoted challenge, you need a 1 as second argument to the call to spacey here:
System.out.println("DEDEE,1 = " + spacey("DEDEE", 1) + ", expected 6");
// ^ ^
The formula to calculate the number of underscores to insert is:
previousindex + n + 1 - i
...where previousindex is the index at which the current letter occurred before, and i is the current index.
You can repeat an underscore with the .repeat string method. Don't forget to update i afterwards, so it keeps pointing to the currently processed character (which moved forward).
So your code could work like this:
import java.lang.Math;
import java.util.HashMap;
import java.util.ArrayList;
public class Spacer {
public static void main (String args[]) {
System.out.println("QQ,2 = " + spacey("QQ", 2) + ", expected 4");
System.out.println("ABCA,2 = " + spacey("ABCA",2) + ", expected 4");
System.out.println("DEDEE,1 = " + spacey("DEDEE", 1) + ", expected 6");
System.out.println("JKJK,2 = " + spacey("JKJK", 2) + ", expected 5");
}
private static int spacey(String word, int spaces) {
HashMap<Character, Integer> hm = new HashMap<>();
for (int i=0; i<word.length(); i++) {
char letter = word.charAt(i);
if (hm.get(letter) == null) {
hm.put(letter, i);
} else {
int underscores = hm.get(letter) + spaces + 1 - i;
if (underscores > 0) { // Need to add underscores
word = word.substring(0, i) + "_".repeat(underscores) + word.substring(i);
i += underscores; // update i so it still points to the current character
}
hm.put(letter, i);
}
}
return word.length();
}
}
if (posOfGuessLetter == -1)
{
System.out.print("Your letter was not found in the
spaces provided");
} //if
if (posOfGuessLetter == 0)
{
displayWordAsDashes = (guessLetter +
displayWordAsDashes.substring(posOfGuessLetter + 1));
displayWord =
displayWordAsDashes.substring(posOfGuessLetter + 1);
} //if
if (posOfGuessLetter == 9)
{
displayWordAsDashes = (displayWordAsDashes.substring(0,
posOfGuessLetter) + guessLetter);
displayWord = (displayWordAsDashes.substring(0,
posOfGuessLetter));
} //if
else
{
displayWordAsDashes = (displayWordAsDashes.substring(0,
posOfGuessLetter) + guessLetter +
displayWordAsDashes.substring(posOfGuessLetter + 1));
displayWord = (displayWordAsDashes.substring(0,
posOfGuessLetter) +
(displayWordAsDashes.substring(posOfGuessLetter + 1)));
}
while (displayWord.contains(guessLetter))
{
displayWordAsDashes = (displayWordAsDashes.substring(0,
posOfGuessLetter) + guessLetter +
displayWordAsDashes.substring(posOfGuessLetter + 1));
displayWord = (displayWordAsDashes.substring(0,
posOfGuessLetter) +
(displayWordAsDashes.substring(posOfGuessLetter + 1)));
} //while
} //else
System.out.print("The updated word is: " +
displayWordAsDashes);
I am trying to create a hangman program, and in this part it checks the index position of a user input for the character they want to find in the word and then removes the dash on that index and reveals the letter they just guessed. However, my program is not revealing both letters if the word has two of the same letter (i.e. naRRowing, lOOps) which is what I tried to program the while loop at the end to do. Can anyone tell me what I messed up on??
I didn't see what error you did but both pos == 0 and pos == 9 are superfluous due to
aString.substring(aString.length());
and
aString.substring(0, 0);
both returning the empty string.
If you don't have to keep track of where the letter was you could do something like this:
private String wordToGuess = "hangman";
private String guessedSoFar = wordToGuess.replaceAll(".", "-");
private String leftToGuess = wordToGuess;
public String guess(char c) {
for(int i = 0 ; i < leftToGuess.length() ; i++) {
if(leftToGuess.charAt(i) == c) {
guessedSoFar = guessedSoFar.substring(0, i) + c + guessedSoFar.substring(i + 1);
}
}
leftToGuess = leftToGuess.replace(c, '-');
return guessedSoFar;
}
I'm trying to populate a 2d list array using 2 user inputs.
Problem I'm having is that in the code below, the 1st for statement isn't producing the outcome I'm expecting, the 2nd for is doing what is needed. Also, with the code below I'm unable to close scanner.
public static void main(String[] args) {
ArrayList<String> listCon = new ArrayList<String>();
ArrayList<String> listCol = new ArrayList<String>();
Scanner txtInput = new Scanner(System.in);
char addTo = 'y';
do {
System.out.println("\nCurrent list is " + listCon + listCol + "\n");
System.out.println("Would you like to add a country to the list?\n\t"
+ "( y ) = YES\n\t( n ) = NO");
addTo = txtInput.next().toLowerCase().charAt(0);
if (addTo == 'y') {
System.out.println("Enter country name: ");
listCon.add(txtInput.next().toLowerCase());
System.out.println("Enter colour: ");
listCol.add(txtInput.next().toLowerCase());
} else if (addTo == 'n') {
int i = 1;
int countCon = listCon.size();
if(countCon == 0) {
System.out.println("No countries have been entered.");
} else {
String str = "country";
if(countCon > 1) {
str = "countries";
}
System.out.println("Thankyou for your input. We found " + countCon + " " +
str + " in the list.");
System.out.println("Listed " + str + ":\n");
for(String n : listCon) {
char[] conDigit = n.toCharArray();
conDigit[0] = Character.toUpperCase(conDigit[0]);
n = new String(conDigit);
for(String b : listCol) {
char[] colDigit = b.toCharArray();
colDigit[0] = Character.toUpperCase(colDigit[0]);
b = new String(colDigit);
System.out.println("Country " + i + " : " + n + " - \t" + b);
i = i + 1;
}
break;
}
break;
}
} else {
System.out.println("Incorrect input detected. please try again. \n");
}
} while (true);
}
}
You need to remove extra break from the first for loop to iterate. Otherwise, you break after first iteration.
for(String n : listCon) {
....
for(String b : listCol) {
...
}
break; //remove this!
}
break;
EDIT
The result im after is Country 1 : France - Blue Country 2 : UK -
White Country 3 : Ireland - Green
You need to iterate like this:
for (int i = 0; i < listCon.size() && i < listCol.size(); i++) {
String n = listCon.get(i);
char[] conDigit = n.toCharArray();
conDigit[0] = Character.toUpperCase(conDigit[0]);
n = new String(conDigit);
String b = listCol.get(i);
char[] colDigit = b.toCharArray();
colDigit[0] = Character.toUpperCase(colDigit[0]);
b = new String(colDigit);
System.out.println("Country " + i + " : " + n + " - \t" + b);
}