4 changed files with 296 additions and 0 deletions
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
/** |
||||
* Evaluate binomial coefficient using dynamic programming. |
||||
*/ |
||||
public class BinomialDP { |
||||
|
||||
private long[][] bc; |
||||
|
||||
public BinomialDP(int n) { |
||||
// NOTE:
|
||||
// n and k both begin at 0, not at 1.
|
||||
// Set bc[] size to n+1, then use bc.length,
|
||||
// instead of using n and possibly getting confused.
|
||||
|
||||
// Initialize dynamic programming array
|
||||
// (this is basically a lower triangular matrix
|
||||
// containing Pascal's Triangle)
|
||||
bc = new long[n+1][n+1]; |
||||
|
||||
// Base cases:
|
||||
// k choose 0 is 1
|
||||
// k choose k is 1
|
||||
for(int i=0; i<bc.length; i++) { |
||||
bc[i][0] = 1L; |
||||
bc[i][i] = 1L; |
||||
} |
||||
|
||||
// Fill in the rest
|
||||
for(int r=1; r<bc.length; r++) { |
||||
for(int c=1; c<r; c++) { |
||||
bc[r][c] = bc[r-1][c-1] + bc[r-1][c]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static void main(String[] args) { |
||||
int m = 26; |
||||
BinomialDP b = new BinomialDP(m); |
||||
for(int i=0; i<=m; i++) { |
||||
System.out.println("binomial("+m+","+i+") = "+b.binomial(m,i)); |
||||
} |
||||
} |
||||
|
||||
public long binomial(int n, int k) { |
||||
return bc[n][k]; |
||||
} |
||||
} |
@ -0,0 +1,209 @@
@@ -0,0 +1,209 @@
|
||||
import java.util.Set; |
||||
import java.util.HashSet; |
||||
import java.util.TreeSet; |
||||
import java.util.Arrays; |
||||
|
||||
/** A class to empirically count the number of strings. |
||||
* |
||||
* This class helped me work out where the extra factor of 2 was coming from. |
||||
* We are generating strings of length n from 26 letters. That's binomial(26,3). |
||||
* We can sort them in reverse lexicographic order. |
||||
* We can then swap two letters to create one letter with correct lexicographic order. That's (n-1) swapped pairs. |
||||
* But this only yields half the number of strings possible. |
||||
* |
||||
* We were missing the fact that we can also move the last character to the front, |
||||
* or we can move the first character to the end. |
||||
* |
||||
* DCB can become: |
||||
* DBC - swap the last two |
||||
* CDB - swap the first two |
||||
* BDC - move back to front |
||||
* CBD - move front to back |
||||
*/ |
||||
|
||||
public class EmpiricalCount { |
||||
|
||||
public static void main(String[] args) { |
||||
System.out.println( lexCount4() ); |
||||
} |
||||
|
||||
|
||||
|
||||
/** Generate ordered strings and count how many satisfy |
||||
* lexicographic condition (only one letter comes lexicographically after |
||||
* the character to its left. |
||||
*/ |
||||
public static int lexCount4() { |
||||
int count = 0; |
||||
char[] mystr = new char[4]; |
||||
for(char c1 = 'A'; c1 <= 'Z'; c1++) { |
||||
for(char c2 = 'A'; c2 <= 'Z'; c2++) { |
||||
for(char c3 = 'A'; c3 <= 'Z'; c3++) { |
||||
for(char c4 = 'A'; c4 <= 'Z'; c4++) { |
||||
Set<Character> s = new HashSet<>(); |
||||
s.add(new Character(c1)); |
||||
s.add(new Character(c2)); |
||||
s.add(new Character(c3)); |
||||
s.add(new Character(c4)); |
||||
if(s.size()!=4) { |
||||
continue; |
||||
} |
||||
mystr[0] = c1; |
||||
mystr[1] = c2; |
||||
mystr[2] = c3; |
||||
mystr[3] = c4; |
||||
if( lexOneAfter(new String(mystr)) ) { |
||||
count++; |
||||
if(s.contains('A')&&s.contains('B')&&s.contains('C')&&s.contains('D')) { |
||||
System.out.println(new String(mystr)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
|
||||
|
||||
public static int lexCount5() { |
||||
int count = 0; |
||||
char[] mystr = new char[5]; |
||||
for(char c1 = 'A'; c1 <= 'Z'; c1++) { |
||||
for(char c2 = 'A'; c2 <= 'Z'; c2++) { |
||||
for(char c3 = 'A'; c3 <= 'Z'; c3++) { |
||||
for(char c4 = 'A'; c4 <= 'Z'; c4++) { |
||||
for(char c5 = 'A'; c5 <= 'Z'; c5++) { |
||||
Set<Character> s = new HashSet<>(); |
||||
s.add(new Character(c1)); |
||||
s.add(new Character(c2)); |
||||
s.add(new Character(c3)); |
||||
s.add(new Character(c4)); |
||||
s.add(new Character(c5)); |
||||
if(s.size()!=5) { |
||||
continue; |
||||
} |
||||
mystr[0] = c1; |
||||
mystr[1] = c2; |
||||
mystr[2] = c3; |
||||
mystr[3] = c4; |
||||
mystr[4] = c5; |
||||
if( lexOneAfter(new String(mystr)) ) { |
||||
count++; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
|
||||
|
||||
public static int lexCount6() { |
||||
int count = 0; |
||||
char[] mystr = new char[6]; |
||||
for(char c1 = 'A'; c1 <= 'Z'; c1++) { |
||||
for(char c2 = 'A'; c2 <= 'Z'; c2++) { |
||||
for(char c3 = 'A'; c3 <= 'Z'; c3++) { |
||||
for(char c4 = 'A'; c4 <= 'Z'; c4++) { |
||||
for(char c5 = 'A'; c5 <= 'Z'; c5++) { |
||||
for(char c6 = 'A'; c6 <= 'Z'; c6++) { |
||||
Set<Character> s = new HashSet<>(); |
||||
s.add(new Character(c1)); |
||||
s.add(new Character(c2)); |
||||
s.add(new Character(c3)); |
||||
s.add(new Character(c4)); |
||||
s.add(new Character(c5)); |
||||
s.add(new Character(c6)); |
||||
if(s.size()!=6) { |
||||
continue; |
||||
} |
||||
mystr[0] = c1; |
||||
mystr[1] = c2; |
||||
mystr[2] = c3; |
||||
mystr[3] = c4; |
||||
mystr[4] = c5; |
||||
mystr[5] = c6; |
||||
if( lexOneAfter(new String(mystr)) ) { |
||||
count++; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
|
||||
|
||||
/** Generate ordered strings and add them to a set. */ |
||||
public static int lexCountConfused() { |
||||
int count = 0; |
||||
char[] mystr = new char[3]; |
||||
Set<String> set = new TreeSet<>(); |
||||
for(char c1 = 'A'; c1 <= 'D'; c1++) { |
||||
for(char c2 = 'A'; c2 <= 'D'; c2++) { |
||||
for(char c3 = 'A'; c3 <= 'D'; c3++) { |
||||
if(c1==c2||c2==c3||c1==c3) { |
||||
continue; |
||||
} |
||||
mystr[0] = c1; |
||||
mystr[1] = c2; |
||||
mystr[2] = c3; |
||||
Arrays.sort(mystr); |
||||
set.add( new String(mystr) ); |
||||
} |
||||
} |
||||
} |
||||
System.out.println(set.size()); |
||||
return set.size(); |
||||
} |
||||
|
||||
|
||||
/** Generate ordered strings and print them out, to help sort out confusion. |
||||
*/ |
||||
public static int lexPrint() { |
||||
int count = 0; |
||||
char[] mystr = new char[3]; |
||||
for(char c1 = 'A'; c1 <= 'D'; c1++) { |
||||
for(char c2 = 'A'; c2 <= 'D'; c2++) { |
||||
for(char c3 = 'A'; c3 <= 'D'; c3++) { |
||||
if(c1==c2||c2==c3||c1==c3) { |
||||
continue; |
||||
} |
||||
mystr[0] = c1; |
||||
mystr[1] = c2; |
||||
mystr[2] = c3; |
||||
if( lexOneAfter(new String(mystr)) ) { |
||||
System.out.println(new String(mystr)); |
||||
count++; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
/** Boolean: does this satisfy our lexicographic condition? */ |
||||
public static boolean lexOneAfter(String s) { |
||||
// Iterate through all characters, count how many come lexicographically
|
||||
// after the character to their left.
|
||||
int lex = 0; |
||||
char[] c = s.toCharArray(); |
||||
for(int i=1; i<c.length; i++) { |
||||
if(c[i]>c[i-1]) { |
||||
lex++; |
||||
} |
||||
} |
||||
if(lex==1) { |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
problem: |
||||
javac Problem158.java && java Problem158 |
||||
empirical: |
||||
javac EmpiricalCount.java && java EmpiricalCount |
||||
binomial: |
||||
javac BinomialDP.java && java BinomialDP |
||||
clean: |
||||
rm -rf *.class |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
public class Problem158 { |
||||
public static void main(String[] args) { |
||||
System.out.println(solve()); |
||||
} |
||||
|
||||
public static int pow(int b, int p) { |
||||
int result = b; |
||||
for(int i=2; i<=p; i++) { |
||||
result *= b; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public static String solve() { |
||||
int m = 26; |
||||
BinomialDP b = new BinomialDP(m); |
||||
|
||||
long p = 0; |
||||
long priorconfigs = 1; |
||||
for(int n=3; n<=26; n++) { |
||||
|
||||
long binom = (long)( b.binomial(26,n) ); |
||||
long configs = (long)(priorconfigs + (pow(2,n-1)-1)); |
||||
long pnew = binom*configs; |
||||
|
||||
//System.out.printf("%12d\t%12d\t%12d\t%12d\n",n,binom,configs,pnew);
|
||||
|
||||
p = Math.max(p,pnew); |
||||
priorconfigs = configs; |
||||
} |
||||
return Long.toString(p); |
||||
} |
||||
} |
Loading…
Reference in new issue