package shootout.knucleotide;
/* The Computer Language Benchmarks Game
http://shootout.alioth.debian.org/
contributed by James McIlree
ByteString code thanks to Matthieu Bentot and The Anh Tran
*/
import java.util.*;
import java.io.*;
import java.util.concurrent.*;
public class KNucleotide {
static ArrayList<Callable<Map<ByteString, ByteString>>> createFragmentTasks(final byte[] sequence, int[] fragmentLengths) {
ArrayList<Callable<Map<ByteString, ByteString>>> tasks = new ArrayList<Callable<Map<ByteString, ByteString>>>();
for (int fragmentLength : fragmentLengths) {
for (int index = 0; index < fragmentLength; index++) {
final int offset = index;
final int finalFragmentLength = fragmentLength;
tasks.add(new Callable<Map<ByteString, ByteString>>() {
public Map<ByteString, ByteString> call() {
return createFragmentMap(sequence, offset, finalFragmentLength);
}
});
}
}
return tasks;
}
static Map<ByteString, ByteString> createFragmentMap(byte[] sequence, int offset, int fragmentLength) {
HashMap<ByteString, ByteString> map = new HashMap<ByteString, ByteString>();
int lastIndex = sequence.length - fragmentLength + 1;
ByteString key = new ByteString(fragmentLength);
for (int index = offset; index < lastIndex; index += fragmentLength) {
key.calculateHash(sequence, index);
ByteString fragment = map.get(key);
if (fragment != null) {
fragment.count++;
} else {
map.put(key, key);
key = new ByteString(fragmentLength);
}
}
return map;
}
// Destructive!
static Map<ByteString, ByteString> sumTwoMaps(Map<ByteString, ByteString> map1, Map<ByteString, ByteString> map2) {
for (Map.Entry<ByteString, ByteString> entry : map2.entrySet()) {
ByteString sum = map1.get(entry.getKey());
if (sum != null)
sum.count += entry.getValue().count;
else
map1.put(entry.getKey(), entry.getValue());
}
return map1;
}
static String writeFrequencies(float totalCount, Map<ByteString, ByteString> frequencies) {
SortedSet<ByteString> list = new TreeSet<ByteString>(frequencies.values());
StringBuilder sb = new StringBuilder();
for (ByteString k : list)
sb.append(String.format("%s %.3f\n", k.toString().toUpperCase(), (float) (k.count) * 100.0f / totalCount));
return sb.append('\n').toString();
}
static String writeCount(List<Future<Map<ByteString, ByteString>>> futures, String nucleotideFragment) throws Exception {
ByteString key = new ByteString(nucleotideFragment.length());
key.calculateHash(nucleotideFragment.getBytes(), 0);
int count = 0;
for (Future<Map<ByteString, ByteString>> future : futures) {
ByteString temp = future.get().get(key);
if (temp != null) count += temp.count;
}
return count + "\t" + nucleotideFragment.toUpperCase() + '\n';
}
public static void main(String[] args) throws Exception {
InputStream stream = KNucleotide.class.getClassLoader().getResourceAsStream("shootout/knucleotide/kNucleotide.class");
String line;
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte bytes[] = new byte[100];
while ((line = in.readLine()) != null) {
if (line.length() > bytes.length)
bytes = new byte[line.length()];
int i;
for (i = 0; i < line.length(); i++)
bytes[i] = (byte) line.charAt(i);
baos.write(bytes, 0, i);
}
byte[] sequence = baos.toByteArray();
long millis = System.currentTimeMillis();
ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
int[] fragmentLengths = {1, 2, 3, 4, 6, 12, 18};
List<Future<Map<ByteString, ByteString>>> futures = pool.invokeAll(createFragmentTasks(sequence, fragmentLengths));
pool.shutdown();
StringBuilder sb = new StringBuilder();
sb.append(writeFrequencies(sequence.length, futures.get(0).get()));
sb.append(writeFrequencies(sequence.length - 1, sumTwoMaps(futures.get(1).get(), futures.get(2).get())));
String[] nucleotideFragments = {"ggt", "ggta", "ggtatt", "ggtattttaatt", "ggtattttaatttatagt"};
for (String nucleotideFragment : nucleotideFragments) {
sb.append(writeCount(futures, nucleotideFragment));
}
/*System.out.print(sb.toString());*/
long total = System.currentTimeMillis() - millis;
System.out.println("[KNucleotide-Java Benchmark Result: " + total + "]");
}
static final class ByteString implements Comparable<ByteString> {
public int hash, count = 1;
public final byte bytes[];
public ByteString(int size) {
bytes = new byte[size];
}
public void calculateHash(byte k[], int offset) {
int temp = 0;
for (int i = 0; i < bytes.length; i++) {
byte b = k[offset + i];
bytes[i] = b;
temp = temp * 31 + b;
}
hash = temp;
}
public int hashCode() {
return hash;
}
public boolean equals(Object obj) {
return Arrays.equals(bytes, ((ByteString) obj).bytes);
}
public int compareTo(ByteString other) {
return other.count - count;
}
public String toString() {
return new String(bytes);
}
}
}