Why does the following program print false, and what changes would I have to make to make it print true?
public class Main {
static int[] codePoints(String s) {
int n = s.length();
int[] temp = new int[n];
for (int i = 0; i < n; i++)
temp[i] = s.codePointAt(i);
return temp;
}
static String construct(int[] codePoints) {
StringBuilder sb = new StringBuilder();
for (int i : codePoints)
sb.appendCodePoint(i);
return sb.toString();
}
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("The symbol ");
sb.appendCodePoint(Character.MAX_VALUE + 1);
sb.append(" is not in the Basic Multilingual Plane.");
String s = sb.toString();
System.out.println(s.equals(construct(codePoints(s))));
}
}
The problem is here:
static int[] codePoints(String s) {
int n = s.length();
int[] temp = new int[n];
for (int i = 0; i < n; i++)
temp[i] = s.codePointAt(i); // <-- HERE
return temp;
}
A code point outside the BMP is two chars wide, not one (see Character.toChars()); you need to check that and advance your index if you encounter such a code point:
static int[] codePoints(final String s)
{
final int len = s.length();
final int[] ret = new int[s.codePointCount(0, len)];
int nrCodePoints = 0;
int codePoint;
int index;
for (index = 0; index < len; index++) {
codePoint = s.codePointAt(index);
ret[nrCodePoints++] = codePoint;
if (codePoint > Character.MAX_VALUE)
index++;
}
return ret;
}
Related
I am solving a problem on hackerrank
Hacker Rank ICPC Team Problem
I have created the following code as solution for problem.
import java.math.BigInteger;
import java.util.Scanner;
public class ACMICPCTeam {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(),m=sc.nextInt(),count=0,maxCount=0,teams=0;
sc.nextLine();
String subjectArray[]=new String[n];
for(int i=0;i<n;i++){
subjectArray[i]=sc.nextLine();
}
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
String temp=""+(new BigInteger(subjectArray[i]).add(new BigInteger(subjectArray[j])));
//System.out.println(temp);
count=temp.replace("0","").length();
if(count>maxCount)
{
maxCount=count;
teams=1;
}
else if(count==maxCount)
{
teams++;
}
}
}
System.out.println(maxCount);
System.out.println(teams);
sc.close();
}
}
So what I am trying to do is I am adding the two teams subjects and I am counting non-zeros of resultant string. The highest count is number of subjects and the occurrence of highest counts are teams which know max number of subject. Even after spending a lot time I am not able to any better solution than this one still I am facing time out as it is not efficient.
I have gone through forum of the question but it was of no help.
Don't use string logic for this.
Parse the string into a BitSet, before entering your loops, i.e. as you read them.
Then use methods or(BitSet set), and cardinality().
I just completed challenge doing that. No timeouts.
Your solution is not optimal you should try something better.
You can utilize BigInteger method or BitSet class to make it easy.
For forming a team you have to use bitwise OR
Here are solutions--
// 1st approach
static int[] acmTeam(String[] topic) {
int n = topic.length;
BigInteger[] bi = new BigInteger[n];
for (int i = 0; i < n; i++)
bi[i] = new BigInteger(topic[i], 2);
int maxTopic = 0;
int teamCount = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
BigInteger iuj = bi[i].or(bi[j]);
int bitCount = iuj.bitCount();
if (bitCount > maxTopic) {
maxTopic = bitCount;
teamCount = 1;
} else if (bitCount == maxTopic) {
teamCount++;
}
}
}
int result[] = { maxTopic, teamCount };
return result;
}
// 2nd approach--using java BitSet class
static int[] acmTeamUsingBitSet(String[] topic) {
int teamCount = 0, maxTopic = 0;
int size = topic.length;
BitSet[] bitset = new BitSet[size];
for (int i = 0; i < size; i++) {
BigInteger b1 = new BigInteger(topic[i], 2);
bitset[i] = BitSet.valueOf(b1.toByteArray());
}
for (int i = 0; i < size - 1; i++) {
BitSet bitset1 = bitset[i];
for (int j = i + 1; j < size; j++) {
BitSet bitset2 = bitset[j];
BitSet tmpset = new BitSet();
tmpset.or(bitset1);
tmpset.or(bitset2);
if (tmpset.cardinality() > maxTopic) {
maxTopic = tmpset.cardinality();
teamCount = 1;
} else if (maxTopic == tmpset.cardinality()) {
teamCount++;
}
}
}
int result[] = { maxTopic, teamCount };
return result;
}
You can refer this link for a detailed video explanation.
I got good result using Java 8.
static int[] acmTeam(String[] topic) {
List<List<Integer>> res = IntStream.range(0, topic.length)
.mapToObj(s -> IntStream.range(0, topic[s].length()).boxed()
.collect(Collectors.groupingBy(i -> topic[s].charAt(i))))
.map(m -> m.get('1'))
.collect(toList());
long maxTopic = 0;
int teamCount = 0;
for (int i = 0; i < res.size(); i++) {
for (int j = i + 1; j < res.size(); j++) {
long topics = Stream.concat(res.get(i).stream(), res.get(j).stream()).distinct().count();
if (topics > maxTopic) {
maxTopic = topics;
teamCount = 1;
} else if (topics == maxTopic) {
teamCount++;
}
}
}
return new int[]{(int) maxTopic, teamCount};
}
I have following the code that loop through array list(mainItems) and find the most similar two arrays and put them in sortedTransactions. It is working fine for small data (10000 transactions) but it is running forever for 88000 transactions. What can be done to make it work for big data.
import java.util.*;
public class Sort {
static private List<Transactions> trans = ReadFile.transactions;
static public List<int[]> mainItems;
static public ArrayList<int[]> sortedTransactions = new ArrayList<int[]>();
static {
mainItems = new ArrayList<int[]>();
for (Transactions t : trans) {
mainItems.add(t.getItems());
}
}
static private double jaccardSimilarity(int[] a, int[] b) {
Set<Integer> s1 = new LinkedHashSet<Integer>();
for(int i =0; i< a.length; i++){
s1.add(a[i]);
}
Set<Integer> s2 = new LinkedHashSet<Integer>();
for(int i =0; i< b.length; i++){
s2.add(b[i]);
}
Set<Integer> intersection = new LinkedHashSet<>(s1);
intersection.retainAll(s2);
Set<Integer> union = new LinkedHashSet<Integer>(s1);
union.addAll(s2);
double jaccardSimilarity = (double)intersection.size()/ (double)union.size();
//System.out.println(intersection);
return jaccardSimilarity;
}
static private boolean isAllEqual(List<Double> a){
for(int i=1; i<a.size(); i++){
if(a.get(0) != a.get(i)){
return false;
}
}
return true;
}
static public void generatePairs() {
for (int i = 0; i < mainItems.size() - 1; i++) {
if (!sortedTransactions.contains(mainItems.get(i))) {
List<Double> myd = new ArrayList<Double>();
List<int[]> mys = new ArrayList<int[]>();
for (int j = i + 1; j < mainItems.size(); j++) {
if (!sortedTransactions.contains(mainItems.get(j))) {
myd.add(jaccardSimilarity(mainItems.get(i),mainItems.get(j)));
mys.add(mainItems.get(j));
}
}
if (isAllEqual(myd) == false) {
sortedTransactions.add(mainItems.get(i));
sortedTransactions.add(mys.get(maxValue(myd)));
}
}
}
}
static private int maxValue(List<Double> d) {
double max = d.get(0);
int f = 0;
for(int i =1; i< d.size(); i++){
if(d.get(i) > max){
max= d.get(i);
f= i;
}
}
return f;
}
}
You don't have to create the union set (union(s1, s2).size() is s1.size() + s2.size() - intersection(s1, s2).size()).
static private double jaccardSimilarity(int[] a, int[] b) {
Set<Integer> s1 = new HashSet<Integer>();
for (int i = 0; i < a.length; i++) {
s1.add(a[i]);
}
Set<Integer> s2 = new HashSet<Integer>();
for (int i = 0; i < b.length; i++) {
s2.add(b[i]);
}
final int sa = s1.size();
final int sb = s2.size();
s1.retainAll(s2);
final int intersection = s1.size();
return 1d / (sa + sb - intersection) * intersection;
}
I have a keyboard that returns how many keypresses it would take to make a string on a user input keyboard, but I'm supposed to only have it calculate strings that dont have any uppercase or punctuation. How can i have it exclude punctuation or strings with upper case letters in them?
public class Keypad
char [][] letters;
public Keypad(String chars, int rowLength)
{
int column = chars.length()/rowLength;
if(chars.length()%rowLength!=0) {
column++;
}
letters = new char[column][rowLength];
for(int i = 0, n=0; i < letters.length ; i++) {
for(int j = 0 ; n < chars.length() && j < letters[i].length ; j++, n++) {
letters[i][j] = chars.charAt(n);
}
}
}
public int[] find(char letter) {
int [] coordinates;
coordinates = new int [2];
for(int i=0; i<letters.length; i++) {
for(int j = 0; j<letters[i].length; j++) {
if(letters[i][j] != letter){
coordinates[0] = -1;
coordinates[1] = -1;
}
else {
coordinates[0]= i;
coordinates[1]= j;
return coordinates;
}
}
}
return coordinates;
}
public int pressesRequired(String wordWanted) {
int total = 0;
char searching;
int [] nextCoordinates = new int [2];
int [] currentCoordinates = new int[] {0, 0};
for(int i=0; i<wordWanted.length(); i++) {
searching = wordWanted.charAt(i);
nextCoordinates = find(searching);
total += Math.abs(currentCoordinates[0]-nextCoordinates[0]);
total += Math.abs(currentCoordinates[1]-nextCoordinates[1]);
currentCoordinates = nextCoordinates;
total++;
}
return total;
}
Use String.toLowerCase() and equality:
public int pressesRequired(String wordWanted) {
if (!wordWanted.equals(wordWanted.toLowerCase())) {
return -1; // -1 indicates an error
}
// otherwise proceed as you were
}
Given a String, ""aabbcdeeeeggi" and k=3, the code should find longest substring with maximum of k unique characters. For the above input, it should be "deeeeggi".
Here is an elegant O(n) solution for the problem in Python. I am implementing in Java. but I am not getting the desired output for all the inputs.
public class SubStringWithKUniqueCharacters {
public static void main(String[] args){
System.out.println(longestSubStringWithUniqueK("aabbcdeeeeggi", 3));
System.out.println(longestSubStringWithUniqueK("aabbcdeeeeggi", 2));
}
public static String longestSubStringWithUniqueK(String input, int k){
int len = input.length();
Set<Character> unique = new HashSet<>();
int i = 0;
int j = 0;
int count = 0;
int maxStartIndex = 0;
int maxEndIndex = 0;
int maxLen = 0;
char[] inputArr = input.toCharArray();
while (i<len){
if (count==k && j -i > maxLen){
maxStartIndex = i;
maxEndIndex = j;
maxLen = maxEndIndex - maxStartIndex;
}
if (count<k && j<len){
if (unique.add(inputArr[j])){
count++;
}
j++;
}
else {
if (unique.remove(inputArr[i])){
count--;
}
i++;
}
}
return input.substring(maxStartIndex,maxEndIndex);
}
}
Here is the output:
eeeeggi //correct output
eeeggi //incorrect output
I am not able to capture where the bug is. Any help would be much appreciated.
Thanks
Your implementation does not work the way as expected, is because the original python solution has bug. I made some modifications to your code. Hope it's now all right:
public class SubStringWithKUniqueCharacters {
public static void main(String[] args){
System.out.println(longestSubStringWithUniqueK("aabbcdeeeeggi", 3));
System.out.println(longestSubStringWithUniqueK("aabbcdeeeeggi", 2));
}
public static String longestSubStringWithUniqueK(String input, int k){
int len = input.length();
Set<Character> unique = new HashSet<>();
int i = 0;
int j = 0;
int count = 0;
int maxStartIndex = 0;
int maxEndIndex = 0;
int maxLen = 0;
char[] inputArr = input.toCharArray();
while (i<len){
if (count==k && j -i > maxLen){
maxStartIndex = i;
maxEndIndex = j;
maxLen = maxEndIndex - maxStartIndex;
}
// 1. if we reach the end of the string, we're done.
if (j + 1 > len){
break;
}
// 2. changed to count <= k here
else if (count<= k && j<len){
if (unique.add(inputArr[j])){
count++;
}
j++;
}
else {
if (unique.remove(inputArr[i])){
// 3. remove all consecutive chars of the same value
char c = inputArr[i]; // save as temp char
while (inputArr[i] == c)
{
i++;
}
count--;
}
}
}
return input.substring(maxStartIndex,maxEndIndex);
}
}
The output now is:
deeeegg
eeeegg
I wrote the following Java code, to find the intersection between the prefix and the suffix of a String in Java.
// you can also use imports, for example:
// import java.math.*;
import java.util.*;
class Solution {
public int max_prefix_suffix(String S) {
if (S.length() == 0) {
return 1;
}
// prefix candidates
Vector<String> prefix = new Vector<String>();
// suffix candidates
Vector<String> suffix = new Vector<String>();
// will tell me the difference
Set<String> set = new HashSet<String>();
int size = S.length();
for (int i = 0; i < size; i++) {
String candidate = getPrefix(S, i);
// System.out.println( candidate );
prefix.add(candidate);
}
for (int i = size; i >= 0; i--) {
String candidate = getSuffix(S, i);
// System.out.println( candidate );
suffix.add(candidate);
}
int p = prefix.size();
int s = suffix.size();
for (int i = 0; i < p; i++) {
set.add(prefix.get(i));
}
for (int i = 0; i < s; i++) {
set.add(suffix.get(i));
}
System.out.println("set: " + set.size());
System.out.println("P: " + p + " S: " + s);
int max = (p + s) - set.size();
return max;
}
// codility
// y t i l i d o c
public String getSuffix(String S, int index) {
String suffix = "";
int size = S.length();
for (int i = size - 1; i >= index; i--) {
suffix += S.charAt(i);
}
return suffix;
}
public String getPrefix(String S, int index) {
String prefix = "";
for (int i = 0; i <= index; i++) {
prefix += S.charAt(i);
}
return prefix;
}
public static void main(String[] args) {
Solution sol = new Solution();
String t1 = "";
String t2 = "abbabba";
String t3 = "codility";
System.out.println(sol.max_prefix_suffix(t1));
System.out.println(sol.max_prefix_suffix(t2));
System.out.println(sol.max_prefix_suffix(t3));
System.exit(0);
}
}
Some test cases are:
String t1 = "";
String t2 = "abbabba";
String t3 = "codility";
and the expected values are:
1, 4, 0
My idea was to produce the prefix candidates and push them into a vector, then find the suffix candidates and push them into a vector, finally push both vectors into a Set and then calculate the difference. However, I'm getting 1, 7, and 0. Could someone please help me figure it out what I'm doing wrong?
I'd write your method as follows:
public int max_prefix_suffix(String s) {
final int len = s.length();
if (len == 0) {
return 1; // there's some dispute about this in the comments to your post
}
int count = 0;
for (int i = 1; i <= len; ++i) {
final String prefix = s.substring(0, i);
final String suffix = s.substring(len - i, len);
if (prefix.equals(suffix)) {
++count;
}
}
return count;
}
If you need to compare the prefix to the reverse of the suffix, I'd do it like this:
final String suffix = new StringBuilder(s.substring(len - i, len))
.reverse().toString();
I see that the code by #ted Hop is good..
The question specify to return the max number of matching characters in Suffix and Prefix of a given String, which is a proper subset. Hence the entire string is not taken into consideration for this max number.
Ex. "abbabba", prefix and suffix can have abba(first 4 char) - abba (last 4 char),, hence the length 4
codility,, prefix(c, co,cod,codi,co...),, sufix (y, ty, ity, lity....), none of them are same.
hence length here is 0.
By modifying the count here from
if (prefix.equals(suffix)) {
++count;
}
with
if (prefix.equals(suffix)) {
count = prefix.length();// or suffix.length()
}
we get the max length.
But could this be done in O(n).. The inbuilt function of string equals, i believe would take O(n), and hence overall complexity is made O(n2).....
i would use this code.
public static int max_prefix_suffix(String S)
{
if (S == null)
return -1;
Set<String> set = new HashSet<String>();
int len = S.length();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < len - 1; i++)
{
builder.append(S.charAt(i));
set.add(builder.toString());
}
int max = 0;
for (int i = 1; i < len; i++)
{
String suffix = S.substring(i, len);
if (set.contains(suffix))
{
int suffLen = suffix.length();
if (suffLen > max)
max = suffLen;
}
}
return max;
}
#ravi.zombie
If you need the length in O(n) then you just need to change Ted's code as below:
int max =0;
for (int i = 1; i <= len-1; ++i) {
final String prefix = s.substring(0, i);
final String suffix = s.substring(len - i, len);
if (prefix.equals(suffix) && max < i) {
max =i;
}
return max;
}
I also left out the entire string comparison to get proper prefix and suffixes so this should return 4 and not 7 for an input string abbabba.