Creating a vertical histogram - java

Basically I've been trying to make my histogram display the asterisks vertically aligned above the letter that it is incrementing above. I've been trying to figure out the most efficient way to get the asterisks to align above the letter repeating. Any suggestions?
**My current output displays this horizontally**
asfklafjasjfk
A (3) ***
F (3) ***
J (2) **
K (2) **
L (1) *
S (2) **
ABCDEFGHIJKLMNOPQRSTUVWXYZ
I want it to display this
abcaaaabbzzzzz
*
* *
** *
** *
*** *
ABCDEFGHIJKLMNOPQRSTUVWXYZ
I have listed my code below
public class histogram {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String lettersInput = input.nextLine();
lettersInput=lettersInput.toUpperCase();
String map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int[] count = new int[map.length()];
for(int x = 0; x < lettersInput.length();x++){
int letter = map.indexOf(lettersInput.charAt(x));
if(letter < 0){
continue;
}
count[letter]++;
}
for(int x = 0; x < count.length; x++){
if(count[x]< 1)
continue;
System.out.println(String.format("%s (%d) %s",
map.charAt(x),
count[x],
new String(new char[count[x]]).replace('\0','*')));
}
System.out.println("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
}

The approach I took was to use a sorted map, whose keys are letters of the alphabet and whose values are the number of occurrences of each letter. Simply iterate over the input string to populate the map. Then, iterate over each row of possible output and print out either a space or an asterisk for each letter. I used Collections.max() on the map's values to find the height of the histogram.
TreeMap<Character, Integer> map = new TreeMap<>();
String input = "abcaaaabbzzzzz".toUpperCase();
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i=0; i < input.length(); ++i) {
Integer val = map.get(input.charAt(i));
map.put(input.charAt(i), val == null ? 1 : val + 1);
}
Collection<Integer> c = map.values();
int maxFrequency = Collections.max(c);
System.out.println("Input:\n" + input);
for (int i=maxFrequency; i > 0; --i) {
for (int j=0; j < alphabet.length(); ++j) {
Integer count = map.get(alphabet.charAt(j));
System.out.print((count != null && count >= i) ? "*" : " ");
}
System.out.println();
}
System.out.println(alphabet);
Output:
Input:
ABCAAAABBZZZZZ
* *
* *
** *
** *
*** *
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Demo here:
Rextester

Related

Writing a toString method for 2D arrays

I have some code for a 2D array but I don't want spaces at the end of each row before I start a new row. For some reason, I can't find where I'm messing up because a space is being put at the end of each row. Basically what I'm trying to do is input a 2D array and the output should make it look the same as the input, except for the {}'s and it'll be a string. For example,
Input:
{1, 2, 3},
{4, 5, 6};
Output:
1 2 3
4 5 6
public class Matrix {
// the dimensions of the matrix
private int numRows;
private int numColumns;
// the internal storage for the matrix elements
private int data[][];
/**
* #param d - the raw 2D array containing the initial values for the Matrix.
*/
public Matrix(int d[][])
{
// d.length is the number of 1D arrays in the 2D array
numRows = d.length;
if(numRows == 0)
numColumns = 0;
else
numColumns = d[0].length; // d[0] is the first 1D array
// create a new matrix to hold the data
data = new int[numRows][numColumns];
// copy the data over
for(int i=0; i < numRows; i++)
for(int j=0; j < numColumns; j++)
data[i][j] = d[i][j];
}
/**
* Returns a String representation of this Matrix.
*/
#Override // instruct the compiler that we intend for this method to override the superclass' (Object) version
public String toString() {
// TODO: replace the below return statement with the correct code.
String arrString = "";
for(int i = 0; i < data.length; i++) {
for(int j = 0; j < data[i].length; j++) {
arrString += data[i][j] + " ";
}
arrString += "\n";
}
return arrString;
}
Next time please post a runnable example.
Your problem was that you always added a space after the item, no matter if it was the last one in the line. I now check that with a conditional + (j == data[i].length - 1 ? "" : " ");
Hint: It's not good to concatenate Strings. Use StringBuilder for better performance an memory usage. I added a second method toString2() to show how it's done.
package stackoverflow;
public class Matrix {
// the dimensions of the matrix
private final int numRows;
private int numColumns;
// the internal storage for the matrix elements
private final int data[][];
/**
* #param d - the raw 2D array containing the initial values for the Matrix.
*/
public Matrix(final int d[][]) {
// d.length is the number of 1D arrays in the 2D array
numRows = d.length;
if (numRows == 0)
numColumns = 0;
else
numColumns = d[0].length; // d[0] is the first 1D array
// create a new matrix to hold the data
data = new int[numRows][numColumns];
// copy the data over
for (int i = 0; i < numRows; i++)
for (int j = 0; j < numColumns; j++)
data[i][j] = d[i][j];
}
/**
* Returns a String representation of this Matrix.
*/
#Override // instruct the compiler that we intend for this method to override the superclass' (Object) version
public String toString() {
// TODO: replace the below return statement with the correct code.
String arrString = "";
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
arrString += data[i][j] + (j == data[i].length - 1 ? "" : " ");
}
arrString += "\n";
}
return arrString;
}
public String toString2() {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
sb.append(data[i][j] + (j == data[i].length - 1 ? "" : " "));
}
sb.append("\n");
}
return sb.toString();
}
public static void main(final String[] args) {
final int[][] arr = new int[2][3];
arr[0][0] = 4;
arr[0][1] = 6;
arr[0][2] = 8;
arr[1][0] = 8;
arr[1][1] = 16;
arr[1][2] = 23;
final Matrix m = new Matrix(arr);
System.out.println("Matrix:\n" + m);
System.out.println("Matrix 2:\n" + m.toString2());
}
}
Output:
Matrix:
4 6 8
8 16 23
Matrix 2:
4 6 8
8 16 23
The Answer by JayC667 seems to correctly address your Question.
Stream, lambda, & method reference
For fun, here is an alternative approach using stream, lambda, and method reference.
Define the array.
int[][] input = { { 1 , 2 , 3 } , { 4 , 5 , 6 } }; // Declaration, initialization.
Make a stream where each element is a row, an array of int values, from your two-dimensional array.
For each of those rows, each being a int[], make a stream of its int primitive values (an IntStream), convert each primitive to an Integer object (boxing), call each Integer object’s toString method to generate a piece of text. Collect those pieces of text by joining them into a longer String with a SPACE character as a delimiter.
So we have transformed each row into a String. Collect all those strings together, with a LINE FEED character as the delimiter. Then, we are done, with a single String object as a result.
All that work, in a single line of code!
String result =
Arrays
.stream( input ) // A series of integer arrays, etc element being a int[].
.map( // Convert each integer array into something else, a `String` object.
( int[] row ) -> Arrays.stream( row ).boxed().map( Object :: toString ).collect( Collectors.joining( " " ) )
)
.collect( Collectors.joining( "\n" ) ); // Join each row of text with the next, using Linefeed as delimiter.
Results.
1 2 3
4 5 6
Here is one way to return a formatted 2D array based on the anticipated width of the values.
%nd - specifies a field width of n digits, right aligned.
%-nd - specifies a field width of n digits, left aligned (would have spaces at end of line).
fields will be filled in with spaces where necessary.
public class TwoDtoString {
int[][] mat = { { 11, 222, 3333 }, { 433, 53, 633 }, { 73, 8, 9333 } };
static String FORMAT = "%5d"; // 5 digit field, right aligned.
public static void main(String[] args) {
TwoDtoString tos = new TwoDtoString();
System.out.println(tos.toString());
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (int[] row : mat) {
sb.append(FORMAT.formatted(row[0]));
for (int i = 1; i < row.length; i++) {
sb.append(FORMAT.formatted(row[i]));
}
sb.append("\n");
}
return sb.toString();
}
}
prints
11 222 3333
433 53 633
73 8 9333

Write a program to print each and every alphabet with how many occured in a user input

I have to write a program to accept a String as input, and as output I'll have to print each and every alphabetical letter, and how many times each occurred in the user input. There are some constraints:
I cannot use built-in functions and collection
The printed result should be sorted by occurrence-value.
For example, with this input:
abbbccccdddddzz
I would expect this output:
a-1,z-2,b-3,c-4,d-5
This is what I have so far:
public static void isCountChar(String s) {
char c1[] = s.toCharArray();
int c3[] = new int[26];
for (int i = 0; i < c1.length; i++) {
char c = s.charAt(i);
c3[c - 'a']++;
}
for (int j = 0; j < c3.length; j++) {
if (c3[j] != 0) {
char c = (char) (j + 'a');
System.out.println("character is:" + c + " " + "count is: " + c3[j]);
}
}
}
But I don't know how to sort.
First of all a tip for your next question: The things you've stated in your comments would fit better as an edit to your question. Try to clearly state what the current result is, and what the expected result should be.
That being said, it was an interesting problem, because of the two constraints.
First of all you weren't allowed to use libraries or collections. If this wasn't a constraint I would have suggested a HashMap with character as keys, and int as values, and then the sorting would be easy.
Second constraint was to order by value. Most people here suggested a sorting like BubbleSort which I agree with, but it wouldn't work with your current code because it would sort by alphabetic character instead of output value.
With these two constraints it is probably best to fake key-value pairing yourself by making both an keys-array and values-array, and sort them both at the same time (with something like a BubbleSort-algorithm). Here is the code:
private static final int ALPHABET_SIZE = 26;
public static void isCountChar(String s)
{
// Convert input String to char-array (and uppercase to lowercase)
char[] array = s.toLowerCase().toCharArray();
// Fill the keys-array with the alphabet
char[] keys = new char[ALPHABET_SIZE];
for (int i = 0; i < ALPHABET_SIZE; i++)
{
keys[i] = (char)('a' + i);
}
// Count how much each char occurs in the input String
int[] values = new int[ALPHABET_SIZE];
for (char c : array)
{
values[c - 'a']++;
}
// Sort both the keys and values so the indexes stay the same
bubbleSort(keys, values);
// Print the output:
for (int j = 0; j < ALPHABET_SIZE; j++)
{
if (values[j] != 0)
{
System.out.println("character is: " + keys[j] + "; count is: " + values[j]);
}
}
}
private static void bubbleSort(char[] keys, int[] values)
{
// BUBBLESORT (copied from http://www.java-examples.com/java-bubble-sort-example and modified)
int n = values.length;
for(int i = 0; i < n; i++){
for(int j = 1; j < (n - i); j++){
if(values[j-1] > values[j]){
// Swap the elements:
int tempValue = values[j - 1];
values[j - 1] = values[j];
values[j] = tempValue;
char tempKey = keys[j - 1];
keys[j - 1] = keys[j];
keys[j] = tempKey;
}
}
}
}
Example usage:
public static void main (String[] args) throws java.lang.Exception
{
isCountChar("TestString");
}
Output:
character is: e; count is: 1
character is: g; count is: 1
character is: i; count is: 1
character is: n; count is: 1
character is: r; count is: 1
character is: s; count is: 2
character is: t; count is: 3
Here is a working ideone to see the input and output.
some sort: easy if not easiest to understand an coding
You loop from the first element to the end -1 : element K
compare element K and element K+1: if element K>element K+1, invert them
continue loop
if you made one change redo that !

JAVA index problems while doing caesar cipher

GOAL OF CODE :(using netbeans)
I was trying to write this code to apply the caesar cipher algorithm where multiple keys can be used in order e.g : key = [1,2,3] , text = test , where it will use key as "1" on "t" then key "2" on "e" then key "3" on "s" then return to key "1" on last t .
OUTPUT :
run:
Enter the text : mohammad rahmat
Enter the number of keys you want to use : 3
Enter 3 number of keys : 1
2
3
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at caesar.Caesar.main(Caesar.java:68)
nqkbopbfbsckncw
Java Result: 1
BUILD SUCCESSFUL (total time: 9 seconds)
CODE :
package caesar;
import java.util.Scanner;
public class Caesar {
/**
* #param args the command line arguments
*/
static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
// TODO code application logic here
char table[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t',
'u','v','w','x','y','z',' ','.'};
String tmp;
System.out.print("Enter the text : ");
tmp = input.nextLine();
char text[] = tmp.toCharArray();
System.out.print("Enter the number of keys you want to use : ");
int keyNo = input.nextInt();
int key[] = new int[keyNo];
System.out.printf("Enter %d number of keys : ",keyNo);
for (int i = 0; i < keyNo; ++i){
key[i] = input.nextInt();
}
char entext[] = new char[text.length];
int k = 0;
int a = 0;
int count = 0;
while (k < text.length){
int j = 0;
while (text[a] != table[j])
j++;
if (key[count]+j >= table.length){
entext[a] = table[(j+key[count])%table.length];
}
else entext[a] = table[j+key[count]];
a++;
count++;
if (count == keyNo)
count = 0;
k++;
}
String answer = new String(entext);
System.out.printf("ENCRYPTION : %s \n\n",answer);
char detext[] = new char[text.length];
k = 0;
a = 0;
count = 0;
while (k < text.length){
int j = 0;
while (text[a] != table[j])
j++;
if (key[count]-j < 0){
detext[a] = table[table.length+(key[count]-j)];
}
else detext[a] = table[j-key[count]];
a++;
count++;
if (count == keyNo)
count = 0;
k++;
}
String answer2 = new String(detext);
System.out.printf("DECRYPTION : %s\n\n",answer2);
}
}
you should use a debugger to analyze your code.
detext[a] = table[table.length+(key[count]-j)];
you're incrementing j and subtracting it from count which is zero. increment count before you operate on finding finding array index.
i found it finally , while converting it back to original text I had to take the converted text , in other words :
replace
while (k < text.length){
int j = 0;
while (text[a] != table[j])
with
while (k < entext.length){
int j = 0;
while (entext[a] != table[j])

I need to print an asterisk at the end of each column if the column is never visually changed. Advice?

/**
* Fills the mutations array and sends to printMutations
* #param firstString original DNA generation.
*/
public static void mutation(String firstString)
{
final int ROWSINDEX = 26;
final int SPACEUSED = firstString.length();
char[][] mutations = new char[ROWSINDEX][SPACEUSED];
String dnaChars = "AGTC";
for (int i = 0; i < SPACEUSED; i++)
{
mutations[0][i] = firstString.charAt(i);
}
for (int i = 1; i < ROWSINDEX - 1; i++)
{
for (int j = 0; j < SPACEUSED; j++)
{
mutations[i][j] = mutations[i - 1][j];
}
int randomIndex = (int) (Math.random() * (SPACEUSED));
int randomChar = (int) (Math.random() * (dnaChars.length()));
mutations[i][randomIndex] = dnaChars.charAt(randomChar);
}
printMutations(mutations, ROWSINDEX, SPACEUSED);
}
/**
* Prints the 25 generations of mutations and the astrixes.
* #param mutations array that holds the mutated generations
* #param ROWSINDEX integer holding the max amount of rows possible
* #param SPACEUSED integer that holds the number of columns
*/
public static void printMutations(char[][] mutations, int ROWSINDEX, int SPACEUSED)
{
for (int i = 0; i < ROWSINDEX; i++)
{
for (int j = 0; j < SPACEUSED; j++)
{
System.out.print(" " + mutations[i][j]);
}
if (i > 0)
{
char[] a = mutations[i];
char[] a2 = mutations[i - 1];
if (Arrays.equals( a, a2 ) == true)
{
System.out.print("*");
}
}
System.out.println("");
}
}
}
At the end of the output, you should print an asterisk below the column of any letter that did not change during the course of the simulation.
An example run of the program should appear like this:
$ java BeckJ0926
Enter a DNA sequence up to 80 bp: ATTCGGCTA
ATTCGGCTA
ATCCGGCTA
ATCCGTCTA
ATCCGTCTA *
...
ATCCGTCTT
AACCGTCTT
AATCGTCTT
* ** **
I don't know whether it would be best to set up a boolean array to determine whether each column has changed or not, which is what I was originally trying to do. I cannot use arrayLists.
You could change the line
mutations[i][randomIndex] = dnaChars.charAt(randomChar);
to
char currentChar = mutations[i][randomIndex];
if (currentChar == randomChar) {
System.out.print("*");
} else {
mutations[i][randomIndex] = dnaChars.charAt(randomChar);
printMutation(mutations[i]);
}
and change the print function to take one mutation and print it.
private void printMutation(char[] mutation) {
for (char a : mutation) {
System.out.print(a + " ");
}
}
Is that helpful?

How to reverse a string of numbers in a nested loop

This is a homework question so I would like help, not an answer.
I'm trying to create 2 triangles out of numbers based on a number entered by the user.
"Enter a number between 2-9: "3"
1
12
123
1
21
321
IE2:
"Enter a number between 2-9: "5"
1
12
123
1234
12345
1
21
321
4321
54321
I have been able to get the first triangle complete. But when I add my nested loop it messes up my first triangle with the numbers developed from the nested loop. It also puts all the numbers in a straight vertical line. I've tried variations for different nest loops and even tried messing with a StringBuilder, but was still unsuccessful.
Here's what I have in code so far:
import java.util.Scanner;
public class NestedLoops
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.print("Enter a Number between 2-9: ");
int width = input.nextInt();
String r = "";
for (int i = 1; i <= width; i++)
{
r = r + i;
System.out.println(r);
}
}
}
Again, I'm looking for help/understanding and not just an answer.
There are two aspects the 2nd part of the question.
You need to generate strings with the numbers in the reverse order:
You could do this by adding the numbers at the other end.
You could do this by reversing the strings.
You need to arrange that there are spaces to the left.
You could do this by adding the required number of spaces to the left end of the string.
You could do this by using the System.out.format(...) with a template that right aligns the string in a field with the required number of characters. (OK, that's a bit too obscure ...)
Or, you can build the string in a character array or string builder rather than using string concatenation.
The "trick" is to figure out what strategy you are going to use ... before you start cutting code.
try
int width = 5;
// for all lines; number of lines = width
for (int line = 1; line <= width; line++) {
// print numbers from 1 to current line number
for (int n = 1; n <= line; n++) {
System.out.print(n);
}
// end of line
System.out.println();
}
// add empty line between triangles
System.out.println();
// for all lines; number of lines = width
for (int line = 1; line <= width; line++) {
// printing padding spaces, number of spaces = with - line number
int nSpaces = width - line;
for (int i = 0; i < nSpaces; i++) {
System.out.print(" ");
}
// print numbers from number of current line to 1
for (int n = line; n >= 1; n--) {
System.out.print(n);
}
// end of line
System.out.println();
}
Can you just add another loop after your first loop like
String r = "";
String space = "";
for (int i = width; i >= 1; i--)
{
r = r + i;
System.out.println(r);
}
Try it. not yet tested
You need to use a queue.
eg. http://docs.oracle.com/javase/1.5.0/docs/api/java/util/LinkedList.html
Enque the numbers till you reach the max, and then start dequing them.
And while you dequeue, you need to apply the reverse
Queue<String> q = new LinkedList<String>();
for (int i = 1; i <= width; i++)
{
r = r + i;
q.add(r);
System.out.println(r);
}
while(!q.isEmpty()){
String j = q.remove();
//reverse j
System.out.println(reverse(j));
}
I leave the reversing part for you to do :)
public static void main(String[] args)
{
int n = 5;
for(int i=1; i<=n; i++)
{
for (int j=(n*2), k=n; j>1; j--)
{
if (k <= i)
{
System.out.print(k);
}
else
{
System.out.print('*');
}
k += (j)-1 > n ? -1 : 1;
}
System.out.println();
}
}
Just tried to implement in scala. Ignore if you don't like it..:-)
class Triangle extends App
{
val width = Console.readInt()
if (width < 2 || width > 9)
{
throw new RuntimeException()
}
var i, j = 1;
for (i <- 1 to width)
{
for (j <- 1 to i)
{
print(j)
}
print("\n")
}
for (i <- 1 to width)
{
for (dummy <- 1 to width-i)
{
print(" ")
}
for (j <- i to 1 by -1)
{
print(j)
}
print("\n")
}
}

Categories