public class SelectionSort {
public static void main(String[] args) {
// Utilities
SwissArmySorter<String> sorter = new SwissArmySorter<String>();
Copier<String> copier = new Copier<String>();
// Default Sequence (selected by Knuth on March 19, 1963)
String[] seq = (args.length > 0) ? args :
new String[] {
"503",
"087",
"512",
"061",
"908",
"170",
"897",
"275",
"653",
"426",
"154",
"509",
"612",
"677",
"765",
"703"
};
// Copies of the Sequence
String[] copy1 = copier.copy(seq, new String[seq.length]);
String[] copy2 = copier.copy(seq, new String[seq.length]);
// Swiss Army Arrays
SwissArmyArray<String> seq1 = new SwissArmyArray<String>(copy1);
SwissArmyArray<String> seq2 = new SwissArmyArray<String>(copy2);
// Sort First Swiss Army Array
sorter.simpleSelectionSort(seq1);
System.out.println(seq1.getMeter().getReading());
System.out.println(seq1.toString());
// Sort Second Swiss Army Array
sorter.pickySelectionSort(seq2);
System.out.println(seq2.getMeter().getReading());
System.out.println(seq2.toString());
}
}
class SwissArmySorter<T extends Comparable<T>> {
public SwissArmyArray<T> simpleSelectionSort(SwissArmyArray<T> seq) {
// Swaps indiscriminately.
SwissArmyIndex i = new SwissArmyIndex(seq);
SwissArmyIndex j = new SwissArmyIndex(seq);
for (i.set(0); !i.tooBig(); i.step()) {
for (j.set(i.plus(1)); !j.tooBig(); j.step()) {
if (seq.inDescendingOrder(i, j)) {
seq.swap(i, j);
}
}
}
return seq;
}
public SwissArmyArray<T> pickySelectionSort(SwissArmyArray<T> seq) {
// Swap selectively instead. (Modify the following code.)
SwissArmyIndex i = new SwissArmyIndex(seq);
SwissArmyIndex j = new SwissArmyIndex(seq);
for (i.set(0); !i.tooBig(); i.step()) {
for (j.set(i.plus(1)); !j.tooBig(); j.step()) {
if (seq.inDescendingOrder(i, j)) {
seq.swap(i, j);
}
}
}
return seq;
}
}
class Converter<T> {
public String toString(T[] seq) {
String s = "[";
for (int i = 0; i < seq.length; i++) {
if (i > 0) {
s += " ";
}
s += seq[i].toString();
}
s += "]";
return s;
}
}
class Copier<T> {
public T[] copy(T[] orig, T[] copy) {
int i;
if (orig != null && copy != null && orig.length == copy.length) {
i = orig.length;
while (--i >= 0) {
copy[i] = orig[i];
}
}
return copy;
}
}
class Meter {
private String reading = "";
public void tick(String s) {
reading += s;
}
public String getReading() {
return reading;
}
}
interface IMeteredWithMaxIndex {
Meter getMeter();
int getMaxIndex();
}
class SwissArmyArray<T extends Comparable<T>>
implements IMeteredWithMaxIndex {
private T[] seq;
private SwissArmyIndex indexReg;
private T valueReg;
private Converter<T> converter;
private Meter meter;
public SwissArmyArray(T[] array) {
seq = array;
converter = new Converter<T>();
meter = new Meter();
}
public Meter getMeter() {
return meter;
}
public void setStoredValue(T value) {
meter.tick("W");
valueReg = value;
}
public T getStoredValue() {
meter.tick("R");
return valueReg;
}
public void setStoredIndex(SwissArmyIndex i) {
meter.tick("W");
SwissArmyIndex copy = new SwissArmyIndex(i);
copy.set(i.get());
indexReg = copy; // Store copy of i, not i itself which may change.
}
public SwissArmyIndex getStoredIndex() {
meter.tick("R");
return indexReg;
}
public T get(int i) {
meter.tick("R");
return seq[i];
}
public void set(int i, T value) {
meter.tick("W");
seq[i] = value;
}
public int getMaxIndex() {
meter.tick("R");
return seq.length - 1;
}
public int compare(int i, int j) {
meter.tick("C");
return seq[i].compareTo(seq[j]);
}
public int compare(SwissArmyIndex i, SwissArmyIndex j) {
return compare(i.get(), j.get());
}
public void swap(int i, int j) {
System.out.print("(" + get(i) + "," + get(j) + ") -> ");
setStoredValue(get(i));
set(i, get(j));
set(j, getStoredValue());
System.out.println("(" + get(i) + "," + get(j) + ")");
}
public void swap(SwissArmyIndex i, SwissArmyIndex j) {
swap(i.get(), j.get());
}
public boolean inDescendingOrder(int i, int j) {
return compare(i, j) > 0;
}
public boolean inDescendingOrder(SwissArmyIndex i, SwissArmyIndex j) {
return compare(i, j) > 0;
}
public boolean inAscendingOrder(int i, int j) {
return compare(i, j) < 0;
}
public boolean inAscendingOrder(SwissArmyIndex i, SwissArmyIndex j) {
return compare(i, j) < 0;
}
public String toString() {
return converter.toString(seq);
}
}
class SwissArmyIndex
implements IMeteredWithMaxIndex {
int i;
int maxIndex;
Meter meter;
public SwissArmyIndex(IMeteredWithMaxIndex obj) {
meter = obj.getMeter();
setMaxIndex(obj.getMaxIndex());
}
public Meter getMeter() {
return meter;
}
public void setMaxIndex(int max) {
meter.tick("w");
maxIndex = max;
}
public int getMaxIndex() {
meter.tick("r");
return maxIndex;
}
public boolean tooBig() {
meter.tick("c");
return i > maxIndex;
}
public int get() {
meter.tick("r");
return i;
}
public void set(int value) {
meter.tick("w");
i = value;
}
public void step() {
meter.tick("w");
i = this.plus(1);
}
public int plus(int n) {
meter.tick("ra");
return i + n;
}
}