fork download
  1. /* package whatever; // don't place package name! */
  2.  
  3. import java.util.*;
  4. import java.lang.*;
  5. import java.io.*;
  6.  
  7. /* Name of the class has to be "Main" only if the class is public. */
  8. class Ideone
  9. {
  10. public static void main (String[] args) throws java.lang.Exception
  11. {
  12. System.out.println(BaseConverter.changeBase(""+0x7FFF_FFFF_FFFF_FFFFL, 10, 16, true));
  13. try{
  14. System.out.println(BaseConverter.changeBase(""+100000, 10, 70000, true));
  15. } catch (Exception e){
  16. System.out.println("Infinite loop handled via "+e.getClass().getName()+": "+e.getMessage());
  17. }
  18. System.out.println(BaseConverter.changeBase("0", 10, 16, true));
  19. System.out.println(BaseConverter.changeBase("-0", 10, 16, true));
  20. try{
  21. System.out.println(BaseConverter.changeBase("--1", 10, 16, true));
  22. } catch(Exception e){
  23. System.out.println("--1 handled via "+e.getClass().getName()+": "+e.getMessage());
  24. }
  25. try{
  26. System.out.println(BaseConverter.changeBase("1-1", 10, 16, true));
  27. } catch(Exception e){
  28. System.out.println("1-1 handled via "+e.getClass().getName()+": "+e.getMessage());
  29. }
  30. }
  31. }
  32.  
  33. class BaseConverter {
  34. protected static final String negativeBaseErrorMessage = "Negative or zero base values are illegal - supplied bases were %d & %d.",
  35. invalidInputNumberErrorMessage = "The supplied number (%s) for base conversion is invalid.",
  36. tooLargeBaseForLookupErrorMessage = "Not enough available characters for substitution. Number of available characters is %d , minimum required number is %d";
  37.  
  38.  
  39. private static String lookup = "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstwxyz+/=,?!;:\"'^`~|\\@#$%&*_<>(){}";
  40. private static StringBuilder builder = new StringBuilder(lookup);
  41.  
  42. private static void updateLookup(int base) {
  43. int charsToAdd = base - lookup.length();
  44. String oldLookup = lookup;
  45. if (charsToAdd > 0) {
  46. for (int i = 0; i < Character.MAX_VALUE && charsToAdd > 0; ++i) {
  47. if ((!oldLookup.contains("" + (char) i)) &&
  48. (!Character.isISOControl((char) i)) &&
  49. (!Character.isWhitespace((char) i)) &&
  50. ((char) i != '.') && (char) i != '-') {
  51. builder.append((char) i);
  52. --charsToAdd;
  53. }
  54. }
  55. }
  56. lookup = builder.toString();
  57. if (charsToAdd > 0) {
  58. throw new IllegalArgumentException(String.format(tooLargeBaseForLookupErrorMessage, lookup.length(), base));
  59. }
  60. }
  61. public static long convertToNumber(String inputNumber, int from_base) {
  62. if (from_base >= lookup.length()) {
  63. updateLookup(from_base);
  64. }
  65. long number = 0;
  66. int length = inputNumber.length();
  67. for (int i = 0; i < length; ++i) {
  68. long digitValue = lookup.indexOf(inputNumber.charAt(i));
  69. if (digitValue < 0) {//this digit does not exist in the lookup, so the input is incorrect
  70. throw new IllegalArgumentException(String.format(invalidInputNumberErrorMessage, inputNumber));
  71. }
  72. number += digitValue * Math.round(Math.pow(from_base, length - 1 - i));
  73. }
  74. return number;
  75. }
  76. private static int countDigits(long number, int to_base) {
  77. int num_digits = 0;
  78. while (number > 0) {
  79. number /= to_base;
  80. ++num_digits;
  81. }
  82. return num_digits;
  83. }
  84. private static int[] createDigits(long number, int to_base) {
  85. int[] digits = new int[countDigits(number, to_base)];
  86. int num_digits = 0;
  87. while (number > 0) {
  88. digits[num_digits++] = (int) (number % to_base);
  89. number /= to_base;
  90. }
  91. return digits;
  92. }
  93. public static String changeBase(String inputNumber, int from_base, int to_base) {
  94. return changeBase(inputNumber, from_base, to_base, true);
  95. }
  96. private static boolean isInvalidInputNumber(String inputNumber, int from_base) {
  97. //there should be no more than 1 - sign, which should have been removed already if it exists
  98. return inputNumber.contains("-") ||
  99. //there should be no more than 1 fixed point, which should have been removed already if it exists
  100. inputNumber.contains(".") ||
  101. //there should be no characters in the string which indicate values for a digit greater than the current base
  102. (!inputNumber.matches(String.format("^[%s]*$", lookup.substring(0, from_base))));
  103. }
  104. public static String changeBase(String inputNumber, int from_base, int to_base, boolean substituteNumerics) {
  105. boolean isNegative = false;
  106. if (inputNumber.startsWith("-")) {
  107. //the provided number is (supposedly) negative
  108. inputNumber = inputNumber.substring(1, inputNumber.length());
  109. isNegative = true;
  110. }
  111. if (from_base <= 0 || to_base <= 0) {
  112. //negative or zero bases can't be handled using simple integer arithmetic
  113. throw new IllegalArgumentException(String.format(negativeBaseErrorMessage, from_base, to_base));
  114. }
  115. updateLookup(Math.max(from_base, to_base));
  116. if (inputNumber.contains(".")) {
  117. return changeBase(inputNumber.substring(0, inputNumber.indexOf(".")), from_base, to_base, substituteNumerics)/*Integer part*/ + "." +
  118. changeBase(inputNumber.substring(inputNumber.indexOf(".") + 1, inputNumber.length()), from_base, to_base, substituteNumerics)/*Fractional part*/;
  119. }
  120. //checking for invalid numbers is easier now when negatives and fixed points should have been taken care of
  121. if (isInvalidInputNumber(inputNumber, from_base)) {
  122. throw new IllegalArgumentException(String.format(invalidInputNumberErrorMessage, inputNumber));
  123. }
  124. //special handling for 0 to avoid undefined behaviour and other bugs
  125. if (inputNumber.matches("^[0]+$")) {//check for any number of only 0s in the input
  126. return (isNegative) ? "-" + lookup.charAt(0) : lookup.charAt(0) + "";//I could simply return "0", but this looks less hardcoded
  127. }
  128. String new_number = "";
  129. int[] digits = createDigits(convertToNumber(inputNumber, from_base), to_base);
  130. if (substituteNumerics) {
  131. //use character representation for digits
  132. for (int i = digits.length - 1; i >= 0; --i) {
  133. new_number += lookup.charAt(digits[i]);
  134. }
  135. } else {
  136. //use numeric representations for digits, separate using space
  137. for (int i = digits.length - 1; i >= 0; --i) {
  138. new_number += digits[i] + " ";
  139. }
  140. }
  141. return (isNegative) ? "-" + new_number.trim() : new_number.trim();
  142. }
  143. }
Success #stdin #stdout 0.16s 320640KB
stdin
Standard input is empty
stdout
7FFFFFFFFFFFFFFF
Infinite loop handled via java.lang.IllegalArgumentException: Not enough available characters for substitution. Number of available characters is 65451 , minimum required number is 70000
0
-0
--1 handled via java.lang.IllegalArgumentException: The supplied number (-1) for base conversion is invalid.
1-1 handled via java.lang.IllegalArgumentException: The supplied number (1-1) for base conversion is invalid.