Advertisement
Guest User

Java Bignum Reimplementation

a guest
Mar 27th, 2017
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.08 KB | None | 0 0
  1. /* package codechef; // don't place package name! */
  2.  
  3. import java.util.*;
  4. import java.lang.*;
  5. import java.io.*;
  6.  
  7. class ProductMath{
  8.   public static final int DEFAULT_RADIX = 1000000000;
  9.   public static int[] breakToInt(long x){// breaks a long into
  10.     // at most two ints.
  11.     // n.b. constant space...
  12.     // because Integer.MAX_VALUE**2 < Long.MAX_VALUE
  13.     int[] digits = new int[2];
  14.     digits[0] = (int)(x % Integer.MAX_VALUE);
  15.     long tempCarry = x - digits[0];
  16.     digits[1] = (int)(tempCarry / Integer.MAX_VALUE);
  17.     return digits;
  18.   }
  19.   public static int countDigits(long x, int radix){
  20.     // counts the number of digits (of size [radix])
  21.     int logRatio = (int)(Math.log(x)/Math.log(radix));
  22.     return logRatio + 1;
  23.     // if x has more than Integer.MAX_VALUE digits
  24.     // you're gonna have a bad time
  25.   }
  26.   public static int[] breakToRadix(long x, int radix){
  27.     // breaks a long into digits between [0, radix]
  28.     int nDigits = countDigits(x, radix);
  29.     // upper nDigits is an upper bound
  30.     ArrayList<Integer> digits = new ArrayList<Integer>(nDigits);
  31.     long carrier = x;// modified trial division.
  32.     int curDigit;
  33.     for(int i = 0; i < nDigits; i++){
  34.       // the following operations are mathematically guaranteed:
  35.       curDigit = (int)(carrier % radix);
  36.       // will fit in an int if radix < INT_MAX
  37.       digits.add(curDigit);
  38.       // curDigit will assuredly be less than radix
  39.       carrier -= curDigit;
  40.       // if b = (a+b)%c, then a is divisible by c
  41.       if(carrier <= 0){ break; }
  42.       carrier /= radix;
  43.     }
  44.     int[] result = new int[digits.size()];
  45.     for(int i = 0; i < digits.size(); i++){
  46.       result[i] = digits.get(i).intValue();
  47.       // unbox int (ArrayList requires object boxing)
  48.     }
  49.     return result;
  50.   }
  51. }
  52.  
  53. class BigProduct{
  54.   public int radix;// so far my code only works radix=10**n
  55.   private ArrayList<Integer> digits;
  56.   public boolean mutable = true;
  57.  
  58.   public BigProduct(){
  59.     this.radix = ProductMath.DEFAULT_RADIX;
  60.     this.digits = new ArrayList<Integer>();
  61.     this.setValue(0);
  62.   }
  63.  
  64.   public BigProduct(int radix){
  65.     this.radix = radix;
  66.     this.digits = new ArrayList<Integer>();
  67.     this.setValue(0);
  68.   }
  69.  
  70.   public BigProduct(BigProduct toClone){
  71.     this.radix = toClone.radix;
  72.     this.digits = new ArrayList<Integer>();
  73.     this.setValue(toClone);
  74.   }
  75.  
  76.   public boolean setValue(long x){
  77.     if(this.mutable){
  78.       this.digits.clear();
  79.       this.consumeAdd(x);
  80.       return true;
  81.     }else{ return false; }
  82.   }
  83.   public void setValue(BigProduct x){
  84.     if(this.mutable){
  85.       this.radix = x.radix;
  86.       this.digits = new ArrayList<Integer>(x.digits);
  87.     }
  88.   }
  89.  
  90.   public boolean consumeAdd(long x, int power){
  91.     if(this.mutable){
  92.       int i = power;
  93.       int j = this.digits.size();
  94.       // first unused index i.e. if the power is somehow very large
  95.       while(j < i){// make room for x * (radix ** power)
  96.         this.digits.add(0);
  97.         j++;
  98.       }
  99.      
  100.       long result = x;
  101.       int cdigit;
  102.       while(true){
  103.         if(i+1 > this.digits.size()){
  104.           this.digits.add(0);
  105.         }
  106.         result += this.digits.get(i);
  107.         cdigit = (int)(result % (long)this.radix);
  108.         this.digits.set(i, cdigit);
  109.         result -= cdigit;
  110.         if(result == 0){break;}
  111.         result /= radix;
  112.         i += 1;
  113.       }
  114.       return true;
  115.     }else{ return false; }
  116.   }
  117.   public boolean consumeAdd(BigProduct x){
  118.     if(this.mutable){
  119.       for(int i = 0; i < x.digits.size(); i++){
  120.         this.consumeAdd(x.digits.get(i), i);
  121.       }
  122.       return true;
  123.     }else{ return false; }
  124.   }
  125.  
  126.   public boolean consumeAdd(long x){
  127.     return this.consumeAdd(x, 0);
  128.   }
  129.  
  130.   public void consumeMultiply(int x){
  131.     // only needs to work for 0 <= n <= 100 for codechef
  132.     long[] newDigits = new long[this.digits.size()];
  133.     for(int i = 0; i < this.digits.size(); i++){
  134.       newDigits[i] = (long)this.digits.get(i) * x;
  135.     }
  136.    
  137.     this.digits.clear();
  138.     for(int i = 0; i < newDigits.length; i++){
  139.       this.consumeAdd(newDigits[i], i);
  140.     }
  141.   }
  142.  
  143.   public String toString(){
  144.     // only works when radix is a power of ten
  145.     StringBuilder result = new StringBuilder();
  146.     int i = this.digits.size() - 1;
  147.     result.append(this.digits.get(i--));
  148.     String current;
  149.     while(i >= 0){
  150.       current = String.format("%09d", this.digits.get(i--));
  151.       result.append(current);
  152.     }
  153.     return result.toString();
  154.   }
  155. }
  156.  
  157. class Factorializer{
  158.   public static ArrayList<BigProduct> memotable;
  159.  
  160.   static int ntoi(int n){
  161.     return (n <= 0)?1:n;
  162.   }
  163.  
  164.   public static void initialize(){
  165.     memotable = new ArrayList<BigProduct>();
  166.    
  167.     BigProduct temp = new BigProduct();
  168.     temp.consumeAdd(1);
  169.     memotable.add(temp);
  170.    
  171.     temp = new BigProduct();
  172.     temp.consumeAdd(1);
  173.     memotable.add(temp);
  174.   }
  175.  
  176.   static{
  177.     initialize();
  178.   }
  179.  
  180.   public static BigProduct factorialize(int n){
  181.     // only concerned about the first 100 factorials
  182.     int i = ntoi(n);
  183.     if(i < memotable.size()){
  184.       return memotable.get(i);
  185.     }
  186.     BigProduct result = new BigProduct(
  187.       factorialize(n-1));
  188.     result.consumeMultiply(n);
  189.     memotable.add(result);
  190.     return result;
  191.   }
  192.  
  193.   public static void clearMemos(){// only useful as debug or gc
  194.     memotable.clear();
  195.     initialize();
  196.   }
  197. }
  198.  
  199. class Main {
  200.   static final String sep = "\n\t";
  201.   static final int nTests = 100;
  202.   static final Scanner x = new Scanner(System.in);
  203.  
  204.   static long randLong(long start, long end){
  205.     //bounds checking must be manual
  206.     double baser = Math.random();
  207.     long range = end - start;
  208.     return Math.round(baser * range) + start;
  209.   }
  210.  
  211.   static void testCase(int n){
  212.     BigProduct y = Factorializer.factorialize(n);
  213.     System.out.printf("\t" + "[n] calculate n! => %d!" +
  214.       sep + "[y] BigProduct: %s\n", n, y.toString());
  215.   }
  216.  
  217.   static long time(){
  218.     return System.nanoTime();
  219.   }
  220.  
  221.   public static void interactiveTests(){
  222.     long start, end;
  223.     int n;
  224.     String input;
  225.    
  226.     x.useDelimiter("\n");
  227.     ArrayList<Long> startTimes = new ArrayList<Long>();
  228.     ArrayList<Long> endTimes = new ArrayList<Long>();
  229.     int i = 0;
  230.     while(true){
  231.       i++;
  232.       input = x.next();
  233.       if(input.equals("clear")){
  234.         System.out.println("Clearing memo table");
  235.         Factorializer.clearMemos();
  236.         continue;
  237.       }
  238.       try{
  239.         n = Integer.parseInt(input);
  240.       }catch(NumberFormatException e){
  241.         break;
  242.       }
  243.       System.out.printf("Test case %d:\n", i, nTests);
  244.       start = time();
  245.       testCase(n);
  246.       end = time();
  247.       System.out.printf("\tResult calculated in %d ns\n", end-start);
  248.       startTimes.add(start);
  249.       endTimes.add(end);
  250.     }
  251.   }
  252.  
  253.   public static void codechefLogic(){
  254.     int n = x.nextInt();
  255.     for(int i = 0; i < n; i++){
  256.       System.out.println(
  257.         Factorializer.factorialize(x.nextInt()).toString());
  258.     }
  259.   }
  260.  
  261.   public static void main(String[] args) {
  262.     interactiveTests();
  263.   }
  264. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement