Java split the BitSet - java

I want to split a bitset in more chunks. The splitting function depends on the cardinality of the bitset, which is the number of bits set to true.
For example I have this BitSet with the cardinality 4:
INPUT: 101101
The desired output is the following:
OUTPUT: 100000 - 001000 - 000100 - 000001
Using the Java library called BitSet is there a function or a possible way to achieve that?

The following code applies every possible mask with a single bit set and only keeps the non-zero results:
int[] split(int input) {
return IntStream.iterate(Integer.reverse(1), mask -> mask >>> 1)
.limit(Integer.SIZE)
.map(mask -> input & mask)
.filter(result -> result != 0)
.toArray();
}

Yes. Using basic operation AND.
Basicaly:
xxxxxx AND 110000 = xx0000.
Repeat procedure for all subsequences.

You need some loops here:
You should to find the positions of 1 then you can make a loop like this :
then If the position exist in the List then print 1 else print 0
public static void main(String[] args) {
String Input = "101101";
//find positions
List<Integer> listPositivePosition = new ArrayList<>();
for(int i = 0; i<Input.length(); i++){
if(Input.charAt(i)=='1'){
listPositivePosition.add(i);
}
}
for(int i = 0; i<listPositivePosition.size(); i++){
for(int j = 0; j<Input.length(); j++){
//If the position exist in the List then print 1 else print 0
if(j == listPositivePosition.get(i)){
System.out.print("1");
}else{
System.out.print("0");
}
}
System.out.println();
}
}
Hope this can help you.

Please forgive my method naming convention :)
public static void main(String[] args) {
final String a = "100100";
System.out.println(Arrays.toString(foo(a)));
}
private static String[] foo(String a) {
final long counted = IntStream.range(0, a.length()).filter(i -> a.charAt(i) == '1').count();
final String[] ret = new String[(int) counted];
int index = 0;
for (int i = 0; i < a.length(); i++) {
if (a.charAt(i) == '1') {
ret[index] = ret(a, i);
index++;
}
}
return ret;
}
private static String ret(String a, int i) {
final StringBuilder sb = new StringBuilder(a.replaceAll(".", "0"));
sb.setCharAt(i, '1');
a = sb.toString();
return a;
}

Pure Java and easy-to-read solution:
List<String> binSplitter(String input) {
String str = new String(new char[input.length()]).replace("\0", "0");
List<String> chunks = new ArrayList<>();
for (int i = 0; i < input.length(); i++) {
if (input.charAt(i) == '1') {
chunks.add(str.substring(0, i) + "1" + str.substring(i + 1, input.length()));
}
}
return chunks;
}

Related

Generate all possible string combinations by replacing the hidden “#” number sign

My task is to generates all possible combinations of that rows without the hidden # number sign. The input is XOXX#OO#XO and here is the example of what the output should be:
XOXXOOOOXO
XOXXOOOXXO
XOXXXOOOXO
XOXXXOOXXO
I am only allowed to solve this solution iteratively and I am not sure how to fix this and have been working on this code for a week now.
Here is my code:
import java.lang.Math;
public class help {
public static void main(String[] args) {
String str = new String("XOXX#OO#XO");
UnHide(str);
}
public static void UnHide(String str) {
//converting string to char
char[] chArr = str.toCharArray();
//finding all combinations for XO
char[] xo = new char[]{'X', 'O'};
int count = 0;
char perm = 0;
String s = "";
//finding amount of times '#' appears in string
for (int i = 0; i < str.length(); i++) {
if (chArr[i] == '#')
count++;
}
int[] combo = new int[count];
int pMax = xo.length;
while (combo[0] < pMax) {
// print the current permutation
for (int k = 0; k < count; k++) {
//print each character
//System.out.print(xo[combo[i]]);
perm = xo[combo[k]];
s = String.valueOf(perm);
char[] xoArr = s.toCharArray();
String strChar = new String(xoArr);
//substituting '#' to XO combo
for (int i = 0; i < chArr.length; i++) {
for (int j = 0; j < s.length(); j++) {
if (chArr[i] == '#') {
chArr[i] = xoArr[j];
strChar = String.copyValueOf(chArr);
i++;
}
}
i++;
if (i == chArr.length - 1) {
System.out.println(strChar);
i = 0;
}
}
}
System.out.println(); //print end of line
// increment combo
combo[count - 1]++; // increment the last index
//// if increment overflows
for (int i = count - 1; combo[i] == pMax && i > 0; i--) {
combo[i - 1]++; // increment previous index
combo[i] = 0; // set current index to zero
}
}
}
}
Since your input has 2 #'s, there are 2n = 4 permutations.
If you count from 0 to 3, and look at the numbers in binary, you get 00, 01, 10, and 11, so if you use that, inserting O for 0 and X for 1, you can do this using simple loops.
public static void unHide(String str) {
int count = 0;
for (int i = 0; i < str.length(); i++)
if (str.charAt(i) == '#')
count++;
if (count > 30)
throw new IllegalArgumentException("Too many #'s found. " + count + " > 30");
char[] buf = str.toCharArray();
for (int permutation = 0, end = 1 << count; permutation < end; permutation++) {
for (int i = buf.length - 1, bit = 0; i >= 0; i--)
if (str.charAt(i) == '#')
buf[i] = "OX".charAt(permutation >>> bit++ & 1);
System.out.println(buf);
}
}
Test
unHide("XOXX#OO#XO");
Output
XOXXOOOOXO
XOXXOOOXXO
XOXXXOOOXO
XOXXXOOXXO
You can iteratively generate all possible combinations of strings using streams as follows:
public static String[] unHide(String str) {
// an array of substrings around a 'number sign'
String[] arr = str.split("#", -1);
// an array of possible combinations
return IntStream
// iterate over array indices
.range(0, arr.length)
// append each substring with possible
// combinations, except the last one
// return Stream<String[]>
.mapToObj(i -> i < arr.length - 1 ?
new String[]{arr[i] + "O", arr[i] + "X"} :
new String[]{arr[i]})
// reduce stream of arrays to a single array
// by sequentially multiplying array pairs
.reduce((arr1, arr2) -> Arrays.stream(arr1)
.flatMap(str1 -> Arrays.stream(arr2)
.map(str2 -> str1 + str2))
.toArray(String[]::new))
.orElse(null);
}
// output to the markdown table
public static void main(String[] args) {
String[] tests = {"XOXX#OOXO", "XOXX#OO#XO", "#XOXX#OOXO#", "XO#XX#OO#XO"};
String header = String.join("</pre> | <pre>", tests);
String matrices = Arrays.stream(tests)
.map(test -> unHide(test))
.map(arr -> String.join("<br>", arr))
.collect(Collectors.joining("</pre> | <pre>"));
System.out.println("| <pre>" + header + "</pre> |");
System.out.println("|---|---|---|---|");
System.out.println("| <pre>" + matrices + "</pre> |");
}
XOXX#OOXO
XOXX#OO#XO
#XOXX#OOXO#
XO#XX#OO#XO
XOXXOOOXOXOXXXOOXO
XOXXOOOOXOXOXXOOOXXOXOXXXOOOXOXOXXXOOXXO
OXOXXOOOXOOOXOXXOOOXOXOXOXXXOOXOOOXOXXXOOXOXXXOXXOOOXOOXXOXXOOOXOXXXOXXXOOXOOXXOXXXOOXOX
XOOXXOOOOXOXOOXXOOOXXOXOOXXXOOOXOXOOXXXOOXXOXOXXXOOOOXOXOXXXOOOXXOXOXXXXOOOXOXOXXXXOOXXO
The process would probably be best to calculate the number of permutations, then loop through each to define what combination of characters to use.
For that, we'll have to divide the permutation number by some value related to the index of the character we're replacing, which will serve as the index of the character to swap it to.
public static void test(String word) {
// Should be defined in class (outside method)
String[] replaceChars = {"O", "X"};
char replCharacter = '#';
String temp;
int charIndex;
int numReplaceable = 0;
// Count the number of chars to replace
for (char c : word.toCharArray())
if (c == replCharacter)
numReplaceable++;
int totalPermutations = (int) Math.pow(replaceChars.length, numReplaceable);
// For all permutations:
for (int permNum = 0; permNum < totalPermutations; permNum++) {
temp = word;
// For each replacement character in the word:
for (int n = 0; n < numReplaceable; n++) {
// Calculate the character to swap the nth replacement char to
charIndex = permNum / (int) (Math.pow(replaceChars.length, n))
% replaceChars.length;
temp = temp.replaceFirst(
replCharacter + "", replaceChars[charIndex]);
}
System.out.println(temp);
}
}
Which can produces:
java Test "#TEST#"
OTESTO
XTESTO
OTESTX
XTESTX
This can also be used with any number of characters, just add more to replaceChars.

Algorithm - Lexicographically largest possible magical substring

I am working on this magical sub-string problem.
Magical binary strings are non-empty binary strings if the following two conditions are true:
The number of 0's is equal to the number of 1's.
For every prefix of the binary string, the number of 1's should not be less than the number of 0's.
I got stuck on how to proceed further in my Java program.
Here is my program:
static String findLargest(String str) {
String[] splits = str.split("");
Set<String> set = new LinkedHashSet<String>();
for (int i = 0; i < splits.length; i++) {
if (splits[i].equals("0")) {
continue;
}
int zeros = 0;
int ones = 0;
StringBuilder sb = new StringBuilder("");
for (int j = i; j < splits.length; j++) {
if (splits[j].equals("0")) {
zeros++;
} else {
ones++;
}
sb.append(splits[j]);
if (zeros == ones && ones >= zeros) {
set.add(sb.toString());
}
}
}
set.remove(str);
List<String> list = new ArrayList<String>(set);
System.out.println(list);
return null;
}
Using this program I am able to get the magical sub-strings for the given input String 11011000 as [10, 101100, 1100] in my list variable.
Now from here I am struggling how to remove the invalid entry of 101100 from my list and then use the elements 10, 1100 to swap from my input 11011000 to get the final result as 11100100
Also please guide me if there is any other alternate approach.
If your question is about only eliminating the unwanted "101100" from the result, here is the answer
import java.util.ArrayList;
import java.util.HashMap;
import java.lang.*;
import java.util.Set;
import java.util.*;
public class HelloWorld{
public static void main(String []args){
findLargest("11011000");
}
public static String findLargest(String str) {
String[] splits = str.split("");
Set<String> set = new LinkedHashSet<String>();
for (int i = 0; i < splits.length; i++) {
if (splits[i].equals("0")) {
continue;
}
int zeros = 0;
int ones = 0;
StringBuilder sb = new StringBuilder("");
for (int j = i; j < splits.length; j++) {
if (splits[j].equals("0")) {
zeros++;
} else {
ones++;
}
sb.append(splits[j]);
if (zeros == ones && ones >= zeros) {
set.add(sb.toString());
j = i +1; // RESET THE INDEX ELEMENT TO SKIP THE SUBSTRING FROM CONSIDERATION
break; // BREAK FROM THE LOOP
}
}
}
set.remove(str);
List<String> list = new ArrayList<String>(set);
System.out.println(list);
return null;
}
}
I can provide some points.
First, get all the magical substrings and store them as a pair of start and end index(l, r) in a list;
Second, sort the list based on index l;
Those who can be potentially swapped substring can get from the same index l. look at the example given "11011000"
the list will have (0,7),(1,2),(1,6),(3,6),(4,5)
obviously only potential swap is among (1,2)(1,6)
deal these substrings have same index l will help find potential swapping substrings, sort them to find the maximum order.
class Pair{
int start;
int end;
}
public List<Pair> findmagicalPairs(String binString){
List<Pair> magicPairs = new ArrayList<Pair>();
for(int start=0;start<binString.length()-1;start++){
int ones=0;
int zeros=0;
for(int i=start; i<binString.length();i++){
if(binString.charAt(i) == '1'){
ones++;
} else if(binString.charAt(i)=='0'){
zeros++;
}
if(ones == zeros){ //check if magical
Pair temp=new Pair();
temp.start=start;
temp.end =i;
magicPairs.add(temp);
}
}
}
return magicPairs;
}
public String largestMagical(String binString) {
// Write your code here
List<Pair> allPairs = findmagicalPairs(binString);
String largest=binString;
//check by swapping each pairs
for(int i=0;i<allPairs.size()-1;i++){
for(int j=i+1;j<allPairs.size()-1;j++){
if(allPairs.get(i).end+1 == allPairs.get(j).start){
//consecutive Pair so swap and see largest
int index = allPairs.get(j).start;
String swapped = binString.substring(0,allPairs.get(i).start)+binString.substring(allPairs.get(j).start,allPairs.get(j).end+1)+binString.substring(allPairs.get(i).start,allPairs.get(i).end+1)+binString.substring(allPairs.get(j).end+1);
largest = LargestString(largest, swapped);
} else {
//else ignore
}
}
}
return largest;
}
public String LargestString(String first, String second){
if(first.compareTo(second)>0){
return first;
} else {
return second;
}
}
JavaScript Code!
const largestMagical = (binString) => {
//console.log({ binString });
const len = binString.length;
const height = Array(len + 1).fill(0),
num = { 1: 1, 0: -1 },
marked = Array(len + 1).fill(false),
sameHeights = {};
let i,
j,
result = "";
for (i = 1; i <= len; ++i) {
height[i] = height[i - 1] + num[binString[i - 1]];
}
//console.log({ height });
for (i = 0; i <= len; ++i) {
if (marked[i]) continue;
marked[i] = true;
sameHeights[i] = [i];
for (j = i + 1; j <= len; ++j) {
if (height[j] < height[i]) break;
if (height[j] === height[i]) {
sameHeights[i].push(j);
marked[j] = true;
}
}
}
//console.log({ sameHeights });
for (let k in sameHeights) {
const leng = sameHeights[k].length;
let startId, midId, endId;
for (startId = 0; startId < leng - 2; ++startId) {
for (midId = startId + 1; midId < leng - 1; ++midId) {
for (endId = midId + 1; endId < leng; ++endId) {
const start = sameHeights[k][startId],
mid = sameHeights[k][midId],
end = sameHeights[k][endId];
//console.log({start, mid, end});
const swapped =
binString.substring(0, start) +
binString.substring(mid, end) +
binString.substring(start, mid) +
binString.substring(end, len);
//console.log({swapped});
if (swapped > result) result = swapped;
}
}
}
}
return result;
};
console.log(largestMagical("1010111000"));
console.log(largestMagical("11011000"));

How to define an exponent as the index position of a string

I am trying to make an int method that converts a binary number into a base 10 number. I think my loop is structured correctly, but I cant figure out how to relate index position to an exponent. Basically if there is a '1' in the string, i want to return it as 2 to the power of whatever the index position of that char is. Also, this would require me to inverse the index (so that the 0 position is the rightmost char of the string. Here is what I have so far:
public static int BinaryToNumber(String numberInput)
{
int len = numberInput.length();
for(int i=len-1; i<len; i--)
{
if(i == '1');
{
return n;
}
}
return 0;
}
Thank you in advance!
I would prefer the Java built-in routines when possible - as I said in my comment Integer.parseInt(numberInput, 2);. By convention, Java method names begin with a lower case letter. Finally, you can fix your code (and I added a small test harness) with something like,
public static int binaryToNumber(String numberInput) {
if (numberInput == null) {
return 0;
}
int ret = 0;
char[] ni = numberInput.trim().toCharArray();
for (int i = 0; i < ni.length; i++) {
if (ni[i] == '1') {
// This is 2 ^ (n) where (n) is based on the position from the right.
ret += 1 << ni.length - i - 1;
}
}
return ret;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
String t = Integer.toBinaryString(i);
System.out.printf("%s = %d%n", t, binaryToNumber(t));
}
}
this is my implementation for the problem
public static void main(String[] args) {
String str = "100101";
System.out.println(toDecimal(str));
}
private static int toDecimal(String binary) {
int result = 0;
for(int i = 0; i < binary.length(); i++) {
int a = (int) binary.charAt(i) - 48;
double secondPart = 1 << (binary.length()-1) - i;
result += a * secondPart;
}
return result;
}
I hope that helps
Salam

Alternating characters of two different inputs

I want to take two strings and alternate the characters into a new string using a for method.
Example: "two" and "one"
Result: "townoe"
This is what I have so far, and I really don't know how to finish it.
public class Alternator {
String alternate(String a, String b) {
String s = "";
for (int i = 0; i < a.length(); i++) {
s += i;
System.out.println(s);
}
return null;
}
}
public class Alternator{
public static String alternate(String a, String b){
String s = "";
int i = 0;
while (i < a.length() && i < b.length()){
s += a.charAt(i) +""+ b.charAt(i);
i++;
}
while (i < a.length() ){
s += a.charAt(i);
i++;
}
while (i < b.length()){
s += b.charAt(i);
i++;
}
return s;
}
public static void main(String[] args){
String a = "two", b = "one";
String s = Alternator.alternate(a,b);
System.out.println(s);
}
}
To use for loop instead of while loop, simply remove all while lines with for lines like the following, then remove the i++ line from each while loop
for(; i < a.length() && i < b.length(); i++){
//the inside of the loop MINUS THE LINE i++
}
for(; i < a.length(); i++){
//the inside of the loop MINUS THE LINE i++
}
for(; i < b.length(); i++){
//the inside of the loop MINUS THE LINE i++
}
Here is some compact way of doing that:
String alternate(String a, String b) {
StringBuilder builder = new StringBuilder();
int smallerStringLength = Math.min(a.length(), b.length());
for (int i = 0; i < smallerStringLength; i++) {
builder.append(a.charAt(i));
builder.append(b.charAt(i));
}
return builder.toString();
}
Or even more optimized:
String alternate(String first, String second) {
char[] firstChars = first.toCharArray();
char[] secondChars = second.toCharArray();
int smallerCharsCount = Math.min(firstChars.length, secondChars.length);
StringBuilder builder = new StringBuilder(smallerCharsCount * 2);
for (int i = 0; i < smallerCharsCount; i++) {
builder.append(firstChars[i]);
builder.append(secondChars[i]);
}
return builder.toString();
}
This will work if string are of same length or of the different lengths.
static void mergeStrings(String a, String b) {
StringBuilder mergedBuilder = new StringBuilder();
char[] aCharArr = a.toCharArray();
char[] bCharArr = b.toCharArray();
int minLength = aCharArr.length >= bCharArr.length ? bCharArr.length : aCharArr.length;
for (int i=0; i<minLength; i++) {
mergedBuilder.append(aCharArr[i]).append(bCharArr[i]);
}
if(minLength < aCharArr.length) {
mergedBuilder.append(a.substring(minLength));
}
else{
mergedBuilder.append(b.substring(minLength));
}
Systemout.println(mergedBuilder.toString());
}
Assuming that the two strings are the exact same length, you can do the following. If they are different length, then currently your prompt doesn't say how you want the resultant string to be set up.
public class Alternator {
String alternate(String a, String b) {
String s = "";
for (int i = 0; i < 2*a.length(); i++) {
if (i%2==0) // modular arithmetic to alternate
s += a.charAt(i/2); // Note the integer division
else
s += b.charAt(i/2);
}
System.out.println(s);
return s;
}
}
Alternatively, even easier, but the index i doesn't mark the length of your string s:
public class Alternator {
String alternate(String a, String b) {
String s = "";
for(int i = 0; i < a.length(); i++){
s += a.charAt(i);
s += b.charAt(i);
}
return s;
}
}
Use this:
String alternate(String a, String b){
StringBuilder builder = new StringBuilder();
final int greaterLength = a.length() > b.length() ? a.length() : b.length();
for(int i = 0; i < greaterLength; i++){
if (i < a.length()) {
builder.append(a.charAt(i));
}
if (i < b.length()) {
builder.append(b.charAt(i));
}
}
return builder.toString();
}
It uses the String.charAt method to obtain letters, and a StringBuilder to create the string.
(When given two strings of non-equal length, this returns an alternation of the first two chars, and then does just the remaining string. EG: Hello and Hi --> HHeillo)
According to the comments I've read, you are having trouble understanding for loops, and how to use them with strings.
For loops are most often used to iterate over arrays, or to perform a task a given number of times.
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
This would give the output
0
1
2
3
4
For loops start at the value of the initializer, the first thing you put in int i = 0;
They then check the expression, the second part of the for loop, and if it returns true, it executes all of the code inside the braces. i < 5;
Once it has done that, it runs the incrementor, the last part of the for loop. i++
After that, it checks the expression again. I guess you can see where this is going. Until the expression returns false, everything inside the curly braces of the for loop gets executed over and over again.
Strings can be iterated over with a for loop, but you can't reference it like an array using array[index]. You have to either convert it into an array, using .toCharArray() on your String, and return the result to an empty char array char[], or use the .charAt(index) method on your string.
This code will go over a string, and output each character, one by one:
for (int i = 0; i < myString.length(); i++) {
System.out.println(myString.charAt(i));
}
If the string had a value of "Hello", the output would be:
H
e
l
l
o
Using this, instead of outputting the characters using System.out.println();, we can put them into an empty string, using +=:
myOtherString += myString.charAt(i);
That means, if we want to go over two Strings at a time, and alternate them, like you do, we can iterate over two strings at the same time, and add them to a new string:
myAlternatedString += myString.charAt(i);
myAlternatedString += myOtherString.charAt(i);
if MyString was still "Hello" and myOtherString was "World", the new string would be:
Hweolrllod
following code reads 2 different inputs and merges into a single string.
public class PrintAlternnateCharacterString {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String a = in.next();
String b = in.next();
String mergedString = "";
int lenA = a.length();
int lenB = b.length();
if (lenA >= lenB) {
for (int i = 0; i < lenA; i++) {
if (i < lenB) {
mergedString += a.charAt(i) + "" + b.charAt(i);
} else {
mergedString += a.charAt(i);
}
}
}
if (lenB > lenA) {
for (int i = 0; i < lenB; i++) {
if (i < lenA) {
mergedString += a.charAt(i) + "" + b.charAt(i);
} else {
mergedString += b.charAt(i);
}
}
}
System.out.println("the merged string is-->" + mergedString);
}
}
public static String stringConcate(String str1,String str2){
String str3="";
if(str1!=null && str2!=null && !str1.isEmpty() && !str2.isEmpty()){
if(str1.length()==str2.length()){
for(int i=0;i<=str1.length()-1;i++){
str3+=str1.charAt(i);
str3+=str2.charAt(i);
}
}
if(str1.length()>str2.length()){
for(int i=0;i<=str1.length()-1;i++){
str3+=str1.charAt(i);
if(i<str2.length()){
str3+=str2.charAt(i);
}
}
}
if(str2.length()>str1.length()){
for(int i=0;i<=str2.length()-1;i++){
if(i<str1.length()){
str3+=str1.charAt(i);
}
str3+=str2.charAt(i);
}
}
}
return str3;
}
String str1 = "one"; String str2 = "two";
StringBuilder sb = new StringBuilder();
int i = 0;
for (; i < str1.length() && i < str2.length(); i++) {
sb.append(str1.charAt(i)).append(str2.charAt(i));
}
for(; i < str1.length(); i++) {
sb.append(str1.charAt(i));
}
for(; i < str2.length(); i++) {
sb.append(str2.charAt(i));
}
System.out.println("result = " + sb.toString());// otnweo
This will handle for different length too
This could be donw with very simple if...else.
public static void main(String... args) {
int[] one = { 1, 2, 3 };
int[] two = { 44, 55, 66, 77, 88 };
System.out.println(Arrays.toString(alternate(one, two)));
}
public static int[] alternate(int[] one, int[] two) {
int[] res = new int[one.length + two.length];
for (int i = 0, j = 0, k = 0; i < res.length; i++) {
if (i % 2 == 0)
res[i] = j < one.length ? one[j++] : two[k++];
else
res[i] = k < two.length ? two[k++] : one[j++];
}
return res;
}
Output:
[1, 44, 2, 55, 3, 66, 77, 88]

Swapping elements in ArrayList

I want to write a method, which takes a String and swaps each pair of characters in it and then concatenates them into a new String. Please let me know how to fix this code (or write a new better one):
static String s;
public static void proc(String w) {
ArrayList k = new ArrayList();
ArrayList m = new ArrayList();
System.out.println(w.length());
int j = 0;
//test arraylist to check if string is written into arraylist
for (int i = 0; i < w.length(); i++){
k.add(w.charAt(i));
}
String p = k.get(2).toString();
System.out.println(p);
//here starts the logic of my app
for (int n = 0; n < w.length(); n++){
String v = k.get(n).toString();
if (n == 0){
m.add(1, v);
}
else if (n == 1){
m.add(0, v);
}
else if ((n % 2) == 0){
m.add(n+1, v);
}
else {
m.add(n, v);
}
}
}
public static void main(String[] args){
s = "tests";
proc(s);
}
Hi this is not a homework, but am doing exercises from a book. Anyway using code provided by Jon managed to work on my own - it may be not as much elegant but is doing the job using dynamic sizing as well:
public static void proc(String w) {
ArrayList k = new ArrayList();
ArrayList g = new ArrayList();
String h = "";
for (int i = 0; i < w.length(); i++){
char temp = w.charAt(i);
k.add(i, temp);
}
for (int i = 0; i < w.length(); i++){
if (i == 0){
h = k.get(1).toString();
g.add(h);
}
else if (i == 1){
h = k.get(0).toString();
g.add(h);
}
else if ((i % 2) == 0){
h = k.get(i+1).toString();
g.add(h);
}
else if ((i % 2) == 1){
h = k.get(i-1).toString();
g.add(h);
}
}
System.out.println(g.toString());
}
public static void main(String[] args){
s = "test";
proc(s);
}
I haven't tried to go through exactly how your code is trying to work, but it looks unnecessarily complicated to me. Given that you don't need dynamic sizing, you can do this more easily with an array:
public static String swapPairs(String input) {
char[] chars = input.toCharArray();
for (int i = 0; i < chars.length - 1; i += 2) {
char tmp = chars[i];
chars[i] = chars[i + 1];
chars[i + 1] = tmp;
}
return new String(chars);
}
Note that while this will work for "simple" characters (where each element of the array is independent of the rest), it doesn't try to take any form of "composite" characters into consideration, such as characters formed from two UTF-16 code units (surrogate pairs) or combined characters such as "e + acute accent". Doing this sort of contextually-aware swapping would take a lot more effort.
This looks like homework, so I'll limit my answer to a couple of hints.
I would accumulate the result in a StringBuilder (called sb in what follows).
I would have a loop (for i = 0; i < w.length(); i += 2). In this loop I would do two things:
if i + 1 is within the bounds of the string, I'd append the i + 1-th character to sb;
append the i-th character to sb.
At the end, call sb.toString().

Categories