Algorithms

An algorithm is a well-defined, complete, step-by-step description that performs a process in a finite amount of time and space.

In [93]:
void setup() {
    int[] heights = new int[100];

    for (int i = 0; i < heights.length; i++) {
        heights[i] = int(random(500));
    }

    int b = biggest(heights);
    int s = smallest(heights);
    
    printArray(heights);

    println("Biggest: " + b + " Smallest: " + s);
}

int biggest(int[] arr) {
    // what goes here?
    int max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        } 
    }
    return max;
}

int smallest(int[] arr) {
    int min = arr[0];
    for (int i=1; i < arr.length; i++) {
        if (arr[i] < min) {
            min = arr[i];
        }
    }
    return min;
}

void printArray(int[] myarray) {
    print("[");
    for (int i = 0; i < myarray.length; i++) {
        print(myarray[i]);
        if (i != myarray.length - 1) {
            print(", ");
        }
    }
    println("]");
}
Sketch #69:

Sketch #69 state: Loading...
[167, 100, 12, 178, 282, 278, 236, 421, 395, 458, 446, 299, 11, 237, 460, 4, 467, 163, 303, 349, 111, 368, 320, 159, 56, 32, 384, 20, 176, 204, 25, 133, 322, 423, 4, 337, 212, 420, 471, 261, 139, 414, 311, 345, 320, 87, 137, 46, 415, 70, 67, 302, 419, 469, 209, 386, 90, 422, 249, 328, 288, 462, 92, 115, 354, 446, 312, 71, 381, 75, 21, 497, 52, 252, 190, 4, 404, 74, 177, 31, 180, 466, 270, 1, 144, 155, 183, 305, 227, 283, 365, 349, 205, 423, 320, 392, 140, 13, 216, 108]
Biggest: 497 Smallest: 1
[38, 378, 490, 364, 65, 247, 296, 474, 339, 124, 473, 159, 233, 111, 314, 0, 49, 495, 51, 318, 42, 29, 210, 427, 140, 241, 11, 138, 381, 122, 389, 345, 75, 381, 328, 398, 231, 360, 316, 455, 235, 217, 171, 200, 57, 129, 268, 36, 227, 485, 180, 342, 50, 62, 366, 101, 408, 399, 420, 423, 154, 200, 461, 415, 439, 417, 200, 380, 251, 420, 268, 329, 47, 169, 211, 211, 387, 252, 184, 172, 57, 374, 249, 236, 133, 13, 212, 477, 454, 413, 314, 334, 126, 425, 379, 250, 196, 178, 366, 109]
Biggest: 495 Smallest: 0
[420, 125, 499, 333, 234, 53, 89, 13, 208, 276, 108, 395, 73, 389, 422, 109, 61, 312, 35, 473, 169, 274, 68, 405, 336, 53, 121, 289, 465, 50, 498, 406, 160, 280, 202, 459, 73, 208, 281, 240, 388, 403, 110, 68, 173, 390, 89, 351, 42, 242, 165, 401, 121, 305, 476, 54, 120, 333, 417, 215, 476, 441, 152, 126, 313, 12, 447, 257, 288, 176, 4, 4, 91, 291, 50, 304, 141, 220, 145, 85, 187, 96, 222, 484, 216, 60, 190, 237, 348, 322, 99, 365, 337, 47, 409, 380, 485, 404, 27, 357]
Biggest: 499 Smallest: 4

Sorting

Double Trouble

Let's design a very bad (slow) algorithm for sorting numbers.

The Double Trouble sort algorithm, stated very abstractly:

Compare all combinations of values at positions i and j:
    Swap where item at i is greater than the item at j

The Squared sort algorithm, stated with more details about an implementation:

Starting at the first element and going to second-to-last item, call this i:
   Starting at i + 1, and going to last item, call this j:
       if the item at location i is greater than the item at location j:
           Swap the items at i and j
       end if
   end j loop
end i loop

An algorithm is not so specific that it requires that it be written in a computer language. However, it is specific enough that it can be written in a programming language.

Sidebar: swapping

The problem with swapping: You can't do this to swap the values of x and y:

x = y;
y = x;

Why not?

Solution:

temp = x;
x = y;
y = temp;
In [95]:
int[] heights = new int[100];

void setup() {
    for (int i = 0; i < 100; i++) {
        heights[i] = int(random(50));
    }
    printArray(heights);
    double_trouble_sort(heights);
    printArray(heights);
}

void double_trouble_sort(int[] myarray) {
    for (int i = 0; i < myarray.length - 1; i++) {
        for (int j = i + 1; j < myarray.length; j++) {
            if (myarray[i] > myarray[j]) {
                // swap
                int temp = myarray[i];
                myarray[i] = myarray[j];
                myarray[j] = temp;
            }
        }
    }
}

void printArray(int[] myarray) {
    print("[");
    for (int i = 0; i < myarray.length; i++) {
        print(myarray[i]);
        if (i != myarray.length - 1) {
            print(", ");
        }
    }
    println("]");
}
Sketch #71:

Sketch #71 state: Loading...
[33, 19, 24, 45, 11, 16, 4, 15, 33, 39, 7, 41, 25, 10, 15, 26, 42, 29, 35, 36, 17, 28, 13, 13, 2, 8, 38, 36, 19, 27, 10, 33, 12, 43, 47, 2, 5, 24, 35, 32, 42, 42, 3, 32, 29, 9, 23, 20, 44, 37, 8, 2, 44, 40, 37, 47, 9, 10, 24, 29, 45, 33, 34, 1, 17, 23, 46, 24, 40, 49, 22, 47, 22, 12, 36, 8, 39, 29, 19, 2, 28, 3, 16, 43, 26, 42, 30, 6, 48, 32, 19, 9, 47, 33, 19, 33, 28, 21, 33, 47]
[1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 12, 12, 13, 13, 15, 15, 16, 16, 17, 17, 19, 19, 19, 19, 19, 20, 21, 22, 22, 23, 23, 24, 24, 24, 24, 25, 26, 26, 27, 28, 28, 28, 29, 29, 29, 29, 30, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 34, 35, 35, 36, 36, 36, 37, 37, 38, 39, 39, 40, 40, 41, 42, 42, 42, 42, 43, 43, 44, 44, 45, 45, 46, 47, 47, 47, 47, 47, 48, 49]
[26, 38, 28, 28, 10, 49, 27, 12, 14, 17, 29, 45, 19, 22, 2, 11, 45, 16, 1, 26, 48, 44, 42, 18, 22, 5, 11, 38, 27, 37, 20, 36, 31, 45, 13, 26, 43, 38, 49, 46, 14, 14, 16, 36, 14, 13, 42, 26, 8, 6, 17, 43, 0, 12, 40, 39, 45, 45, 24, 0, 15, 31, 8, 39, 30, 15, 6, 48, 1, 45, 28, 4, 21, 22, 37, 14, 23, 8, 7, 48, 29, 35, 48, 20, 29, 37, 33, 25, 23, 4, 0, 43, 5, 37, 2, 22, 35, 43, 47, 20]
[0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 10, 11, 11, 12, 12, 13, 13, 14, 14, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19, 20, 20, 20, 21, 22, 22, 22, 22, 23, 23, 24, 25, 26, 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, 29, 30, 31, 31, 33, 35, 35, 36, 36, 37, 37, 37, 37, 38, 38, 38, 39, 39, 40, 42, 42, 43, 43, 43, 43, 44, 45, 45, 45, 45, 45, 45, 46, 47, 48, 48, 48, 48, 49, 49]
[30, 23, 39, 47, 20, 43, 9, 7, 2, 45, 16, 9, 9, 33, 46, 7, 0, 16, 29, 42, 22, 5, 9, 8, 30, 38, 6, 48, 14, 31, 17, 8, 47, 39, 27, 7, 37, 34, 36, 10, 30, 18, 23, 35, 28, 44, 39, 14, 19, 13, 11, 25, 32, 34, 28, 33, 6, 0, 21, 34, 23, 9, 47, 3, 15, 45, 22, 33, 34, 48, 27, 4, 11, 38, 6, 6, 9, 49, 17, 4, 43, 48, 4, 20, 30, 32, 7, 17, 37, 47, 9, 8, 0, 25, 11, 15, 3, 30, 18, 34]
[0, 0, 0, 2, 3, 3, 4, 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 11, 11, 11, 13, 14, 14, 15, 15, 16, 16, 17, 17, 17, 18, 18, 19, 20, 20, 21, 22, 22, 23, 23, 23, 25, 25, 27, 27, 28, 28, 29, 30, 30, 30, 30, 30, 31, 32, 32, 33, 33, 33, 34, 34, 34, 34, 34, 35, 36, 37, 37, 38, 38, 39, 39, 39, 42, 43, 43, 44, 45, 45, 46, 47, 47, 47, 47, 48, 48, 48, 49]

Using Double Trouble to Sort Colors

In [96]:
PImage pic;
int p;
PImage big;

void setup() {
    size(500, 500);
    colorMode(HSB, 255);
    pic = createImage(25, 25, RGB); 
    pic.loadPixels();
    for (int i=0; i < pic.pixels.length; i++) {
        pic.pixels[i] = color(random(255), 255, 255);
    }
    pic.updatePixels();
    p = 0;
    big = createImage(width, height, RGB);
}

void double_trouble_sort(PImage pic) {
    // outer loop removed, so we can see the pixels sort!
    pic.loadPixels();
    for (int j=p + 1; j < pic.pixels.length; j++) {
        if (hue(pic.pixels[p]) > hue(pic.pixels[j])) {
            color temp = pic.pixels[p];
            pic.pixels[p] = pic.pixels[j];
            pic.pixels[j] = temp;
        }
    }
    pic.updatePixels();
}

void draw() {
    background(0);
    double_trouble_sort(pic);
    big.copy(pic,0,0,pic.width,pic.height,0,0,width,height);
    image(big, 0, 0);
    p++;
    if (p >= pic.pixels.length - 2) {
        noLoop();
        println("Done!");
    }
}
Sketch #72:

Sketch #72 state: Loading...
Done!
Done!
Done!

Bubble Sort

Bubble sort is the name given to a simple, and somewhat interesting, sorting algorithm.

The Bubblesort algorithm in abstract terms:

While not done:
    Run through all items in a set, i:
        if item i is greater than item i + 1:
            Swap items i and i + 1
    If no swaps were made on last sweep, you are done

The Bubblesort algorithm, with more implementation details:

Let stop be the length of the array
While stop is not at the beginning:
    Starting at the first element and going to stop - 1, call this i:
       Let new_stop be the beginning position
       if the item at location i is greater than the item at location i + 1:
           swap the items at i and i + 1
           Save i as new_stop
       end if
    Let stop be new_stop
end while

And written in Java:

void bubble_sort(int[] array) {
    int stop = array.length;
    int last_swap;
    while (stop != 0) {
        last_swap = 0;
        for (int i = 0; i < stop - 1; i++) {
            if (array[i] > array[i + 1]) {
                color temp = array[i];
                array[i] = array[i + 1];
                array[i + 1] = temp;
                last_swap = i + 1;
            }
        }
        stop = last_swap;
    }
}

Buuble Sort on Colors

In [97]:
PImage pic;
PImage big;
int stop;

void setup() {
    size(500, 500);
    colorMode(HSB, 255);
    pic = createImage(25, 25, RGB); 
    pic.loadPixels();
    for (int i=0; i < pic.pixels.length; i++) {
        pic.pixels[i] = color(random(255), 255, 255);
    }
    pic.updatePixels();
    big = createImage(width, height, RGB);
    stop = pic.pixels.length;
}

void bubble_sort(PImage pic) {
    pic.loadPixels();
    //int stop = pic.pixels.length;
    int last_swap;
    if (stop != 0) {
        last_swap = 0;
        for (int i = 0; i < stop - 1; i++) {
            if (hue(pic.pixels[i]) > hue(pic.pixels[i + 1])) {
                color temp = pic.pixels[i];
                pic.pixels[i] = pic.pixels[i + 1];
                pic.pixels[i + 1] = temp;
                last_swap = i + 1;
            }
        }
        stop = last_swap;
    } else {
        noLoop();
        println("Done!");
    }
    pic.updatePixels();
}

void draw() {
    background(0);
    bubble_sort(pic);
    big.copy(pic,0,0,pic.width,pic.height,0,0,width,height);
    image(big, 0, 0);
}
Sketch #73:

Sketch #73 state: Loading...
Done!
Done!
Done!
Done!

Quick Sort

The final algorithm that we will look at today is Quicksort. Quicksort represents a class of algorithms in computer science that capture the motto "divide and conquer".

The Quicksort algorithm, at 30,000 feet (abstract view):

Pick a pivot value
Break set of items into two parts:
    first part is all less than the pivot value
    second part is all greater than the pivot value
Sort the first part
Sort the second part

The Quicksort algorithm, with more implementation details:

Quicksort on start and end:
    if start less than end:
        Partition from start to end around p:
        Quicksort on start and p - 1
        Quicksort on p and end

The partition picks a point,

Partition from start to end:
   Pick a pivot position, p, and pivot value
   Partition array into:
       those less than pivot value
       pivot value
       those less than pivot value
   return partition

In Java, the main quicksort function looks like:

void quicksort(int lo, int hi) {
    if (lo < hi) {
        int p = partition(lo, hi);
        quicksort(lo, p - 1);
        quicksort(p + 1, hi);
    }
}

Here is the whole algorithm in code:

In [99]:
int [] array;

void quicksort(int lo, int hi) {
    if (lo < hi) {
        int p = partition(lo, hi);
        quicksort(lo, p - 1);
        quicksort(p + 1, hi);
    }
}

int partition(int lo, int hi) {
    int pivotIndex = choosePivot(lo, hi);
    int pivotValue = array[pivotIndex];
    // put the chosen pivot at array[hi]
    int tmp = array[pivotIndex];
    array[pivotIndex] = array[hi];
    array[hi] = tmp;

    int storeIndex = lo;
    // Compare remaining array elements against pivotValue = array[hi]
    for (int i = lo; i <= hi - 1; i++)  {
        counter++;
        if (array[i] < pivotValue) {
            swap++;
            tmp = array[i];
            array[i] = array[storeIndex];
            array[storeIndex] = tmp;
            storeIndex = storeIndex + 1;
        }
    }
    tmp = array[hi];
    array[hi] = array[storeIndex];
    array[storeIndex] = tmp;
    return storeIndex;
}

int choosePivot(int lo, int hi) {
    return ceil((hi + lo) / 2);
}

void print_array() {
    for (int i = 0; i < array.length; i++) {
        print("" + array[i] + ", ");
    }
    println("");
}

void setup() {
    println("-----------------------------------------------------------------");

    array = new int [1000];
    for (int i = 0; i < array.length; i++) {
        array[i] = int(random(array.length));
    }

    println("Before sorting:");
    if (array.length < 100)
        print_array();

    int start = millis();
    quicksort(0, array.length - 1);
    int stop = millis();
    println("Quicksort took: " + (stop - start) + " ms");
    if (array.length < 100)
        print_array();
}
Sketch #75:

Sketch #75 state: Loading...
-----------------------------------------------------------------
Before sorting:
Quicksort took: 1 ms
-----------------------------------------------------------------
Before sorting:
Quicksort took: 1 ms
-----------------------------------------------------------------
Before sorting:
Quicksort took: 2 ms

Quick Sort applied to Colors

In [100]:
PImage pic;
PImage big;

void quicksort(int lo, int hi) {
    if (lo < hi) {
        int p = partition(lo, hi);
        quicksort(lo, p - 1);
        quicksort(p + 1, hi);
    }
}

int partition(int lo, int hi) {
    int pivotIndex = choosePivot(lo, hi);
    int pivotValue = pic.pixels[pivotIndex];
    // put the chosen pivot at pic.pixels[hi]
    color tmp = pic.pixels[pivotIndex];
    pic.pixels[pivotIndex] = pic.pixels[hi];
    pic.pixels[hi] = tmp;

    int storeIndex = lo;
    // Compare remaining array elements against pivotValue = pic.pixels[hi]
    for (int i = lo; i <= hi - 1; i++)  {
        if (hue(pic.pixels[i]) < hue(pivotValue)) {
            tmp = pic.pixels[i];
            pic.pixels[i] = pic.pixels[storeIndex];
            pic.pixels[storeIndex] = tmp;
            storeIndex = storeIndex + 1;
        }
    }
    tmp = pic.pixels[hi];
    pic.pixels[hi] = pic.pixels[storeIndex];
    pic.pixels[storeIndex] = tmp;
    return storeIndex;
}

int choosePivot(int lo, int hi) {
    return ceil((hi + lo) / 2);
}

void print_array() {
    for (int i = 0; i < pic.pixels.length; i++) {
        print("" + pic.pixels[i] + ", ");
    }
    println("");
}

void draw() {
    background(0);
    quicksort(0,  pic.pixels.length - 1);
    big.copy(pic,0,0,pic.width,pic.height,0,0,width,height);
    image(big, 0, 0);
}
void setup() {
    size(500, 500);
    colorMode(HSB, 255);
    pic = createImage(25, 25, RGB); 
    pic.loadPixels();
    for (int i=0; i < pic.pixels.length; i++) {
        pic.pixels[i] = color(random(255), 255, 255);
    }
    pic.updatePixels();
    big = createImage(width, height, RGB);
}
Sketch #76:

Sketch #76 state: Loading...
Done!
Done!
Done!
Done!