I'm trying to convert an integer to a 7 bit Boolean binary array. So far the code doesn't work:
If i input say integer 8 to be converted, instead of 0001000 I get 1000000, or say 15 I should get 0001111 but I get 1111000. The char array is a different length to the binary array and the positions are wrong.
public static void main(String[] args){
String maxAmpStr = Integer.toBinaryString(8);
char[] arr = maxAmpStr.toCharArray();
boolean[] binaryarray = new boolean[7];
for (int i=0; i<maxAmpStr.length(); i++){
if (arr[i] == '1'){
binaryarray[i] = true;
}
else if (arr[i] == '0'){
binaryarray[i] = false;
}
}
System.out.println(maxAmpStr);
System.out.println(binaryarray[0]);
System.out.println(binaryarray[1]);
System.out.println(binaryarray[2]);
System.out.println(binaryarray[3]);
System.out.println(binaryarray[4]);
System.out.println(binaryarray[5]);
System.out.println(binaryarray[6]);
}
Any help is appreciated.
There's really no need to deal with strings for this, just do bitwise comparisons for the 7 bits you're interested in.
public static void main(String[] args) {
int input = 15;
boolean[] bits = new boolean[7];
for (int i = 6; i >= 0; i--) {
bits[i] = (input & (1 << i)) != 0;
}
System.out.println(input + " = " + Arrays.toString(bits));
}
I would use this:
private static boolean[] toBinary(int number, int base) {
final boolean[] ret = new boolean[base];
for (int i = 0; i < base; i++) {
ret[base - 1 - i] = (1 << i & number) != 0;
}
return ret;
}
number 15 with base 7 will produce {false, false, false, true, true, true, true} = 0001111b
number 8, base 7 {false, false, false, true, false, false, false} = 0001000b
Hints: Think about what happens when you get a character representation that's less than seven characters.
In particular, think about how the char[] and boolean[] arrays "line up"; there will be extra elements in one than the other, so how should the indices coincide?
Actual answer: At the moment you're using the first element of the character array as the first element of the boolean array, which is only correct when you're using a seven-character string. In fact, you want the last elements of the arrays to coincide (so that the zeros are padded at the front not at the end).
One way to approach this problem would be to play around with the indices within the loop (e.g. work out the size difference and modify binaryarray[i + offset] instead). But an even simpler solution is just to left pad the string with zeros after the first line, to ensure it's exactly seven characters before converting it to the char array.
(Extra marks: what do you do when there's more than 7 characters in the array, e.g. if someone passes in 200 as an argument? Based on both solutions above you should be able to detect this case easily and handle it specifically.)
What you get when you do System.out.println(maxAmpStr); is "1000" in case of the 8.
So, you only get the relevant part, the first "0000" that you expected is just ommitted.
It's not pretty but what you could do is:
for (int i=0; i<maxAmpStr.length(); i++)
{
if (arr[i] == '1')
{
binaryarray[i+maxAmpStr.length()-1] = true;
}
else if (arr[i] == '0')
{
binaryarray[i+maxAmpStr.length()-1] = false;
}
}
Since nobody here has a answer with a dynamic array length, here is my solution:
public static boolean[] convertToBinary(int number) {
int binExpo = 0;
int bin = 1;
while(bin < number) { //calculates the needed digits
bin = bin*2;
binExpo++;
}
bin = bin/2;
boolean[] binary = new boolean[binExpo]; //array with the right length
binExpo--;
while(binExpo>=0) {
if(bin<=number) {
binary[binExpo] = true;
number =number -bin;
bin = bin/2;
}else {
binary[binExpo] = false;
}
binExpo--;
}
return binary;
}
The char-array is only as long as needed, so your boolean-array might be longer and places the bits at the wrong position. So start from behind, and when your char-array is finished, fill your boolean-array with 0's until first position.
Integer.toBinaryString(int i) does not pad. For e.g. Integer.toBinaryString(7) prints 111 not 00000111 as you expect. You need to take this into account when deciding where to start populating your boolean array.
15.ToBinaryString will be '1111'
You are lopping through that from first to last character, so the first '1' which is bit(3) is going into binaryArray[0] which I'm assuming should be bit 0.
You ned to pad ToBinaryString with leading zeros to a length of 7 (8 ??)
and then reverse the string, (or your loop)
Or you could stop messing about with strings and simply use bit wise operators
BinaryArray[3] = (SomeInt && 2^3 != 0);
^ = power operator or if not (1 << 3) or whatever is left shift in Java.
public static boolean[] convertToBinary(int b){
boolean[] binArray = new boolean[7];
boolean bin;
for(int i = 6; i >= 0; i--) {
if (b%2 == 1) bin = true;
else bin = false;
binArray[i] = bin;
b/=2;
}
return binArray;
}
public static String intToBinary(int num) {
int copy = num;
String sb = "";
for(int i=30; i>=0; i--) {
sb = (copy&1) + sb;
copy = copy >>>=1;
}
return sb;
}
AND the number with 1
Append the vale to a string
do unsigned right shift
repeat steps 1-3 for i=30..0
String maxAmpStr = Integer.toBinaryString(255);
char[] arr = maxAmpStr.toCharArray();
boolean[] binaryarray = new boolean[20];
int pivot = binaryarray.length - arr.length;
int j = binaryarray.length - 1;
for (int i = arr.length - 1; i >= 0; i--) {
if (arr[i] == '1') {
binaryarray[j] = true;
} else if (arr[i] == '0') {
binaryarray[j] = false;
}
if (j >= pivot)
j--;
}
System.out.println(maxAmpStr);
for (int k = 0; k < binaryarray.length; k++)
System.out.println(binaryarray[k]);
}
Related
iv made a method to check if a given number is symmetric or not.
-the method is based on the idea that the given number is an array .
-i gave the methood 4 deifferent parameters- numberLength , middle , point1,point2(both pointing at a certain digit in the number(as an array))
-although wrote the code correctly , and it works when im initializing a specific array ,
i dont know how to use the method for a given number .
How can i set this Method - with parameter (int number) , so i can chek on the given number.
Thank you A lot
update** i added the code :
public boolean isSymmetric(int num){
int digits;
int[] number;
number = new int[num];
int length = number.length;
int mid;
if(length%2 == 0) //
{
mid = length/2;
}else {
mid = length/2+1;
}
int pointer1 =0;
int pointer2 = mid;
while(pointer1<mid && pointer2 < length)
{
if(number[pointer1] == number[pointer2])
{
pointer1=pointer1+1;
pointer2=pointer2+1;
}
else
System.out.println("number is not symmetric");
return false;
}
System.out.println("number is symmetric");
return true;
}
The easiest way to check if number symmetric or not is to map it to String::class, just like this:
// Your input number
Integer maybeSymmetricNumber = 12321;
String str = String.valueOf(maybeSymmetricNumber), reverseStr = "";
int strLength = str.length();
for (int i = (strLength - 1); i >=0; --i) {
reverseStr = reverseStr + str.charAt(i);
}
if (str.toLowerCase().equals(reverseStr.toLowerCase())) {
System.out.println(str + " is a symmetric number.");
}
else {
System.out.println(str + " is not a symmetric number.");
}
First, here is a method to convert your number to an array of ints.
it works by using the Math.log10 to compute the exponent of 10 for that number.
e.g. Math.log10(1234) = 3.xxx. So convert to an int and add 1 to get 4.
e.g. Math.log10(1000) = 3 so do the same thing.
then use that number to create an array of proper size.
and use the remainder(%) and division(/) operators to populate it.
then return the array.
public static int[] toArray(int number) {
number = Math.abs(number);
int[] arr = new int[(int) Math.log10(number)+1];
int i = 0;
while (number > 0) {
arr[i++] = number%10;
number/=10;
}
return arr;
}
Unfortunately, your method doesn't work properly as it always returns false. This is because of missing {} around the following.
else
System.out.println("number is not symmetric");
return false;
But it still doesn't process all values properly. Try 1234321 and 112211. They both return false but are symmetric. This is because pointer1 starts at 0 and pointer2 starts at mid and they are both incremented by 1.
I suggest you start pointer2 at length-1, going from outside in toward mid. This should then solve the issue (with a little debugging of course).
I Find longest sequence of zeros in binary representation of an integer but result incorrect on app.codility.com with n = 6 and n =328
https://imgur.com/rzFsjaY
public int solution(int N) {
Integer result = 1;
StringBuilder modNumber = new StringBuilder();
while (result > 0) {
result = n / 2;
modNumber.append(n % 2 + "");
n = result;
}
int length = modNumber.length();
String modString = modNumber.toString();
Integer binaryGap = 0;
List<Integer> lstResult = new ArrayList<>();
Boolean isBinaryGap = false;
if (modString.charAt(0) == '0') {
binaryGap = 0;
} else {
for (int i = 1; i < length; i++) {
char c = modString.charAt(i);
if (c == '0') {
binaryGap += 1;
isBinaryGap = true;
} else {
isBinaryGap = false;
}
if(!isBinaryGap) {
lstResult.add(binaryGap);
binaryGap = 0;
}
}
}
int max=0;
if(!lstResult.isEmpty()) {
max = lstResult.stream().collect(Collectors.summarizingInt(Integer::intValue)).getMax();
}
return max;
}
The problem is this part:
if (modString.charAt(0) == '0') {
binaryGap = 0;
} else {
I suspect your intention is to handle the case of the input being zero (so why not do that right off the bat, using the original value of N?), but you get many false positives because your technique for forming the string places the bits in order from least-significant to most-significant. The least-significant bit is zero for every even number, and you therefore report a gap of 0 for all of them, but the only even number for which that's the correct result is 0.
I'm sure that with that information you could fix your code to produce the correct results, but the problem would not even have arisen if you had chosen a simpler approach. For example, how about scanning the binary representation just once, keeping track of the current and maximum gap lengths as you go? You already perform the needed scan, but instead of just computing the result directly, you go through all that mess of building and then analyzing a string representation. Simpler code leaves less room for bugs, and when they arise, they are usually easier to spot.
I'm having a little trouble wrapping my head around this logic and thought I had a fix but am stumped now.
The goal is to create a 4 digit pin and have 3 unique numbers and 1 can be a duplicate. They can be in any order as well. Here is what i have so far:
boolean UniqueNums(String nums)
{
for (int i=0; i < 3; i++)
for (int j=i+1; j < 3; j++)
if (nums.charAt(i) == nums.charAt(j))
return false;
// If no duplicate characters encountered,
// return true
return true;
}
So if i pass the numbers 1137 it fails but other like 1371 pass.
I feel this is the different then the linked duplicate answer link, due to im not trying to do it in one line and I'm not just counting the number of times the number occurs. More a long the lines of validating the values being passed.
Any help or advice would be appreciated.
What about:
boolean UniqueNums(String data) {
Set<Character> found = new HashSet<>();
int count = 0;
for (char c : data.toCharArray()) {
boolean noClash = found.add(c);
count += (noClash ? 0 : 1);
if (count == 2) {
return false;
}
}
return true;
}
1234 returns true (no duplicate)
1231 returns true (a single duplicate)
1221 returns false (a pair of duplicates)
1112 returns false (a number used more than twice)
It also works if your PIN is longer then 4 characters, it only requires a single loop making it O(n), and it fails fast
Instead of nested for loops (with complexity O(n^2)), you can use hashing to count the occurrences of each digit and then check for valid pin number. Here is algorithm:
static boolean UniqueNums(String digit){
int array[] = new int[10];
for (int i=0;i<digit.length();i++){
array[digit.charAt(i)-48]++; //48 because ascii of 0 is 48
}
//Now check for frequency
int count = 0;
for (int i=0;i<10;i++){
if(array[i] > 2) return false;
if(array[i] == 2){
++count;
}
}
if(count <= 1) return true;
return false;
}
This will be of O(k), where k is number of digits in your number.
Because of the numeric limitations involved, your predicate can be reduced from:
a 4 digit pin and have 3 unique numbers and 1 can be a duplicate. they can be in any order as well.
to
have 3 unique characters
(Your code doesn't test for digits and length so I assume some other code does that.)
boolean hasAtLeastThreeUniqueCharacters = "1123".codePoints().distinct().count() >= 3;
You only need one additional int to maintain bit mask for each of the digits. A short would do but it gets widened to int in Integer.bitCount() call either way.
boolean uniqueNums(String nums) {
int pin = Integer.parseInt(nums);
int mask = 0;
for (int i = 0; i < nums.length(); i++) {
mask |= 1 << pin % 10;
pin /= 10;
}
return Integer.bitCount(mask) >= 3;
}
resulting in
uniqueNums("1234") // true
uniqueNums("9393") // false
You could also group numbers by occurrences, filter those which are at most 2 occurrences and so that their count could be as long as num length, or length - 1 (one duplicate) :
boolean atMostOneOneDuplicate(String num) {
long occurences = num.chars()
.mapToObj(i -> (char) i)
.collect(Collectors.groupingBy(c -> c, Collectors.counting()))
.entrySet()
.stream()
.map(Map.Entry::getValue)
.filter(v -> v < 3)
.count();
return occurences == num.length() || occurences == num.length() - 1;
}
I think keeping counters in a Map is simpler:
public boolean UniqueNums(String pin){
if(pin.length() > 4) {
//pin too long
return false;
}
Map<Character, Integer> counters = new HashMap<>();
for(int i = 0; i < pin.length(); i++){
Character c = pin.charAt(i);
if(!Character.isDigit(c)){
//not a number.
return false;
}
counters.put(c, counters.getOrDefault(c,0) + 1);
if(counters.get(i) > 2){
// digit appear 3 times.
return false;
}
}
if(counters.keySet().size() < pin.length() - 1){
// not 3 unique numbers e.g 1122
return false;
}
return true;
}
Use a map to keep track of occurances
import java.util.HashMap;
import java.util.Map;
class Main{
public static void main(String[] args) {
System.out.println(isValid("1137"));
System.out.println(isValid("1371"));
System.out.println(isValid("1234"));
System.out.println(isValid("1222"));
}
public static boolean isValid(String num){
Map<Character,Integer> digitsWithNumberOfOccurances = new HashMap<>();
int numOfDigitsThatOccuredTwice = 0;
for(int i = 0; i < num.length(); i++){
char currentChar = num.charAt(i);
int currentNumberOfOccurences = digitsWithNumberOfOccurances.getOrDefault(currentChar,0);
currentNumberOfOccurences ++;
digitsWithNumberOfOccurances.put(currentChar,currentNumberOfOccurences);
if(currentNumberOfOccurences == 2){
numOfDigitsThatOccuredTwice++;
// only one digit can occur twice
if(numOfDigitsThatOccuredTwice > 1) {
return false;
}
}else if(currentNumberOfOccurences > 2){ // no digit can occur more than twice
return false;
}
}
return true;
}
}
I need to write a method for comparing two binary numbers. I am storing the binary numbers in character arrays, so I can store big numbers (I can't use the BigInteger class or any other packages).
Example to make things clear:
char[] num1 = {'1','1','0'}
char[] num2 = {'1','1','1'}
I need to return 0 if they are equal, -1 if a < b and 1 if a > b
This is the approach I took:
static int compare(char[]a, char[]b) {
//If arrays lengths aren't equal I already know, one is bigger then the other
int a_len = a.length;
int b_len = b.length;
int a_bits = 0;
int b_bits = 0;
if (a_len > b_len)
return 1;
if (b_len > a_len)
return -1;
//I count the number of bits that are 1 in both arrays
for (int i = 0; i < a.length; i++) {
if (a[i] == '1') a_bits++;
if (b[i] == '1') b_bits++;
}
if(a_bits>b_bits)
return 1;
if(b_bits>a_bits)
return -1;
return 0;
}
So as far as I understand, this works in every case, but the case where the number of bits are equal (1100 is bigger than 1001 for example).
I was thinking I could add up the indexes in the for loop for each array and work from there, but I started thinking I may be overcomplicating things. Is this even a good approach to it? I'm starting to doubt it. Any insight is appreciated
I would look for the first index that is 1 in one of the numbers but 0 in the other number. You can replace the bit counting loop(keeping the length check) with:
for (int i = 0; i < a.length; i++) {
if (a[i] == '1' && b[i] == '0') return 1;
if (b[i] == '1' && a[i] == '0') return -1;
}
return 0;
Using some conversion and the binary parseInt offered by class Integer you can do this simple comparison regardless of the arrays' size. (I'd be careful instead with checking the length of the arrays because if you have leading zeros in one array this could bring some comparisons to miss).
String first = new String(a);
String second = new String(b);
int firstint = Integer.parseInt(first, 2);
int secondint = Integer.parseInt(second, 2);
if(firstint > secondint)
return 1;
if(firstint < secondint)
return -1;
return 0;
An alternative approach would be as follows:
Convert Array Of Characters into String.
Convert the resulting String into int.
Work out the logic from the resulting int
It will always work and you can print out the resulting conversion.
Hope this helps.
public static void main(String[] args) {
char[] num1 = {'1','1','0'};
char[] num2 = {'1','1','1'};
System.out.println(compare(num1, num2));
}
public static int compare(char[]num1, char[]num2) {
// Convert Array of Characters to String
String one = String.valueOf(num1);
String two = String.valueOf(num2);
// Convert to Integer (Binary to Decimal Conversion to base2)
int a = Integer.parseInt(one,2);
int b = Integer.parseInt(two,2);
int result = 0; // return result as equals i.e. 0.
if(a > b) { // Yes. Curly brackets are important in Java
result = 1;
} else if(a < b){
result = -1;
}
return result; // Use only one return, i.e. a variable.
}
I'm having the hardest time trying to get my class to work properly. It's a natural number class with methods like increase and decrease. I'm trying to make it immutable, and I'm stuck. If I increment a number such that it's least significant digit isn't 9, it works fine. But once I get to the boundary case, it fails.
IE. I have a number that's 69999, I increment it and it's 7.
private SlowBigNatural(int[] natural, int nSize){
this.nSize = nSize - 1;
this.natural = new int[this.nSize];
for (int i = 0; i < this.nSize; i++) {
this.natural[i] = natural[i];
}
}
#Override
public BigNatural increment() {
int[] nClone = natural.clone();
if (nSize == 1 || nClone[nSize - 1] != HIGHEST) {
nClone[nSize - 1]++;
String nString = "";
for(int i = 0; i < nSize; i++){
nString += String.valueOf(nClone[i]);
}
BigNatural nInc = new SlowBigNatural(nString);
return nInc;
}
else {
nClone[nSize - 1] = 0;
BigNatural temp = new SlowBigNatural(nClone, nSize);
return temp.increment();
}
}
I'm a little confused as to the endianness of your BigNatural. You don't explicitly mention how you're storing your number. You can either store with the most significant digit first, or least significant digit first.
That is the number 12,345 can be stored as {1,2,3,4,5} (Big Endian) or {5,4,3,2,1} (Little Endian).
If your increment is correct then getting 7 from adding 1 to 69,999 is likely a problem with endianness.
That is {7,0,0,0,0} is 70,000 if Big Endian or 7 if Little Endian. Check the string constructor. See what endianness it expects.
The problem is in the else. You have to compose the number after increment:
else {
nClone[nSize - 1] = 0;
BigNatural temp = new SlowBigNatural(nClone, nSize);
BigNatural incremented = temp.increment();
return new SlowBigNatural(addElement(incremented.natural, 0), nSize + 1);
}
private int[] addElement(int[] arr, int element) {
int[] copy = new int[arr.length+1];
for (int index = 0; index < arr.length+1; index++){
copy[index] = arr[index-1];
}
copy[arr.length] = element;
return copy;
}