how can I create a loop that also turns string "abcc" into the sum of their letter position, say a=1 b=2 c=3 and it sums the string 1+2+3+3=9.
import java.util.Arrays;
public class Test
{
public static void main(String[] args)
{
String original = "hello";
char[] chars = original.toCharArray();
Arrays.sort(chars);
String sorted = new String(chars);
System.out.println(sorted);
}
}
You can use the ASCII values. a has value 97, b has 98 and so on.
private int printSum(String original){
int sum = 0;
if(original!=null){
char[] arr = original.toLowerCase().toCharArray();
for(int x :arr){
sum+= (x-96);
}
}
return sum;
}
You can make use of the fact that characters can be cast to an Integer, and thereby take on their ASCII value. e.g. System.out.println((int)'a') would print '97'. Knowing that, you only have to subtract a certain number based on whether it's an upper- or lowercase letter and you get 1 for a, 2 for b etc.
Remove non-alphabet characters from the string using regular expressions
Modify string with toLower() or toUpper()
Convert the string into charArray
Set initial result as 0
Foreach char in the array, subtract the char value with 64 (if you use UPPERCASE) or 96 (if you use lowercase) and add it into result
Here are two solutions: One with a loop as requested, and one with recursion.
This works with both upper- and lowercase letters, but doesn't take non-alphabetical letters into account. This can easily be tested for in an if-statement, with the following criteria: Character.isAlphabetic( c ).
public class Main {
static final int LOWERCASE_OFFSET = 96;
static final int UPPERCASE_OFFSET = 64;
public static void main( String[] args ){
System.out.println(recursion( "Abcc" ));
}
static int recursion( String str ) {
if( str.isEmpty() )
return 0;
char c = str.charAt( 0 );
int charVal = Character.isUpperCase( c ) ? c - UPPERCASE_OFFSET : c - LOWERCASE_OFFSET;
return charVal + recursion( str.substring( 1 ) );
}
static int loop( String str ) {
int val = 0;
for( char c : str.toCharArray() ) {
val += Character.isUpperCase( c ) ? c - UPPERCASE_OFFSET : c - LOWERCASE_OFFSET;
}
return val;
}
}
Related
Lets say I have a string like this:
String str = "~asdfl;kjx,~rgadfaeg,dsafnewgfljka;ldfjsfa;dlkjfa;lvjvbnaber;fwelfjadfafa"
int character = 12
What I want to do is delete every 12th character in the string, so i would delete the 12 index, then the 24th, then the 36th, etc until the string is over.
Which index I delete (every 12th, or every 2nd) has to equal the character variable I have, since that variable changes.
I tried doing this with regex:
System.out.println(s.replaceAll(".(.)", "$12"));
But it didnt work. any help?
Sometimes, a simple for loop is all you need:
public class Test {
public static void main(String[] args) {
String str = "~asdfl;kjx,~rgadfaeg,dsafnewgfljka;ldfjsfa;dlkjfa;lvjvbnaber;fwelfjadfafa";
int character = 12;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
if ((i + 1) % character != 0) {
sb.append(str.charAt(i));
}
}
String result = sb.toString();
System.out.println(result);
}
}
If you insist on using regular expressions, you can interpolate the character variable into the expression as follows:
public class Test {
public static void main(String[] args) {
String str = "~asdfl;kjx,~rgadfaeg,dsafnewgfljka;ldfjsfa;dlkjfa;lvjvbnaber;fwelfjadfafa";
int character = 12;
System.out.println(str.replaceAll("(.{" + (character - 1) + "}).", "$1"));
}
}
To delete every 12th character using regex, use this pattern:
(.{11}).
And then replace with just the captured $1.
Sample Java code:
String str = "~asdfl;kjx,~rgadfaeg,dsafnewgfljka;ldfjsfa;dlkjfa;lvjvbnaber;fwelfjadfafa";
String output = str.replaceAll("(.{11}).", "$1");
System.out.println(output);
This prints:
~asdfl;kjx,rgadfaeg,dsfnewgfljka;dfjsfa;dlkja;lvjvbnabe;fwelfjadfaa
Edit:
To do a regex replacement of some fixed width, use:
String str = "~asdfl;kjx,~rgadfaeg,dsafnewgfljka;ldfjsfa;dlkjfa;lvjvbnaber;fwelfjadfafa";
int width = 11;
String output = str.replaceAll("(.{" + width + "}).", "$1");
System.out.println(output);
Avoid char
The char type in Java is legacy, essentially broken. As a 16-bit value, a char is incapable of representing most characters.
Code points
Instead, use code point integers.
Make an array of each character’s code point.
int[] codePointsArray = input.codePoints().toArray() ;
Make a list of that array.
List< Integer > codePoints = List.of( codePointsArray ) ;
Alternatively:
List< Integer > codePoints = input.codePoints().boxed().toList() ;
Make an IntStream of the indexes we need to access each element of that list. Use each index to pull out a code point, and filter by the nth element. Collect into a StringBuilder.
String result =
IntStream
.range( 0 , codePoints.size() )
.filter( n -> n % 12 != 0 )
.mapToObj( codePoints :: get )
.collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append )
.toString()
;
That is untested code, but should be close to what you need.
My code here is based on what I saw on this similar Question.
I want to take the value of a ASCII value(Saved as a string) and convert it to the character to reveal a message. I tried this and it keeps throwing an index out of bound at the declaration of the int b.It also shows that str and b do not have a value
String value = "104 101 108 108 111";
char[] ch = new char[value.length()];
for (int i = 0; i < value.length(); i++) {
ch[i] = value.charAt(i);
}
System.out.println(ch.length);
String ans = "";
int i = 0;
while (i+2 < ch.length) {
int b= ch[i]+ch[i++]+ch[i+2];
String str = new Character((char) b).toString();
System.out.println(str);
System.out.println(b);
ans = ans+str;
i=i+3;
}
Using string split function
String value = "104 101 108 108 111";
String[] arrOfStr = value.split(" ");
String ans = "";
for(String str : arrOfStr) {
String str1 = Character.toString((char)Integer.parseInt(str));
ans += str1;
}
System.out.println(ans); // output: hello
We can switch the Imperative code to Declarative code using Java 8 Streams.
Key points to observe:
Declarative style is more readable and easy to write.
String Joiner is faster than simple String Concatenation.
No need to write an iterator.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String value = "104 101 108 108 111";
Arrays.stream(value.split(" ")) // Starting a stream of String[]
.mapToInt(Integer::parseInt) // mapping String to int
.mapToObj(Character::toChars) // finding ASCII char from int
.forEach(System.out::print); // printing each character
}
}
If you wish to store the result and then print it, this is how is done.
import java.util.Arrays;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
String value = "104 101 108 108 111";
String result = Arrays.stream(value.split(" ")) // Starting a stream of String[]
.mapToInt(Integer::parseInt) // mapping String to int
.mapToObj(Character::toChars) // finding ASCII char from int
.map(String::new) // convert char to String
.collect(Collectors.joining()); // combining individual result using String Joiner
System.out.println(result);
}
}
Comments to code:
There is a built-in method for for getting a char[] with the characters of a string, so the following two blocks of code are the same:
// Code from question
char[] ch = new char[value.length()];
for (int i = 0; i < value.length(); i++) {
ch[i] = value.charAt(i);
}
// Using built-in method
char[] ch = value.toCharArray();
It is better to use a for loop when increment a value while looping. The following two ways of writing the loop behave the same, but the for loop keeps the loop logic together:
// Code from question
int i = 0;
while (i+2 < ch.length) {
// some code here
i=i+3;
}
// Using for loop
for (int i = 0; i + 2 < ch.length; i=i+3) {
// some code here
}
The following line of code is entirely wrong:
int b= ch[i]+ch[i++]+ch[i+2];
i++ increments the value is i, but it is the value before the increment that is used in the expression, which means that if i = 0 before the line, the result is the same as this code:
int b = ch[0] + ch[0] + ch[2];
i = i + 1;
You need to replace i++ with i + 1, and realize that those are not the same.
Since you no longer increment the value of i by 1 in that statement, the loop much be changed from i=i+3 to i = i + 4, to correctly skip the spaces in the input.
The value of ch[i] is a char value, which is widened to an int value by the use of the + operator. The int value of a char is the Unicode Code Point value, which for your text is also the same as the ASCII code for the character.
This means that if i = 0, the expression would (after fixing issue #1) evaluate as:
int b = ch[0] + ch[1] + ch[2];
int b = `1` + `0` + `4`;
int b = 49 + 48 + 52;
int b = 149;
That matches the output from running the code is in question, where the second printed number is 149 (after fixing issue #1).
What you really wanted was to get the substring "104" and convert that to a number, then cast that ASCII code value to a char, like this:
String numberStr = value.substring(i, i + 3); // E.g. "104"
int number = Integer.parseInt(numberStr); // E.g. 104
String str = String.valueOf((char) number); // E.g. "h"
With that, you no longer need the char[], so the final code would be:
String value = "104 101 108 108 111";
String ans = "";
for (int i = 0; i + 2 < value.length(); i += 4) {
String numberStr = value.substring(i, i + 3);
int number = Integer.parseInt(numberStr);
String str = String.valueOf((char) number);
ans = ans + str;
}
System.out.println(ans);
Output
hello
For java practice, I'm trying to write a class that generates all combinations of letters in a character array and puts them in String array.
The object should be built with a character array, and it should have a method that takes an int as input. The int will determine how long the combinations should be.
So, for example, input:
char[] charArray = { 'a', 'b' };
int k = 3;
Output:
[ "aaa", "aab", "aba", "abb", "baa", "bab", "bba", "bbb" ]
The method should be recursive, each time it should call itself with k-1.
I've tried a simplified version, generating a String with all the permutations separated by an underscore, but I'm not getting the output I want.
public String generate(int k) {
if (k == 0) return "_";
String s = "";
for (char c : charArray) {
s = s+c+generate(k-1);
}
return s;
}
My output is:
"aaa_b_ba_b_baa_b_ba_b_"
Instead of:
"aaa_aab_aba_abb_baa_bab_bba_bbb"
You need one more parameter for your method which holds prevalues.
You can try below code segment for your purpose:
public static String generate(String prefix, int k) {
String s = "";
if (k == 0)
return prefix + "_";
for (char c : charArray) {
String newPrefix = prefix + c;
s = s + generate(newPrefix, k - 1);
}
return s;
}
This code will generate "aaa_aab_aba_abb_baa_bab_bba_bbb_" so you have to remove last underscore.
Try something like this (uses java 8):
public String generate(String[] stringArray, String accumulator, int k) {
if (k == 0) return accumulator;
return Arrays.stream(stringArray).map(s -> generate(accumulator + s, k - 1)).collect(Collectors.joining("_"));
}
public String generate(String[] stringArray, int k) {
returngenerate(stringArray, "", k);
}
I just needed to change the array of chars to array of Strings:
String[] stringArray = new String[]{ "a", "b" };
Then invoking the method generate(stringArray, 3) generates the result:
aaa_aab_aba_abb_baa_bab_bba_bbb
I need to write a program that should ask two strings from user and show the common characters in this.
It must not have duplicates: even if ‘a’ is found more than once in both strings, it should be displayed only once.
My Java knowledge is very limited, so I'm not looking for efficiency but for understandability.
Here is what I came up with at the moment.
//Get String 1
System.out.print( "Enter a string: " );
string1 = sc.next();
//Get String 2
System.out.print( "Enter another string: " );
string2 = sc.next();
System.out.print ( "Common characters: " );
//Common chars
for ( a = 0 ; a < string1.length() ; a++){
for ( b = 0 ; b < string2.length() ; b++){
if ( string1.charAt(a) == string2.charAt(b) ){
System.out.print(string1.charAt(a));
}
Can anyone help me ?
You can use the chars() stream of the input string, e.g.:
public class StringCharCount {
public static void main(final String[] args) {
final String s1 = args[0];
final String s2 = args[1];
s1.chars()
.distinct()
.mapToObj(ch -> String.valueOf((char) ch))
.filter(s2::contains)
.forEach(System.out::println);
}
}
This works with Java 8 or later.
chars() creates a stream of characters from the string
distinct() ensures, that each value occurs only once
mapToObj(...) is required, because the String#contains() method requires a String as input. So we are converting the stream value to a String. Unfortunately, Java has issues with the primitive types, so the stream of chars is in fact a stream of int. So we have to cast each value to char.
forEach(...) prints each value to System.out
I would use a Set<Character>. This would naturally handle the duplicate issue and has a simple retainAll method to do the heavy lifting for you.
private Set<Character> characterSet(String s) {
Set<Character> set = new HashSet<>();
// Put each character in the string into the set.
for (int i = 0; i < s.length(); i++) {
set.add(s.charAt(i));
}
return set;
}
public Set<Character> common(String a, String b) {
// Make a set out of each string.
Set<Character> aSet = characterSet(a);
Set<Character> bSet = characterSet(b);
// Work out the common characters using retainAll.
Set<Character> common = new HashSet<>(aSet);
common.retainAll(bSet);
return common;
}
public void test(String[] args) throws Exception {
System.out.println(common("abcdef", "afxyzfffaa"));
}
You can use Set
String str1 = "abcdefg";
String str2 = "abcaaadefg";
StringBuilder result = new StringBuilder();
Set<Character> sets = new HashSet<Character>();
for(char ch : str1.toCharArray()){//init
sets.add(ch);
}
for(char ch : str2.toCharArray()){
if(sets.contains(ch)){//str1 char contains str2 char
result.append(ch);
sets.remove(ch);//avoid duplicates
}
}
System.out.println(result.toString());
Input : "107501AB021F"
Output: "1075 1AB 21F"
Assume the input is always of 12 digit hexadecimal value.
For each 2 digit char, if 0 occurs on the first position, it should be replaced with space
I know we can do this with an if condition and a charAt, but is there an option to do this without using it?
I believe the most efficient solution is to iterate and compare every second char in char array.
public class ReplaceOddIndexesInString {
public String replace(final String hex){
final char[] arr = hex.toCharArray();
for (int i = 0; i<arr.length; i=i+2) {
if (arr[i]=='0'){
arr[i]=' ';
}
}
return new String(arr);
}
#Test
public void testIt(){
TestCase.assertEquals("1075 1AB 21F", replace("107501AB021F"));
}
}