/* BabelCalc.java * Inspired by Jorge Luis Borges' short story, "The Library of Babel". * Calculates how many books there are in the Library of Babel * that differ from a given book by n characters. * Coded by Adam Lee (ebonmusings@gmail.com) * March 2006 * See . * This code is released under a Creative Commons license: * http://creativecommons.org/licenses/by-nc-sa/2.5/ */ import java.lang.Integer; import java.math.BigInteger; public class BabelCalc { /* Twiddle these knobs to set the parameters of the simulation. The values given below are as Borges originally defined them. NUM_CHARACTERS includes all possible punctuation marks (the original story stipulated a 22-letter alphabet, the comma, the period and the space). */ public static final int NUM_PAGES = 410; /* number of pages per book */ public static final int NUM_LINES = 40; /* number of lines per page */ public static final int NUM_POSITIONS = 80; /* number of positions per line */ public static final int BOOK_LENGTH = NUM_PAGES * NUM_LINES * NUM_POSITIONS; public static final int NUM_CHARACTERS = 25; /* number of possible symbols for any position */ public static final int BOOK_VOLUME = 2400; /* in cubic centimeters, see below */ /* The observable universe is approximately 10^87 cubic centimeters in volume. */ public static final int UNIVERSE_VOLUME_MAGNITUDE = 87; public static void main(String[] args) { int n; if(args == null || args.length == 0) { /* ignore all arguments beyond the first */ System.out.println("Please enter a value for n."); return; } try { n = Integer.parseInt(args[0]); } catch(NumberFormatException excep) { System.out.println("That is not a valid number."); return; } /* The reasoning behind this is as follows: * The Library of Babel has BOOK_LENGTH * (NUM_CHARACTERS - 1) books that differ from * a given book by at most 1 character - i.e., we can replace any one character at any * position in the book with a different character. * The number of 2-character variant books is this number, multiplied by * (BOOK_LENGTH - 1) * (NUM_CHARACTERS - 1) - i.e., for each possible 1-character change, * we can then replace any character at some other position in the book * with a different character. * The number of 3-character variant books is the number of 2-character variant books * times (BOOK_LENGTH - 2) * (NUM_CHARACTERS - 1), and so on. */ BigInteger result = new BigInteger("1"); for(int i = 0; i < n; i++) { result = result.multiply(new BigInteger(""+((NUM_CHARACTERS - 1) * (BOOK_LENGTH - i))+"")); } /* Insert commas correctly. */ int power = result.toString().length(); String bignum = commaize(result.toString()); System.out.println("The Library of Babel contains "+bignum+" books that differ "+ "from a given book by exactly "+n+" characters. (Order of magnitude = 10^"+power+")."); /* Assumptions for volume calculation: A sheet of paper is 0.1mm thick. Each sheet is 8.5 x 11 inches, which works out to approximately 21.6 by 28 cm. Given these facts, a 410-page book occupies a volume of approximately 2400cc. */ result = result.multiply(new BigInteger(""+BOOK_VOLUME+"")); power = result.toString().length(); bignum = commaize(result.toString()); System.out.println("It would require "+bignum+" cc to store "+ "all these books. (Order of magnitude = 10^"+power+")."); if(power == UNIVERSE_VOLUME_MAGNITUDE) { System.out.println("This many books would approximately fill the observable universe."); } else if(power > UNIVERSE_VOLUME_MAGNITUDE) { System.out.println("This many books would more than fill the observable universe."); } } public static String commaize(String tmp) { StringBuffer bignum = new StringBuffer(); int chars_copied = 0; for(int i = tmp.length()-1; i >= 0; i--) { bignum.append(tmp.charAt(i)); chars_copied++; if(chars_copied % 3 == 0 && i > 0) bignum.append(','); } /* Reverse in place. StringBuffer.reverse() doesn't do what you'd expect. */ for(int i = 0; i < bignum.length()/2; i++) { char c = bignum.charAt(i); bignum.setCharAt(i, bignum.charAt(bignum.length() - (i+1))); bignum.setCharAt(bignum.length() - (i+1), c); } return bignum.toString(); } } /* EOF */