Histogram pracs

Histogram pracs

Task 1

Histogram

public class Histogram
{
    protected long[] bins;
    protected int min, max, range;
    protected int numBins;

    public Histogram(int max, int min, int numBins)
    {
        this.max = max;
        this.min = min;
        this.numBins = numBins;
        bins = new long[numBins];
        range = max - min + 1;
    }

    public void add(int num)
    {
        int bin = (int) Math.floor(((num - min) * 1.0 / range) * numBins);
        bins[bin]++;
    }

    public int absDifference(Histogram histogram)
    {
        int sum = 0;
        if (histogram.min == min && histogram.max == max && histogram.numBins == numBins)
            for (int i = 0; i < bins.length; i++)
                sum += (int) Math.abs(bins[i] - histogram.bins[i]);

        return sum;
    }

    @Override
    public String toString()
    {
        String out = String.format("{Min: %d, Max: %d, # Bins: %d, Values: ", min, max, numBins);
        for (int i = 0; i < bins.length; i++)
            out += bins[i] + ", ";

        out = out.substring(0, out.length() - 2);
        out += "}";
        return out;
    }
}

Histogram safe

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class HistogramSafe extends Histogram
{
    private Lock[] binLocks;

    public HistogramSafe(int max, int min, int numBins)
    {
        super(max, min, numBins);

        binLocks = new ReentrantLock[numBins];
        for (int i = 0; i < numBins; i++)
            binLocks[i] = new ReentrantLock();
    }

    @Override
    public void add(int num)
    {
        int bin = (int) Math.floor(((num - min) * 1.0 / range) * numBins);

        binLocks[bin].lock();
        bins[bin]++;
        binLocks[bin].unlock();
    }
}

Task 2 - Populating histogram

Histogram Populator thread

public class HistogramPopulator implements Runnable
{
    //represents range of arrays to access
    int min, max;

    public HistogramPopulator(int min, int max)
    {
        this.min = min;
        this.max = max;
    }

    @Override
    public void run()
    {
        for (int i = min; i < max; i++)
            for (int j = 0; j < 1000; j++)
                Main.histogramUnsafe.add(Main.ints[i][j]);

        //increase thread completion count
        int completed = Main.completeThreads.incrementAndGet();

        //notify main thread of completion if this is the last populator thread running
        if (Main.numThreads.get() == completed)
        {
            Main.noMoreThreadsLock.lock();
            Main.noMoreThreadsCondition.signalAll();
            Main.noMoreThreadsLock.unlock();
        }
    }
}

Main class

public class Main
{
    public static int[][] ints;
    public static Histogram histogramUnsafe;
    public static Histogram correct;
    public static AtomicInteger completeThreads;
    public static Lock noMoreThreadsLock;
    public static Condition noMoreThreadsCondition;
    public static AtomicInteger numThreads;
    public static int[] threadCount = new int[]{2, 4, 6, 8, 10, 15, 20, 25, 30, 40, 50};
    public static long[][] results;

    public static void main(String[] args)
    {
        ints = new int[10000][1000];
        results = new long[threadCount.length][10];

        //populate arrays
        Random rand = new Random();
        for (int i = 0; i < 10000; i++)
            for (int j = 0; j < 1000; j++)
                ints[i][j] = rand.nextInt(100) + 1;

        //find correct answer
        correct = new Histogram(100, 1, 20);
        for (int i = 0; i < 10000; i++)
            for (int k = 0; k < 1000; k++)
                correct.add(ints[i][k]);

        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < threadCount.length; j++)
                testHistogram(j, i);
        }

        try
        {
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("resultsT03.txt"));
            for (int j = 0; j < threadCount.length; j++)
            {
                long sum = 0;
                for (int i = 0; i < 10; i++)
                {
                    sum += results[j][i];
                }
                sum /= 10;

                //write to file
                osw.write(threadCount[j] + "," + sum + "\n");
            }
            osw.close();
        }
        catch (Exception e)
        {
            System.out.println("Oh no! Your process seems to have come to an untimely end! What will we do!?");
            System.out.println("Well, I don't know! Lay down, try not to cry, cry a lot. :'(");
        }
    }

    public static void testHistogram(int j, int count)
    {
        int N = threadCount[j];

        //create variables
        histogramUnsafe = new Histogram(100, 1, 20);
        completeThreads = new AtomicInteger(0);
        numThreads = new AtomicInteger(N);
        noMoreThreadsLock = new ReentrantLock();
        noMoreThreadsCondition = noMoreThreadsLock.newCondition();

        //divide array into N partitions
        HistogramPopulator[] populators = new HistogramPopulator[N];

        for (int i = 0; i < N; i++)
        {
            int lower = (10000/N)*i;
            int upper;

            //last thread
            if (i == N - 1)
                upper = 10000;
            else
                upper = lower + (10000/N);

            populators[i] = new HistogramPopulator(lower, upper);
        }

        //process arrays on separate threads
        for (int i = 0; i < N; i++)
        {
            //start thread
            (new Thread(populators[i])).start();
        }

        //wait for threads to finish
        noMoreThreadsLock.lock();
        try
        {
            while (completeThreads.get() < N)
                noMoreThreadsCondition.await();

        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        finally
        {
            noMoreThreadsLock.unlock();
        }

        //compare histograms and save result
        if (N > 1)
        {
            int diff = correct.absDifference(histogramUnsafe);
            results[j][count] = diff;
        }
    }
}

Send over server

Send Histogram over server

Client

import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

public class Client
{
    private Socket client;
    private ObjectInputStream input;
    private ObjectOutputStream output;
    private DatagramPacket sendPacket, recievePacket;
    private DatagramSocket socket;
    private byte[] iBytes;
    private int[] iArrayCur;

    public static void main(String args[])
    {
        new Client();
    }

    public Client()
    {
        try
        {
            System.out.println("Client started");

            // Step 1: Create a Socket to make connection.
            //client = new Socket("192.168.56.1", 500);
            client = new Socket("10.0.0.9", 500);
            //socket = new DatagramSocket(550);
            System.out.println("Connected to: " + client.getInetAddress().getHostName());

            // Step 2: Get the input and output streams.
            input = new ObjectInputStream(client.getInputStream());
            output = new ObjectOutputStream(client.getOutputStream());
            System.out.println("Got I/O Streams");

            // Step 3: Process connection.
            Histogram iHistCur = new Histogram(1, 100, 20);

            //RECEIVE ARRAY
            System.out.println("CLIENT: Receiving array " + 1 + " for processing...");
            //WaitForPackets();

            iArrayCur = (int[]) input.readObject();
            //iBytes = recievePacket.getData();
            //CONVERT TO int[]
            //ByteBuffer buffer = ByteBuffer.wrap(iBytes).order(ByteOrder.LITTLE_ENDIAN);
            //iArrayCur = new int[iBytes.length / 4];
            //buffer.asIntBuffer().put(iArrayCur);

            System.out.println("CLIENT: Array received. Processing...");
            //GET FACTORS
            for (int j = 0; j < iArrayCur.length; j++)
            {
                //Determine factors
                int iCur = iArrayCur[j];
                int[] iFactors = getFactors(iCur);
                for (int k = 0; k < iFactors.length; k++)
                {
                    if (iFactors[k] != 0)
                    {
                        if (iFactors[k] == iCur)
                        {
                            iHistCur.addDataPoint(iFactors[j]);
                        }
                        else
                        {
                            iHistCur.addDataPoint(iFactors[j]);
                        }
                    }
                }
            }

            System.out.println("CLIENT: Array processed. Sending histogram...");
            output.writeObject(iHistCur);

            //ByteBuffer byteBuffer = ByteBuffer.allocate(iVals.length * 4);
            //IntBuffer intBuffer = byteBuffer.asIntBuffer();
            //intBuffer.put(iVals);

            //iBytes = byteBuffer.array();
            //sendPacket = new DatagramPacket(iBytes, iBytes.length, InetAddress.getLocalHost(), 550);

            //System.out.println("CLIENT: Server message: " + input.readUTF());
            //System.out.println("CLIENT: Sending message \"Thank you\"");
            //output.writeUTF("Thank you");

            // Step 4: Close connection.
            System.out.println("Transmission complete. " + "Closing connection.");
            client.close();
        }
        catch (SocketException se)
        {
            System.out.println("Error");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public int[] getFactors(int iCur)
    {
        int[] iFactors = new int[iCur];
        int iCount = 0;

        for (int i = 1; i <= iCur; i++)
        {
            if (iCur % i == 0)
            {
                iFactors[iCount] = i;
                iCount++;
            }
        }

        return iFactors;
    }

    public void WaitForPackets()
    {
        try
        {
            while (true)
            {
                iBytes = new byte[1000];
                recievePacket = new DatagramPacket(iBytes, iBytes.length);

                socket.receive(recievePacket);

                System.out.println('\n' + new String(recievePacket.getData()) + '\n' + recievePacket.getLength() + '\n' + recievePacket.getAddress() + '\n' + recievePacket.getPort());
            }
        }
        catch (IOException ioException)
        {
            ioException.printStackTrace();
        }
    }
}

Server

import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;

public class Server
{
    private ServerSocket server;
    private Socket connection;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    private DatagramPacket sendPacket, recievePacket;
    private DatagramSocket socket;
    private byte[] iBytes;

    public static void main(String args[])
    {
        new Server();
    }

    public Server()
    {
        try
        {
            // Step 1: Create a ServerSocket.
            server = new ServerSocket(500, 1);
            //socket = new DatagramSocket(550);
            System.out.println("SERVER: Server started " + InetAddress.getLocalHost().getHostAddress());

            while (true)
            {
                // Step 2: Wait for a connection.
                connection = server.accept();
                System.out.println("SERVER: Connection received from: " + connection.getInetAddress().getHostName());

                // Step 3: Get input and output streams.
                input = new ObjectInputStream(connection.getInputStream());
                output = new ObjectOutputStream(connection.getOutputStream());
                System.out.println("SERVER: Got I/O streams");

                // Step 4: Process connection.
                //CREATE 10,000 ARRAYS
                System.out.print("SERVER: Creating 10,000 arrays... ");
                ArrayList<int[]> iArrays = new ArrayList<>();
                int[] iArrayCur;

                for (int i = 0; i < 10000; i++)
                {
                    iArrayCur = new int[1000];
                    for (int j = 0; j < 1000; j++)
                    {
                        iArrayCur[j] = (int) (Math.random () * 100);
                    }
                    iArrays.add(iArrayCur);
                }
                //ALL 10,000 ARRAYS CREATED
                System.out.println("10,000 arrays created successfully.");

                Histogram iHistCur;

                //SEND ARRAY
                System.out.println("SERVER: Sending array " + 1 + " for processing...");
                iArrayCur = iArrays.get(0);

                output.writeObject(iArrayCur);
                System.out.println("SERVER: Waiting for array...");
                iHistCur = (Histogram) input.readObject();

                iHistCur.display();
                //ByteBuffer byteBuffer = ByteBuffer.allocate(iArrayCur.length * 4);
                //IntBuffer intBuffer = byteBuffer.asIntBuffer();
                //intBuffer.put(iArrayCur);

                //iBytes = byteBuffer.array();
                //sendPacket = new DatagramPacket(iBytes, iBytes.length, InetAddress.getLocalHost(), 550);

                //socket.send(sendPacket);

                //WaitForPackets();

                //System.out.println("SERVER: Sending message \"Connection successful\"");
                //output.writeUTF("Connection successful");
                //System.out.println("SERVER: Client message: " + input.readUTF());

                // Step 5: Close connection.
                System.out.println("SERVER: Transmission complete. " + "Closing socket.");
                connection.close();
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }

    public void WaitForPackets()
    {
        try
        {
            while (true)
            {
                iBytes = new byte[1000];
                recievePacket = new DatagramPacket(iBytes, iBytes.length);

                socket.receive(recievePacket);
            }
        }
        catch (IOException ioException)
        {
            ioException.printStackTrace();
        }
    }
}
```

**Histogram**

```
import java.io.Serializable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Histogram implements Serializable
{
    private long[] iBins;
    private double iNumBins;
    private double iMin;
    private double iMax;
    private Lock iLock;

    public Histogram(int iMin, int iMax, int iNumBins)
    {
        this.iNumBins = iNumBins;
        this.iMin = iMin;
        this.iMax = iMax;
        iBins = new long[iNumBins];
        for (long iValue : iBins)
        {
            iValue = 0;
        }
        this.iLock = new ReentrantLock();
    }

    public void addDataPoint(long iVal)
    {
        iLock.lock();
        double iRange = (iMax - iMin + 1) / iNumBins; // = (100 - 1) / 5 = 100 / 5 = 20
        double iPos1 = iVal / iRange;
        int iPos = (int) iPos1;
        iBins[iPos]++;
        iLock.unlock();
    }

    public void display()
    {
        System.out.print("Frequencies = (");
        for (int i = 0; i < iNumBins; i++)
        {
            if (i == iNumBins - 1)
            {
                System.out.println(iBins[i] + ")");
            }
            else
            {
                System.out.print(iBins[i] + ", ");
            }
        }
    }

    public long[] getArray()
    {
        return iBins;
    }
}

Custom Adapter List View

Step 1: Create Custom Data Class

public class Person {
	public String firstName;
	public String surname;

	public Person(String firstName, String surname) {
		this.firstName = firstName;
		this.surname = surname;
	}

	@Override
	public String toString() {
		return surname + ", " + firstName;
	}
}

Step 2: Create View to Display

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >


    <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/imageView"
            android:background="@drawable/ic_launcher"
            />

    <LinearLayout
            android:orientation="vertical"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">

        <TextView
            android:id="@+id/txtSurname"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Medium Text"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <TextView
            android:id="@+id/txtFirstname"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView" />
    </LinearLayout>

</LinearLayout>

Step 3: Create Custom Adapter Class

public class PersonAdapter extends ArrayAdapter<Person> {
	public PersonAdapter(Context context, List<Person> people) {
		super(context, R.layout.person_layout, people);
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// get the inflater that will convert the person_layout.xml file into an
		// actual object (i.e. inflate it)
		LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		
		// create a view to display the person's info - NOTE different than when
        // inflating an Activity's view
		View personView = inflater.inflate(R.layout.person_layout, parent, false);
		
		// keep track of person this view is working with
		personView.setTag(getItem(position));
		
		// get text views that will hold strings
		TextView txtSurname = (TextView) personView.findViewById(R.id.txtSurname);
		TextView txtFirstname = (TextView) personView.findViewById(R.id.txtFirstname);
		
		// set text fields
		txtSurname.setText(getItem(position).surname);
		txtFirstname.setText(getItem(position).firstName);
		
		// return view to ListView to display
		return personView;
	}
}

Step 4: Link to List View

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // get views
        Button btnAdd = (Button) findViewById(R.id.btnAdd);
        ListView lstInfo = (ListView) findViewById(R.id.lstInfo);

        // create data (model)
        final List<Person> items = new ArrayList<Person>();
        items.add(new Person("John", "Doe"));
        items.add(new Person("Jane", "Soap"));
        items.add(new Person("Solly", "Someone"));

        // create adapter to transform string items
        final PersonAdapter adapter = new PersonAdapter(this, items);

        // attach adapter to list view
        lstInfo.setAdapter(adapter);

        // add more items when clicked
        btnAdd.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                adapter.add(new Person("New", "Person"));
            }
        });

        lstInfo.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                Toast.makeText(Example07.this,
                        "Clicked item " + position, Toast.LENGTH_LONG).show();
            }
        });
    }

GitHub – LadySith

Yaa

Lusaka, Zambia

Computer Science student and a bunch of other things.