Adding a while and for loop - java

The question asks: Design and implement an application that first reads a list of 10 three-digit integers and then counts the number of appearances for each digit from 0 to 9.
Here is an example of 3 three-digit numbers
Input number [123, 456, 789]
Output:
Digit 0 has appeared 0 times
Digit 1 has appeared 1 times
Digit 2 has appeared 1 times
…
Digit 9 has appeared 1 times
I believe that I have figured out the correct formulas to computate the amount of times each number appears, but I am not sure how to create the array and begin searching through it. I think I need a while and a for loop, but I am not sure how to incorporate them. I am afraid however, that my current if statements will need to change once the loops are implemented. Am I going in the right direction here? Any help would be greatly appreciated!
double i1, i2, i3, i4, i5, i6, i7, i8, i9, i10;
int c0=0, c1=0, c2=0, c3=0, c4=0, c5=0, c6=0, c7=0, c8=0, c9=0;
Scanner scan = new Scanner(System.in);
System.out.println ("Enter 10 3-digit integers");
//Counts the 1st number
System.out.println ("Enter first 3-digit integer");
i1 = scan.nextDouble();
if (i1%10==0)
c0++;
if (i1%10==1)
c1++;
if (i1%10==2)
c2++;
if (i1%10==3)
c3++;
if (i1%10==4)
c4++;
if (i1%10==5)
c5++;
if (i1%10==6)
c6++;
if (i1%10==7)
c7++;
if (i1%10==8)
c8++;
if (i1%10==9)
c9++;
if ((i1%100>=0) & (i1%100<10))
c0++;
if ((i1%100>=10) & (i1%100<20))
c1++;
if ((i1%100>=20) & (i1%100<30))
c2++;
if ((i1%100>=30) & (i1%100<40))
c3++;
if ((i1%100>=40) & (i1%100<50))
c4++;
if ((i1%100>=50) & (i1%100<60))
c5++;
if ((i1%100>=60) & (i1%100<70))
c6++;
if ((i1%100>=70) & (i1%100<80))
c7++;
if ((i1%100>=80) & (i1%100<90))
c8++;
if ((i1%100>=90) & (i1%100<100))
c9++;
if((i1/1000>=.0) & (i1/1000<.1))
c0++;
if((i1/1000>=.1) & (i1/1000<.2))
c1++;
if((i1/1000>=.2) & (i1/1000<.3))
c2++;
if((i1/1000>=.3) & (i1/1000<.4))
c3++;
if((i1/1000>=.4) & (i1/1000<.5))
c4++;
if((i1/1000>=.5) & (i1/1000<.6))
c5++;
if((i1/1000>=.6) & (i1/1000<.7))
c6++;
if((i1/1000>=.7) & (i1/1000<.8))
c7++;
if((i1/1000>=.8) & (i1/1000<.9))
c8++;
if((i1/1000>=.9) & (i1/1000<1.00))
c9++;

Hints:
Get rid of all of the c<n> and i<n> declarations and all of the if tests. They don't help you solve the problem.
Make use of the fact that '0' + <n> == '<n>' where <n> is 0 .. 9.
Or use Character.digit(char, 10). Read the javadocs.
You don't use nextDouble() to read an integer. Read the javadocs.

More Hints:
Generalise the problem to 'count the distinct characters in a string'. Since you're reading the input as a string anyway, just forget that you're counting integers for the moment, and focus on counting char appearances within a string.
Think of a data structure that can contain a pair of (distinct char, count).
Iterate through the characters within a string, add the character to your data structure in point 2 if it doesn't exist with a default value of 0, then increment the count of the char you're currently looking at.
When showing the output of your program, iterate through the entries of your data structure, validate that the char is an integer (if validation is important), and return the count for that char.
I'm not sure if you have trouble with iteration or not, but here is how to loop through the characters of a string:
String s = "123 456 789";
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
// process c
}
// or, if you know what 'smart loops' in Java are...
for(char c : s.toCharArray()) {
// process c
}
To confuse matters, here it is in... 'pseudocode' (edited based on comments) ;)
>>> s = "012 345 678 900"
>>> datastructure = {}
>>> for c in s:
... if c not in datastructure:
... datastructure[c] = 0
... datastructure[c] += 1
...
>>> for c in '0123456789':
... if c not in datastructure:
... datastructure[c] = 0
... print 'Digit %s appeared %d times' % (c, datastructure[c])
...
Digit 0 appeared 3 times
Digit 1 appeared 1 times
Digit 2 appeared 1 times
Digit 3 appeared 1 times
Digit 4 appeared 1 times
Digit 5 appeared 1 times
Digit 6 appeared 1 times
Digit 7 appeared 1 times
Digit 8 appeared 1 times
Digit 9 appeared 1 times

Your idea isn't that bad, you just obviously need some loops :)
1: loop to get numbers - you can't duplicate the same code 10x - write it once, in a loop.
2: loop to check digits - you can use your's ifs, or do it as Josh said
but before - you need data structure to store your data - occurs of digits. 10 variables is bad, BAD:), idea.
use array[2][10] or simply array[10] (where number of digits = index of array and value = occurs) or even better - HashMap<> - google it.
then inside loop you do:
for(int i = 0; i<10; i++){
if (myCurrentNumberToCheck %10 == i)
array[i] = array[i] + 1; // approach with simple array[10]
if ((myCurrentNumberToCheck %100 >= i*10) && (myCurrentNumberToCheck %100 < (i+1)*10 )) // needs to be tested
array[i] = array[i] + 1;
if ((myCurrentNumberToCheck %1000 >= i*100) && (myCurrentNumberToCheck %1000 < (i+1)*100 )) // needs to be tested
array[i] = array[i] + 1;
}
ahh and your inserted numbers should be in some structure too - try List numbers = new ArrayList<int>() here :) and iterate thou list, to take a look at next number.
so you will need to add numbers to List, and nextly - go thou that list and check them and here use that loop i wrote above

the problem with readInt() and readDouble() is that it ignores leading 0 and trailing 0 after the decimal i.e. 01.10 => 1.1
A much simpler approach is to just read every character.
int ch;
while((ch = System.in.read())>=0) {
// you have one character
}

Related

find the maximum possible ones

I have a string of 0's and 1's
Now I want to change 0 to 1 only if adjacent elements for that 0 are not 1'string. Find the maximum ones possible after doing this operation.
Example:
110011000001 is the input string
Option 1:
I can change position 8 and position 10 from 0 to 1 to make the string: 110011010101, here there are 7 ones
Option 2:
Another way is to change position 9 from 0 to 1, to make the string: 110011001001, here there are 6 ones.
So the maximum between 6 and 7 is 7. So the result is 7.
Here is my code, I am able to find only one possible way here:
int process(String s) {
char[] ch = s.toCharArray();
int n = ch.length;
for(int i=1; i<n-1; i++) {
char e = ch[i];
if(e == '0' && ch[i-1] != '1' && ch[i+1] != '1') {
ch[i] = '1';
}
}
int count = 0;
for(char c : ch) {
if(c == '1') count++;
}
return count;
}
How to get the maximum possible ones here.
Notice that if the 0's are surrounded by 1's, you only need 2n + 1
adjacent 0's in order to add n 1's. In order to add one 1, you
need at least three 0's: 2*1+1=3. In order to add two 1's, you
need at least five 0's: 2*2+1=5. Since the number of 0's can be
described as, Z >= 2n + 1, we can instead solve for n. We get n <= (Z - 1) / 2. Thus, when surrounded by 1's, each group of 0's can
fit n=floor((Z-1)/2); we floor the value since we can't add half of a 1.
For groups of 0's only bounded by a 1 on a single side, we notice
that we need at least 2n 0's in order to add n 1's. Again, we
rearrange the equation Z >= 2n in order to get n <= Z / 2. Thus,
for groups bounded by a single 1, n=floor(Z/2).
For our last case, with a string of all 0's, we see that Z >= 2n - 1. So, n <= (Z + 1) / 2, or for our purposes floor((Z+1)/2).
Least common will be category 3. This will only happen if there are no 1's. If this is the case, you cannot have anything from category 1 or 2 -- so check this category first.
Second most common will be category 2. This happens when the beginning OR end of the string is a 0, but there are 1's elsewhere. Check this category second because you can fit more 1's with it than with the formula for the first case. Depending on your solution, you may have to keep track of the places you've already checked before moving on to using case 1 by using a substring of the original.
Most cases will land in category 1, since (in a random combination of 1's and 0's) most groups of 0's will be surrounded by 1's.
Your answer only checks the first case. Using these three cases together will give you the number of 1's that you can add to the string. Add this to the number of 1's you had originally and you'll have your answer.
Edited for clarity.
Count all existing ones as they are going to be a part of the answer.
To convert 0 to 1, count all zeroes between two ones.
If string is 100001, you have total 4 zeroes in between. Here let us leave boundary zeroes as we can't change them as they are adjacent to 1. So, now we are left with 2 zeroes in the middle out of which we can place only in 1 of them.
So count is just ceil(all valid zeroes / 2).
If you have a string like 00001, here you can place 2 ones excluding that boundary 0 adjacent to 1. So, count is ceil(3/2) which is 2. Your string would look like 10101.
Final answer is just step 1 + step 2.

print random characters without repeat in square?

I'm generating random characters via my code below:
static void printRandomWhatEver(int NUMBER_OF_CHARACTER,
int NUMBER_OF_LINES,
char char1, char char2) {
int DIFFERENCE_SQUARE = 4;
char oldChar, newChar, random;
for (int i = 0; i < NUMBER_OF_CHARACTER; i++) {
random = getRandomCharacter(char1, char2);
if ((i + 1) % NUMBER_OF_LINES == 0) { // new line each new NUMBER_OF_LINE
System.out.println(random);
} else {
System.out.print(random);
}
}
}
My getReandomCharacter:-
private static char getRandomCharacter(char ch1, char ch2) {
return (char) (ch1 + Math.random() * (ch2 - ch1 + 1));
}
All working fine, what i need is the chars inside square 2*2 numbers to not be equal, here is image to explain what i need.
The digit 4 is in the same square:-
**
**
How i can prevent digits to be equal in a part of square?
Thanks in advance.
Just store the last line of your output, and compare the digit at position N to the digits last_line[N-1], last_line[N] and last_line[N+1]. Take care of the array boundaries for N-1 and N+1.
But you should be aware that you reduce the strength of your random number generator this way. To a human it will most likely look "more random", though.
But there may be even more patterns a human may recognize as "not random", e.g. sequential digits:
154
298
364
To avoid repeats you are better off shuffling rather than picking randomly. You will have to repeatedly select different groups of digits to shuffle to avoid repeats.
To start, pick four digits from [0..9] and shuffle them:
0 1
2 3
Working from left to right, the next two digits come from [0, 2, 4..9] with 1 and 3 omitted:
0 1 7
2 3 8
Repeat the process, adding two from the eight possible digits at a time.
Use a similar "pick two from seven" process to add digits in the next row. You only have seven digits to pick from because it is dangerous to pick an '8' in the given configuration:
0 1 7
2 3 8
1 8
Would be an error, so the '8' cannot be picked:
0 1 7
2 3 8
1 5
Is safe.
Once you move away from the left hand edge, you will be picking from six, as there will be four digits in the row above that you must avoid.
ETA: Working with two rows is overly complex. Generate one row at a time, with any existing adjacent digits cut out of the pre-shuffle selection. That will be 3 digits in the row above, plus the previous digit in the current row, with appropriate adjustments for left and right boundaries.

Could someone please explain how shifting is used in this code?

I'm solving sample problems while simultaneously trying to learn Python %\ ... but the problem book I got has problems and solutions in Java, so I'm trying to convert back and forth between the two languages. I just learned how bit shifting works and I've been staring at this code trying to figure out what exactly is going on here on line 5 (and 8) ... I tried writing down some examples just going through the code line by line but for some reason it's still not entirely obvious to me ...
Could someone please clarify?
Also, it's really strange to me that str.charAt(i) returns a character, as far as I understand, and you can then proceed to subtract it from another character like numbers ... Is applying int to a character the same as ord() in Python?
Problem: Implement an algorithm to determine is a string has all unique characters.
Solution (in the case with only characters a-z):
1 boolean isUniqueChars(String str){
2 int checker = 0
3 for (int i = 0; i < str.length(); i++){
4 int val = str.charAt(i) - 'a';
5 if ((checker & (1 << val)) > 0){
6 return false;
7 }
8 checker |= (1 << val);
9 }
10 return true;
11 }
Sure. This code will really only work if str has only lower case letters in it.
checker is a 32-bit integer, and you're using 26 of the 32 bits to record the presence of a particular letter in str. So bit 0 will be used to record the presence of a, bit 1 will be used to record the presence of b, and so on up to bit 25, which will be used to record the presence of z.
The basic algorithm is to work through str, character by character. For each character, find the corresponding bit in checker. If it's already been set, this character must be occurring for the second time - so we can stop processing and return false. Otherwise, set that bit.
If you get to the end of the string without finding any duplicate characters, then return true.
The magic is in the following steps.
Subtracting 'a' from each character converts it to a number from 0 to 25.
The symbol << is the "left shift" operator, which moves a bit pattern a number of bits to the left. The result of this is that 1 << val is the place value of a particular bit (1, 2, 4, 8 etc).
The symbol & does a binary AND, so the expression checker & (1 << val) will be 0 if bit val is cleared, or equal to 1 << val if it is set.
The symbol |= does a binary OR, and assigns the result to the variable on the left. So the expression checker |= (1 << val) sets bit val.
Let's try a simpler variation:
boolean isUniqueChars(String str) {
boolean[] seen = new boolean[26];
for (int i = 0; i < str.length(); i++) {
// convert char to 0-based offset
int index = str.charAt(i) - 'a';
if (seen[index]) {
// this char was seen already
return false;
}
seen[index] = true;
}
// no duplicates found
return true;
}
Pretty straighforward, right? We create a boolean array, using the character offset as an index, and check each character in the string to see if we've come across it yet. The code you posted uses the same logic, but with a more efficient bit set instead.
(1 << val) turns val into a bit index. checker & (1 << val) filters out other indexes so we can check just this one. (checker & (1 << val)) > 0 checks if there's any value at the index. checker |= (1 << val) turns the bit on at the index. All of the other logic is identical.
First, the code will only work reliably if the input string contains letters 'a' to 'z'.
The variable checker is a 32 bit int. Each bit in checker is used as a flag to indicate the presence of one of the 26 letters 'a' to 'z'.
The line
int val = str.charAt(i) - 'a';
converts the character stored at str index i into an integer stored in val, by subtracting the value of character 'a' so. Yes I think pascal has the Ord('') function which does the same.
a = 0
b = 1
c = 2
etc
etc
etc
z = 25
the code
(1 << val)
shifts val into the appropriate value for its bit position,
so
a = 0 = 1
b = 1 = 2
c = 2 = 4
d = 3 = 8
etc
etc
z = 25 = 33554432
if ((checker & (1 << val)) > 0)
determines if the bit is already set in checker, indicating a duplicate character. If so the function returns false.
else
checker |= (1 << val)
sets the bit in checker via a binary OR and then loops round again.

find a number in another number without using Array

Recently i attended an interview where i was asked to write a function to find a term in a number and the number of times it occurs.
Lets say term = 51, number = 164518351, so 51 does exits in number and it occurs for 2 times, so return 2.
My Solution - Convert the number and term into string and , replace term string with "A" in the number string and then finally count the number of "A" in the number string. He asked me to solve without using strings, so i gave an array approach.
But he said that i cannot use arrays as well. so i want to know if there are other ways to do this ? I don't want the exact code or algo i just want to know various approaches we can take to solve this problem in minimum time complexity.
you can try something like this
int term_count = 0;
while(number > 0){
if(number % 100 == term)
term_count++;
number = number/10
}
This will check if the last two digits of the number is equal to the term, and continue doing so ignoring every unit digits of the number.
something like this
164518351 % 100 == 51
16451835 % 100 == 51
1645183 % 100 == 51
164518 % 100 == 51
....
of course, here i know that the term is two digits and so i mod by 100. if you don't know that, you can find the number of digits in the term and then mod number by
10^(num_of_digits_in_term)
you can find the number of digits like this
int tempTerm = term, termDigitCount = 0;
while(tempTerm > 0){
termDigitCount++;
tempTerm /= 10;
}
// 51 > 0 -> termDigitCount = 1
// 1 > 0 -> termDigitCount = 2
// 0 > 0 -> exit while loop
and in the end if the term_count is 0, then there is no occurrence of the term in the number
Hope this helps.
P.S - the solution may not be syntactically correct since OP does not want an exact answer. just the logic.

Please explain the logic behind Kernighan's bit counting algorithm

This question directly follows after reading through Bits counting algorithm (Brian Kernighan) in an integer time complexity . The Java code in question is
int count_set_bits(int n) {
int count = 0;
while(n != 0) {
n &= (n-1);
count++;
}
}
I want to understand what n &= (n-1) is achieving here ? I have seen a similar kind of construct in another nifty algorithm for detecting whether a number is a power of 2 like:
if(n & (n-1) == 0) {
System.out.println("The number is a power of 2");
}
Stepping through the code in a debugger helped me.
If you start with
n = 1010101 & n-1=1010100 => 1010100
n = 1010100 & n-1=1010011 => 1010000
n = 1010000 & n-1=1001111 => 1000000
n = 1000000 & n-1=0111111 => 0000000
So this iterates 4 times. Each iteration decrements the value in such a way that the least significant bit that is set to 1 disappears.
Decrementing by one flips the lowest bit and every bit up to the first one. e.g. if you have 1000....0000 -1 = 0111....1111 not matter how many bits it has to flip and it stops there leaving any other bits set untouched. When you and this with n the lowest bit set and only the lowest bit becomes 0
Subtraction of 1 from a number toggles all the bits (from right to left) till the rightmost set bit(including the righmost set bit).
So if we subtract a number by 1 and do bitwise & with itself (n & (n-1)), we unset the righmost set bit. In this way we can unset 1s one by one from right to left in loop.
The number of times the loop iterates is equal to the number of set
bits.
Source : Brian Kernighan's Algorithm

Categories

Resources