Check for duplication of number in ArrayList - Java - java

I'm currently making a sudoku program, however my current code seems to fail me. The script below should put out a print "Inconsistent sudoku puzzle" if a row contains the same number several times, but sadly it doesn't.. I've tried several different attempts but no succes.
public void checkRow() {
int count = 0;
for(int j = 0; j < list.size(); j++) {
for(int a = 1; a < 10; a++) {
for (int i=0; i < list.get(j).length(); i++) {
if(list.get(j).charAt(i) == a) {
count++;
if(count >= 2) {
System.out.println("Inconsistent sudoku puzzle");
count = 0;
}
}
}
count = 0;
}
}
}
This is the collection of all my error checks:
public void errorCheck() {
this.checkRow();
this.checkColumn();
this.checkBox();
}
Here i load it into my main. The code is a lot more elaborate, but these should be the sections involving the issue.
public static void main(String[] args) throws Exception {
Sudoku s = new Sudoku("C:\\Users\\caspe\\Downloads\\Sudoku001.sdk");
s.printBoard();
s.errorCheck();
s.getNum();
while(getNum() > 0) {
System.out.println("Next move, please (row , column , value )");
Scanner scanner = new Scanner(System.in);
int row = scanner.nextInt();
int column = scanner.nextInt() ;
int value = scanner.nextInt();
if (s.moves(row, column, value)); {
s.errorCheck();
}
s.printBoard();
}
}

The issue
You're using charAt and trying to compare the result of that to a number:
list.get(j).charAt(i) == a
However doing so you're comparing the ascii value of the character to the number.
Example:
String a = "3";
System.out.println((int) a.charAt(0)); // This prints 51
The solution
If you wanted to compare number values you'd have to do something like this:
String a = "3";
System.out.println(Character.getNumericValue(a.charAt(0))); // This prints 3
Character.getNumericValue(a.charAt(0)) returns the number value of the character.
Implementation
Implementing that into your code would look like this:
Character.getNumericValue(list.get(j).charAt(i)) == a

This line:
if(list.get(j).charAt(i) == a)
is always false because you compare a char with an int.
Replace it with
if((list.get(j).charAt(i)-'0') == a)
list.get(j).charAt(i)-'0' gives you the numeric representation of the char

the problem is:
'if(list.get(j).charAt(i) == a)'
its comparing with the "a" value on the ascii table

Related

What's the best way to separate numbers manually for learning algorithm

I am learning Java and wonder how I can get two numbers in same line.
Is this algorithm is okay, what can I do improve? What can you suggest me?
import java.util.Scanner;
public class Main{
public static int Separate(String Values, int Order){
String toReturn = "";
int Counter = 0;
for(int Iterator = 0; Iterator < Values.length(); Iterator = Iterator + 1){
if(Values.charAt(Iterator) == ' ') {
if(Order == Counter) break;
else{
toReturn = "";
Counter = Counter + 1;
}
}
else toReturn += Values.charAt(Iterator);
}
return Integer.parseInt(toReturn);
}
public static void main(String[] args){
Scanner Entry = new Scanner(System.in);
System.out.print("Enter two numbers separated by space: ");
String Number = Entry.nextLine();
int Frst = Separate(Number, 0);
int Scnd = Separate(Number, 1);
}
}
what can I do improve? What can you suggest me?
Adopt the Java Naming Conventions:
Method Names are camelCase, starting with a lower case letter
Field and Property Names and Method Argument Names are camelCase, too
Basically only Class and Interface Names start with an upper case letter in Java.
public static int separate(String values, int order){
String toReturn = "";
int counter = 0;
for(int iterator = 0; ...) { ...
Else I'd say: This algorithm is pretty solid for a beginner. It's easy to understand what's going on.
Of course Java provides much more sophisticated tools to solve this, using for example Regular Expressions with myString.split(...), or Streams with IntStream intStream = myString.chars().
Last but not least you could add Exception Handling: What happens if Integer.parseInt is given some non-number? It will crash.
try {
return Integer.parseInt(toReturn);
} catch (NumberFormatException e) {
// when "toReturn" cannot be parsed to an int, return a
// default value instead of crashing your application
return 0;
}
Or if crashing is the desired behavior, or you can ensure that this method is never called with an illegal String, leave it as it is (= don't add try catch)
I think what you've done is great for well-formatted input, where you have a single space character between the numbers. As others have pointer out, following Java naming conventions will greatly improve the readability of your code.
Handling sequences of space characters, possible before, between, and after your numbers is a little tricky. The general pattern would be to consume any sequences of spaces, remember the current position, consume the sequence of digits, then if we're at the correct position return the parsed number.
public static int separate(String str, int order)
{
for(int i = 0, pos = 0; ; pos++)
{
while(i < str.length() && str.charAt(i) == ' ') i += 1;
int j = i;
while(i < str.length() && str.charAt(i) != ' ') i += 1;
if(i == j) throw new IllegalStateException("Missing number!");
if(order == pos)
{
// handle NumberFormatException
return Integer.parseInt(str.substring(j, i));
}
}
}
Test:
String s = " 23432 798 44";
for(int i=0; i<3; i++)
System.out.print(separate(s, i) + " ");
Output:
23432 798 44

Increasing number sequence in a string java

Problem: Check if the numbers in the string are in increasing order.
Return:
True -> If numbers are in increasing order.
False -> If numbers are not in increasing order.
The String sequence are :
CASE 1 :1234 (Easy) 1 <2<3<4 TRUE
CASE 2 :9101112 (Medium) 9<10<11<12 TRUE
CASE 3 :9991000 (Hard) 999<1000 TRUE
CASE 4 :10203 (Easy) 1<02<03 FALSE
(numbers cannot have 0 separated).
*IMPORTANT : THERE IS NO SPACES IN STRING THAT HAVE NUMBERS"
My Sample Code:
// converting string into array of numbers
String[] str = s.split("");
int[] numbers = new int[str.length];
int i = 0;
for (String a : str) {
numbers[i] = Integer.parseInt(a.trim());
i++;
}
for(int j=0;j<str.length;j++)
System.out.print(numbers[j]+" ");
//to verify whether they differ by 1 or not
int flag=0;
for(int j=0;j<numbers.length-1;j++){
int result=Integer.parseInt(numbers[j]+""+numbers[j+1]) ;
if(numbers[j]>=0 && numbers[j]<=8 && numbers[j+1]==numbers[j]+1){
flag=1;
}
else if(numbers[j]==9){
int res=Integer.parseInt(numbers[j+1]+""+numbers[j+2]) ;
if(res==numbers[j]+1)
flag=1;
}
else if(result>9){
//do something
}
}
This is the code I wrote ,but I cant understand how to perform for anything except one-digit-numbers ( Example one-digit number is 1234 but two-digit numbers are 121314). Can anyone have a solution to this problem?. Please share with me in comments with a sample code.
I'm gonna describe the solution for you, but you have to write the code.
You know that the input string is a sequence of increasing numbers, but you don't know how many digits is in the first number.
This means that you start by assuming it's 1 digit. If that fails, you try 2 digits, then 3, and so forth, until you've tried half the entire input length. You stop at half, because anything longer than half cannot have next number following it.
That if your outer loop, trying with length of first number from 1 and up.
In the loop, you extract the first number using substring(begin, end), and parse that into a number using Integer.parseInt(s). That is the first number of the sequence.
You then start another (inner) loop, incrementing that number by one at a time, formatting the number to text using Integer.toString(i), and check if the next N characters of the input (extracted using substring(begin, end)) matches. If it doesn't match, you exit inner loop, to make outer loop try with next larger initial number.
If all increasing numbers match exactly to the length of the input string, you found a good sequence.
This is code for the pseudo-code suggested by Andreas .Thanks for the help.
for (int a0 = 0; a0 < q; a0++) {
String s = in.next();
boolean flag = true;
for (int i = 1; i < s.length() / 2; i++) {
int first = Integer.parseInt(s.substring(0, i));
int k=1;
for (int j = i; j < s.length(); j++) {
if (Integer.toString(first + (k++)).equals(s.substring(j, j + i)))
flag = true;
else{
flag=false;
break;
}
}
if (flag)
System.out.println("YES");
else
System.out.println("NO");
}
I would suggest the following solution. This code generates all substrings of the input sequence, orders them based on their start index, and then checks whether there exists a path that leads from the start index to the end index on which all numbers that appear are ordered. However, I've noticed a mistake (I guess ?) in your example: 10203 should also evaluate to true because 10<203.
import java.util.*;
import java.util.stream.Collectors;
public class PlayGround {
private static class Entry {
public Entry(int sidx, int eidx, int val) {
this.sidx = sidx;
this.eidx = eidx;
this.val = val;
}
public int sidx = 0;
public int eidx = 0;
public int val = 0;
#Override
public String toString(){
return String.valueOf(this.val);
}
}
public static void main(String[] args) {
assert(check("1234"));
assert(check("9101112"));
assert(check("9991000"));
assert(check("10203"));
}
private static boolean check(String seq) {
TreeMap<Integer,Set<Entry>> em = new TreeMap();
// compute all substrings of seq and put them into tree map
for(int i = 0; i < seq.length(); i++) {
for(int k = 1 ; k <= seq.length()-i; k++) {
String s = seq.substring(i,i+k);
if(s.startsWith("0")){
continue;
}
if(!em.containsKey(i))
em.put(i, new HashSet<>());
Entry e = new Entry(i, i+k, Integer.parseInt(s));
em.get(i).add(e);
}
}
if(em.size() <= 1)
return false;
Map.Entry<Integer,Set<Entry>> first = em.entrySet().iterator().next();
LinkedList<Entry> wlist = new LinkedList<>();
wlist.addAll(first.getValue().stream().filter(e -> e.eidx < seq
.length()).collect(Collectors.toSet()));
while(!wlist.isEmpty()) {
Entry e = wlist.pop();
if(e.eidx == seq.length()) {
return true;
}
int nidx = e.eidx + 1;
if(!em.containsKey(nidx))
continue;
wlist.addAll(em.get(nidx).stream().filter(n -> n.val > e.val).collect
(Collectors.toSet()));
}
return false;
}
}
Supposed the entered string is separated by spaces, then the code below as follows, because there is no way we can tell the difference if the number is entered as a whole number.
boolean increasing = true;
String string = "1 7 3 4"; // CHANGE NUMBERS
String strNumbers[] = string.split(" "); // separate by spaces.
for(int i = 0; i < strNumbers.length - 1; i++) {
// if current number is greater than the next number.
if(Integer.parseInt(strNumbers[i]) > Integer.parseInt(strNumbers[i + 1])) {
increasing = false;
break; // exit loop
}
}
if(increasing) System.out.println("TRUE");
else System.out.println("FALSE");

Reduce the value of a letter, e.g. can change 'd' to 'c', but cannot change 'c' to 'd'. In order to form a palindrome

public class Solution {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int tc = Integer.parseInt(br.readLine());//I get Numberformat Exception here
for(int i=0;i<tc;i++) // Even if my inputs are on separate lines
{
String original = br.readLine();
palindrome(original);
}
}
public static void palindrome(String original)
{
String reverse="";
int length = original.length();
for ( int i = length - 1 ; i >= 0 ; i-- )
reverse = reverse + original.charAt(i);
if (original.equals(reverse))
{
System.out.println(0);
}
else
{
char[] org = original.toCharArray();
int len = org.length;
int mid = len / 2;
if(len % 2 == 0)
{
char[] front = new char[mid];
char[] back = new char[mid];
for(int i=0;i<mid;i++)
{
front[i] = org[i];
}
int j=0;
for(int i=len-1;i>=mid;i--)
{
back[j] = org[i];
j++;
while(j > mid)
{
break;
}
}
change(front,back,mid);
}
else
{
char[] front = new char[mid];
char[] back = new char[mid];
for(int i=0;i<mid;i++)
{
front[i] = org[i];
}
int j=0;
for(int i=len-1;i>mid;i--)
{
back[j] = org[i];
j++;
while(j > mid)
{
break;
}
}
change(front,back,mid);
}
}
}
public static void change(char[] front,char[] back,int len)
{
int count =0;
for(int i =0;i<len;i++)
{
if(front[i] != back[i] )
{
count += (back[i] - front[i]);
}
}
System.out.println(count)
}
}
What i try to do here is get an input from the number of test cases say 3 in my first line followed by the test-cases themselves.
sample input :
3
abc
abcba
abcd
Now it has to check if the string is a palindrome if its so it ll print 0
else it breaks the string into two halves front and back and finds the minimum number of changes to make it a palidrome.
here i have also checked if its a odd or even length string if odd i have omitted the middle char.
By changes we can only change 'd' to 'b' not 'b' to 'd'
Once a letter has been changed to 'a', it can no longer be changed.
My code works fine for the above input but it doesnt for some other inputs i dont quiet understand why..
for instance if i give a custom test case as
5
assfsdgrgregedhthtjh
efasfhnethiaoesdfgv
ehadfghsdfhmkfpg
wsertete
agdsjgtukgtulhgfd
I get a Number Format Exception.
Your code works fine here, whithout NumberFormatException: http://ideone.com/QJqjmG
This may not solve your problem, but improves your code...
As first user input you are expecting an integer. You are parsing the String returned by br.readLine() and do not take care of the NumberFormatException parseInt(...) may throw.
Just imagine someone hits space or return key as first input.
So I propose to put a try-catch-block around the parseInt(...). Here is an example how this may look like.
Guys thank you for all your suggestion i just found out why my other test cases weren't working
public static void change(char[] front,char[] back,int len)
{
int count =0;
for(int i =0;i<len;i++)
{
if(front[i] != back[i] )
{
count += (back[i] - front[i]);
}
}
System.out.println(count)
}
This part of my code has to be changed to
public static void change(char[] front,char[] back,int len)
{
int count =0;
for(int i =0;i<len;i++)
{
if(front[i] != back[i] )
{
char great = findGreatest(front[i],back[i]);
if(great == back[i])
{
count += (back[i] - front[i]);
}
else
{
count += (front[i] - back[i]);
}
}
}
System.out.println(count);
}
public static char findGreatest(char first,char second)
{
int great = first;
if(first < second)
{
great = second;
}
return (char)great;
}
Because i get negative values coz of subtracting ascii's which are greater than them and as i have already mentioned i can only do 'd' to 'a' not the other way round.
Thank you for your time guys!

java display method

Here im required to Write a method printArray that displays the contents of the array num and Display the contents of the array with each
number separated by a space. and i have to start a new line after every 20 elements.
i wrote this code but whenever i try to execute it, it shows the array without the new line
public class project2 {
public static void main(String[] args) {
int num []= new int [100];
for (int i=0;i<num.length;i++){
num[i]=-1;
num[7]=7;
}
printArray(num);
System.out.println(num);
}
public static void printArray (int array1[]){
int count =20;
for (int x=0;x<array1.length;x++){
System.out.print(array1[x]+" ");
if (array1[x]==count){
System.out.println(" ");
count=array1[x]+count;
}
}
}
}
import java.util.Arrays;
import java.util.Random;
public class project2 {
public static void main(String[] args) {
int num[] = new int[100];
Random random = new Random();
for (int i = 0; i < num.length; i++) {
num[i] = random.nextInt(100);
}
printArray(num);
System.out.println('\n' + Arrays.toString(num));
}
public static void printArray(int array1[]) {
int count = 20;
for (int i = 0; i < array1.length; i++) {
System.out.printf("%2d ", array1[i]);
if ((i + 1) % count == 0) {
System.out.println("");
}
}
}
}
You should use the modulo (or remainder) operator (%), that suits your usage much better:
for (int x=0;x<array1.length;x++){
System.out.print(array1[x]+" ");
if (x>0 && (x%count)==0){
System.out.println(" ");
}
}
This way, you will get a new line every count characters, and the first line will not have it (that is why the x>0 check is there).
Also, in the original post, this line is frankly totally bad:
count=array1[x]+count;
Just what would it do? Why do you add the value stored in the array to the fixed counter? Considering this line, I advise that you should really sit back a bit, and try to think about how things work in the background... There is no magic!
Take a closer look at your if-statement:
if (array1[x]==count)
According to your array values, this will never return true
i have to start a new line after every 20 elements.
Change to following code:
if (x%20 == 0)
{
System.out.println();
}
in place of
if (array1[x]==count)
{
System.out.println(" ");
count=array1[x]+count;
}
Problem is with
if (array1[x]==count)
You are comparing count with value present in array. Instead compare it with desired count ie 20 or Use modulo operator as suggested in other answers / comments .
int count = 1;
for (int x=0;x<array1.length;x++){
System.out.print(array1[x]+" ");
if (count == 20){ // Check if its 20th element
System.out.println(" ");
count=1; // reset count
}
count++;
}

interviewstreet.com - String similarity

I'm trying to solve the string similarity question on interviewstreet.com. My code is working for 7/10 cases (and it is exceeding the time limit for the other 3).
Here's my code -
public class Solution {
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
String v1 = user_input.next();
int number_cases = Integer.parseInt(v1);
String[] cases = new String[number_cases];
for(int i=0;i<number_cases;i++)
cases[i] = user_input.next();
for(int k=0;k<number_cases;k++){
int similarity = solve(cases[k]);
System.out.println(similarity);
}
}
static int solve(String sample){
int len=sample.length();
int sim=0;
for(int i=0;i<len;i++){
for(int j=i;j<len;j++){
if(sample.charAt(j-i)==sample.charAt(j))
sim++;
else
break;
}
}
return sim;
}
}
Here's the question -
For two strings A and B, we define the similarity of the strings to be the length of the longest prefix common to both strings. For example, the similarity of strings "abc" and "abd" is 2, while the similarity of strings "aaa" and "aaab" is 3.
Calculate the sum of similarities of a string S with each of it's suffixes.
Input:
The first line contains the number of test cases T. Each of the next T lines contains a string each.
Output:
Output T lines containing the answer for the corresponding test case.
Constraints:
1 <= T <= 10
The length of each string is at most 100000 and contains only lower case characters.
Sample Input:
2
ababaa
aa
Sample Output:
11
3
Explanation:
For the first case, the suffixes of the string are "ababaa", "babaa", "abaa", "baa", "aa" and "a". The similarities of each of these strings with the string "ababaa" are 6,0,3,0,1,1 respectively. Thus the answer is 6 + 0 + 3 + 0 + 1 + 1 = 11.
For the second case, the answer is 2 + 1 = 3.
How can I improve the running speed of the code. It becomes harder since the website does not provide a list of test cases it uses.
I used char[] instead of strings. It reduced the running time from 5.3 seconds to 4.7 seconds and for the test cases and it worked. Here's the code -
static int solve(String sample){
int len=sample.length();
char[] letters = sample.toCharArray();
int sim=0;
for(int i=0;i<len;i++){
for(int j=i;j<len;j++){
if(letters[j-i]==letters[j])
sim++;
else
break;
}
}
return sim;
}
used a different algorithm. run a loop for n times where n is equals to length the main string. for each loop generate all the suffix of the string starting for ith string and match it with the second string. when you find unmatched character break the loop add j's value to counter integer c.
import java.io.BufferedReader;
import java.io.InputStreamReader;
class Solution {
public static void main(String args[]) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(in.readLine());
for (int i = 0; i < T; i++) {
String line = in.readLine();
System.out.println(count(line));
}
}
private static int count(String input) {
int c = 0, j;
char[] array = input.toCharArray();
int n = array.length;
for (int i = 0; i < n; i++) {
for (j = 0; j < n - i && i + j < n; j++)
if (array[i + j] != array[j])
break;
c+=j;
}
return c;
}
}
I spent some time to resolve this question, and here is an example of my code (it works for me, and pass thru all the test-cases):
static long stringSimilarity(String a) {
int len=a.length();
char[] letters = a.toCharArray();
char localChar = letters[0];
long sim=0;
int sameCharsRow = 0;
boolean isFirstTime = true;
for(int i=0;i<len;i++){
if (localChar == letters[i]) {
for(int j = i + sameCharsRow;j<len;j++){
if (isFirstTime && letters[j] == localChar) {
sameCharsRow++;
} else {
isFirstTime = false;
}
if(letters[j-i]==letters[j])
sim++;
else
break;
}
if (sameCharsRow > 0) {
sameCharsRow--;
sim += sameCharsRow;
}
isFirstTime = true;
}
}
return sim;
}
The point is that we need to speed up strings with the same content, and then we will have better performance with test cases 10 and 11.
Initialize sim with the length of the sample string and start the outer loop with 1 because we now in advance that the comparison of the sample string with itself will add its own length value to the result.
import java.util.Scanner;
public class StringSimilarity
{
public static void main(String args[])
{
Scanner user_input = new Scanner(System.in);
int count = Integer.parseInt(user_input.next());
char[] nextLine = user_input.next().toCharArray();
try
{
while(nextLine!= null )
{
int length = nextLine.length;
int suffixCount =length;
for(int i=1;i<length;i++)
{
int j =0;
int k=i;
for(;k<length && nextLine[k++] == nextLine[j++]; suffixCount++);
}
System.out.println(suffixCount);
if(--count < 0)
{
System.exit(0);
}
nextLine = user_input.next().toCharArray();
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Categories

Resources