Java: New Line after 18 Chars & new Array Index after 13 Lines - java

I am pretty new to Java and I have a little problem with formatting a String. I have add "\n" for a new line after every 18th char and I have to split these new lines into array indexes, 13 lines for each index.
My code so far:
String[] strings = str.split("\n");
String result;
for (int i = 1; i < strings.length; i++) {
i++;
if ((i % 13) == 0) {
result += strings[i];
} else {
result += strings[i] + "\n";
}
}
It doesn't work as it should, I tested a bit around bit I don't know how to do this, could someone help me please?

You're incrementing i twice in each loop - once in the increment expression of the for statement, and once inside the loop itself. This means i is always even, so i % 13 is probably not 0 when you expect it to be. In addition, the first index of an array is 0, so you would currently ignore the first element. As a more minor point, I would advise using a StringBuilder instead of appending Strings:
String[] strings = str.split("\n");
StringBuilder resultBuilder = new StringBuilder();
for (int i = 0; i < strings.length; i++) {
String s = strings[i];
if ((i % 13) == 0) {
resultBuilder.append(s);
} else {
resultBuilder.append(s).append("\n");
}
}
String result = resultBuilder.toString();

Related

How to find frequency of characters in a string without using array in java

Given a String, I want to create a frequency distribution of characters in the String. That is, for each distinct character in the string, I want to count how many times it occurs.
Output is a String that consists of zero or more occurrences of the pattern xd, where x is a character from the source String, and d is the number of occurrences of x within the String. Each x in the output should occur once.
The challenge is to do this without using an array or Collection.
Examples:
Source: "aasdddr" Result: "a2s1d3r1"
Source: "aabacc" Result: "a3b1c2"
Source: "aasdddraabcdaa" Result: "a6s1d4r1b1c1"
I tried this way:
String str = "aasdddr", result = "";
int counter = 0;
for(int i = 0; i < str.length(); i++){
result += "" + str.charAt(i);
for(int j = 1; j < str.length(); j++){
if(str.charAt(i) == str.charAt(j)){
counter++;
}
}
result += counter;
}
System.out.println(result);
My output is a1a2s3d6d9d12r13
Finally, I found the solution. But I think any question has more than one solution.
First, we should declare an empty string to keep the result. We use a nested loop because the outer loop will keep a character fixed during each iteration of the inner loop. Also, we should declare a count variable inside the outer loop. Because in each match, it will be increased by one and after controlling each character in the inner loop, it will be zero for the next check. Finally, after the inner loop, we should put a condition to check whether we have that character inside the result string. If there isn't any character like that, then it will be added to the result string. After that, its frequency (count) will be added. Outside of the loop, we can print it.
public class FrequenciesOfChar {
public static void main(String[] args) {
String str = "aabcccd"; // be sure that you don't have any digit in your string
String result = ""; // this will hold new string
for (int i = 0; i < str.length(); i++) { // this will hold a character till be checked by inner loop
int count = 0; // put here so that it can be zero after each cycle for new character
for (int j = 0; j < str.length(); j++) { // this will change
if(str.charAt(i) == str.charAt(j)){ // this will check whether there is a same character
count++; // if there is a same character, count will increase
}
}
if( !(result.contains(""+str.charAt(i))) ){ // this checks if result doesn't contain the checked character
result += ""+str.charAt(i); // first if result doesn't contain the checked character, character will be added
result += count; // then the character's frequency will be added
}
}
System.out.println(result);
}
}
Run Result:
aabcccd - a2b1c3d1
First, counter needs to be reset inside the for loop. Each time you encounter a character in the source String, you want to restart the counter. Otherwise, as you have seen, the value of the counter is strictly increasing.
Now, think about what happens if a character occurs in more than one place in the source String, as in the "aasdddraabcdaa" example. A sequence of 1 or more a appears in 3 places. Because, at the time you get to the 2nd occurrence of a, a has been previously counted, you want to skip over it.
Because the source String cannot contain digits, the result String can be used to check if a particular character value has already been processed. So, after fixing the problem with counter, the code can be fixed by adding these two lines:
if (result.indexOf (source.charAt(i)) >= 0) {
continue; }
Here is the complete result:
package stackoverflowmisc;
public class StackOverflowMisc {
public static String freqDist(String source) {
String result = "";
int counter ;
for (int i = 0; i < source.length(); i++) {
if (result.indexOf (source.charAt(i)) >= 0) { continue; }
counter = 1;
result += source.charAt(i);
for (int j = 1; j < source.length(); j++) {
if (source.charAt(i) == source.charAt(j)) {
counter++;
}
}
result += counter;
}
return result;
}
public static void main(String[] args) {
String [] test = {"aasdddr", "aabacc", "aasdddraabcdaa"};
for (int i = 0; i < test.length; ++i) {
System.out.println (test[i] + " - " + freqDist (test[i]));
}
System.out.println ("End of Program");
}
}
Run results:
aasdddr - a2s2d4r2
aabacc - a3b2c3
aasdddraabcdaa - a6s2d5r2b2c2
End of Program
In one of the Q&A comments, you said the source string can contain only letters. How would the program work if it were allowed to contain digits? You can't use the result String, because the processing inserts digits there. Again, this is an easy fix: Add a 3rd String to record which values have already been found:
public static String freqDist2(String source) {
String result = "", found = "";
int counter ;
for (int i = 0; i < source.length(); i++) {
if (found.indexOf (source.charAt(i)) >= 0) { continue; }
counter = 1;
result += source.charAt(i);
found += source.charAt(i);
for (int j = 1; j < source.length(); j++) {
if (source.charAt(i) == source.charAt(j)) {
counter++;
}
}
result += counter;
}
return result;
}
Another possibility is to delete the corresponding characters from the source String as they are counted. If you are not allowed to modify the Source String, make a copy and use the copy.
Comment: I don't know if this is what your professor or whomever had in mind by placing the "No array" restriction, because a String is essentially built on a char array.

Printing values

I am posting this question related to how to write values one below the other without using System.out.println(). I believe generally when we want to print out values we can use arrays or lists etc. It would go something like this, for example:
public class Main {
public static void main(String[]args){
int[] myList = new int[10] ;
for(int i = 0 ; i < myList.length ; i++){
myList[i] = i ;
System.out.println(myList[i] + "\n");
}
}
}
But I want to know how to print values in a box like this:
1 2 3 4
5 6 7 8
Thank you,
It is not completely clear what you want to achieve. If your purpose is to display data on standard out (console) I don't see any reason not to use System.out.println(), .print() or .printf().
Warning, long answer with questionable relevance
To print your values in two rows can be done in many different ways. Here is one option:
private static void printNums2() {
int rowLength = 4;
for (int i = 1; i < 9; i++) {
System.out.print(i + ((i % rowLength == 0) ? " \n" : " "));
}
System.out.println();
}
Prints the current number, i, and then checks if i has reached the end of a row with modulus. If so, prints a new line character. (Loop starts at 1 and goes to 8 to match the numbers in your output.)
I noticed in your example output there are varying number of spaces as well. Here is a version of the above which achieves this as well:
private static void printNums2b() {
int rowLength = 4;
for (int i = 1; i < 9; i++) {
System.out.printf("%-" + (i % rowLength + 2) + "d" + ((i % rowLength == 0) ? " \n" : ""), i);
}
System.out.println();
}
In short, it uses printf() to format the output and sets the padding on the number to modulus of the position (to account for rows) + 1 (because 0 doesn't work).
One interpretation of your question is that you don't want to print too often. There is no reason we have to print every number by itself. We can accumulate the output and then print it all at once.
Here is a solution using a StringBuilder (standard Java, no extra libraries needed):
private static void printNums3() {
int rowLength = 4;
StringBuilder sb = new StringBuilder();
for (int i = 1; i < 9; i++) {
sb.append(i).append(' ');
if ((i % rowLength == 0)) {
sb.append('\n');
}
}
System.out.println(sb.toString());
}
Puts all the numbers in the StringBuilder, adds a newline at the end after every 4th number and then prints the entire thing at the end.
And again, with varying spaces:
private static void printNums3b() {
int rowLength = 4;
StringBuilder sb = new StringBuilder();
for (int i = 1; i < 9; i++) {
sb.append(String.format("%-" + (i % rowLength + 2) + "d", i));
if ((i % rowLength == 0)) {
sb.append('\n');
}
}
System.out.println(sb.toString());
}
I don't think there is any particular benefit to using arrays. But then again, there are many ways to achieve this output. Since we don't know more about what you really want to achieve, if your array serves some other purpose (I removed the array because it's not needed for the printing) or what type of data you want to print other than numbers, I can't really give more ideas.

Java : Index out of bound exception when creating a string with no matching consecutive characters

This is my function which takes a string as input for example aabbaaa. I am deleting the character if the next one to it is the same. In this way I am removing consecutive occurrences of a character i.e the string will become aba. But it is throwing me indexoutofbounds exception.
static int alternatingCharacters(String s)
{
StringBuilder sb = new StringBuilder(s);
try
{
for(int i = 0; i < sb.length(); i++)
{
while (sb.charAt(i) == sb.charAt(i+1) && i+1<sb.length())
{
sb=sb.deleteCharAt(i);
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
return 0;
System.out.println(sb);
}
Irrespective of the exception, this is a very inefficient way to delete chars from the string.
Every time you invoke sb.deleteCharAt(i), it has to shift all of the characters to the right of i along by 1. In the worst case, this has quadratic time complexity.
Instead, it is much more efficient simply to move the characters, and then trim the end:
StringBuilder sb = new StringBuilder(s);
if (!s.isEmpty()) {
int len = 1;
for (int i = 1; i < sb.length(); ++i) {
if (sb.charAt(i) != sb.charAt(len - 1)) {
sb.setCharAt(len++, sb.charAt(i));
}
}
sb.setLength(len);
}
This has linear time complexity.
You can do it a little more directly, too, by operating directly on a char[]:
if (!s.isEmpty()) {
char[] cs = s.toCharArray();
int len = 1; // Start at 1, since the first character isn't equal to the one before it.
for (int i = 1; i < cs.length; ++i) {
if (cs[i] != cs[len-1]) {
cs[len++] = cs[i];
}
}
s = new String(cs, len);
}
while (sb.charAt(i) == sb.charAt(i+1) && i+1<sb.length())
In this line, sb.charAt(i) == sb.charAt(i+1) is evaluated before i+1<sb.length(), which means that you check that a following character exists only after you try to retrieve it.
Swap the two conditions, so that the check is performed before.
The index goes out of bounds because of the i+1
The for(int i = 0; i < sb.length(); i++) makes i vary from 0 to length - 1 due to the less than symbol.
This is correct because a String or N characters will start at index 0 and finish at index N-1.
When you do i+1 in the for loop, when it reaches the last character at index i, i+1 goes out of the character array bounds.
Your problem, as mentioned in the comments, is the while loop - so you should first check i + 1 < sb.length() and then check sb.charAt(i) == sb.charAt(i + 1).
Also - two other things:
Remove the println statement as this makes it not compile
No point returning an int (and hardcoded to 0), so change it to String
Example:
static String alternatingCharacters(String s) {
StringBuilder sb = new StringBuilder(s);
try {
for (int i = 0; i < sb.length(); i++) {
while (i + 1 < sb.length() && sb.charAt(i) == sb.charAt(i + 1)) {
sb = sb.deleteCharAt(i);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
Online Demo
Your problem is that you are iterating till sb.length() and then inside the loop in the while condition you are using :
while (sb.charAt(i) == sb.charAt(i+1) && i+1<sb.length())
And the sentence sb.charAt(i+1) is what icauses the IndexOutOfBoundException because there's no such index in the string.
When the loop reaches the last element, you call sb.charAt(i+1) in the while which is placed before i+1<sb.length() so it will be always executed.
What you need to do is to swap the two conditions in the while loop: while(i+1<sb.length() && sb.charAt(i) == sb.charAt(i+1)).
Index out of bounds is generally caused when you are referencing an index that doesn't exist. Also remember that the index count starts from 0 not 1. On the last loop sb.charAt(i+1) would be 7 + 1 = 8, which doesn't exist since your upper boundary is sb.Length(), to fix this just make your upper boundary for(int i = 0; i < sb.length() - 1; i++)
Loop and delete will cause certainly IndexOutOfBoundsException
StringBuilder sb = new StringBuilder("hello"); // length is 5
sb.deleteCharAt(2); // length is 4
And you still iterate until reaching 5, this will cause the exception
You can use Regex to build a clean solution:
"aaabbcccc".replaceAll("([a-z])\\1{1,}", "$1"); // the result will be abc

I am trying to insert a string character to another string. How can I achieve it in java?

This is the code I am working upon. I dont know where I am going wrong.
package mcdcpairwise;
import java.io.*;
import java.util.*;
public class Permutation
{
public static void main(String[] args)
{
String a="000";
String b="|&";
for (int i=0; i < a.length(); i++){
if (i % 2 != 0){
a = a.substring(0,i-1) + b.substring(0,i-1). + a.substring(i, a.length()) + b.substring(i, b.length());
System.out.println(a);
}
}
}
}
The error I am facing is:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: -2 at
java.lang.String.substring(String.java:1967) at
mcdcpairwise.Permutation.main(Permutation.java:13)
The output should be :
0|0&0
It isn't clear from your question exactly what your "rules" are for processing this. However, your output seems to simply insert a character between each character of your source a string.
Instead of using a substring, create a separate StringBuilder to add individual characters to. The code below produces the output you are looking for:
String string = "000";
StringBuilder output = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
// Get current character in the string
char c = string.charAt(i);
// Add the current character to the output
output.append(c);
// If more characters exist, add the pipe
if (i != string.length() - 1) {
output.append("|");
}
}
System.out.println(output.toString());
The right code should be a.substring(0,i).
You can use String.toCharArray to get a char[] from a String. That way we can iterate more easily both String using an index.
String a="000";
String b="|&";
char[] arrayA = a.toCharArray();
char[] arrayB = b.toCharArray();
Then, all we have to do is to merge two array (from Strings) taking one character from both. Adding two conditions (one per array) to prevent any ArrayIndexOutOfBOundsException, we can insure we will merge two arrays.
StringBuilder sb = new StringBuilder();
//Add a char from both array (until we reach on of the limit)
int i = 0;
while( i < arrayA.length && i < arrayB.length){
sb.append(arrayA[i]).append(arrayB[i]);
++i;
}
Then we just need to add the remaining characters using a for loop on both arrays. Only one of those loop will be triggered (or none) since at least one previous condition (i < arrayA.length && i < arrayB.length) is already false.
//Add the rest of `a` if any
for(int j = i; j < arrayA.length; ++j){
sb.append(arrayA[j]);
}
//Add the rest of `b` if any
for(int j = i; j < arrayB.length; ++j){
sb.append(arrayB[j]);
}
System.out.println(sb.toString());
0|0&0
Here’s a one line solution:
System.out.println((a + b).replaceAll("(?<=.)(?=.{" + (a.length() - 1) + "}(.))|.(?=.{0," + (b.length() - 1) + "}$)", "$1"));
This works with all combinations of non-blank starting strings.
See live demo.

Algorithm for combinatorics (6 choose 2)

Following this question, I want to now code "6 choose 2" times "4 choose 2." By that I mean, lets say I have 6 characters "A B C D E F." The first time I choose any two characters to delete. The 2nd time I want to choose 2 different letters to delete and then I append the results of these two trials. Hence, I will receive 90("6 choose 2" times "4 choose 2") eight character strings. The characters in the pattern are from the same pattern {1,2,3,4,5, 6}. All the characters are unique and no repetition.
Here is what I have so far.
public String[] genDelPatterns(String design){
char[] data = design.toCharArray();
String[] deletionPatterns = new String[15];
int x = 0;
StringBuilder sb = new StringBuilder("");
int index = 0;
for(int i = 0; i < (6-1); i++){
for(int j = i+1; j < 6; j++){
for(int k= 0; k < 6; k++){
if((k != j) && (k != i))
sb.append(String.valueOf(data[k]));
}
deletionPatterns[x++] = sb.toString();
sb = new StringBuilder("");
}
}
return deletionPatterns;
}
public String[] gen8String(String[] pattern1, String[] pattern2){
String[] combinedPatterns = new String[225];
int k = 0;
for(int i = 0; i < 15; i++)
{
for(int j = 0; j < 15; j++)
combinedPatterns[k++] = pattern1[i] + pattern2[j];
}
return combinedPatterns;
}
I will be calling the methods like this:
gen8String(genDelPatterns("143256"), genDelPatterns("254316"));
Currently, I am generating all the possible 8 letter strings. But I want to only generate the 8 character strings according to the aforementioned specifications. I am really stuck on how I can elegantly do this multiplication. The only way I can think of is to make another method that does "4 choose 2" and then combine the 2 string arrays. But this seems very roundabout.
EDIT: An example of an 8 character string would be something like "14322516", given the inputs I have already entered when calling gen8String, (143256,254316). Note that the first 4 characters are derived from 143256 with the 5 and 6 deleted. But since I deleted 5 and 6 in the first trail, I am no longer allowed to delete the same things in the 2nd pattern. Hence, I deleted the 3 and 4 from the 2nd pattern.
you have a chain of methods , each one called a variation itself.
For so, my advice is to use a recursive method!
to achieve your goal you have to have a little experience with this solution.
A simple example of a method that exploits the recursion:
public static long factorial(int n) {
if (n == 1) return 1;
return n * factorial(n-1);
}
I can also suggest you to pass objects (constructed to perfection) for the method parameter, if is too complex to pass simple variables
This is the heart of this solution in my opinion.
While what you tried to do is definitely working, it seems you are looking for other way to implement it. Here is the skeleton of what I would do given the small constrains.
// Very pseudo code
// FOR(x,y,z) := for(int x=y; x<z;x++)
string removeCharacter(string s, int banA, int banB){
string ret = "";
FOR(i,1,7){
if(i != banA && i != banB){
ret += s[i];
}
}
return ret;
}
List<string> Generate(s1,s2){
List<string> ret = new List<string>();
FOR(i,1,7) FOR(j,i+1,7) FOR(m,1,7) FOR(n,m+1,7){
if(m != i && m != j && n != i && n != j){
string firstHalf = removeCharacter(s1,i,j);
string secondHalf = removeCharacter(s2,m,n);
ret.Add(firstHalf + secondHalf);
}
}
return ret;
}
This should generate all possible 8-characters string.
Here is the solution I came up with. Doesn't really take "mathematical" approach, I guess. But it does the job.
//generating a subset of 90 eight character strings (unique deletion patterns)
public static String[] gen8String(String[] pattern1, String[] pattern2){
String[] combinedSubset = new String[90]; //emty array for the subset of 90 strings
String combinedString = ""; //string holder for each combined string
int index = 0; //used for combinedSubset array
int present = 0; //used to check if all 6 characters are present
for(int i = 0; i < 15; i++){
for(int j = 0; j < 15; j++){
combinedString = pattern1[i] + pattern2[j]; //combine both 4 letter strings into 8 char length string
char[] parsedString = combinedString.toCharArray(); //parse into array
//check if all 6 characters are present
for(int k = 1; k <= 6; k++)
{
if(new String(parsedString).contains(k+"")) {
present++;
}
else
break;
//if all 6 are present, then add it to combined subset
if(present == 6)
combinedSubset[index++] = combinedString;
}
present = 0;
}
}
return combinedSubset;
}

Categories

Resources