I created the byte array but don't know if this is the way you put strings of numbers into it. I am new to this byte array and am having trouble knowing if I did it right.
public class AdditionOnlyInt implements BigInt
{
private byte[] data;
public AdditionOnlyInt(String number)
{
data = new byte[number.length()];
number.replace("0","");
int i = 0;
int counter = number.length();
while(i<number.length())
{
data[i] = (byte) number.charAt(counter);
i++;
}
}
}
I have to get rid of the leading zeros then put the number in the array from least significant to most significant that is the reason for the counter variable
Try this..
public class AdditionOnlyInt implements BigInt
{
private byte[] data;
public AdditionOnlyInt(String number)
{
data = new byte[number.length()];
String num=number.replace("0","");
int i = 0;
int counter = number.length()-1;
while(counter>=0)
{
data[i++] = Byte.parseByte(String.valueOf(num.charAt(counter--)));
}
}
}
Well this is a bug:
number.replace("0","");
Firstly, it doesn't do anything: String is immutable, so all String methods return a new string, so you must assign the return value:
number = number.replace("0","");
Secondly, this with remove all zeroes - leading or otherwise. Not what you want. To remove leading zeroes, do this:
number = number.replaceAll("^0+","");
This uses a regex to target just the leading zeroes.
Finally, if you're trying to represent the digits of a number, use int[] and to get the integer value of a character, subtract '0':
int[] data;
data[i] = number.charAt(counter) - '0'; // '0' --> 0, '1' --> 1, '2' --> 2 etc
Make those changes and see if you get closer.
Related
I have a String of length >10^4 which has only binary numbers.
How can I take 1's complement of it ?
Example- Sting a = "0101"
I want String b = "1010"
Is there any better method other than replacing every character using StringBuffer/StringBuilder?
I suggest to avoid reinventing the wheel you use BigInteger. It’s not method gives you almost what you want, only it gives you a negative number when applied to a positive one. To get back into positive, add 2^n where n is the length of the original string:
String a = "0101";
BigInteger twoToLength = new BigInteger("2").pow(a.length());
String b = twoToLength.add(new BigInteger(a, 2).not()).toString(2);
System.out.println(b);
This prints:
1010
The argument 2 to the constructor and toString() is an radix indicating binary numbers.
We are not quite there yet: if the original string has leading ones, the leading zeroes in the result are not printed. You will have to prepend these manually to get the same string length as you had originally. I think the easiest way to do this is to add 2^(n+1) instead of 2^n so we are sure there is at least one 1 bit in front of the bits we really care about. So we remove this bit only after converting back to a string:
String a = "0101";
int length = a.length();
// add a couple of more bits in front to make sure we have a positive number
BigInteger twoToLengthPlus1 = BigInteger.ONE.shiftLeft(length + 1);
String b = twoToLengthPlus1.add(new BigInteger(a, 2).not()).toString(2);
// remove extra bits from the front again
b = b.substring(b.length() - length);
With this change 1010 becomes 0101.
Does it have to be a String? If a CharSequence is enough, you can do this:
public class BinaryComplementCharSequence implements CharSequence {
private final String source;
public BinaryComplementCharSequence(String source) {
this.source = source;
}
#Override
public int length() {
return source.length();
}
#Override
public char charAt(int index) {
switch (source.charAt(index)) {
case '0':
return '1';
case '1':
return '0';
default:
throw new IllegalStateException();
}
}
#Override
public CharSequence subSequence(int start, int end) {
return new BinaryComplementCharSequence(source.substring(start, end));
}
#Override
public String toString() {
return new StringBuilder(length()).append(this).toString();
}
}
If you really need a String, call toString() (but that uses a StringBuilder again).
You've already figured it out: use a StringBuilder and replace every bloody char individually.
You could also use a char array: char ca[] = str.toCharArray() to extract the characters, modify individual chars in ca, String newstr =new String(ca) to pack the array back into a String. Might be slightly faster.
Take your pick.
Every char check with '1' and invert:
char[] charsConverted = new char[a.length()];
char[] charArray = a.toCharArray();
for (int i = 0; i < charArray.length; i++) {
boolean b = charArray[i] == '1';
charsConverted[i] = !b ? '1' : '0';
}
String b= String.valueOf(charsConverted);
First off, here is my code so far
public int encrypt() {
/* This method will apply a simple encrypted algorithm to the text.
* Replace each character with the character that is five steps away from
* it in the alphabet. For instance, 'A' becomes 'F', 'Y' becomes '~' and
* so on. Builds a string with these new encrypted values and returns it.
*/
text = toLower;
encrypt = "";
int eNum = 0;
for (int i = 0; i <text.length(); i++) {
c = text.charAt(i);
if ((Character.isLetter(c))) {
eNum = (int) - (int)'a' + 5;
}
}
return eNum;
}
(text is the inputted string by the way. And toLower makes the string all lower case to make it easier converting.)
I got most of my assignment done, but one part of it is tasking me with moving every letter inputted 5 spaces over. A becomes F, B becomes G, etc.
So far from I got the letter converted to a number, but I am having trouble adding to it and then returning it back to a letter.
When I run the program and I enter my input such as "abc" I get '8'. It just adds them all up.
Any help would be much appreciated, and I can post the full code if necessary.
Few issues -
First of all - eNum = (int) - (int)'a' + 5; you do not need the first (int) - i believe, you can just do - eNum = (int)c + 5; . Your expression would always result in a negative integer.
Instead of returning eNum you should convert it to character and add it to a string and return the string at end (or you can create a character array of same length as string , keep storing the characters in the array, and return a string created from the character array).
Instead of using a in the condition , you should use c which denotes the current character at the ith index.
I am guessing not all of the variables in your code are member variables (instance variables) of the class , so you should define them with a datatype in your code.
Example changes to your code -
String text = toLower; //if toLower is not correct, use a correct variable to get the data to encrypt from.
String encrypt = "";
for (int i = 0; i <text.length(); i++) {
char c = text.charAt(i);
if ((Character.isLetter(c))) {
encrypt += (char)((int)c + 5);
}
}
return encrypt;
//Just a quick conversion for testing
String yourInput = "AbC".toLowerCase();
String convertedString = "";
for (int i = 0; i <text.length(); i++) {
char c = yourInput.charAt(i);
int num = Character.getNumericValue(c);
num = (num + 5)%128 //If you somehow manage to pass 127, to prevent errors, start at 0 again using modulus
convertedString += Integer.toString(num);
}
System.out.println(convertedString);
Hope this is what you're looking for.
Try something like this, I believe this has several advantages:
public String encrypt(String in) {
String workingCopy = in.toLowerCase();
StringBuilder out = new StringBuilder();
for (int i = 0; i < workingCopy.length(); i++) {
char c = workingCopy.charAt(i);
if ((Character.isLetter(c))) {
out.append((char)(c + 5));
}
}
return out.toString();
}
This code is a little bit verbose, but perhaps then it is easier to follow. I introduced the StringBuilder because it is more efficient than doing string = string + x
Heres my code that takes a string and returns an array of the ascii values for each character in the array in order. Compile error is 'array required, but java.lang.String found'
public class Q1E {
int[] stringToCodes(String characters){
int characterLength= length(characters);
int[] array=new int[characterLength];
for(int i=0;i<characterLength;i++) {
array[i] =(int) characters[i];
}
}
}
You can't use array syntax on a String, use character.charAt(i)instead. Also, you need to return the array at the end.
Java uses Unicode/UTF-16 for strings, not ASCII.
If want to restrict your method to processing characters in the ASCII range, it should throw an exception when it encounters one outside that range.
If you want a sequence of "character codes" (aka codepoints), you have to use the String.codePointAt() at method. Because String holds a counted sequences of UTF-16 code-units and there might be one or two code-units per codepoint, you only know that String.length() is an upper bound of the number of codepoints in advance.
public class Q1E {
int[] stringToCodes(String s) {
int[] codepoints = new int[s.length()]; // there might be fewer
int count = 0;
for(int cp, i = 0; i < s.length(); i += Character.charCount(cp)) {
cp = s.codePointAt(i);
// for debugging, output in Unicode stylized format
System.out.println(String.format(
cp < 0x10000 ? "U+%04X" : "U+%05X", cp));
codepoints[count++] = cp;
}
int[] array = java.util.Arrays.copyOf(codepoints, count);
return array;
}
}
Try it with this Wikipedia link on an English word:
stringToCodes("http://en.wikipedia.org/wiki/Résumé");
Your code appears to have a few bugs, it's String#length() and I would suggest you add a null check. Finally (since characters isn't an array), I think you want to use String#charAt(int)
int[] stringToCodes(String characters) {
int characterLength = 0;
if (characters != null) {
characterLength = characters.length();
}
int[] array = new int[characterLength];
for (int i = 0; i < characterLength; i++) {
array[i] = characters.charAt(i);
}
return array;
}
Of course, you could shorten it with a ternary
int characterLength = (characters != null) ? characters.length() : 0;
int[] array = new int[characterLength];
try this:
public class Test {
public static void main(String[] args) {
int []ascii=stringToCodes("abcdef");
for(int i=0;i<ascii.length;i++){
System.out.println(ascii[i]);
}
}
public static int [] stringToCodes(String characters){
int []ascii=new int[characters.length()];
for(int i=0;i<characters.length();i++){
ascii[i]=(int)characters.charAt(i);
}
return ascii;
}
}
I'm making a tool for optimizing script and now I want to compress all names in it to the minimum.
I got the function started for it, but it somehow bugs and stops after length 2 is exceeded.
Is there an easier way to do this? I just need a pattern that generates a String starting from a -> z then aa -> az ba -> bz and so on.
public String getToken() {
String result = ""; int i = 0;
while(i < length){
result = result + charmap.substring(positions[i], positions[i]+1);
positions[length]++;
if (positions[current] >= charmap.length()){
positions[current] = 0;
if ( current < 1 ) {
current++;length++;
}else{
int i2 = current-1;
while( i2 > -1 ){
positions[i2]++;
if(positions[i2] < charmap.length()){
break;
}else if( i2 > 0 ){
positions[i2] = 0;
}else{
positions[i2] = 0;
length++;current++;
}
i2--;
}
}
}
i++;
}
return result;
}
UNLIKE THE OTHER QUESTIONS!! I dont just want to increase an integer, the length increases to much.
Here's one I used
public class AsciiID {
private static final String alphabet=
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private int currentId;
public String nextId() {
int id = currentId++;
StringBuilder b = new StringBuilder();
do {
b.append(alphabet.charAt(id % alphabet.length()));
} while((id /=alphabet.length()) != 0);
return b.toString();
}
}
I would use a base 36 or base 64 (depending on case sensitivity) library and run it with an integer and before you output, convert the integer to a base 36/64 number. You can think in terms of sequence, which is easier, and the output value is handled by a trusted library.
You can use:
Integer.toString(i++, Character.MAX_RADIX)
It's base36. It will be not as greatly compressed as Base64 but you have a 1-line implementation.
You could search for some library that operates numbers of any radix, say 27, 37 or more. Then you output that number as alphanumeric string (like HEX, but with a-zA-Z0-9).
Well let's assume we can only output ASCII (for unicode this problem gets.. complicated): As a quick look shows its printable characters are in the range [32,126]. So to get the most efficient representation of this problem we have to encode a given integer in base 94 so to speak and add 32 to any generated char.
How you do that? Look up how Sun does it in Integer.toString() and adapt it accordingly. Well it's probably more complex than necessary - just think about how you convert a number into radix 2 and adapt that. In its simplest form that's basically a loop with one division and modulo.
In your tool you need to create a dictionary, which will contain an unique integer id for each unique string and the string itself. When adding strings to the dictionary you increment given id for each newly added unique string. Once dictionary is completed, you can simply convert ids to String using something like this:
static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static final int CHARS_LENGTH = CHARS.length();
public String convert(int id) {
StringBuilder sb = new StringBuilder();
do {
sb.append(CHARS.charAt(id % CHARS_LENGTH));
id = id / CHARS_LENGTH;
} while(id != 0);
return sb.toString();
}
This function generates the Nth Bijective Number (except zeroth). This is the most optimal coding ever possible. (The zeroth would be an empty string.)
If there were 10 possible characters, 0-9, it generates, in order:
10 strings of length 1, from "0" to "9"
10*10 strings of length 2, from "00" to "99"
10*10*10 strings of length 3, from "000" to "999"
etc.
The example uses 93 characters, because I just happened to need those for Json.
private static final char[] ALLOWED_CHARS =
" !#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~"
.toCharArray();
private static final AtomicInteger uniqueIdCounter = new AtomicInteger();
public static String getToken() {
int id = uniqueIdCounter.getAndIncrement();
return toBijectiveNumber(id, ALLOWED_CHARS);
}
public static String toBijectiveNumber(int id, char[] allowedChars) {
assert id >= 0;
StringBuilder sb = new StringBuilder(8);
int divisor = 1;
int length = 1;
while (id >= divisor * allowedChars.length) {
divisor *= allowedChars.length;
length++;
id -= divisor;
}
for (int i = 0; i < length; i++) {
sb.append(allowedChars[(id / divisor) % allowedChars.length]);
divisor /= allowedChars.length;
}
return sb.toString();
}
I am probably overlooking something silly, but I've never had to deal with binary in code and thought it'd be a good idea to practice it in an encryption program, for kicks.
Long story short, I'm able to convert a string into binary (in the form of a string), but can't figure out how to do the reverse.
Right now, I have something like this:
public static String bytesToString(String bytes){
int i = bytes.length()/8;
int pos = 0;
String result = "";
for(int j=0; j<i; j++){
String temp = bytes.substring(pos,pos+8);
byte b = (byte) Integer.parseInt(temp);
result = result + Byte.toString(b);
pos++;
}
System.out.println("Result: " + result);
return result;
}
I think the bytes are being parsed as literal numbers. What am I missing?
Edit: To clarify, I will previously have parsed a string of text into bits and written them to a string. I want to split this string into bytes and parse them back into letters. It would take "011010000110010101111001" and return "hey".
How about using Integer.parseInt(text, 2)? As in,
public static int binaryToInt(String binary)
{
return Integer.parseInt(binary, 2);
}
I'm not sure why your binaryToString method both takes and returns a string.
Integer.parseInt(temp) will attempt to read temp as a number and return the corresponding int. For example, Integer.parseInt("123") returns 123
EDIT: Be aware that the binary value of a character or text depends on the encoding you are using. For example "hi" is 0110100001101001 in ASCII but it may not in UTF-16 or UTF-32. And Java encodes characters into UTF-16 characters: see http://download.oracle.com/javase/6/docs/api/java/lang/String.html
(for this reason Java chars are 16-bit unsigned integers).
So your bytesToString method must treat input differently depending on the encoding of the input. Or you may write it specifically for ASCII characters, and maybe rename it to, say, asciiBytesToString
You'd better see:
constructor String(byte[])
http://download.oracle.com/javase/6/docs/api/java/lang/String.html
Integer.parseInt(String s, int radix) http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html
public class BinaryStringToChars {
public static void main(String[] args) {
String bin = "011010000110010101111001";
StringBuilder b = new StringBuilder();
int len = bin.length();
int i = 0;
while (i + 8 <= len) {
char c = convert(bin.substring(i, i+8));
i+=8;
b.append(c);
}
System.out.println(b.toString());
}
private static char convert(String bs) {
return (char)Integer.parseInt(bs, 2);
}
}
You need to advance 8 digits at a time, not digit by digit. Otherwise you are reusing bits. Also, you need to tell Integer.parseInt() what radix you want to use, since parseInt(String val) cannot really detect binary (you want Integer.parseInt(String val, int radix). You also need to choose a character encoding to convert bytes into characters (they are not the same thing!). Assuming ISO-8859-1 is ok:
public static String bytesToString(String bytes){
int i = bytes.length()/8;
int pos = 0;
String result = "";
byte[] buffer = new byte[i];
for(int j=0; j<i; j++){
String temp = bytes.substring(pos,pos+8);
buffer[j] = (byte) Integer.parseInt(temp, 2);
pos+=8;
}
result = new String(buffer, "ISO-8859-1");
System.out.println("Result: " + result);
return result;
}