I'm trying to learn java using the basic tictactoe example, but just for fun I wanted to design an ai later.
I'm having an issue flattening the char[] to Array. I'm so confused is there a better way to do this?
Do I need to create another method to specific convert this char[] to array?
ERROR:
The method mapToCharater(Charater.class::cast) is undefined for the type Stream<Object>
CONSOLE OUTPUT
EDIT:
Exception in thread "main" java.lang.ClassCastException: Cannot cast [C to java.lang.Character
at java.base/java.lang.Class.cast(Class.java:3610)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:550)
at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:517)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:523)
at aiPackage.game.Board.<init>(Board.java:17)
at aiPackage.game.Tester.main(Tester.java:15)
package aiPackage.game;
import java.util.*;
import java.util.stream.*;
public class Board {
//declaration of private members
private int score;
private Board previousB = null;
private char[][] thisBoard;
// ------------------------------------------------------;
public Board (char [][] inBoard) {
//what
//char[] flats = flatten(inBoard).map
Object[] flats = flatten(inBoard).map(Character.class::cast).toArray(); //mapToCharater(Charater.class::cast).toArray();
int[] flat = flatten(inBoard).mapToInt(Integer.class::cast).toArray();
int flatSize = flat.length;
// ------------------------------------------------------;
//check if square
if (Math.sqrt(flatSize)==3) {
if(inBoard.length == 3) {
thisBoard = inBoard;
}
else {
System.out.println("The array isnt a square.");
}
}
else {
System.out.println("It doesnt match the dimensions of a tictactoe board.");
}
//we'll assume its not gonna break from the input atm
setThisBoard(inBoard);
}
//https://stackoverflow.com/questions/31851548/flatten-nested-arrays-in-java
private static Stream<Object> flatten(Object[] array) {
return Arrays.stream(array)
.flatMap(o -> o instanceof Object[]? flatten((Object[])o): Stream.of(o));
}
public Board getPreviousB() {
return previousB;
}
public void setPreviousB(Board previousB) {
this.previousB = previousB;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public char[][] getThisBoard() {
return thisBoard;
}
public void setThisBoard(char[][] thisBoard) {
this.thisBoard = thisBoard;
}
//if there are even elements on the board, its x's turn
public ArrayList<Board> getChildren(){
return null;
}
public void checkIfEnded() {
for (int i = 0; i < 3; i++) {
//check row wins
if (thisBoard[i][0] != '-' &&
thisBoard[i][0] == thisBoard[i][1] &&
thisBoard[i][1] == thisBoard[i][2]) {
//updates score based on winner
if (thisBoard[0][2] == 'x') {
updateScore(1);
}
else {
updateScore(-1);
}
return;
}
//check column wins
if (thisBoard[i][0] != '-' &&
thisBoard[0][i] == thisBoard[1][i] &&
thisBoard[1][i] == thisBoard[2][i]) {
//updates score based on winner
if (thisBoard[0][2] == 'x') {
updateScore(1);
}
else {
updateScore(-1);
}
return;
}
}
//check diagnals
if (thisBoard[0][0] != '-' &&
thisBoard[0][0] == thisBoard[1][1] &&
thisBoard[1][1] == thisBoard[2][2]) {
//updates score based on winner
if (thisBoard[0][2] == 'x') {
updateScore(1);
}
else {
updateScore(-1);
}
return;
}
if (thisBoard[0][2] != '-' &&
thisBoard[0][2] == thisBoard[1][1] &&
thisBoard[1][1] == thisBoard[2][0]) {
//updates score based on winner
if (thisBoard[0][2] == 'x') {
updateScore(1);
}
else {
updateScore(-1);
}
return;
}
}
//outputs the board's contents as a string
public String toString() {
String result = "";
//gets the previous board's info to output first
result = "" + previousB;
//gets this boards info to output
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
result += thisBoard[i][j] + " ";
}
//adds newline char at end of row
result += "\n";
}
//adds an extra newline char at end of board
result += "\n";
return result;
}
private void updateScore(int win) {
if (win > 0) {
score = 1;
} else if(win == 0){
score = 0;
}else {
score = -1;
}
}
}
package aiPackage.game;
import java.util.*;
public class Tester {
private static Board start;
private static Board finish;
public static void main(String[] args) {
char temp [][] = {
{'o','-','x'},
{'-','-','-'},
{'-','-','-'}};
start = new Board(temp);
finish = minMax(start.getChildren());
System.out.println();
}
public static Board minMax(ArrayList<Board> resultList) {
return null;
}
}
The reason it fails is because Arrays.stream() does not accept char[] The following should work.
Arrays.stream(inBoard)
.flatMap(x -> (Stream<Character>)new String(x).chars().mapToObj(i->(char)i))
.collect(Collectors.toList())
check out
Want to create a stream of characters from char array in java for
and
Why is String.chars() a stream of ints in Java 8?
for better understanding.
Your problem is here:
private static Stream<Object> flatten(Object[] array) {
return Arrays.stream(array)
.flatMap(o -> o instanceof Object[]? flatten((Object[])o): Stream.of(o));
}
You are using the comparation with Object[] to decompose the array, but in reality is a char[].
That makes that your result instead of being an Stream Object is a Stream char[].
The main point is that you can't use a Stream to work with primitives. Stream only works with Objects and char is a primitive.
you can manually flatten the char[][] using a classic loop.
flattening char[][] or impossible doesn't count
char[] array = Stream.of( inBoard ).flatMap( arr -> Stream.of( String.valueOf( arr ) ) )
.collect( Collectors.joining() ).toCharArray(); // [o, -, x, -, -, -, -, -, -]
Related
I'm doing a homework task that is:
Find a unique vowel in the string that is preceded by a consonant, and this consonant is preceded by a vowel.
Example: "eeaaAOEacafu"
Result is: u
What i already did:
Main.class
public class Principal {
public static void main(String[] args) {
// TODO Auto-generated method stub
Stream str = new Stream();
str.setText("eeaaAOEacafu");
System.out.println(str.returnChar(str.getVowel()));
}
Stream.class
public class Stream {
String text;
char vowel;
public String getText() {
return texto;
}
public void setText(String text) {
this.text = text;
}
public char getVowel() {
return vowel;
}
public void setVowel(char vowel) {
this.vowel = vowel;
}
public boolean isVowel(String str) {
str = str.toLowerCase();
for(int i=0; i<str.length(); i++) {
char c = str.charAt(i);
if(c=='a' || c=='e' || c=='i' || c=='o'|| c=='u') {
return true;
} else {
return false;
}
}
return false;
}
public char returnChar(String str) {
char last;
char next;
char result = '0';
int j=1;
for(int i=0; i<str.length(); i++) {
last = str.charAt(i-1);
next = str.charAt(i+1);
j++;
if(!vogal(str.charAt(i))) {
if(vogal(last) && vogal(next)) {
result = next;
}
}
}
this.setVowel(result);
return result;
} }
This returns: String index out of range: -1
This j=1, was to fix this -1 out of range. It fix but i got new one: out of range 11 because of the next.
The thing is: I have to use pure java and no API.
Can you guys help me?
use regular expressions for the test and locating the character
[aeiouAEIOU][bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ]([aeiouAEIOU])
Use a String as a cheap map to keep track of which vowels you've already seen. Also, keep a count of how many consecutive consonants you've encountered. Then, when you hit a vowel that you haven't seen before preceded by a single consonant you've found your answer.
public static void main(String[] args)
{
String s = "eeaaAOEacafu".toLowerCase();
int consCount = 0;
String seenVowels = "";
for(int i=0; i<s.length(); i++)
{
char c = s.charAt(i);
if("aeiou".indexOf(c) >= 0)
{
if(seenVowels.indexOf(c) == -1)
{
if(consCount == 1)
{
System.out.println("Result: " + c);
break;
}
seenVowels += c;
}
consCount = 0;
}
else consCount++;
}
}
Output:
Result: u
The above works if we take 'unique' to mean that we haven't seen the vowel before. If the vowel has to be unique within the input string then things are a little more complicated. Now we have to keep track of each vowel that meets the original criteria, but remove the solution if we subsequently encounter another instance of the same vowel.
Here's some code to illustrate:
public static void main(String[] args)
{
String s = "afuxekozue".toLowerCase();
int consCount = 0;
String seenVowels = "";
String answer = "";
for(int i=0; i<s.length(); i++)
{
char c = s.charAt(i);
if("aeiou".indexOf(c) >= 0)
{
if(seenVowels.indexOf(c) == -1)
{
if(consCount == 1)
{
answer += c;
}
seenVowels += c;
}
else if(answer.indexOf(c) >= 0)
{
answer = answer.replaceAll(String.valueOf(c), "");;
}
consCount = 0;
}
else consCount++;
}
if(answer.length() > 0)
System.out.println("Result: " + answer.charAt(0));
}
Output:
Result: o
i'm writing a program in java that checks if a letter appers exactly twice, i was able to write it but my problem is that for some words the code doesn't check if the letter appear exactly twice.
here is my code:
public class Test {
public static void main(String[] args) {
isDoubloon("abba");
isDoubloon("Shanghaiingss");/*it still prints out true though 's' does appear exactly twice*/}
//checks if every letter appears twice in a word
public static void isDoubloon(String s){
String l=s.toLowerCase();
int count=0;
for(int i= 0; i<l.length()-1;i++){
for(int j=i+1;j<l.length();j++){
if(l.charAt(i)==l.charAt(j)) count++;
}
}
if(count%2==0){
System.out.println("True, This is a doubloon");
}else
System.err.println("False, This is not a doubloon");
}}
Your whole logic is not correct. You have to check for every letter in your text if it occurs twice.
Try this:
String l=s.toLowerCase();
boolean check = true;
for(int i= 0; i<l.length();i++){
int count=0;
for(int j=0;j<l.length();j++){
if(l.charAt(i)==l.charAt(j)) count++;
}
if (count != 2) {
check = false;
break;
}
}
if(check==true){
System.out.println("True, This is a doubloon");
}else
System.out.println("False, This is not a doubloon");
}
Your code counts how often each letter occurs (-1) and adds all this values. If the result is even you imply that each letter is exactly twice in the word. That cannot work.
Simply try the word "aaabbbb". (your code think it is a doubloon)
So you need to check if no character occurs exactly twice and that for each character separately.
You could do it this way:
public static void main(String[] args) {
if(isDoubloon("Shanghaiingss")){
System.out.println("True, This is a doubloon");
}else{
System.err.println("False, This is not a doubloon");
}
}
public static boolean isDoubloon(final String s) {
final String l = s.toLowerCase();
for (int i = 0; i < l.length(); i++) {
int count = 0;
for (int j = 0; j < l.length(); j++) {
if (l.charAt(i) == l.charAt(j)) {
count++;
if (2 < count) {
return false; // more than twice
}
}
}
if (1 == count) {
return false; // character occurs only once
}
}
return true;
}
This algorithm is similar to yours. But it is far from fast O(n²). Is you need it you can implement it faster O(n) but you would need some extra space.
The main flaw here is that you are using a single "count" variable when you want to do a count for each letter.
I would suggest using a map to hold a count for each letter, loop over the list and add each letter to your map and finally iterate over the map and confirm all values are 2.
public static void isDoubloon(String s){
String l=s.toLowerCase();
Map<Character, Integer> counts = new HashMap();
for(int i= 0; i<l.length()-1;i++){
int prevValue = counts.getOrDefault(l.charAt(i), 0);
counts.put(l.charAt(i), prevValue + 1);
}
for (Map.Entry<Character, Integer> entry: counts.entrySet()) {
if (entry.getValue() != 2) {
System.err.println("False, This is not a doubloon");
}
}
System.out.println("True, This is a doubloon");
}
Other solution
private boolean isDoubloon(String s) {
String convertWord = s.toLowerCase();
char[] letter = convertWord.toCharArray();
int[] count = new int[26];
for (int letters = 0; letters < letter.length; letters++) {
char index = letter[letters];
count[index - 97]++;
}
for( int i = 0; i < 26; i++ ) {
if (count[i] != 0 && count[i] != 2) return false;
}
return true;
}
public static boolean isDoubloon(String s) {
if (s.length() %2 != 0)
return false;
String str = s.toLowerCase();
while (str.length() > 0) {
int index2 = str.indexOf(str.charAt(0), 1);
if (index2 == -1) {
return false;
}
int index3 = str.indexOf(str.charAt(0), index2 + 1);
if (index3 != -1) {
return false;
}
str = str.substring(1, index2) + str.substring(index2 + 1);
}
return true;
}
Obligatory Java Streams examples:
groupingBy() and counting()
public static boolean isDoubloon(String str) {
return
// Stream over chars, and box to Integer
// These will be the ASCII values of the chars
!str.chars().boxed()
// Group by identity
.collect(Collectors.groupingBy(Function.identity(),
// and map each key to the count of characters
Collectors.counting()))
// We now have a Map<Integer, Long>, the Integer being the character
// value and the Long being the number of occurrences.
// Stream over the Map's values
.values().stream()
// Retain all values unequal to 2
.filter(i -> !Objects.equals(i, 2L))
// Shortcut if found and check if a value is present
.findAny().isPresent();
// If a value is present, that means that there are one or more
// characters with less or more than two occurrences.
}
https://ideone.com/PT8sQi
distinct() and count()
public static boolean isDoubloon(String str) {
long distinct = str.chars().distinct().count();
long length = str.length();
return (length % 2 == 0 && length / 2 == distinct);
}
https://ideone.com/UaOKDF
I have a quick question. How would I find the most common character in a string in Java. I know logically how to do it, but I am not sure if my syntax in correct:
public class HelloWorld {
public static void main(String[] args){
String votes = "ABBAB";
char[] StoringArray = votes.toCharArray();
int numOFB = 0;
int numOFA = 0;
if (StoringArray.contains("A")) {
numOFA++;
} else if (StoringArray.contains("B")) {
numOFAB++;
}
if (numOFA = numOFB) {
System.out.println("Tie");
} else if (numOFA > B) {
System.out.println("A");
} else {
System.out.println("B");
}
}
}
Could anyone help me with how to correctly do this in Java?
You can not compare char Array with string, below logic should work and give you what you need:
public static void main(String[] args){
String votes = "ABBAB";
char[] storingArray = votes.toCharArray();
int numOFB = 0;
int numOFA = 0;
for(char c : storingArray) {
if(c == 'A') {
numOFA++;
}
if(c == 'B') {
numOFB++;
}
}
if (numOFA == numOFB) {
System.out.println("Tie");
} else if (numOFA > numOFB) {
System.out.println("A");
} else {
System.out.println("B");
}
}
There are couple of mistakes in your code:
You can not use if (numOFA = numOFB) it is not valid expression. You should use == to compare
You can not compare char Array with contains method. It should be used on String object
As the comments said; it looks like you're counting the number of A's or B's, not the longest substring. Are you only analyzing a String composed of A's and B's?
Also, you're using = to check for equality when you should be using ==. I would recommend using an IDE like Eclipse which would show you when you're doing this.
Edit: also, you're not looping through the array. You're just checking if the String contains an A or a B and adding 1 if it does. You need to loop through the entire array.
Actually, I was working with it, and I found this is the nicest way to do it:
String votes = "ABBAB";
char[] StoringArray = votes.toCharArray();
int B = 0;
int A = 0;
for (int i = 0; i < StoringArray.length; i ++) {
if (StoringArray[i] == 'A') {
A++;
} else if (StoringArray[i] == 'B') {
B++;
}
}
if (A == B) {
System.out.println("Tie");
} else if (A > B) {
System.out.println("A");
} else {
System.out.println("B");
}
I would give you a more abstract solution:
public class Counter{
private char c;
private int count;
Counter(char c, int count){
this.c=c;
this.count=count;
}
public char getC() {
return c;
}
public void setC(char c) {
this.c = c;
}
public int getCount() {
return count;
}
public void addOcurrence() {
this.count++;
}
#Override
public boolean equals(Object obj) {
if(obj!=null)
if(((Counter)obj).getC()== this.c)
return true;
return false;
}
}
public static void main(String[] args){
String votes = "whateveryouwanttoputhereorcanbefromaparameter";
char[] storingArray = votes.toCharArray();
List<Counter> listCounter = new ArrayList<Counter>();
for(char aChar : storingArray){
Counter compareCounter = new Counter(aChar,1);
if(listCounter.contains(compareCounter)){
listCounter.get(listCounter.indexOf(compareCounter)).addOcurrence();
}else{
listCounter.add(compareCounter);
}
}
Counter max = listCounter.get(0);
for( Counter c : listCounter){
if(c.getCount() > max.getCount()){
max = c;
}
}
System.out.println("the character with more ocurrence is: "+max.getC());
}
I came across a post showing how to arrange char array by alphabet order.
seeing this can be done, I want to output the alphabetical order of each character of the input string, in order of the characters of the input string.
I'm a bit stuck. I can get the string reordered alphabetically, but I don't know what to do next.
example is 'monkey' to '354216'
because 'ekmnoy' e is alphabetically first from the set of given characters so e = 1 , k is the second alpha char when sorted so k = 2, and so on.
if you cannot understand I can provide more example to make things clear out.
Code
String str = "airport";
Character[] chars = new Character[str.length()];
for (int z = 0; z < chars.length; z++) {
chars[z] = str.charAt(z);
}
Arrays.sort(chars, new Comparator<Character>() {
public int compare(Character c1, Character c2) {
int cmp = Character.compare(
Character.toLowerCase(c1.charValue()),
Character.toLowerCase(c2.charValue()));
if (cmp != 0) {
return cmp;
}
return Character.compare(c1.charValue(), c2.charValue());
}
});
StringBuilder sb = new StringBuilder(chars.length);
for (char c : chars) {
sb.append(c);
}
str = sb.toString();
System.out.println(sb);
Output
aioprrt
expected output
Orange -> aegnOr
561432 - 123456
Monkey -> ekMnoy
354216 -> 123456
I dont know what you want to do with double characters, but if you add this few lines to your code at the end you are getting the right result. Iterate over the sorted String and replace the charakters in the original String with their indices in the sorted String.
String originalStr = "airport";
for(int i = 0; i<str.length(); i++) {
originalStr = originalStr.replace(str.charAt(i), String.valueOf(i+1).charAt(0));
}
System.out.println(originalStr);
Output: 1254357
If you want to get the output: 1254367 use replaceFirst:
originalStr = originalStr.replaceFirst(String.valueOf(str.charAt(i)), String.valueOf(i+1));
Input:Orange
Output:561432
Input:Monkey
Output:354216
The whole code:
String str = "airport";
String originalStr = str; //creat a backup of str because you change it in your code
Character[] chars = str.toCharArray();
Arrays.sort(chars, new Comparator<Character>() {
public int compare(Character c1, Character c2) {
int cmp = Character.compare(
Character.toLowerCase(c1.charValue()),
Character.toLowerCase(c2.charValue()));
if (cmp != 0) {
return cmp;
}
return Character.compare(c1.charValue(), c2.charValue());
}
});
str = String.valueOf(chars);
System.out.println(str);
//Iterate over the sorted String and replace the charakters in the original String with their indices in the sorted String
for(int i = 0; i<str.length(); i++) {
originalStr = originalStr.replaceFirst(String.valueOf(str.charAt(i)), String.valueOf(i+1));
}
System.out.println(originalStr);
Once you have arranged the characters in order (in a different array from the original) then create a third array by walking the original string and choosing the index of each character from te sorted string.
input: edcba
sorted: abcde
index: 01234
Pseudocode...
for( int i = 0; i < input.length(); i++ ) {
index[i] = sorted.indexOf(input[i]);
}
Result should be 43210 with the given input.
Note that strings with more than 10 characters will result in ambiguous output, which can be handled by inserting spaces in the output. Example:
abcdefghijk ->
012345678910
You can use this below code:
package Test;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
public class Arrange {
public static void main(String[] args) {
String str = "money";
List<Test> strs=new LinkedList<Test>();
List<Test> final_result=new LinkedList<Test>();
for(int i=0;i<str.length();i++)
{
Test t=new Test(i, ""+str.charAt(i), 0);
strs.add(t);
}
Collections.sort(strs,new Comparator<Test>() {
#Override
public int compare(Test o1, Test o2) {
return (o1.getS().compareToIgnoreCase(o2.getS()));
}
});
Integer i=1;
for (Test st : strs) {
st.setJ(i);
final_result.add(st);
i++;
}
Collections.sort(final_result,new Comparator<Test>() {
#Override
public int compare(Test o1, Test o2) {
return (o1.getI().compareTo(o2.getI()));
}
});
for (Test test : final_result) {
System.out.println(test.getJ());
}
}
}
class Test{
private Integer i;
private String s;
private Integer j;
public Test() {
// TODO Auto-generated constructor stub
}
public Test(Integer i, String s, Integer j) {
super();
this.i = i;
this.s = s;
this.j = j;
}
public Integer getI() {
return i;
}
public void setI(Integer i) {
this.i = i;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
public Integer getJ() {
return j;
}
public void setJ(Integer j) {
this.j = j;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((i == null) ? 0 : i.hashCode());
result = prime * result + ((j == null) ? 0 : j.hashCode());
result = prime * result + ((s == null) ? 0 : s.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Test other = (Test) obj;
if (i == null) {
if (other.i != null)
return false;
} else if (!i.equals(other.i))
return false;
if (j == null) {
if (other.j != null)
return false;
} else if (!j.equals(other.j))
return false;
if (s == null) {
if (other.s != null)
return false;
} else if (!s.equals(other.s))
return false;
return true;
}
}
I want to convert a string input like 2,3,6,7,8,10,12,14,15,16 to 2-3,6-8,10,12,14-16 using java
I tried using the below code
Vector ar=new Vector();
int lastadded=0;
String ht="";
String [] strarray=str.split(",");
strarray=sortArray(strarray);
Vector intarray=new Vector();
for(int i=0;i<strarray.length;i++)
{
int temp=1;
for(int j=1;j<=intarray.size();j++)
{
if(Integer.parseInt(strarray[i])==Integer.parseInt(intarray.get(j-1).toString()))
{
temp=0;
}
}
if(temp==1)
{
intarray.add(Integer.parseInt(strarray[i]));
ar.add(Integer.parseInt(strarray[i]));
}
}
ht="";
String strdemo="";
for(int i=0;i<intarray.size();i++)
{
if(ht=="")
{
ht=ar.get(i)+"";
lastadded=i;
}
else
{
strdemo=(String)ht;
if(strdemo.length()==ar.get(0).toString().length())
{
if(Integer.parseInt(strdemo.substring(0))==Integer.parseInt(ar.get(i).toString())-1)
{
strdemo=strdemo+"-"+ar.get(i);
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
else
{
strdemo=strdemo+","+ar.get(i);
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
}
else if(strdemo.length()==3)
{
strdemo=(String)ht;
if(Integer.parseInt(strdemo.substring(strdemo.length()-1,strdemo.length()))==Integer.parseInt(ar.get(i).toString())-1)
{
strdemo=strdemo.substring(0,strdemo.length()-2)+"-"+Integer.parseInt(ar.get(i).toString());
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
else
{
strdemo=strdemo+","+Integer.parseInt(ar.get(i).toString());
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
}//Else IF
else{
strdemo=(String)ht;
int de=1;
int ddd=lastadded;
if(ddd==Integer.parseInt(ar.get(i).toString())-1)
{
int lastaddedlen=(lastadded+"").length();
String symbol=strdemo.substring(strdemo.length()-lastaddedlen-1,strdemo.length()-lastaddedlen);
if(symbol.equalsIgnoreCase("-"))
strdemo=strdemo.substring(0,strdemo.length()-lastaddedlen-1)+"-"+Integer.parseInt(ar.get(i).toString());
else
strdemo=strdemo+"-"+Integer.parseInt(ar.get(i).toString());
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
else
{
strdemo=strdemo+","+Integer.parseInt(ar.get(i).toString());
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
}
}
}
Here sortArray function sorts the array descending and returns
protected static String[] sortArray(String ss[])
{
String temp;
for(int i=0;i<ss.length;i++)
{
for(int j=0;j<ss.length;j++)
{
if(Integer.parseInt(ss[i])<Integer.parseInt(ss[j]))
{
temp=ss[i];
ss[i]=ss[j];
ss[j]=temp;
}
}
}
return ss;
}
I am not getting consistant results for some inputs for example for the below case
2,3,6,7,8,10,12,14,15,16 it gives 2-3,6-8,10,12,14-16 (which is correct)
while for 2,4,5,6,7,8,10,12,14,15,16 it gives 2-8,10,12,14-16 (which actually should have been 2,4-8,10,12,14-16)
Where does the code go inconsistent is what I need to find out..
This is pretty ugly and verbose in Java, but here is a version. Note, it uses StringUtils from Spring at the very end for the trivial but also ugly process of converting a String collection to a comma delimited string.
The key is to use a separate class to model the numeric ranges. Let this class know how to turn itself into a String. Then you won't have so much logic around appending to a StringBuilder.
Also, try to think in terms of collections. This always makes things clearer. The pseudo-code is something like: String becomes List<Integer> becomes List<Range> and finally becomes String.
public class Ranges {
// A class that models a range of integers
public static class Range {
private int low;
private int high;
public Range(int low, int high) {
this.low = low;
this.high = high;
}
public int getHigh() {
return high;
}
public void setHigh(int high) {
this.high = high;
}
#Override
public String toString() {
return (low == high) ? String.valueOf(low) : String.format("%d-%d", low, high);
}
}
public static void main(String[] args) {
String input = "2,3,6,7,8,10,12,14,15,16";
// Turn input string into a sorted list of integers
List<Integer> inputNumbers = new ArrayList<Integer>();
for (String num : input.split(",")) {
inputNumbers.add(Integer.parseInt(num));
}
Collections.sort(inputNumbers);
// Flatten list of integers into a (shorter) list of Ranges
Range thisRange = null; // the current range being built
List<Range> ranges = new ArrayList<Range>();
for (Integer number : inputNumbers) {
if (thisRange != null && number <= thisRange.getHigh() + 1) {
// if we are already building a range (not null) && this new number is
// the old high end of the range + 1, change the high number.
thisRange.setHigh(number);
} else {
// create a new range and add it to the list being built
thisRange = new Range(number, number);
ranges.add(thisRange);
}
}
// Join List<String> into a single String
String result = StringUtils.collectionToCommaDelimitedString(ranges);
System.out.println("result = " + result);
}
}
Here is my implementation. Hope this help.
You have to pass these values
e.g int[] a = {2,3,4,5,6,7,8,10,12, 14,15,16,18,19,21,22,26};
to the following method.
public List<String> listIntRange(int[] values)
{
List<String> intRangeList = new ArrayList<String>();
int first = 0;
int current = 0;
int prev = 0;
int count = 0;
if (values == null || values.length < 1)
return intRangeList;
first = prev = values[0];
int index = 1;
boolean range = false;
for(index = 1; index < values.length; index++)
{
current = values[index];
if(current - prev == 1)
{
range = true;
prev = current;
continue;
}
if(range == true)
{
intRangeList.add(first + "-" + prev);
}
else
{
intRangeList.add("" + first);
}
first = current;
prev = current;
range = false;
}
if(range == true)
{
intRangeList.add(first + "-" + current);
}
else
{
intRangeList.add("" + current);
}
return intRangeList;
}
Output is as follows, when print out the values from intRangeList:
2-8,10,12,14-16,18-19,21-22,26,
Please ignore last comma ','.