I'm writing a Java program for Horspool's algorithm, and am having a bit of trouble. I'm trying to create an array of chars that will hold each letter in a string, but I don't want duplicates of the letters. Right now this is my code:
public static void main(String[] args)
{
Scanner scanIn = new Scanner (System.in);
int count = 0;
int count2 = 0;
int inc = 0;
//The text to search for the phrase in
String t = "";
//The phrase/pattern to search for
String p = "";
System.out.println(" ");
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("Harspool's Algorithm: ");
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println(" ");
System.out.println("Please enter the full text: ");
t = scanIn.nextLine();
System.out.println("Please enter the pattern to search for: ");
p = scanIn.nextLine();
char[] text = new char[t.length()];
char[] pattern = new char[p.length()];
char[] alphabet = new char[t.length()];
for (int i = 0; i < alphabet.length; i++)
{
alphabet[i] = ' ';
}
for (int i = 0; i < text.length; i++)
{
text[i] = t.charAt(i);
}
for (int i = 0; i < pattern.length; i++)
{
pattern[i] = p.charAt(i);
}
while (inc < text.length)
{
for (int j = 0; j < text.length; j++)
{
if (text[inc] != alphabet[j])
{
count++;
}
if (count == p.length() - 1 && count2 < text.length)
{
alphabet[count2] = text[inc];
count2++;
count = 0;
inc++;
}
}
}
for (int i = 0; i < alphabet.length; i++)
{
System.out.print(alphabet[i]);
}
}
I believe the problem is in the while loop, but I can't figure out what exactly is going wrong. Right now, it will print out the entire string passed in, when it should be printing each letter only once. Could someone please help?
Instead of counting the occurrences of each character, Use Set<Character>. A set contains unique elements and so you will not have duplicates that way.
You can also convert a Set to an array by doing mySet.toArray(new String[mySet.size()]); or just mySet.toArray(new String[0]);
Your code is not easy to read. You might consider using the following algorithm instead.
int ccount[256];
int ii;
for(ii=0;ii<256;ii++) ccount[ii]=0;
for (ii = 0; ii < text.length; ii++)
{
ccount[t.charAt(i)%256]++;
}
for (ii = 0; ii<256; ii++) {
if(ccount[ii]>0) System.out.printf("%c", ii);
}
EDIT - made sure ccount was initialized, and captured characters outside of range 0-255 with % operator.
Related
I have been stuck on this exercise for 2 weeks now, hopefully someone can help...
So basically the user starts by providing the number of lines and columns and the corresponding crossed words table(which is a 2d char array) , then inputs the number of words and the words that have to be detected in that board.
The program is supposed to print the table that was given but with every non-word substituted for zeros.
An example:
Input:
4 5
GBCDP
AGGGM
MYIEU
ENBHJ
2
GAME
JUMP
Should output:
G000P
A000M
M000U
E000J
My problem is still in the method for finding the words...
this is my code(it's commented to be easier to understand)
NOTE: the words cannot be found diagonally... also I am missing the part of the program that's supposed to substitute non-words for zeros, because I still can't find the words
import java.util.Scanner;
class game {
private int rows;
private int cols;
private char m[][];
game(int r, int c)
{
rows = r;
cols = c;
m = new char[r][c];
}
//read the game
public void read(Scanner in) {
for (int i=0; i<rows; i++) {
m[i] = in.next().toCharArray();
}
}
//writes the game
public void write() {
for(int i = 0; i < rows;i++)
{
for(int j = 0; j < cols; j++)
{
System.out.print(m[i][j]);
}
System.out.println();
}
}
//finds the words
public void find(String word) {
for(int i = 0; i < rows; i++)
{
if(word.equals(new String(m[i]))){
System.out.print(i);
}
}
for(int z = 0; z < cols; z++)
{
if(word.equals(new String(m[z]))) {
System.out.print(z);
}
}
}
}
public class wordg {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int rows = scan.nextInt();
int columns = scan.nextInt();
game j = new game(rows,columns);
j.read(scan);
//j.write();
int wordnumber = scan.nextInt();
String words[] = new String[wordnumber];
for(int i = 0; i < wordnumber; i++)
{
words[i] = scan.nextLine();
}
for(int w = 0; w < words.length; w++)
{
j.find(words[w]);
}
}
}
Thanks!
How to fix the code
In this part of the answer, I will try to give a step-by-step guide on how to make your code work properly:
The first problem with your code is that you are using the rows instead of the columns, although you obviously want to use columns. This can be done like this:
String col = "";
for(int i = 0; i < rows; i++) {
col += m[i][z];
}
The next problem is that you also have to search for the reversed words. You can do that by just calling the method find with the reversed words also:
for(int w = 0; w < words.length; w++)
{
j.find(words[w]);
j.find(j.reverse(words[w]);
}
The reverse-method could look like this:
public String reverse(String word) {
String result = "";
for(int i = word.length() - 1; i >= 0; i--) {
result += word.charAt(i);
}
return result;
}
After this, your find-method should work.
To output the grid like you want it to look like, we will have to save, where we found a word. This can be done like this:
if(word.equals(new String(m[i]))){
System.out.println("Word found in row: " + i);
for(int j = 0; j < cols; j++) {
test[i][j] = true;
}
}
test is a boolean-array initialized with false in the constructor.
Now we just have to change the write-method:
//writes the game
public void write() {
for(int i = 0; i < rows;i++)
{
for(int j = 0; j < cols; j++)
{
if(test[i][j]) { //Only print found words, otherwise print "0"
System.out.print(m[i][j]);
}
else {
System.out.print("0");
}
}
System.out.println();
}
}
At this point the program should produce the output you want it to produce.
Possible improvements
If you want to improve your find-method, you could make the program recognize words inside a row or a column, for example recognize the word "YOU" in this grid:
AAYOUA
AAAAAA
AAAAAA
AAAAAA
This can be done like this:
public void find(String word) {
for(int i = 0; i < rows; i++) {
int index = new String(m[i]).indexOf(word); //Index were found word starts (-1 if row/col doesn't contain the word)
if(index >= 0) {
System.out.println("Word found in row: " + i); //Added some information for the user
for(int j = index; j < index + word.length(); j++) {
test[i][j] = true; //Save that word was found in this "cell"
}
}
}
for(int z = 0; z < cols; z++) {
String col = "";
for(int i = 0; i < rows; i++) { //Get column
col += m[i][z];
}
int index = col.indexOf(word);
if(index >= 0) {
System.out.println("Word found in col: " + z);
for(int j = index; j < index + word.length(); j++) {
test[j][z] = true;
}
}
}
}
Some other suggestions:
Class-names should begin with an uppercase-letter
Try to always use the same indentation
Try to always use the same "bracket-style"
(I changed this for you in the final code.)
Final code
All in all your code looks like this now:
Game.java
import java.util.Scanner;
public class Game { //Classes start with uppercase
private int rows;
private int cols;
private char m[][];
private boolean test[][]; //Purpose: test if "cell" where word was found
Game(int r, int c) {
rows = r;
cols = c;
m = new char[r][c];
test = new boolean[r][c];
}
//read the game
public void read(Scanner in) {
for (int i=0; i<rows; i++) {
m[i] = in.next().toCharArray();
}
}
//writes the game
public void write() {
for(int i = 0; i < rows;i++) {
for(int j = 0; j < cols; j++) {
if(test[i][j]) { //Only print found words, otherwise print "0"
System.out.print(m[i][j]);
}
else {
System.out.print("0");
}
}
System.out.println();
}
}
//finds the words
public void find(String word) {
for(int i = 0; i < rows; i++) {
int index = new String(m[i]).indexOf(word); //Index were found word starts (-1 if row/col doesn't contain the word)
if(index >= 0) {
System.out.println("Word found in row: " + i); //Added some information for the user
for(int j = index; j < index + word.length(); j++) {
test[i][j] = true; //Save that word was found in this "cell"
}
}
}
for(int z = 0; z < cols; z++) {
String col = "";
for(int i = 0; i < rows; i++) { //Get column
col += m[i][z];
}
int index = col.indexOf(word);
if(index >= 0) {
System.out.println("Word found in col: " + z);
for(int j = index; j < index + word.length(); j++) {
test[j][z] = true;
}
}
}
}
public String reverse(String word) {
String result = "";
for(int i = word.length() - 1; i >= 0; i--) {
result += word.charAt(i);
}
return result;
}
}
WordG.java
import java.util.Scanner;
public class WordG {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int rows = scan.nextInt();
int columns = scan.nextInt();
Game j = new Game(rows,columns);
j.read(scan);
int wordnumber = scan.nextInt();
scan.nextLine(); //To clear the scanner
String words[] = new String[wordnumber];
for(int i = 0; i < wordnumber; i++) {
words[i] = scan.nextLine();
}
for(int w = 0; w < words.length; w++) {
j.find(words[w]);
j.find(j.reverse(words[w])); //You also have to search for reversed words!
}
j.write(); //Write grid after searching
}
}
(I added comments on the right where I changed your code to explain what I did.)
Output
With your example-input, this code creates the following output:
Word found in col: 0
Word found in col: 4
G000P
A000M
M000U
E000J
And with the added functionality, the input
5 5
SHARK
AYOUB
MABCD
EABCD
ABCDE
3
YOU
ME
SHARK
gives the output
Word found in row: 1
Word found in col: 0
Word found in row: 0
SHARK
0YOU0
M0000
E0000
00000
i am having trouble with reversing this code. what i am trying to have as
this is what i have so far but i can't seem to wrap my head around how the third for loop is supposed to be
public static void main(String[] args) {
Scanner input = new Scanner(System.in); //gets the users input
int rows;
int number = 0;
int i = 0;
rows = input.nextInt(); //takes the users input from console
while (rows <= 0) {
System.out.println("INVALID");
rows = input.nextInt();
}
for (int c = 1; c <= rows; c++) {
for (i = 0; i < c; i++) {
System.out.print(++number + " ");
}
for (int j = c; j < rows; j++) {
System.out.print("* * ");
}
for(i = 0; i < c; i++) {
System.out.print(number + " ");
//number--;
}
System.out.println();
}
Before running your last loop you should store number in some temp variable:
int temp = number;
for(i = 0; i < c; i++) {
System.out.print(temp-- + " ");
}
As I said in the comment, you need to decrement the number but at the same time need to keep track of the highest values in a line to use it as a starting value in the next iteration. Something like this should work:
public static void main(String[] args) {
int rows;
int number = 0;
int highestValue = 0;
int i = 0;
rows = 5;
for (int c = 1; c <= rows; c++) {
number = highestValue; // reset number to the highest value from previous line
for (i = 0; i < c; i++) {
System.out.print(++number + " ");
}
highestValue = number; // setting the highest value in line
for (int j = c; j < rows; j++) {
System.out.print("* * ");
}
for(i = 0; i < c; i++) {
System.out.print(number-- + " "); // decrementing
}
System.out.println();
}
Do you have to implement this yourself, because otherwise there are tons of libraries handling arrays.
The steps you have to take are:
Find a way to read the input (integers) in a single line and store them in some kind of container (either an array, or a list).
You may have to isolate what a single integer is (e.g. "1 2 3" is 3 integers, which you want to reverse, while "12 3" is just 2, and you only want to reverse 2).
You need to ensure that your input is valid (e.g. a user may enter "1 a b c")
You need to flip the integers within the container or better copy the original container in reverse order. For this, you only need to iterate over the container's elements and add them to the target container in reverse order
for (Integer in : inputList) {
outputList.addFirst(in);
}
If you only want to print the integers, you don't have to store them in a list, you could just iterate over the container in reverse order.
It seems to bit a pattern program, you can add the number-- in you sysout
public static void main( String[] args )
{
Scanner input = new Scanner(System.in); //gets the users input
int rows;
int number = 0;
int i = 0;
rows = input.nextInt(); //takes the users input from console
while (rows <= 0) {
System.out.println("INVALID");
rows = input.nextInt();
}
for (int c = 1; c <= rows; c++) {
for (i = 0; i < c; i++) {
System.out.print(++number + " ");
}
for (int j = c; j < rows; j++) {
System.out.print("* * ");
}
for(i = 0; i < c; i++) {
System.out.print(number-- + " ");
//number--;
}
System.out.println();
}
}
Such type of pattern you can create through collections
I'm working on a Caesar cipher and I've gotten the majority of the code to work as planned.
the code is supposed to
remove all special characters and spaces
bring everything to uppercase
add spaces at an inputted interval any additional leftover spaces with x's
so for example if i were to type
plaintext: Hi im Doug
key: 1
buffer: 3
my output should be
IJJ NEP VHX
now I've gotten everything to work but the buffer part
this is my code in its entirety
import java.util.Scanner;
import java.lang.String;
public class Main {
public static void main(String[] args) {
System.out.print("Enter plaintext: ");
Scanner pTextInp = new Scanner(System.in);
String pText = pTextInp.nextLine();
System.out.print("Enter key value: ");
Scanner kInp = new Scanner(System.in);
int key = kInp.nextInt();
pText = normalizeText(pText);
pText = caesarify(pText, key);
System.out.print("Enter desired grouping number: ");
Scanner grpInp = new Scanner(System.in);
int grpInt = grpInp.nextInt();
pText = groupify(grpInt, pText);
System.out.println(pText);
}
// CONVERT STRING TO A CHAR ARRAY
public static char[] sArray(String s) {
int sLen = s.length();
char[] sChar = new char[sLen + 1];
for (int i = 0; i < sLen; i++){
sChar[i] = s.charAt(i);
}
return sChar;
}
public static String caesarify(String s, int k) {
int sLen = s.length();
char cText[] = sArray(s);
for (int i = 0; i < sLen; i++){
int j = cText[i] - 65;
int l = (((j + k) % 26) + 65);
cText[i] = (char) l;
}
s = new String(cText);
return s;
}
// normalizes text (removes all spaces and special characters)
public static String normalizeText(String s) {
int sLen = s.length();
char[] t1 = s.toCharArray();
for (int i = 0; i < sLen; i++ ){
if(t1[i] < 'A' || t1[i] > 'z' || (t1[i] > 'Z' && t1[i] < 'a')) {
t1[i] = ' ';
}
else{
t1[i] = s.charAt(i);
}
}
String t = new String(t1);
t = t.replaceAll(" ", "" );
t = t.toUpperCase();
return t;
}
public static String groupify(int i , String s){
int sLen = s.length();
char[] t = new char[sLen];
for (int j = 0; j < s.length(); j++){
t[j] = s.charAt(j);
if ( j % i == 0) {
t[j] = ' ';
sLen++;
}
}
s = new String(t);
return s;
}
and this is the section in particular that i think is the issue
public static String groupify(int i , String s){
int sLen = s.length();
char[] t = new char[sLen];
for (int j = 0; j < s.length(); j++){
t[j] = s.charAt(j);
if ( j % i == 0) {
t[j] = ' ';
sLen++;
}
}
s = new String(t);
return s;
}
with this this if i input
Hi Im Doug
I get
JJ EP H
as output
Thanks a bunch
Currently your code t[i] += ' ' is adding the space character's value to value in the array. That's not what you want. Rather you want to be storing a space in next position. I also suggest that you use better names for your variable - single character variables should generally only be used for indexes.
int pos = 0;
for (int j = 0; j < input.length(); j++)
result[pos++] = input.charAt(j);
if ( j % group == 0) {
result[pos++] = ' ';
}
}
For the code You have highlighted you are missing curly brackets after the for Loop. Try to define j outside the for-loop and assign the value 0 to j in the for-loop. It would be a better practice if you Store the size of your new Char-Array in a separate variable as it is easier to read when finding bugs in the code.
I'm trying to randomly place 1D string array into 2D char array but I'm having issues with my for-loop.
userWords is 1D array of String while puzzleBoard is a 2D array of char.
I've tried
for(int i=0; i<userWords.length;i++) {
puzzleBoard[r++] = userWords[i].toCharArray();
}
but it's not placing it randomly like I want it to
So I tried
for(int i=0; i<userWords.length;i++) {
int r = rand.nextInt(ROW) + 1;
int c = rand.nextInt(COLUMN) + 1;
puzzleBoard[r][c] = userWords[i].charAt(i);
}
but it's printing only 3 char instead of the 3 strings of char into the char array.
I've also tried
puzzleBoard[r][c] = userWords[i].toCharArray();
instead of
puzzleBoard[r][c] = userWords[i].charAt(i);
But it display error "cannot convert from char[] to char"
Thank you
Full Code
public static void main(String[] args) {
String[] userWords = new String[3];
Methods.userInput(userWords); //ask user for input
Methods.fillPuzzle(puzzleBoard); //fill the puzzle with random char
for(int i=0; i<userWords.length;i++) {
int r = rand.nextInt(ROW) + 1;
int c = rand.nextInt(COLUMN) + 1;
puzzleBoard[r][c] = userWords[i].charAt(i);
}
Methods.printPuzzle(puzzleBoard); //print out the puzzle
}//end main
public static void printPuzzle(char a[][]) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
System.out.print(a[i][j] + " ");
}
System.out.print((i+1));
System.out.println();
}
}//end printPuzzle
public static void fillPuzzle(char a[][]) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
a[i][j] = '*';
}
}
}//end fillPuzzle
public static void userInput(String a[]) {
Scanner input = new Scanner(System.in);
for(int i = 0; i < a.length;i++) {
System.out.println((i+1) + ". enter word:");
a[i] = input.next().toUpperCase();
}
}//end userInput
You can try this one:
for (int i = 0; i < userWords.length; i++) {
int r = rand.nextInt(puzzleBoard.length);
int c = rand.nextInt(puzzleBoard[r].length - userWords[i].length());
for (int j = 0; j < userWords[i].length(); j++) {
puzzleBoard[r][c + j] = userWords[i].charAt(j);
}
}
And you should add something that detects whether there is already a word at this position, otherwise you would overwrite it if the random numbers point to a location where is already written a word.
I think you should use 2 for-loops because you want to select first the string and next the characters in the string.
for(int i=0; i<userWords.length;i++) {
int r = rand.nextInt(ROW) + 1;
int c = rand.nextInt(COLUMN) + 1;
for (int j = 0; j < userWords[i].length(); j++) {
puzzleBoard[r][c + j] = userWords[i].charAt(j);
}
}
import java.util.*;
public class HistogramGenerator {
public int getHeightOfHistogram(int[] occurences) {
// occurences = {1,0,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0]
int max = occurences[0];
for (int i = 1; i < occurences.length; i++) {
if (occurences[i] > max) {
max = occurences[i];
}
}
return max;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter a line: ");
String sentenceEntered = sc.nextLine();
System.out.println("Letter Histogram");
HistogramGenerator histogram = new HistogramGenerator();
String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //Map of all the characters
int[] occurences = new int[letters.length()]; //max size of all possible matches
// loop through sentenceEntered to find occurences of each character
for (int i = 0; i < sentenceEntered.length(); i++) {
int charValue = sentenceEntered.charAt(i);
int index = letters.indexOf(charValue); // index of the character we are searching for
if (index < 0)
continue;
occurences[index]++;
}
int heightOfHistogram = histogram.getHeightOfHistogram(occurences);
String[][] histogramArray = new String[heightOfHistogram][letters.length()]; //[2][26]
for (int j =0; j < occurences.length; j++) {
int numXtoInsert = occurences[j];
while(numXtoInsert > 0){
histogramArray[heightOfHistogram - numXtoInsert][j] = "X";
numXtoInsert--;
}
}
// print 26 dashes (length of letters)
for(int k=0; k < letters.length(); k++){
System.out.print("-");
}
System.out.println();
// print histogram
for(int row =0; row < histogramArray.length; row++){
for(int col=0; col < histogramArray[row].length; col++){
if (histogramArray[row][col] == null) {
System.out.print("");
continue;
}
System.out.print(histogramArray[row][col] + " ");
}
System.out.println();
}
System.out.println();
// print 26 dashes ( length of letters)
for(int u=0; u < letters.length(); u++){
System.out.print("-");
}
System.out.println();
// print all characters in letters
System.out.print(letters);
}
}
basically whatever word i put in it prints out something close to it, but not really correctly, if i type in apple for example it'll print out an X close to A, and X on P and an X close to P, and and X close to l and E.
maybe there's something wrong with the logic? I don't know, need some quick help!
The issue is with the printing logic. When you find a null value, you need to print a space. When you don't find a null value, you should not add an extra space. See below for the updated working logic:
// print histogram
for(int row =0; row < histogramArray.length; row++){
for(int col=0; col < histogramArray[row].length; col++){
if (histogramArray[row][col] == null) {
System.out.print(" ");
continue;
}
System.out.print(histogramArray[row][col]);
}
System.out.println();
}
System.out.println();