My X's are being placed 1 space off in my histogram - java

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();

Related

How to create a method in java which prints out the elements of a matrix in shown pattern?

The contents of the matrix starts from 1 to the product of rows and columns. The method "scan" should print out as per following:
If the row is entered 4 and column is entered 7, the contents of the matrix should look like the image provided here:
the correct matrix
So far I have tried absolutely noting because I just don't know how to make this possible. I can print in zigzag, spiral but I just have no idea about this one. Please have mercy on me and grant me an insight.
This code currently prints out in a spiral pattern.
How should I modify this "scan" method so it satisfies the aforementioned condition?
import java.util.Scanner;
import java.util.Random;
public class that {
public static void main(String[] args) {
int range;
range = 100;
Scanner scn = new Scanner(System.in);
while(true) {
int m, n;
System.out.println("Enter the number of row: ");
m = scn.nextInt();
System.out.println("Enter the number of column: ");
n = scn.nextInt();
if(m <= 0||n <= 0) break;
int[][] tab = new int[m][n];
generate(tab, range);
scan(tab);
}
scn.close();
}
static int len(int x) { return (""+x).length(); }
static void generate(int[][] tab, int range) {
// Random generation
Random rg = new Random();
for(int i=0; i<tab.length; ++i)
for(int j=0; j<tab[0].length; ++j)
tab[i][j] = rg.nextInt(2*range) - range;
}
static void scan(int[][] tab) {
int m = tab.length;
int n = tab[0].length;
int totalWidth = 0;
int num = 1;
int rowStart = m - 1, rowEnd = 0, colStart = 0, colEnd = n - 1;
// Compute column widths
int[] colw = new int[n];
for(int j=0; j<n; ++j) { // For every column look down
colw[j] = len(j); // (""+j).length();
for(int i=0; i<m; ++i) {
int w = len(tab[i][j]); //("" + tab[i][j]).length();
if(w > colw[j]) colw[j] = w;
}
totalWidth += colw[j];
}
// Printing
int ris = len(m-1); // row index size
System.out.printf("%"+ris+"s ", " ");
for(int j=0; j<n; ++j)
System.out.printf("%" + colw[j] +"d ", j);
System.out.println();
System.out.printf("%"+ris+"s+"," ");
for(int j=0; j<totalWidth+n-1; ++j)
System.out.printf("-");
System.out.println();
while (rowStart >= rowEnd && colStart <= colEnd) {
// Print leftmost column from bottom to top
if (colStart <= colEnd) {
for (int i = rowStart; i >= rowEnd; i--) {
tab[i][colStart] = num++;
}
colStart++;
}
// Print top row from right to left
if (rowStart >= rowEnd) {
for (int i = colStart; i <= colEnd; i++) {
tab[rowEnd][i] = num++;
}
rowEnd++;
}
// Print rightmost column from top to bottom
if (colStart <= colEnd) {
for (int i = rowEnd; i <= rowStart; i++) {
tab[i][colEnd] = num++;
}
colEnd--;
}
// Print bottom row from left to right
if (rowStart >= rowEnd) {
for (int i = colEnd; i >= colStart; i--) {
tab[rowStart][i] = num++;
}
rowStart--;
}
}
// Prints the matrix
for(int i=0; i<m; ++i) {
System.out.printf("%"+ris+"d|", i);
for(int j=0; j<n; ++j)
System.out.printf("%" + colw[j] +"d ", tab[i][j]);
System.out.println();
}
System.out.println();
}
}

Crossed words game in Java

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

initialize only some elements of array in java

So I want to skip the first and last elements of the array to initialize. What am I doing wrong?
public static void main(String args[]) throws Exception {
//Write code here
Scanner sc = new Scanner(System.in);
System.out.println("Input Rows: ");
int m = sc.nextInt();
System.out.println("Input Columns: ");
int n = sc.nextInt();
System.out.println("Enter values: ");
int[][] arr = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (arr[i][j] == arr[0][0] || arr[i][j] == arr[m][n]) {
continue;
} else {
arr[i][j] = sc.nextInt();
}
}
System.out.println();
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
Here is my output:
Input Rows:
3
Input Columns:
3
Entered Values:
0 0 0
0 0 0
0 0 0
You need to change the if condition inside the loop like following:
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if ((i == 0 && j==0) || (i == m -1 && j == n -1)) {
continue;
} else {
arr[i][j] = sc.nextInt();
}
}
System.out.println();
}
In this line:
if (arr[i][j] == arr[0][0] || arr[i][j] == arr[m][n]) {
You are testing for the equality of values within your array. You should be comparing whether the indices you are looking at are the beginning or end of the array.
That is to say, you want to compare whether (in pseudo code):
i==0 and j==0, OR i==max index in its dimension and j==max index in its dimension
I have deliberately omitted the literal answer, because this looks a tiny bit like homework.
You compare the value of arr[i][j] with the value of arr[0][0]. You should instead compare i==0 && j==0 || i==m -1 && j==n -1
As your array was empty, and as you start the loop, arr[i][j] was equal to arr[0][0], skipping the first element. but for the next loop, arr[i][j] was still empty, and as you compare it to a non-initialised value, it's always true, skipping in each step
public static void main(String args[]) throws Exception {
//Write code here
Scanner sc = new Scanner(System.in);
System.out.println("Input Rows: ");
int m = sc.nextInt();
System.out.println("Input Coloumns: ");
int n = sc.nextInt();
System.out.println("Enter values: ");
int[][] arr = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i==0 && j==0 || i==m-1 && j==n-1) {
continue;
} else {
arr[i][j] = sc.nextInt();
}
}
System.out.println();
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
You don't need to check whether the array items are equal, you just want to check whether the row and column are equal to the last and first.

Printing a word in a diamond format

My assignment is to print a word in the shape of a diamond like so:
*****s
****p*p
***i***i
**d*****d
*e*******e
r*********r
*e*******e
**d*****d
***i***i
****p*p
*****s
P.S. The asterisks are only there to show spacing, pretend one asterisk represent one space.
So far I have this:
public class DiamondWords
{
public static void main(String[] args)
{
Scanner kbReader = new Scanner(System.in);
System.out.print("Enter a word to be printed in diamond format: ");
String word = kbReader.nextLine();
int wordLength = word.length();
for(int i = 0; i<wordLength-1; i++)
{
System.out.print(" ");
}
wordLength = wordLength - 1;
System.out.print(word.charAt(0));
System.out.println();
int x =1;
int d =1;
for(int j =wordLength; j>0; j--)
{
wordLength = j;
for(int a =1; a<wordLength; a++)
{
System.out.print(" ");
}
System.out.print(word.charAt(x));
for(int q =0; q<d; q++)
{
System.out.print(" ");
}
d+=2;
System.out.print(word.charAt(x));
x++;
System.out.println();
}
//r*********r
//*e*******e
//**d*****d
//***i***i
//****p*p
//*****s
}
}
Which prints the first half of the diamond perfectly:
*****s
****p*p
***i***i
**d*****d
*e*******e
r*********r
The only part where I'm getting stuck is when I have to print the latter half of the diamond. Can anyone point me in the right direction? Please do not write the code for me, just try and give me some pointers based off the logic I've shown. Thank you.
Try to have only one loop. A very easy way to handle the "technicalities" of the problem is to work with an char array for the output. First you initialize it with the proper length, fill it with blanks (there is a library function for it), fill the two characters, and only then convert it to a String.
The only open question is where to put the characters, and I don't want (and should) to spoil that.
int fullLength = 2 * word.length() - 1;
for(int i = 0; i < fullLength; i++) {
char[] line = new char[fullLength];
Arrays.fill(line, ' ');
int k = ???;
char c = s.charAt(k);
line[word.length() - 1 - k] = c;
line[word.length() - 1 + k] = c;
System.out.println(new String(line));
}
Obviously, you want to calculate the position "from the middle" (so we have something like word.length() - 1 +- k), and for the first half of the word, k is equal to i.
Your task, should you decide to accept it, is to find out how to "bend k back" for the second half of the word.
import java.util.Scanner;
public class DiamondWords
{
public static void main(String[] args)
{
Scanner kbReader = new Scanner(System.in);
System.out.print("Enter a word to be printed in diamond format: ");
String word = kbReader.nextLine();
int wordLength = word.length();
int wordLength2 = word.length();
int wordSize = word.length();
int wordLengthReverse = word.length();
for(int i = 0; i<wordLength-1; i++)
{
System.out.print(" ");
}
wordLength = wordLength - 1;
System.out.print(word.charAt(0));
System.out.println();
int x =1;
int d =1;
for(int j =wordLength; j>0; j--)
{
wordLength = j;
for(int a =1; a<wordLength; a++)
{
System.out.print(" ");
}
System.out.print(word.charAt(x));
for(int q =0; q<d; q++)
{
System.out.print(" ");
}
d+=2;
System.out.print(word.charAt(x));
x++;
System.out.println();
}
System.out.print(" " + word.charAt(wordLength2-2));
int spaceLength =((wordLength2*2)-1) -4;
int u =spaceLength -2;
for(int i =0; i < spaceLength; i++)
{
System.out.print(" ");
}
System.out.print(word.charAt(wordLength2-2));
System.out.println();
int m=3;
for(int num =2; num<wordSize-1; num++)
{
wordLength2 = num;
for(int i =0; i<num; i++)
{
System.out.print(" ");
}
System.out.print(word.charAt(wordSize-m));
for(int b = 0; b<u; b++)
{
System.out.print(" ");
}
System.out.print(word.charAt(wordSize-m));
System.out.println();
m++;
u = u-2;
}
for(int r =0; r<word.length()-1; r++)
{
System.out.print(" ");
}
System.out.print(word.charAt(0));
}
}
I have finished. This is my final code. I understand it is not as efficient as possible, or easy to follow, but it is flexible and not hard-coded, so I am content.

Getting each letter in a String only once

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.

Categories

Resources