Optimizing apriori algorithm code - algorithm

I am writing code for apriori algorithm in data mining my code takes as long as 60 seconds for a pretty small dataset which is solved by other code i got from internet in just 2 seconds but i am not getting where am i doing wrong, can someone tell me why the other code is fast over mine.
My code:
import java.util.*;
import java.io.*;
public class Apriori_p {
double support;
ArrayList<String> trans;
Map<String, Integer> map;
long start;
void print(ArrayList<String> temp) {
for (int i = 0; i < temp.size(); i++) {
System.out.println(temp.get(i));
}
System.out.println("Count :" + temp.size());
}
void run() throws FileNotFoundException {
start = System.currentTimeMillis();
trans = new ArrayList<>();
ArrayList<String> temp = new ArrayList<>();
map = new HashMap<>();
Scanner sc = new Scanner(System.in);
System.out.println("Enter support %");
support = sc.nextDouble();
System.out.println("Enter file name");
String file = sc.next();
sc = new Scanner(new File(file));
int lines = 0;
while (sc.hasNextLine()) {
String s = sc.nextLine();
if (s.matches("\\s*")) {
continue;
}
lines++;
String[] spl = s.split("\\s+");
ArrayList<Integer> elem = new ArrayList<>();
for (int i = 0; i < spl.length; i++) {
String cand;
int n = Integer.parseInt(spl[i]);
cand = spl[i].trim();
if (!elem.contains(n)) {
elem.add(n);
}
if (map.containsKey(cand)) {
int count = map.get(cand);
map.put(cand, count + 1);
} else {
map.put(cand, 1);
}
}
Collections.sort(elem);
String con = " ";
for (int i = 0; i < elem.size(); i++) {
con = con + elem.get(i) + " ";
String s1 = String.valueOf(elem.get(i)).trim();
if(!temp.contains(s1))
temp.add(s1);
}
trans.add(con);
}
support = (support * lines) / 100;
System.out.println(System.currentTimeMillis() - start);
apriori(temp, 1);
}
public static void main(String[] args) throws FileNotFoundException {
new Apriori_p().run();
}
public void apriori(ArrayList<String> temp, int m) {
Set<String> diff = null;
if (m == 1) {
diff = new HashSet<>();
}
for (int i = 0; i < temp.size(); i++) {
if (map.get(temp.get(i)) < support) {
if (m == 1) {
diff.add(temp.get(i));
}
temp.remove(i);
i--;
}
}
for (int i = 0; i < trans.size() && m == 1; i++) {
for (String j : diff) {
String rep = " " + j + " ";
trans.get(i).replace(rep, " ");
}
}
if (temp.size() == 0) {
return;
}
System.out.println("Size " + m + " :");
print(temp);
ArrayList<String> ntemp = new ArrayList<>();
int n = temp.size();
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
StringTokenizer st1 = new StringTokenizer(temp.get(i), " ");
StringTokenizer st2 = new StringTokenizer(temp.get(j), " ");
String str1 = "", str2 = "";
for (int s = 0; s < m - 2; s++) {
str1 = str1 + " " + st1.nextToken();
str2 = str2 + " " + st2.nextToken();
}
if (str2.compareToIgnoreCase(str1) == 0) {
int s1 = Integer.parseInt(st1.nextToken()), s2 = Integer.parseInt(st2.nextToken());
String s3;
if (s1 <= s2) {
s3 = (str1 + " " + s1 + " " + s2).trim();
} else {
s3 = (str1 + " " + s2 + " " + s1).trim();
}
if(!ntemp.contains(s3)){
ntemp.add(s3);
}
}
}
}
temp.clear();
for (int j = 0; j < ntemp.size(); j++) {
int c = 0;
for (int i = 0; i < trans.size(); i++) {
int check = 0;
String tr = trans.get(i);
StringTokenizer st1 = new StringTokenizer(ntemp.get(j)," ");
while(st1.hasMoreElements()){
String str = st1.nextToken();
if(!tr.contains(" " + str + " ")){
check = 1;
break;
}
}
if(check == 0){
c= 1;
if (map.containsKey(ntemp.get(j))) {
int count = map.get(ntemp.get(j));
map.put(ntemp.get(j), count + 1);
} else {
map.put(ntemp.get(j), 1);
}
}
}
if (c == 0) {
ntemp.remove(j);
j--;
}
}
apriori(ntemp, m + 1);
}
}
Fast code:
import java.io.*;
import java.util.*;
public class Apriori3{
public static void main(String[] args) throws Exception {
Apriori3 ap = new Apriori3(args);
}
private List<int[]> itemsets;
private String transaFile;
private int numItems;
private int numTransactions;
private double minSup;
private boolean usedAsLibrary = false;
public Apriori3(String[] args) throws Exception {
configure(args);
go();
}
private void go() throws Exception {
long start = System.currentTimeMillis();
createItemsetsOfSize1();
int itemsetNumber = 1;
int nbFrequentSets = 0;
while (itemsets.size() > 0) {
calculateFrequentItemsets();
if (itemsets.size() != 0) {
nbFrequentSets += itemsets.size();
log("Found " + itemsets.size() + " frequent itemsets of size " + itemsetNumber + " (with support " + (minSup * 100) + "%)");;
createNewItemsetsFromPreviousOnes();
}
itemsetNumber++;
}
long end = System.currentTimeMillis();
log("Execution time is: " + ((double) (end - start) / 1000) + " seconds.");
log("Found " + nbFrequentSets + " frequents sets for support " + (minSup * 100) + "% (absolute " + Math.round(numTransactions * minSup) + ")");
log("Done");
}
private void foundFrequentItemSet(int[] itemset, int support) {
if (usedAsLibrary) {
} else {
System.out.println(Arrays.toString(itemset) + " (" + ((support / (double) numTransactions)) + " " + support + ")");
}
}
private void log(String message) {
if (!usedAsLibrary) {
System.err.println(message);
}
}
private void configure(String[] args) throws Exception {
if (args.length != 0) {
transaFile = args[0];
} else {
transaFile = "chess.dat"; // default
}
if (args.length >= 2) {
minSup = (Double.valueOf(args[1]).doubleValue());
} else {
minSup = .8;
}
if (minSup > 1 || minSup < 0) {
throw new Exception("minSup: bad value");
}
numItems = 0;
numTransactions = 0;
BufferedReader data_in = new BufferedReader(new FileReader(transaFile));
while (data_in.ready()) {
String line = data_in.readLine();
if (line.matches("\\s*")) {
continue;
}
numTransactions++;
StringTokenizer t = new StringTokenizer(line, " ");
while (t.hasMoreTokens()) {
int x = Integer.parseInt(t.nextToken());
if (x + 1 > numItems) {
numItems = x + 1;
}
}
}
outputConfig();
}
private void outputConfig() {
log("Input configuration: " + numItems + " items, " + numTransactions + " transactions, ");
log("minsup = " + minSup + "%");
}
private void createItemsetsOfSize1() {
itemsets = new ArrayList<int[]>();
for (int i = 0; i < numItems; i++) {
int[] cand = {i};
itemsets.add(cand);
}
}
private void createNewItemsetsFromPreviousOnes() {
int currentSizeOfItemsets = itemsets.get(0).length;
log("Creating itemsets of size " + (currentSizeOfItemsets + 1) + " based on " + itemsets.size() + " itemsets of size " + currentSizeOfItemsets);
HashMap<String, int[]> tempCandidates = new HashMap<String, int[]>(); //temporary candidates
for (int i = 0; i < itemsets.size(); i++) {
for (int j = i + 1; j < itemsets.size(); j++) {
int[] X = itemsets.get(i);
int[] Y = itemsets.get(j);
assert (X.length == Y.length);
int[] newCand = new int[currentSizeOfItemsets + 1];
for (int s = 0; s < newCand.length - 1; s++) {
newCand[s] = X[s];
}
int ndifferent = 0;
for (int s1 = 0; s1 < Y.length; s1++) {
boolean found = false;
for (int s2 = 0; s2 < X.length; s2++) {
if (X[s2] == Y[s1]) {
found = true;
break;
}
}
if (!found) {
ndifferent++;
newCand[newCand.length - 1] = Y[s1];
}
}
assert (ndifferent > 0);
if (ndifferent == 1) {
Arrays.sort(newCand);
tempCandidates.put(Arrays.toString(newCand), newCand);
}
}
}
itemsets = new ArrayList<int[]>(tempCandidates.values());
log("Created " + itemsets.size() + " unique itemsets of size " + (currentSizeOfItemsets + 1));
}
private void line2booleanArray(String line, boolean[] trans) {
Arrays.fill(trans, false);
StringTokenizer stFile = new StringTokenizer(line, " ");
while (stFile.hasMoreTokens()) {
int parsedVal = Integer.parseInt(stFile.nextToken());
trans[parsedVal] = true;
}
}
private void calculateFrequentItemsets() throws Exception {
log("Passing through the data to compute the frequency of " + itemsets.size() + " itemsets of size " + itemsets.get(0).length);
List<int[]> frequentCandidates = new ArrayList<int[]>();
boolean match;
int count[] = new int[itemsets.size()];
BufferedReader data_in = new BufferedReader(new InputStreamReader(new FileInputStream(transaFile)));
boolean[] trans = new boolean[numItems];
for (int i = 0; i < numTransactions; i++) {
String line = data_in.readLine();
line2booleanArray(line, trans);
for (int c = 0; c < itemsets.size(); c++) {
match = true;
int[] cand = itemsets.get(c);
for (int xx : cand) {
if (trans[xx] == false) {
match = false;
break;
}
}
if (match) {
count[c]++;
}
}
}
data_in.close();
for (int i = 0; i < itemsets.size(); i++) {
if ((count[i] / (double) (numTransactions)) >= minSup) {
foundFrequentItemSet(itemsets.get(i), count[i]);
frequentCandidates.add(itemsets.get(i));
}
}
itemsets = frequentCandidates;
}
}

Related

How to parallelize merge sort using JavaRDD<Integer> Spark?

public class MergeSort {
public static List<Integer> serialSort(List<Integer> array) {
if (array.size() > 1) {
int mid = array.size() / 2;
List<Integer> firstHalf = new ArrayList<>(mid);
List<Integer> secondHalf = new ArrayList<>(array.size() - mid);
for (int i = 0; i < array.size(); i++) {
if (i <= mid) {
firstHalf.add(array.get(i));
} else {
secondHalf.add(array.get(i));
}
}
serialSort(firstHalf);
serialSort(secondHalf);
merge(firstHalf, secondHalf, array);
}
return array;
}
//
private static void merge(List firstHalf, List secondHalf, List array) {
int currentIndexFirst = 0;
int currentIndexSecond = 0;
int currentIndexArray = 0;
while (currentIndexFirst < firstHalf.size() && currentIndexSecond < secondHalf.size()) {
if (firstHalf.get(currentIndexFirst) < secondHalf.get(currentIndexSecond)) {
array.set(currentIndexArray, firstHalf.get(currentIndexFirst));
currentIndexArray++;
currentIndexFirst++;
} else {
array.set(currentIndexArray, secondHalf.get(currentIndexSecond));
currentIndexArray++;
currentIndexSecond++;
}
}
while (currentIndexFirst < firstHalf.size()) {
array.set(currentIndexArray, firstHalf.get(currentIndexFirst));
currentIndexArray++;
currentIndexFirst++;
}
while (currentIndexSecond < secondHalf.size()) {
array.set(currentIndexArray, secondHalf.get(currentIndexSecond));
currentIndexArray++;
currentIndexSecond++;
}
}
public static JavaRDD<Integer> parallelSort(JavaRDD<Integer> data) {
SparkConf conf = new SparkConf().setAppName("surya").setMaster("local[6]");
JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD<Integer> distData = (JavaRDD<Integer>) sc.parallelize(data);
return data.union(data);
}
}
public class Main {
public static void main(String[] args) {
List<Integer> unsorted = new ArrayList<>(10000);
for (int i = 0; i < 10000; i++) {
unsorted.add((int) Math.floor(Math.random() * 100000));
}
List<Integer> sorted = new ArrayList<>(unsorted);
sorted.sort(Integer::compareTo);
long startTime = System.currentTimeMillis();
List<Integer> serialSorted = MergeSort.serialSort(new ArrayList<>(unsorted));
long serialTime = System.currentTimeMillis() - startTime;
System.out.println("Unsorted serial list: " + unsorted +"\n");
System.out.println("Sorted serial list: " + sorted+"\n");
System.out.println("Serial implementation took " + serialTime + " milliseconds.");
assert serialSorted.equals(sorted);
// parallelization
// SparkConf conf = new SparkConf().setAppName("surya").setMaster("local[6]");
// JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD<Integer> data = sc.parallelize(new ArrayList<>(unsorted));
startTime = System.currentTimeMillis();
data = MergeSort.parallelSort(data);
long parallelTime = System.currentTimeMillis() - startTime;
System.out.println("Parallel implementation took " + parallelTime + " milliseconds.");
List<Integer> parallelSorted = data.collect();
sc.stop();
assert parallelSorted.equals(sorted);
}
}
I tried to parallelize this but succeeded. Any help is appreciated.

sentiment analysis using SentiWordNet.

I want to classify sentences as positive, negative or neutral. I have got the code written in java but i am not understanding how to use the code for my file.In the above code where i should use my file and the results for each sentence should come as positive, negative and neutral. Please guide me for this.
public class SWN3 {
private String pathToSWN = "data"+File.separator+"SentiWordNet_3.0.0.txt";
private HashMap<String, String> _dict;
public SWN3(){
_dict = new HashMap<String, String>();
HashMap<String, Vector<Double>> _temp = new HashMap<String, Vector<Double>>();
try{
BufferedReader csv = new BufferedReader(new FileReader(pathToSWN));
String line = "";
while((line = csv.readLine()) != null)
{
String[] data = line.split("\t");
Double score = Double.parseDouble(data[2])- Double.parseDouble(data[3]);
String[] words = data[4].split(" ");
for(String w:words)
{
String[] w_n = w.split("#");
w_n[0] += "#"+data[0];
int index = Integer.parseInt(w_n[1])-1;
if(_temp.containsKey(w_n[0]))
{
Vector<Double> v = _temp.get(w_n[0]);
if(index>v.size())
for(int i = v.size();i<index; i++)
v.add(0.0);
v.add(index, score);
_temp.put(w_n[0], v);
}
else
{
Vector<Double> v = new Vector<Double>();
for(int i = 0;i<index; i++)
v.add(0.0);
v.add(index, score);
_temp.put(w_n[0], v);
}
}
}
Set<String> temp = _temp.keySet();
for (Iterator<String> iterator = temp.iterator(); iterator.hasNext();) {
String word = (String) iterator.next();
Vector<Double> v = _temp.get(word);
double score = 0.0;
double sum = 0.0;
for(int i = 0; i < v.size(); i++)
score += ((double)1/(double)(i+1))*v.get(i);
for(int i = 1; i<=v.size(); i++)
sum += (double)1/(double)i;
score /= sum;
String sent = "";
if(score>=0.75)
sent = "strong_positive";
else
if(score > 0.25 && score<=0.5)
sent = "positive";
else
if(score > 0 && score>=0.25)
sent = "weak_positive";
else
if(score < 0 && score>=-0.25)
sent = "weak_negative";
else
if(score < -0.25 && score>=-0.5)
sent = "negative";
else
if(score<=-0.75)
sent = "strong_negative";
_dict.put(word, sent);
}
}
catch(Exception e){e.printStackTrace();}
}
public String extract(String word, String pos)
{
return _dict.get(word+"#"+pos);
}
}

print shapes in java

I want to print this shape big X from collection of small x using recursion
this is my code
private static void shape(PrintWriter output, int times, int k, int times2) {
if(times < 0){
return;
} else{
for (int i =0; i<times; i++){
if (i==times)
output.print("X");
else if(i==k)
output.print("X");
else
output.print(" ");
}
output.println();
shape(output,times-1,k+1,times2);
}
}
but I couldn't print the shape requested
Try this.
static void shape(PrintWriter output, int size, int index) {
if (index >= size)
return;
char[] buffer = new char[size];
Arrays.fill(buffer, ' ');
buffer[index] = buffer[size - index - 1] = 'X';
output.println(new String(buffer));
shape(output, size, index + 1);
}
and
try (PrintWriter output = new PrintWriter(new OutputStreamWriter(System.out))) {
shape(output, 11, 0);
}
Just change
int arr[] = new int[times]
to
int arr[] = new int[times2]
where times2 is the width of a single row.
However a more cleaner way would be:
public class InputTest {
private static void FCITshape(int times, int k,int times2) {
if (times < 0) {
return;
} else {
for (int i = 0; i <= times2; i++) {
if (i == times)
System.out.print("X");
else if (i == k)
System.out.print("X");
else
System.out.print(" ");
}
System.out.println();
FCITshape(times - 1, k + 1, times2);
}
}
public static void main(String[] args) {
FCITshape(10, 0, 10);
}
}
Regards.
With recursion
Now just call printX(0, 10);
public static void printX(int x, int l) {
if (x <= l) {
if (x < l / 2) {
for (int i = 0; i < x ; i++) {
System.out.print(" ");
}
} else {
for (int i = 0; i < l - x; i++) {
System.out.print(" ");
}
}
System.out.print("x");
if (x < l / 2) {
for (int j = 0; j < l - x * 2 - 1; j++) {
System.out.print(" ");
}
} else {
for (int j = 0; j < (x * 2 - l) - 1; j++) {
System.out.print(" ");
}
}
if (x != l / 2) {
System.out.print("x");
}
System.out.println();
printX(x + 1, l);
}
}

Processing skipping every other

I am trying to group segments of the XBee output into a variable that joins them. I am using Processing to code and compile. The issue I am having is that the output (println) is skipping every other byte (maybe that's the wrong term). So XBee output for i = 4 though 11 should look like this:
0,19,162,0,64,121,230,206 (this is the XBee address converted from hex).
But the println shows this:
19,0,121,206,125,1,0,3 (which starts getting into other segments of the output).
Later, I tried a different route by using an array. It still skips every other entry and I've found that it has to do with my check for i == 126. Is there an alternate way of doing a check like this?
Substitute this draw section for the one below. It's simpler to follow. This was a test with same results...
void draw() {
if (myPort.available() > 21) {
int[] XBeeAddr = new int[22];
for (int i=0; i<22; i++) {
XBeeAddr[i] = myPort.read();
if (myPort.read == 126) {
i=0;
}
println(XBeeAddr[0] + "," + XBeeAddr[1] + "," + XBeeAddr[2]);
}
}
Original code
import processing.serial.*;
import de.bezier.data.sql.*; // For SQLite database
SQLite db; // For SQLite database
Serial myPort;
void setup() {
println(Serial.list());
myPort = new Serial(this, Serial.list()[0],9600);
// For SQLite database...
size( 100, 100 );
db = new SQLite( this, "test.db" ); // Open database file
if ( db.connect() ) {
String[] tableNames = db.getTableNames();
db.query( "SELECT * FROM %s", tableNames[0] );
while (db.next()) {
TableOne t = new TableOne();
db.setFromRow( t );
println( t );
}
}
}
// For SQLite database
class TableOne {
public String fieldOne;
public int fieldTwo;
public String toString () {
return String.format("fieldOne: %s fieldTwo: %d", fieldOne, fieldTwo);
}
}
void draw() {
if (myPort.available() > 21) {
int XBeeAddr1 = 0;
int XBeeAddr2 = 0;
int XBeeAddr3 = 0;
int XBeeAddr4 = 0;
int XBeeAddr5 = 0;
int XBeeAddr6 = 0;
int XBeeAddr7 = 0;
int XBeeAddr8 = 0;
for (int i=0; i<22; i++) {
int inByte = myPort.read();
if (inByte == 126) {
i=0; // This resets the counter if XBee data was incomplete on the last run.
}
if (i == 4) {
XBeeAddr1 = myPort.read();
}
if (i == 5) {
XBeeAddr2 = myPort.read();
}
if (i == 6) {
XBeeAddr3 = myPort.read();
}
if (i == 7) {
XBeeAddr4 = myPort.read();
}
if (i == 8) {
XBeeAddr5 = myPort.read();
}
if (i == 9) {
XBeeAddr6 = myPort.read();
}
if (i == 10) {
XBeeAddr7 = myPort.read();
}
if (i == 11) {
XBeeAddr8 = myPort.read();
}
String XBeeAddrAll = XBeeAddr1 + "," +
XBeeAddr2 + "," +
XBeeAddr3 + "," +
XBeeAddr4 + "," +
XBeeAddr5 + "," +
XBeeAddr6 + "," +
XBeeAddr7 + "," +
XBeeAddr8;
println(XBeeAddrAll);
}
}
}
It was fixed by changing myPort.read == 126 to if XBeeAddr[0] != 126, break. Then later I did an if XBeeAddr[0] == 126 println.

Uva Judge 10149, Yahtzee

UPDATE: I have found the problem that my DP solution didn't handle bonus correctly. I added one more dimension to the state array to represent the sum of the first 6 categories. However, the solution got timed out. It's not badly timeout since each test case can be solved less than 1 sec on my machine.
The problem description is here: http://uva.onlinejudge.org/external/101/10149.html
I searched online and found that it should be solved by DP and bitmask. I implemented the code and passed all test cases I tested, but the Uva Judge returns wrong answer.
My idea is to have state[i][j] to be matching round i to category bitmasked by j. Please point out my mistakes or link some code that can solve this problem correctly. Here is my code:
public class P10149 {
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(new FileInputStream("input.txt"));
// Scanner in = new Scanner(System.in);
while (in.hasNextLine()) {
int[][] round = new int[13][5];
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 5; j++) {
round[i][j] = in.nextInt();
}
}
in.nextLine();
int[][] point = new int[13][13];
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 13; j++) {
point[i][j] = getPoint(round[i], j);
}
}
int[][] state = new int[14][1 << 13];
for (int i = 1; i <= 13; i++) {
Arrays.fill(state[i], -1);
}
int[][] bonusSum = new int[14][1 << 13];
int[][] choice = new int[14][1 << 13];
for (int i = 1; i <= 13; i++) {
for (int j = 0; j < (1 << 13); j++) {
int usedSlot = 0;
for (int b = 0; b < 13; b++) {
if (((1 << b) & j) != 0) {
usedSlot++;
}
}
if (usedSlot != i) {
continue;
}
for (int b = 0; b < 13; b++) {
if (((1 << b) & j) != 0) {
int j2 = (~(1 << b) & j);
int bonus;
if (b < 6) {
bonus = bonusSum[i - 1][j2] + point[i - 1][b];
} else {
bonus = bonusSum[i - 1][j2];
}
int newPoint;
if (bonus >= 63 && bonusSum[i - 1][j2] < 63) {
newPoint = 35 + state[i - 1][j2] + point[i - 1][b];
} else {
newPoint = state[i - 1][j2] + point[i - 1][b];
}
if (newPoint > state[i][j]) {
choice[i][j] = b;
state[i][j] = newPoint;
bonusSum[i][j] = bonus;
}
}
}
}
}
int index = (1 << 13) - 1;
int maxPoint = state[13][index];
boolean bonus = (bonusSum[13][index] >= 63);
int[] mapping = new int[13];
for (int i = 13; i >= 1; i--) {
mapping[choice[i][index]] = i;
index = (~(1 << choice[i][index]) & index);
}
for (int i = 0; i < 13; i++) {
System.out.print(point[mapping[i] - 1][i] + " ");
}
if (bonus) {
System.out.print("35 ");
} else {
System.out.print("0 ");
}
System.out.println(maxPoint);
}
}
static int getPoint(int[] round, int category) {
if (category < 6) {
int sum = 0;
for (int i = 0; i < round.length; i++) {
if (round[i] == category + 1) {
sum += category + 1;
}
}
return sum;
}
int sum = 0;
int[] count = new int[7];
for (int i = 0; i < round.length; i++) {
sum += round[i];
count[round[i]]++;
}
if (category == 6) {
return sum;
} else if (category == 7) {
for (int i = 1; i <= 6; i++) {
if (count[i] >= 3) {
return sum;
}
}
} else if (category == 8) {
for (int i = 1; i <= 6; i++) {
if (count[i] >= 4) {
return sum;
}
}
} else if (category == 9) {
for (int i = 1; i <= 6; i++) {
if (count[i] >= 5) {
return 50;
}
}
} else if (category == 10) {
for (int i = 1; i <= 3; i++) {
if (isStraight(count, i, 4)) {
return 25;
}
}
} else if (category == 11) {
for (int i = 1; i <= 2; i++) {
if (isStraight(count, i, 5)) {
return 35;
}
}
} else if (category == 12) {
for (int i = 1; i <= 6; i++) {
for (int j = 1; j <= 6; j++) {
if (i != j && count[i] == 3 && count[j] == 2) {
return 40;
}
}
}
}
return 0;
}
static boolean isStraight(int[] count, int start, int num) {
for (int i = start; i < start + num; i++) {
if (count[i] == 0) {
return false;
}
}
return true;
}
}
Here is the working solution.
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;
public class P10149 {
static final int MAX_BONUS_SUM = 115;
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(new FileInputStream("input.txt"));
// Scanner in = new Scanner(System.in);
long t1 = System.currentTimeMillis();
while (in.hasNextLine()) {
int[][] round = new int[13][5];
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 5; j++) {
round[i][j] = in.nextInt();
}
}
in.nextLine();
int[][] point = new int[13][13];
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 13; j++) {
point[i][j] = getPoint(round[i], j);
}
}
int[][] state = new int[1 << 13][MAX_BONUS_SUM + 1];
int[][] newState = new int[1 << 13][MAX_BONUS_SUM + 1];
for (int j = 0; j < (1 << 13); j++) {
Arrays.fill(state[j], -1);
Arrays.fill(newState[j], -1);
}
state[0][0] = 0;
int[][][] choice = new int[13][1 << 13][MAX_BONUS_SUM + 1];
for (int i = 0; i < 13; i++) {
for (int j = 0; j < (1 << 13); j++) {
int usedSlot = 0;
for (int b = 0; b < 13; b++) {
if (((1 << b) & j) != 0) {
usedSlot++;
}
}
if (usedSlot != i + 1) {
continue;
}
for (int b = 0; b < 13; b++) {
if (((1 << b) & j) != 0) {
int j2 = (~(1 << b) & j);
for (int s = 0; s <= MAX_BONUS_SUM; s++) {
int oldSum;
if (b < 6) {
if (s < point[i][b]) {
s = point[i][b] - 1;
continue;
}
oldSum = s - point[i][b];
} else {
oldSum = s;
}
if (state[j2][oldSum] < 0) {
continue;
}
int newPoint;
if (s >= 63 && oldSum < 63) {
newPoint = 35 + state[j2][oldSum] + point[i][b];
} else {
newPoint = state[j2][oldSum] + point[i][b];
}
if (newPoint > newState[j][s]) {
choice[i][j][s] = b;
newState[j][s] = newPoint;
}
}
}
}
}
for (int j = 0; j < (1 << 13); j++) {
for (int s = 0; s <= MAX_BONUS_SUM; s++) {
state[j][s] = newState[j][s];
}
Arrays.fill(newState[j], -1);
}
}
int index = (1 << 13) - 1;
int maxPoint = -1;
int sum = 0;
for (int s = 0; s <= MAX_BONUS_SUM; s++) {
if (state[index][s] > maxPoint) {
maxPoint = state[index][s];
sum = s;
}
}
boolean bonus = (sum >= 63);
int[] mapping = new int[13];
for (int i = 12; i >= 0; i--) {
mapping[choice[i][index][sum]] = i;
int p = 0;
if (choice[i][index][sum] < 6) {
p = point[i][choice[i][index][sum]];
}
index = (~(1 << choice[i][index][sum]) & index);
sum -= p;
}
for (int i = 0; i < 13; i++) {
System.out.print(point[mapping[i]][i] + " ");
}
if (bonus) {
System.out.print("35 ");
} else {
System.out.print("0 ");
}
System.out.println(maxPoint);
}
long t2 = System.currentTimeMillis();
// System.out.println(t2 - t1);
}
static int getPoint(int[] round, int category) {
if (category < 6) {
int sum = 0;
for (int i = 0; i < round.length; i++) {
if (round[i] == category + 1) {
sum += category + 1;
}
}
return sum;
}
int sum = 0;
int[] count = new int[7];
for (int i = 0; i < round.length; i++) {
sum += round[i];
count[round[i]]++;
}
if (category == 6) {
return sum;
} else if (category == 7) {
for (int i = 1; i <= 6; i++) {
if (count[i] >= 3) {
return sum;
}
}
} else if (category == 8) {
for (int i = 1; i <= 6; i++) {
if (count[i] >= 4) {
return sum;
}
}
} else if (category == 9) {
for (int i = 1; i <= 6; i++) {
if (count[i] >= 5) {
return 50;
}
}
} else if (category == 10) {
for (int i = 1; i <= 3; i++) {
if (isStraight(count, i, 4)) {
return 25;
}
}
} else if (category == 11) {
for (int i = 1; i <= 2; i++) {
if (isStraight(count, i, 5)) {
return 35;
}
}
} else if (category == 12) {
for (int i = 1; i <= 6; i++) {
if (count[i] >= 5) {
return 40;
}
}
for (int i = 1; i <= 6; i++) {
for (int j = 1; j <= 6; j++) {
if (i != j && count[i] == 3 && count[j] == 2) {
return 40;
}
}
}
}
return 0;
}
static boolean isStraight(int[] count, int start, int num) {
for (int i = start; i < start + num; i++) {
if (count[i] == 0) {
return false;
}
}
return true;
}
}
Use Munker's algorithm to solve this problem

Resources