Erastotenes Sieve in paraller programm Java - java

I would like to make a programm which count prime numbers using Erastotenes Sieve. In this issue I want to use semaphore to communicate between thread to make calculations on table with numbers.
So far I have written code like that.
public static void main( String[] args ) throws InterruptedException {
System.out.println("Podaj gorny zakres\n");
Scanner scanner = new Scanner(System.in);
Erastotenes erastotenes = new Erastotenes(Integer.parseInt(scanner.nextLine()));
erastotenes.initializeTable();
long start = System.nanoTime();
List<SingleProcess.MyThread> list = new ArrayList<>();
List<Integer> numbers = Dollar.$(2,erastotenes.getMaximumNumber()+1).toList();
for(int i=0;i<2;i++)
{
list.add(new SingleProcess.MyThread(erastotenes,numbers.subList((numbers.size()/2)*i,(numbers.size()/2)*i+numbers.size()/2)));
list.get(list.size()-1).start();
list.get(list.size()-1).join();
}
System.out.println(System.nanoTime() - start);
//System.out.println("Liczba elementów: "+erastotenes.countPrimeElements());
}
Erastotenes class.
public class Erastotenes {
private int upperRange;
private int maximumNumber;
private int table[];
public Erastotenes(int upperRange) {
this.upperRange = upperRange;
this.maximumNumber = (int)(Math.floor(Math.sqrt(upperRange)));
this.table = new int[upperRange+1];
}
public int getMaximumNumber() {
return maximumNumber;
}
public int getUpperRange() {
return upperRange;
}
public void initializeTable()
{
for(int i=1;i<=upperRange;i++) {
table[i] = i;
}
}
public void makeSelectionOfGivenNumber(int number)
{
if (table[number] != 0) {
int multiple;
multiple = number+number;
while (multiple<=upperRange) {
table[multiple] = 0;
multiple += number;
}
}
}
public List<Integer> getList()
{
List<Integer> list = Ints.asList(table);
return list.stream().filter(item->item.intValue()!=0 && item.intValue()!=1).collect(Collectors.toList());
}
}
The class describing single Thread to make calculations with static Semaphore looks like this.
public class SingleProcess {
static Semaphore semaphore = new Semaphore(1);
static class MyThread extends Thread {
Erastotenes erastotenes;
List<Integer> numbers;
MyThread(Erastotenes erastotenes,List<Integer> numbers) {
this.erastotenes = erastotenes;
this.numbers=numbers;
}
public void run() {
for(int number:numbers) {
try {
semaphore.acquire();
//1System.out.println(number + " : got the permit!");
erastotenes.makeSelectionOfGivenNumber(number);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
}
}
}
I thought that splitting on half table with numbers from 2 to maximum numbers as square root like in erastotrenes algorithm for these two Threads will boost calculations, but with upperRange to 100000000 the difference between paraller and sequence is not so big. How can I in another realize this problem of paraller programming Erastotenes Sieve?

I think your main problem is this:
for(int i=0;i<2;i++)
{
list.add(new SingleProcess.MyThread(erastotenes,numbers.subList((numbers.size()/2)*i,(numbers.size()/2)*i+numbers.size()/2)));
list.get(list.size()-1).start();
list.get(list.size()-1).join();
}
You start a thread and then immediately wait for it to finish; that kills the parallelism entirely. You can start and wait in the end:
for(int i=0;i<2;i++)
{
list.add(new SingleProcess.MyThread(erastotenes,numbers.subList((numbers.size()/2)*i,(numbers.size()/2)*i+numbers.size()/2)));
list.get(list.size()-1).start();
}
for (Thread t : list) {
t.join();
}
But, there's also a problem with your semaphore tbh. Each thread blocks all other threads from doing anything as long as it's working on a number; that means that again, all parallelism is gone.
You can do away with the semaphore altogether IMO; there's not really a lot of danger in setting the same index to 0 several times, which is all that happens in this "critical section" - but it's not critical at all because no one ever reads the array value in question before all threads are finished.

Related

How can I assign a value to the threadArray variable in Task1 , Task2, Task3 class run() method?

I have to insert the elements using three threads by creating three classes, namely Task1,Task2 and Task3. The values to be inserted into the array are 0,1,2,....299.
Override the run method in the threads. Three integer i,j, and k representing the number of elements each thread should append inside the given array.
Thread one should append 0 to i-1 inside the array,thread two should append i to i+j-1 inside the array,and the third thread should append i+j to 299 inide the array.
Threads one and two must run simultaneously, and the values of the threads one and two must be inserted inside the indices of the array from 0 to i+j-1 randomly.The third thread should start only after the first two threads have been executed completely.
In these code three task are given.
first task and second task start executing the thread at the same time and after completion of first two task then only third task start. If these situation getting correct then test() method return true.
public static final int[] threadArray = new int[300]; how I add random number into these array using Task1 Task2 and Task3 class.
Input :
80
130
90
Output :
True
import java.util.Scanner;
class Task1 extends Thread
{
static int a = 0;
static int beg = 0;
public void run()
{
for(int i=a;i<=beg;i++)
{
Solution.threadArray[i] = i;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Task2 extends Thread
{
static int a = 0;
static int beg = 0;
#Override
public void run()
{
// TODO Auto-generated method stub
for(int i=a;i<=beg;i++)
{
Solution.threadArray[i] = i;
}
}
}
class Task3 extends Thread
{
static int a = 0;
static int beg = 0;
public void run()
{
// TODO Auto-generated method stub
for(int i=a;i<=beg;i++)
{
Solution.threadArray[i] = i;
}
}
}
public class Solution
{
public static final int[] threadArray = new int[300];
public static volatile String i = 0+"";
public boolean test() throws InterruptedException
{
Task1 task1 = new Task1();
Task2 task2 = new Task2();
Task3 task3 = new Task3();
Thread task2Thread = new Thread(task2);
Thread task3Thread = new Thread(task3);
task1.start();
task2Thread.start();
task1.join();
task2Thread.join();
task3Thread.start();
int first = Task1.a+Task2.a;
int containsSecondThread = Task1.a;
String oneAndTwo = "";
String sizeOfTask1 = "";
for(int i=0;i<first;i++)
{
oneAndTwo += threadArray[i]+" ";
}
for(int i=0;i<containsSecondThread;i++)
{
sizeOfTask1 += threadArray[i]+" ";
}
int begOfTask3 = Task3.beg;
String checkingString = "";
for(int i=begOfTask3;i<threadArray.length;i++)
{
checkingString += i + " ";
}
String task3String = "";
for(int j = begOfTask3;j<threadArray.length;j++)
{
task3String += threadArray[j]+" ";
}
if((!oneAndTwo.contains(begOfTask3+"") && sizeOfTask1.contains(Task2.beg+"")) || task3String.equals(checkingString))
{
return true;
}
return false;
}
public static void main(String[] args) throws InterruptedException
{
Scanner sc= new Scanner(System.in);
Solution solution = new Solution();
int one = sc.nextInt();
Task1.a = one;
Task1.beg = 0;
int two = sc.nextInt();
Task2.a = two;
Task2.beg = one;
int three = sc.nextInt();
Task3.a = three;
Task3.beg = one+two;
System.out.print(solution.test());
}
}
First, some observations regarding your code: Instead of using static variables in the classes (i.e., Task1, Task2, and Task3) that extend the class Thread (to understand why have a look at Why are static variables considered evil?):
static int a = 0;
static int beg = 0;
use non-static final fields, and initialize them via the constructor:
class Task1 extends Thread
{
private final int begin;
private final int end;
Task1(int begin, int end){
this.begin = begin;
this.end = end;
}
public void run(){
for(int i=begin; i<= end; i++)
....
}
}
adapt the main method accordingly:
public static void main(String[] args){
...
Task1 task1 = new Task1(begin, end);
}
and then pass the tasks-related objects as parameters of to the test method:
public boolean test(Task1 task1, Task2 task2, Task3 task3){
...
}
For the concatenation of the strings use StringBuilder:
StringBuilder oneAndTwo = new StringBuilder();
for(int i=0;i<first;i++)
{
oneAndTwo.append(threadArray[i]).append(" ");
}
This looks wrong:
Task1.a = one;
Task1.beg = 0;
by looking at the loop of the run method from Task1, this means that, if Task1.a is not a negative number, then Task1 will not do any work.
To use the threads to generate the random values of the array:
int[] threadArray = new int[300];
you can start by extracting a method to generate those random values, based on formula:
r.nextInt(high-low) + low;
this formula generates a random value between low and high.
Adapt the tasks, accordingly:
class Task1 extends Thread
{
private final Random random_values = new Random();
private final int low;
private final int high;
...
public int generate_random(){
return r.nextInt(high-low) + low;
}
public void run()
{
for(....)
{
Solution.threadArray[i] = generate_random();
...
}
}
}
Make sure to pass to the threads the information about the range of the random values to be generated (i.e., the low and high parameters), and the reference to the array that will be filled up with those random values (i.e., array int[] threadArray) . Also make sure that you split the iterations int[] threadArray among the threads. Therefore, each thread should generate a chunk of the random values. An example of such distribution would be:
Thread 1 : 0 to 100;
Thread 2 : 100 to 200;
Thread 3 : 200 to 300;
You can make this more robust and divide the array length by the number to threads and assign the work among threads, accordingly.
I could have provided you with the entire solution, but I feel that is better instead if I give you the pointers so that you can do it in your own.
EDIT: Based on the new edit of your question:
You just need to adapt the Task classes as follows:
class Task1 extends Thread {
static int a = 0;
static int beg = 0;
public void run(){
for(int i=beg;i < a;i++)
Solution.threadArray[i] = i;
}
}
class Task2 extends Thread {
static int a = 0;
static int beg = 0;
public void run(){
for(int i=beg; i< beg + a;i++)
Solution.threadArray[i] = i;
}
}
class Task3 extends Thread{
static int a = 0;
static int beg = 0;
public void run(){
for(int i=beg;i< a + beg;i++)
Solution.threadArray[i] = i;
}
}
Thread1 and Thread2 are supposed to access Common Resource in threadArray[0... Task1.a+Task2+a]. So we have to make use of static volatile variable i declared in Solution Class.
class Task1 extends Thread
{
static int a=0,beg=0;
public void run()
{
int k=Task1.beg;
int i1=0;
while(i1<Task1.a)
{
Solution.threadArray[Integer.parseInt(Solution.i)]=k++;
int a1=Integer.parseInt(Solution.i);
a1++;i1++;
Solution.i=a1+"";
try{
Thread.sleep(1);
}
catch(InterruptedException e){}
}
}
}
class Task2 extends Thread
{
static int a=0,beg=0;
public void run()
{
int y=0;
int k=Task2.beg;
while(y<Task2.a)
{
Solution.threadArray[Integer.parseInt(Solution.i)]=k++;
int a1=Integer.parseInt(Solution.i);
a1++;y++;
Solution.i=a1+"";
try{
Thread.sleep(1);
}
catch(InterruptedException e){}
}
}
}
Thread3 work independently after First 2 threads complete.
class Task3 extends Thread
{
static int beg=0,a=0;
public void run()
{
for(int i=Task3.beg;i<Task3.beg+Task3.a;i++)
{
Solution.threadArray[i]=i;
}
}
}

Concurrency - write a program in which multiple threads add the same amount of elements to list

So I am supposed to write a program, in which multiple threads add some number of items to a list. I was given two interfaces that I should implement. The number added is a sum of two previous numbers added (like Fibonacci series)
public interface Main
{
List<Integer> sum(int count, int threadCount, int firstElement, int secondElement);
}
and
public interface Sum extends Runnable
{
//how many elements each thread should add
int getHowMany();
List<Integer> getList();
}
So I thought of doing it this way: I create a class DefaultSum, which implements Sum interface, implement methods from it, and in the run() method I would call a method actually adding elements to list.
This is my DefaultSum class
public class DefaultSum implements Sum {
DefaultMain main = new DefaultMain();
DefaultSum() {
}
#Override
public void run() {
int count = getHowMany();
List<Integer> list = getList();
int firstElement = list.get(list.size() - 2).intValue();
int secondElement = list.get(list.size() - 1).intValue();
int j = 2;
while (j < count) {
int adder = firstElement + secondElement;
list.add(adder);
System.out.println(list);
firstElement = secondElement;
secondElement = adder;
if (j == count) {
notifyAll();
}
j++;
}
System.out.println(list);
}
#Override
public int getHowMany() {
try {
Field[] fields = DefaultMain.class.getFields();
for (int i = 0; i < fields.length; i++) {
Object val = fields[i].get(main);
if (fields[i].getName().equalsIgnoreCase("count")) {
int number = (Integer) val;
return number;
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return -1;
}
#Override
public List<Integer> getList() {
try {
Field[] fields = DefaultMain.class.getFields();
for (int i = 0; i < fields.length; i++) {
Object val = fields[i].get(main);
if (fields[i].getName().equalsIgnoreCase("list")) {
return (List<Integer>) val;
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
And my main class, DefaultMain, where the number of items added is given and user can decide how many threads he wants to work on this list.
public class DefaultMain implements Main {
static int firstElement = 0;
static int secondElement = 1;
static int count = 10;
public static List<Integer> lista = new ArrayList<Integer>();
public static List<Integer> list = Collections.synchronizedList(lista);
static int threadCount;
public static void main(String[] args) throws InterruptedException {
list.add(firstElement);
list.add(secondElement);
System.out.println("how many threads");
Scanner sc = new Scanner(System.in);
threadCount = sc.nextInt();
Main exa = new DefaultMain();
exa.sum(count, threadCount, firstElement, secondElement);
}
#Override
public List<Integer> sum(int count, int threadCount, int firstElement, int secondElement) {
synchronized(this.list) {
for (int i = 0; i < DefaultMain.threadCount; i++) {
new Thread(new DefaultSum()).start();
}
return list;
}
}}
I tried running this program multiple times, however, it seems that the list is not updated after first two elements are added. Seems that methods getHowMany() and getList() work fine, I'm not sure what could be wrong, I'll appreciate any answer, this problem has been bugging me for some time now.
Edit: I'll paste what I get in console
Edit2: tried changing some bits, but it does not work at all.
how many threads
4
[0, 1]
[0, 1]
[0, 1]
[0, 1]
You just need to create a single thread Executor and then from any thread call execute() with the operations you need to do on the list in a Runnable provided as the only parameter. Here is what it looks like with a lambda.
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(() -> {
int size = list.size();
list.add(list.get(size - 1) + list.get(size - 2));
});
As the JavaDoc (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor--) states "Creates an Executor that uses a single worker thread operating off an unbounded queue...Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time."

Prime Numbers Generating Threads in Java printing twice

I am trying to print prime numbers between one point to another, lets say from 1 to 1000 in one thread and 1000 to 2000 in another thread but when I print each thread using foreach loop it gives me an unordered Arraylist which is printed twice.
I am trying to print 1, 2, 3, 5, 7... using two concurrent threads. Please help me out so that I can better understand threading.
public class PrimeNumberGenerator implements Runnable{
protected long from, to;
static ArrayList<Long> primeList = new ArrayList<Long>();
public PrimeNumberGenerator(long from,long to)
{
this.from = from;
this.to = to;
}
public long count = 0;
public void run() {
for(long n=from; n<=to; n++){
boolean isPrime = true;
for(long i = 2; i<n; i++) {
if(n % i==0) {
isPrime = false;
break;
}
}
if(isPrime) {
count++;
primeList.add(n);
}
}
}
public ArrayList<Long> getPrimes() {
return primeList;
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
PrimeNumberGenerator gen1 = new PrimeNumberGenerator(1L,1000L);
PrimeNumberGenerator gen2 = new PrimeNumberGenerator(1001L,2000L);
Thread t1 = new Thread(gen1);
Thread t2 = new Thread(gen2);
t1.start();
t2.start();
t1.join();
t2.join();
gen1.getPrimes().forEach(primeList -> System.out.println(primeList));
gen2.getPrimes().forEach(primeList -> System.out.println(primeList));
}
}
The problem is that you have two threads filling the same ArrayList at the same time, because your ArrayList is static (meaning there will only be one instand shared throughout the whole application)
The first thread may add three numbers, then the second thread adds three numbers and then the first again, resulting in an ArrayList that contains
[1, 2, 3, 1009, 1013, 1019, 5, 7, 11]
Then in the end you (correctly) wait for the Threads to finish and print the same (incorrectly ordered) ArrayList twice!
Just make your ArrayList non static and it will work, that way both PrimeNumberGenerator will have their own ArrayList!
I recommend using a TreeSet to keep the primes ordered. The TreeSet will need to be properly synchronized for multiple thread access.
public class PrimeNumberGenerator implements Runnable {
protected long from, to;
static Set<Long> primeList = new TreeSet<Long>();
public PrimeNumberGenerator(long from, long to)
{
this.from = from;
this.to = to;
}
public long count=0;
public void run() {
for(long n=from;n<=to;n++) {
boolean isPrime = true;
for(long i = 2; i<n; i++) {
if(n % i==0) {
isPrime = false;
break;
}
}
if(isPrime) {
count++;
synchronized(primeList) {
primList.add(n);
}
}
}
}
public static ArrayList<Long> getPrimes(){
//Make a copy so we don't need to synchronize outside of this class
return new ArrayList<>(primeList);
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
PrimeNumberGenerator gen1 = new PrimeNumberGenerator(1L,1000L);
PrimeNumberGenerator gen2 = new PrimeNumberGenerator(1001L,2000L);
Thread t1 = new Thread(gen1);
Thread t2 = new Thread(gen2);
t1.start();
t2.start();
t1.join();
t2.join();
PrimeNumberGenerator.getPrimes().forEach(primeList -> System.out.println(primeList));
}
}

some elements processed more than once, some not at all

I have a fairly straightforward task: I have a list of strings each of which is processed and a score is produced. The string and its score then get added to a map:
public class My1Thread
{
final private static List<String> ids = Arrays.asList("id1","id2","id3","id4","id5");
private static HashMap<String,Double> result = null;
private Double computeResult(String id)
{
Double res = 0.0;
// do stuff to compute result
return res;
}
public static void main(String[] args)
{
result = new HashMap<String,Double>();
for (String id: ids)
{
result.put(id,computeResult(id));
}
}
}
Since scores of any two strings are independent of each other, this seems to be a perfect case to use multithreading. However, I am getting unexpected results, which is probably a typical result for a multithreading newbie.
Here's a m/t version of the above:
public class MyMultiThread
{
final private static int nWorkers = 3; // number of threads
final private static List<String> ids = Arrays.asList("id1","id2","id3","id4","id5");
private static int curIndex = 0; // indexing pointing to position in ids currently being processed
private static HashMap<String,Double> result = null;
public static class Worker implements Runnable {
private int id;
public Worker(int id) {
this.id = id;
}
synchronized void setCounter(final int counter)
{
curIndex = counter;
}
synchronized int getCounter()
{
return curIndex;
}
synchronized void addToResult(final String id, final Double score)
{
result.put(id,score);
}
#Override
public void run()
{
try {
while (true)
{
int index = getCounter();
if (index >= ids.size())
{
// exit thread
return;
}
String id = ids.get(index);
setCounter(index+1);
System.out.print(String.format("Thread %d: processing %s from pos %d\n", id, id, curIndex-1));
Double score = ... // compute score here
addToResult(id,score);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static void main(String[] args)
{
result = new HashMap<String,ArrayList<Pair<Document,Double>>>();
for (int i = 0; i < nWorkers; i++) {
Thread worker = new Thread(new MyMultiThread.Worker(i));
worker.start();
}
}
}
According to the output produced by System.out.print, this code appears to be processing some elements of ids more than once while not processing others at all. What am I doing wrong here?
Your while(true) loop inside the thread starts at the index specified in the constructor, and then increment it by one, and then the loop starts again. So thread 0 does index 0, then index 1, etc.. Thread 1 does index 1, then index 2, etc... So index 2 will be done 3 times.
I would use a synchronized linked list for ids, and have each thread take and remove the first element of the list, until the list is empty. Use LinkedList.removeFirst().
Also the result hash map also needs to be synchronized, since multiple threads may write to it at the same time.
The problem is that the map is being modified concurrently in multiple threads, so some updates are getting lost.
You declared the methods that modify the map as synchronized, but note that they are synchronized on multiple worker objects: not on a single object, which would provide the locking you are after.
I'd recommend using ConcurrentHashMap and getting rid of all the synchronized declarations.
Some of your synchronization is too narrow - for example, this bit here:
int index = getCounter();
if (index >= ids.size())
{
// exit thread
return;
}
String id = ids.get(index);
setCounter(index+1);
What happens if thread A reads the counter, thread B reads the counter, then thread A updates the counter?
A: int index = getCounter(); // returns 3
B: int index = getCounter(); // returns 3
...
A: setCounter(index + 1); // sets it to 4
B: setCounter(index + 1); // Uh-oh, sets it to 4 as well, we lost an update!
In this case, when you read a variable, then write to it based on the value you read, both the read and the write need to be within the same synchronization block. Declaring getCounter and setCounter as synchronized is not enough.
Simply use Java 8 Stream API :
Map<String, Double> map = ids.parallelStream().collect(Collectors.toConcurrentMap(id -> id, id -> computeScore(id)));
...
Double computeScore(String id) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return ThreadLocalRandom.current().nextDouble(100);
}
Here's a nice tutorial.

how to spwan recursive calls and for loop iterations in multiple threads in java (if possible)?

I was wondering if it is possible to spawn each loop iteration (each iteration into a thread by itself) and finally collect the result. consider this example, nothing fancy in it at all. Just a simple for-loop, but the idea is to extend on it. The body of for loop does not matter, I just filled up with some code. but basically assume it has some expensive calculation which will take few minutes to complete for each iteration. so I want to do each loop calculation in a separate thread.
public class Threadspawns {
private double[] arr = new double[4];
public void calculations(){
for (int i =2; i < 6; i++){
//expensive calculation
arr[i-2]=Math.pow(i,500);
}
}
public static void main(String[] args){
Threadspawns t = new Threadspawns();
long start = System.currentTimeMillis();
t.calculations();
long end = System.currentTimeMillis();
System.out.println(Arrays.toString(t.arr));
System.out.println("time taken "+ (end-start));
}
}
on the same note,
if it is possible to actually split the recursive calls into multiple threads and collect them as they return.
Example is that of fibonacci
public static int fibonacci(int n){
if (n==0)
return 0;
if (n==1)
return 1;
return fibonacci(n-2)+fibonacci(n-1);
}
It is possible that it cannot be done for fibonacci recurive method. but any other example of paralleling recursive calls between threads IF POSSIBLE would be nice to know.
P.S: I have basic knowledge of Thread and Runnable, but wondering if the above is doable
Solution to your first requirement that is moving the expensive calculation into a Callable task. Hope it find it useful:
import java.util.Arrays;
import java.util.concurrent.*;
public class Threadspawns {
private final int THREAD_COUNT = 8;
private final int CALCULATION_COUNT = 60000;
private double[] arr = new double[CALCULATION_COUNT];
public void calculations() {
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);
ExecutorCompletionService<Double> completionService = new ExecutorCompletionService<Double>(executorService);
for (int i = 2; i < CALCULATION_COUNT; i++) {
completionService.submit(new Calculation(i));
}
//Get from all Future tasks till all tasks completed
for (int i = 2; i < CALCULATION_COUNT; i++) {
try {
arr[i] = completionService.take().get();
} catch (InterruptedException e) {
e.printStackTrace(); //do something
} catch (ExecutionException e) {
e.printStackTrace(); //do something
}
}
}
private static class Calculation implements Callable<Double> {
private final int num;
private Calculation(int num) {
this.num = num;
}
#Override
public Double call() throws Exception {
return Math.pow(num, 500);
}
}
public static void main(String[] args) {
Threadspawns t = new Threadspawns();
long start = System.currentTimeMillis();
t.calculations();
long end = System.currentTimeMillis();
System.out.println(Arrays.toString(t.arr));
System.out.println("time taken " + (end - start));
}
}

Categories