Converting an integer to a 3 character String (base62)
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
I wrote a code to convert an Integer
between 1 and 238328 to a unique String
, formed from base62 characters (A-Za-z0-9) and of length 3. The String
generated can be reconverted to get back the initial Integer
.
For example, if the number was 238328 I can convert it to "zzz". I want to be able to use that String
"zzz" and get back the number 238328. I have written 2 methods to perform these operations and based on my testing it is working fine.
I am looking for some inputs on making it more readable and possibly more efficient. The conversion consists of 3 nested loops which really does not look right, though I can't get my head around a better way to do this.
class Permutation
private final String DICTIONARY = new String
"0","1","2","3","4","5","6","7","8","9",
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z";
private Map<String, Integer> codes = new HashMap<>();
private Map<Integer, String> numbers = new HashMap<>();
String generateCode(int num) num < 1) return null;
if(numbers.containsKey(num))
return numbers.get(num);
int counter = 0;
for (int i = 0; i < DICTIONARY.length; i++)
for (int j = 0; j < DICTIONARY.length; j++)
for (int k = 0; k < DICTIONARY.length; k++)
String code = DICTIONARY[i] + DICTIONARY[j] + DICTIONARY[k];
counter++;
numbers.put(counter, code);
codes.put(code, counter);
if(counter == num) return code;
return null;
int decode(String code)
if(codes.containsKey(code))
return codes.get(code);
return 0;
java algorithm
add a comment |Â
up vote
3
down vote
favorite
I wrote a code to convert an Integer
between 1 and 238328 to a unique String
, formed from base62 characters (A-Za-z0-9) and of length 3. The String
generated can be reconverted to get back the initial Integer
.
For example, if the number was 238328 I can convert it to "zzz". I want to be able to use that String
"zzz" and get back the number 238328. I have written 2 methods to perform these operations and based on my testing it is working fine.
I am looking for some inputs on making it more readable and possibly more efficient. The conversion consists of 3 nested loops which really does not look right, though I can't get my head around a better way to do this.
class Permutation
private final String DICTIONARY = new String
"0","1","2","3","4","5","6","7","8","9",
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z";
private Map<String, Integer> codes = new HashMap<>();
private Map<Integer, String> numbers = new HashMap<>();
String generateCode(int num) num < 1) return null;
if(numbers.containsKey(num))
return numbers.get(num);
int counter = 0;
for (int i = 0; i < DICTIONARY.length; i++)
for (int j = 0; j < DICTIONARY.length; j++)
for (int k = 0; k < DICTIONARY.length; k++)
String code = DICTIONARY[i] + DICTIONARY[j] + DICTIONARY[k];
counter++;
numbers.put(counter, code);
codes.put(code, counter);
if(counter == num) return code;
return null;
int decode(String code)
if(codes.containsKey(code))
return codes.get(code);
return 0;
java algorithm
As you noticed, it is base 62. Conversion is a simple matter of 3 multiplications/divisions.
â vnp
Mar 20 at 19:56
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I wrote a code to convert an Integer
between 1 and 238328 to a unique String
, formed from base62 characters (A-Za-z0-9) and of length 3. The String
generated can be reconverted to get back the initial Integer
.
For example, if the number was 238328 I can convert it to "zzz". I want to be able to use that String
"zzz" and get back the number 238328. I have written 2 methods to perform these operations and based on my testing it is working fine.
I am looking for some inputs on making it more readable and possibly more efficient. The conversion consists of 3 nested loops which really does not look right, though I can't get my head around a better way to do this.
class Permutation
private final String DICTIONARY = new String
"0","1","2","3","4","5","6","7","8","9",
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z";
private Map<String, Integer> codes = new HashMap<>();
private Map<Integer, String> numbers = new HashMap<>();
String generateCode(int num) num < 1) return null;
if(numbers.containsKey(num))
return numbers.get(num);
int counter = 0;
for (int i = 0; i < DICTIONARY.length; i++)
for (int j = 0; j < DICTIONARY.length; j++)
for (int k = 0; k < DICTIONARY.length; k++)
String code = DICTIONARY[i] + DICTIONARY[j] + DICTIONARY[k];
counter++;
numbers.put(counter, code);
codes.put(code, counter);
if(counter == num) return code;
return null;
int decode(String code)
if(codes.containsKey(code))
return codes.get(code);
return 0;
java algorithm
I wrote a code to convert an Integer
between 1 and 238328 to a unique String
, formed from base62 characters (A-Za-z0-9) and of length 3. The String
generated can be reconverted to get back the initial Integer
.
For example, if the number was 238328 I can convert it to "zzz". I want to be able to use that String
"zzz" and get back the number 238328. I have written 2 methods to perform these operations and based on my testing it is working fine.
I am looking for some inputs on making it more readable and possibly more efficient. The conversion consists of 3 nested loops which really does not look right, though I can't get my head around a better way to do this.
class Permutation
private final String DICTIONARY = new String
"0","1","2","3","4","5","6","7","8","9",
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z";
private Map<String, Integer> codes = new HashMap<>();
private Map<Integer, String> numbers = new HashMap<>();
String generateCode(int num) num < 1) return null;
if(numbers.containsKey(num))
return numbers.get(num);
int counter = 0;
for (int i = 0; i < DICTIONARY.length; i++)
for (int j = 0; j < DICTIONARY.length; j++)
for (int k = 0; k < DICTIONARY.length; k++)
String code = DICTIONARY[i] + DICTIONARY[j] + DICTIONARY[k];
counter++;
numbers.put(counter, code);
codes.put(code, counter);
if(counter == num) return code;
return null;
int decode(String code)
if(codes.containsKey(code))
return codes.get(code);
return 0;
java algorithm
edited Mar 20 at 23:51
Phrancis
14.6k645137
14.6k645137
asked Mar 20 at 19:35
karvai
184
184
As you noticed, it is base 62. Conversion is a simple matter of 3 multiplications/divisions.
â vnp
Mar 20 at 19:56
add a comment |Â
As you noticed, it is base 62. Conversion is a simple matter of 3 multiplications/divisions.
â vnp
Mar 20 at 19:56
As you noticed, it is base 62. Conversion is a simple matter of 3 multiplications/divisions.
â vnp
Mar 20 at 19:56
As you noticed, it is base 62. Conversion is a simple matter of 3 multiplications/divisions.
â vnp
Mar 20 at 19:56
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
Your problem definition is .... odd. your code, will, for the input value 1
generate the output 000
. Is that what you really want? Why do you need to 1-index the value set instead of 0-index it?
Further, your code caches all values up-to-and-including the input value in a HashMap
. This can become quite large.... for the full dataset you're looking at about a quarter-million values where each is about 128 bytes of memory (a String
, an Integer
, and a Map.Entry
plus some other overheads), or about 70 megabytes of data.
Your DICTIONARY
should be an array of chars
, not an array of String
.
The maxNumber
should be a static constant too.
Finally, you return a null value for an invalid input. That's very unconventional, you should throw an IllegalArgumentException
instead.
As mentioned in a comment, you can "easily" solve your problem with a few "simple" operations.
private static final char DIGITS = ("0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz").toCharArray();
private static final int BASE = DIGITS.length;
private static final int MAX_NUMBER = BASE * BASE * BASE;
public static String generateCode(int num)
Note that I compute each digit separately (in to ac
, bc
, and cc
) and then return the combination as a string.
Further, when running the code, I discovered that you are off on your - I discovered I had a text transpose of zzz
assertion .... the max value you propose for zzz
is wrong, what you have is yyy
.zy
instead of yz
in my constant.
See the code running on ideone: https://ideone.com/EZqXlJ
For the inputs supplied in the tests I get the values:
Value 0 Error Illegal input value: 0
Value 1: 000
Value 2: 001
Value 62: 00z
Value 63: 010
Value 1000: 0G7
Value 238328: zzz
Value 238329 Error Illegal input value: 238329
Maybe specifyingDICTIONARY
with a long literal isn't the best of ideas - I doubt doing same forMaxNumber
without sanity check againstDICTIONARY
is. Without specification, I'd use "little-endian" "digit" strings.
â greybeard
Mar 20 at 22:12
@greybeard - not sure I follow all you are suggesting, but you've made me realize that the naming conventions are off, and using an array of "digits" is better than aDictionary.charAt()
concept. Editing my answer.
â rolflâ¦
Mar 20 at 23:27
@karvai - I subtract the number by 1 because your specification demands it. What does your code give you forgenerateCode(1)
... it gives000
... right? That's why I subtract 1, and that was the first issue I noted in my answer.
â rolflâ¦
Mar 20 at 23:30
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Your problem definition is .... odd. your code, will, for the input value 1
generate the output 000
. Is that what you really want? Why do you need to 1-index the value set instead of 0-index it?
Further, your code caches all values up-to-and-including the input value in a HashMap
. This can become quite large.... for the full dataset you're looking at about a quarter-million values where each is about 128 bytes of memory (a String
, an Integer
, and a Map.Entry
plus some other overheads), or about 70 megabytes of data.
Your DICTIONARY
should be an array of chars
, not an array of String
.
The maxNumber
should be a static constant too.
Finally, you return a null value for an invalid input. That's very unconventional, you should throw an IllegalArgumentException
instead.
As mentioned in a comment, you can "easily" solve your problem with a few "simple" operations.
private static final char DIGITS = ("0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz").toCharArray();
private static final int BASE = DIGITS.length;
private static final int MAX_NUMBER = BASE * BASE * BASE;
public static String generateCode(int num)
Note that I compute each digit separately (in to ac
, bc
, and cc
) and then return the combination as a string.
Further, when running the code, I discovered that you are off on your - I discovered I had a text transpose of zzz
assertion .... the max value you propose for zzz
is wrong, what you have is yyy
.zy
instead of yz
in my constant.
See the code running on ideone: https://ideone.com/EZqXlJ
For the inputs supplied in the tests I get the values:
Value 0 Error Illegal input value: 0
Value 1: 000
Value 2: 001
Value 62: 00z
Value 63: 010
Value 1000: 0G7
Value 238328: zzz
Value 238329 Error Illegal input value: 238329
Maybe specifyingDICTIONARY
with a long literal isn't the best of ideas - I doubt doing same forMaxNumber
without sanity check againstDICTIONARY
is. Without specification, I'd use "little-endian" "digit" strings.
â greybeard
Mar 20 at 22:12
@greybeard - not sure I follow all you are suggesting, but you've made me realize that the naming conventions are off, and using an array of "digits" is better than aDictionary.charAt()
concept. Editing my answer.
â rolflâ¦
Mar 20 at 23:27
@karvai - I subtract the number by 1 because your specification demands it. What does your code give you forgenerateCode(1)
... it gives000
... right? That's why I subtract 1, and that was the first issue I noted in my answer.
â rolflâ¦
Mar 20 at 23:30
add a comment |Â
up vote
2
down vote
accepted
Your problem definition is .... odd. your code, will, for the input value 1
generate the output 000
. Is that what you really want? Why do you need to 1-index the value set instead of 0-index it?
Further, your code caches all values up-to-and-including the input value in a HashMap
. This can become quite large.... for the full dataset you're looking at about a quarter-million values where each is about 128 bytes of memory (a String
, an Integer
, and a Map.Entry
plus some other overheads), or about 70 megabytes of data.
Your DICTIONARY
should be an array of chars
, not an array of String
.
The maxNumber
should be a static constant too.
Finally, you return a null value for an invalid input. That's very unconventional, you should throw an IllegalArgumentException
instead.
As mentioned in a comment, you can "easily" solve your problem with a few "simple" operations.
private static final char DIGITS = ("0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz").toCharArray();
private static final int BASE = DIGITS.length;
private static final int MAX_NUMBER = BASE * BASE * BASE;
public static String generateCode(int num)
Note that I compute each digit separately (in to ac
, bc
, and cc
) and then return the combination as a string.
Further, when running the code, I discovered that you are off on your - I discovered I had a text transpose of zzz
assertion .... the max value you propose for zzz
is wrong, what you have is yyy
.zy
instead of yz
in my constant.
See the code running on ideone: https://ideone.com/EZqXlJ
For the inputs supplied in the tests I get the values:
Value 0 Error Illegal input value: 0
Value 1: 000
Value 2: 001
Value 62: 00z
Value 63: 010
Value 1000: 0G7
Value 238328: zzz
Value 238329 Error Illegal input value: 238329
Maybe specifyingDICTIONARY
with a long literal isn't the best of ideas - I doubt doing same forMaxNumber
without sanity check againstDICTIONARY
is. Without specification, I'd use "little-endian" "digit" strings.
â greybeard
Mar 20 at 22:12
@greybeard - not sure I follow all you are suggesting, but you've made me realize that the naming conventions are off, and using an array of "digits" is better than aDictionary.charAt()
concept. Editing my answer.
â rolflâ¦
Mar 20 at 23:27
@karvai - I subtract the number by 1 because your specification demands it. What does your code give you forgenerateCode(1)
... it gives000
... right? That's why I subtract 1, and that was the first issue I noted in my answer.
â rolflâ¦
Mar 20 at 23:30
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Your problem definition is .... odd. your code, will, for the input value 1
generate the output 000
. Is that what you really want? Why do you need to 1-index the value set instead of 0-index it?
Further, your code caches all values up-to-and-including the input value in a HashMap
. This can become quite large.... for the full dataset you're looking at about a quarter-million values where each is about 128 bytes of memory (a String
, an Integer
, and a Map.Entry
plus some other overheads), or about 70 megabytes of data.
Your DICTIONARY
should be an array of chars
, not an array of String
.
The maxNumber
should be a static constant too.
Finally, you return a null value for an invalid input. That's very unconventional, you should throw an IllegalArgumentException
instead.
As mentioned in a comment, you can "easily" solve your problem with a few "simple" operations.
private static final char DIGITS = ("0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz").toCharArray();
private static final int BASE = DIGITS.length;
private static final int MAX_NUMBER = BASE * BASE * BASE;
public static String generateCode(int num)
Note that I compute each digit separately (in to ac
, bc
, and cc
) and then return the combination as a string.
Further, when running the code, I discovered that you are off on your - I discovered I had a text transpose of zzz
assertion .... the max value you propose for zzz
is wrong, what you have is yyy
.zy
instead of yz
in my constant.
See the code running on ideone: https://ideone.com/EZqXlJ
For the inputs supplied in the tests I get the values:
Value 0 Error Illegal input value: 0
Value 1: 000
Value 2: 001
Value 62: 00z
Value 63: 010
Value 1000: 0G7
Value 238328: zzz
Value 238329 Error Illegal input value: 238329
Your problem definition is .... odd. your code, will, for the input value 1
generate the output 000
. Is that what you really want? Why do you need to 1-index the value set instead of 0-index it?
Further, your code caches all values up-to-and-including the input value in a HashMap
. This can become quite large.... for the full dataset you're looking at about a quarter-million values where each is about 128 bytes of memory (a String
, an Integer
, and a Map.Entry
plus some other overheads), or about 70 megabytes of data.
Your DICTIONARY
should be an array of chars
, not an array of String
.
The maxNumber
should be a static constant too.
Finally, you return a null value for an invalid input. That's very unconventional, you should throw an IllegalArgumentException
instead.
As mentioned in a comment, you can "easily" solve your problem with a few "simple" operations.
private static final char DIGITS = ("0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz").toCharArray();
private static final int BASE = DIGITS.length;
private static final int MAX_NUMBER = BASE * BASE * BASE;
public static String generateCode(int num)
Note that I compute each digit separately (in to ac
, bc
, and cc
) and then return the combination as a string.
Further, when running the code, I discovered that you are off on your - I discovered I had a text transpose of zzz
assertion .... the max value you propose for zzz
is wrong, what you have is yyy
.zy
instead of yz
in my constant.
See the code running on ideone: https://ideone.com/EZqXlJ
For the inputs supplied in the tests I get the values:
Value 0 Error Illegal input value: 0
Value 1: 000
Value 2: 001
Value 62: 00z
Value 63: 010
Value 1000: 0G7
Value 238328: zzz
Value 238329 Error Illegal input value: 238329
edited Mar 20 at 23:29
answered Mar 20 at 20:54
rolflâ¦
90.2k13186390
90.2k13186390
Maybe specifyingDICTIONARY
with a long literal isn't the best of ideas - I doubt doing same forMaxNumber
without sanity check againstDICTIONARY
is. Without specification, I'd use "little-endian" "digit" strings.
â greybeard
Mar 20 at 22:12
@greybeard - not sure I follow all you are suggesting, but you've made me realize that the naming conventions are off, and using an array of "digits" is better than aDictionary.charAt()
concept. Editing my answer.
â rolflâ¦
Mar 20 at 23:27
@karvai - I subtract the number by 1 because your specification demands it. What does your code give you forgenerateCode(1)
... it gives000
... right? That's why I subtract 1, and that was the first issue I noted in my answer.
â rolflâ¦
Mar 20 at 23:30
add a comment |Â
Maybe specifyingDICTIONARY
with a long literal isn't the best of ideas - I doubt doing same forMaxNumber
without sanity check againstDICTIONARY
is. Without specification, I'd use "little-endian" "digit" strings.
â greybeard
Mar 20 at 22:12
@greybeard - not sure I follow all you are suggesting, but you've made me realize that the naming conventions are off, and using an array of "digits" is better than aDictionary.charAt()
concept. Editing my answer.
â rolflâ¦
Mar 20 at 23:27
@karvai - I subtract the number by 1 because your specification demands it. What does your code give you forgenerateCode(1)
... it gives000
... right? That's why I subtract 1, and that was the first issue I noted in my answer.
â rolflâ¦
Mar 20 at 23:30
Maybe specifying
DICTIONARY
with a long literal isn't the best of ideas - I doubt doing same for MaxNumber
without sanity check against DICTIONARY
is. Without specification, I'd use "little-endian" "digit" strings.â greybeard
Mar 20 at 22:12
Maybe specifying
DICTIONARY
with a long literal isn't the best of ideas - I doubt doing same for MaxNumber
without sanity check against DICTIONARY
is. Without specification, I'd use "little-endian" "digit" strings.â greybeard
Mar 20 at 22:12
@greybeard - not sure I follow all you are suggesting, but you've made me realize that the naming conventions are off, and using an array of "digits" is better than a
Dictionary.charAt()
concept. Editing my answer.â rolflâ¦
Mar 20 at 23:27
@greybeard - not sure I follow all you are suggesting, but you've made me realize that the naming conventions are off, and using an array of "digits" is better than a
Dictionary.charAt()
concept. Editing my answer.â rolflâ¦
Mar 20 at 23:27
@karvai - I subtract the number by 1 because your specification demands it. What does your code give you for
generateCode(1)
... it gives 000
... right? That's why I subtract 1, and that was the first issue I noted in my answer.â rolflâ¦
Mar 20 at 23:30
@karvai - I subtract the number by 1 because your specification demands it. What does your code give you for
generateCode(1)
... it gives 000
... right? That's why I subtract 1, and that was the first issue I noted in my answer.â rolflâ¦
Mar 20 at 23:30
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f190062%2fconverting-an-integer-to-a-3-character-string-base62%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
As you noticed, it is base 62. Conversion is a simple matter of 3 multiplications/divisions.
â vnp
Mar 20 at 19:56