Browse Source

adding Problem 158 solution.

master
Charles Reid 8 years ago
parent
commit
8cab0c1047
  1. 46
      scratch/Round5_150-160/158/BinomialDP.java
  2. 209
      scratch/Round5_150-160/158/EmpiricalCount.java
  3. 8
      scratch/Round5_150-160/158/Makefile
  4. 33
      scratch/Round5_150-160/158/Problem158.java

46
scratch/Round5_150-160/158/BinomialDP.java

@ -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];
}
}

209
scratch/Round5_150-160/158/EmpiricalCount.java

@ -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;
}
}
}

8
scratch/Round5_150-160/158/Makefile

@ -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

33
scratch/Round5_150-160/158/Problem158.java

@ -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…
Cancel
Save