September 30, 2008
Chapter: Generics
Create and test a SixTuple generic.
In Java:
package chapter.generics;
class SixTuple<A, B, C, D, E, F> {
public final A a;
public final B b;
public final C c;
public final D d;
public final E e;
public final F f;
public SixTuple(A a, B b, C c, D d, E e, F f) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
}
}
public class Exercise3 {
static SixTuple<Integer, String, Double, Boolean, String, Integer> foo() {
return new SixTuple<Integer, String, Double, Boolean, String, Integer>(
5, "hi", 33.3, true, "bye", 100);
}
public static void main(String[] args) {
SixTuple<Integer, String, Double, Boolean, String, Integer> x = foo();
System.out.println(x.b);
System.out.println(x.a);
System.out.println(x.e);
}
}
Lisp can return values in many natural and easy ways, including lists and the values function. Since a lisp programmer would probably avoid creating a special tuple class just to return multiple values, here is an alternative and simple way to accomplish the feat:
(defun foo ()
(values 5 "hi" 33.3 t "bye" 100))
(multiple-value-bind (a b c d e f) (foo)
(print b)
(print a)
(print e))
August 9, 2008
Chapter: Holding Your Objects
Create and populate a List. Create a second List of the same size as the first, and use ListIterators to read elements from the first List and insert them into the second in reverse order.
In Java:
package chapter.holdingYourObjects;
import java.util.*;
public class Exercise12 {
public static void main(String[] args) {
List<Integer> x = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
List<Integer> y = new ArrayList<Integer>(x);
ListIterator<Integer> it = x.listIterator();
while(it.hasNext()) {
y.set(x.size() - it.nextIndex() - 1, it.next());
}
System.out.println("x = " + x);
System.out.println("y = " + y);
}
}
/* Output:
* x = [1, 2, 3, 4, 5]
* y = [5, 4, 3, 2, 1]
*/
In Python:
x = [1, 2, 3, 4, 5]
y = x[:]
y.reverse()
print "x = " + str(x)
print "y = " + str(y)
In Lisp:
(defparameter *x* '(1 2 3 4 5))
(defparameter *y* (reverse *x*))
(format t "x = ~s~%" *x*)
(format t "y = ~s" *y*)
Chapter: Holding Your Objects
Create a class, then make an initialized array of objects of your class. Fill a List from your array. Create a subset of you List by using subList(), then remove this subset from your list.
In Java:
package chapter.holdingYourObjects;
import java.util.*;
class MyClass {}
public class Exercise7 {
public static void main(String[] args) {
MyClass[] myClassArray = {new MyClass(), new MyClass(), new MyClass()};
List<MyClass> myClassList = new ArrayList<MyClass>(Arrays.asList(myClassArray));
// Can't use sublist because removeall won't work
List<MyClass> sublist = Arrays.asList(myClassList.get(0), myClassList.get(1));
System.out.println("myClassList = " + myClassList);
System.out.println("sublist = " + sublist);
myClassList.removeAll(sublist);
System.out.println("myClassList = " + myClassList);
}
}
/* Output:
myClassList = [chapter.holdingYourObjects.MyClass@3e25a5, chapter.holdingYourObjects.MyClass@19821f, chapter.holdingYourObjects.MyClass@addbf1]
sublist = [chapter.holdingYourObjects.MyClass@3e25a5, chapter.holdingYourObjects.MyClass@19821f]
myClassList = [chapter.holdingYourObjects.MyClass@addbf1]
*/
In Python:
class MyClass():
pass
myClassArray = [MyClass(), MyClass(), MyClass()]
sublist = myClassArray[0:2]
print "myClassArray = " + str(myClassArray)
print "sublist = " + str(sublist)
for item in sublist:
myClassArray.remove(item)
print "myClassArray = " + str(myClassArray)
#>>> ## working on region in file /tmp/python-7533hFb...
#myClassArray = [<__main__.MyClass instance at 0xb7d9ee8c>, <__main__.MyClass instance at 0xb7d9ef0c>, <__main__.MyClass instance at 0xb775830c>]
#sublist = [<__main__.MyClass instance at 0xb7d9ee8c>, <__main__.MyClass instance at 0xb7d9ef0c>]
#myClassArray = [<__main__.MyClass instance at 0xb775830c>]
In Lisp:
(defclass MyClass () ())
(defparameter *MyClass-array* (list (make-instance 'MyClass)
(make-instance 'MyClass)
(make-instance 'MyClass)))
(defparameter *sublist* (butlast *MyClass-array* 1))
(format t "MyClass = ~s~%" *MyClass-array*)
(format t "sublist = ~s~%" *sublist*)
(loop for item in *sublist* do
(setf *MyClass-array* (remove item *MyClass-array*)))
(format t "MyClass = ~s~%" *MyClass-array*)
;;;Output:
;MyClass = (#<MYCLASS #x20513866> #<MYCLASS #x20513876> #<MYCLASS #x20513886>)
;sublist = (#<MYCLASS #x20513866> #<MYCLASS #x20513876>)
;MyClass = (#<MYCLASS #x20513886>)
July 28, 2008
Chapter: Holding Your Objects
Create a new class called Gerbil with an int gerbilNumber that's initialized in the constructor. Give it a method called hop() that displays which gerbil number this is, and that it's hopping. Create an ArrayList and add Gerbil objects to the List. Now use the get() method to move through the List and call hop() for each Gerbil.
As we proceed deeper into the book, completing the exercises using multiple languages exposes the differences more clearly. In my opinion Lisp and Java are completely different beasts, with Python combining Lisp's ease of programming with Java-like syntax.
In Java:
package chapter.holdingYourObjects;
import java.util.*;
class Gerbil {
private int gerbilNumber;
Gerbil(int gerbilNumber) {
this.gerbilNumber = gerbilNumber;
}
public void hop() {
System.out.println("Gerbil " + gerbilNumber + " is hopping");
}
}
public class Exercise1 {
public static void main(String[] args) {
ArrayList<Gerbil> gerbils = new ArrayList<Gerbil>();
for(int i = 0; i < 10; i++)
gerbils.add(new Gerbil(i));
for(int i = 0; i < gerbils.size(); i++)
gerbils.get(i).hop();
}
}
In Python:
class Gerbil:
def __init__(self, gerbilNumber):
self.gerbilNumber = gerbilNumber
def hop(self):
print "Gerbil " + str(self.gerbilNumber) + " is hopping"
gerbils = []
for i in range(10):
gerbils.append(Gerbil(i))
for i in range(len(gerbils)):
gerbils[i].hop()
In Lisp:
(defclass Gerbil ()
((gerbil-number :accessor gerbil-number
:initarg :num)))
(defmethod hop ((g Gerbil))
(format t "Gerbil ~d is hopping~%" (gerbil-number g)))
(defparameter *gerbil-list*
(loop for i from 0 to 9 append
(list (make-instance 'Gerbil :num i))))
(loop for a-gerbil in *gerbil-list* do (hop a-gerbil))
July 10, 2008
Chapter: Inner Classes
Create an interface U with three methods. Create a class A with a method that produces a reference to a U by building an anonymous inner class. Create a second class B that contains an array of U. B should have one method that accepts and stores a reference to a U in the array, a second method that sets a reference in the array (specified by the method argument) to null, and a third method that moves through the array and calls the methods in U. In main(), create a group of A objects and a single B. Fill the B with U references produced by the A objects. Use the B to call back into all the A objects. Remove some of the U references from the B.
I also added a couple lines of code to show that A's inner class has access to it's private methods.
package chapter.innerClasses;
interface U {
void one();
void two();
void three();
}
class A {
U getU() {
return new U() {
public void one() {System.out.println("one");}
public void two() {System.out.println("two");}
public void three() {System.out.println("three"); printSomething();}
};
}
private void printSomething() {System.out.println("Something");}
}
class B {
private U[] arrayOfU = new U[10];
private int position = 0;
public void storeU(U U_Reference) {
if (position < 10 && position >= 0)
arrayOfU[position++] = U_Reference;
}
public void setNull(int index) {
if (index < 10 && index >= 0)
arrayOfU[index] = null;
}
public void callU() {
for (U myU : arrayOfU) {
if (myU != null) {
myU.one();
myU.two();
myU.three();
}
}
}
}
public class Excercise23 {
public static void main(String[] args) {
A firstA = new A(), secondA = new A();
B theB = new B();
theB.storeU(firstA.getU());
theB.storeU(secondA.getU());
theB.storeU(secondA.getU());
theB.callU();
theB.setNull(1);
theB.callU();
}
}
July 7, 2008
Chapter: Interfaces
Create a framework using Factory Methods that performs both coin tossing and dice tossing.
In Java:
package chapter.interfaces;
import java.util.*;
interface Game {
int toss();
}
interface GameFactory {
Game getGame();
}
class Dice implements Game {
public int toss() {
Random rand = new Random(55);
return rand.nextInt(7);
}
}
class DiceFactory implements GameFactory {
public Game getGame() {
return new Dice();
}
}
class Coins implements Game {
public int toss() {
Random rand = new Random(55);
return rand.nextInt(3);
}
}
class CoinsFactory implements GameFactory {
public Game getGame() {
return new Coins();
}
}
public class Exercise19 {
public static void playGame(GameFactory factory) {
Game game = factory.getGame();
for (int i = 0; i < 8; i++)
System.out.println(game.toss());
}
public static void main(String[] args) {
playGame(new CoinsFactory());
playGame(new DiceFactory());
}
}
Chapter: Interfaces
Create three interfaces, each with two methods. Inherit a new interface that combines the three, adding a new method. Create a class by implementing the new interface and also inheriting from a concrete class. Now write four methods, each of which takes one of the four interfaces as an argument. In main(), create an object of your class and pass it to each of the methods.
In Java:
package chapter.interfaces;
interface A {
void a1();
void a2();
}
interface B {
void b1();
void b2();
}
interface C {
void c1();
void c2();
}
interface D extends A, B, C {
void d1();
}
class E {
public void e1() {System.out.println("e1");}
}
class F extends E implements A, B, C, D {
public void a1() {System.out.println("a1");}
public void a2() {System.out.println("a2");}
public void b1() {System.out.println("b1");}
public void b2() {System.out.println("b2");}
public void c1() {System.out.println("c1");}
public void c2() {System.out.println("c2");}
public void d1() {System.out.println("d1");}
}
public class Exercise14 {
public static void foo(A a) {
a.a1();
a.a2();
}
public static void bar(B b) {
b.b1();
b.b2();
}
public static void yen(C c) {
c.c1();
c.c2();
}
public static void zen(D d) {
d.a1();
d.a2();
d.b1();
d.b2();
d.c1();
d.c2();
d.d1();
}
public static void main(String[] args) {
F f = new F();
foo(f);
bar(f);
yen(f);
zen(f);
f.e1();
}
}
Chapter: Interfaces
Create an interface, and inherit two new interfaces from that interface. Multiply inherit a third interface from the second two.
In Java:
package chapter.interfaces;
interface AI {
void top();
}
interface BI extends AI {
void left();
}
interface CI extends AI {
void right();
}
interface DI extends CI, BI {
void bottom();
}
class EC implements DI {
public void top() {System.out.println("Top");}
public void left() {System.out.println("Left");}
public void right() {System.out.println("Right");}
public void bottom() {System.out.println("Bottom");}
}
public class Exercise13 {
public static void main(String[] args) {
EC e = new EC();
e.top();
e.left();
e.right();
e.bottom();
}
}
Chapter: Polymorphism
Create an inheritance hierarchy of Rodent: Mouse, Gerbil, and Hamster. In the base class, provide methods that are common to all Rodents, and override these in the derived classes to perform different behaviors depending on the specific type of Rodent. Create an array of Rodent, fill it with different types of Rodents, and call your base class methods to see what happens.
In Java:
package chapter.polymorphism;
class Rodent {
public void play() {
System.out.println("Rodent playing");
}
public void eat() {
System.out.println("Rodent eating");
}
}
class Mouse extends Rodent {
public void play() {
System.out.println("Mouse playing");
}
public void eat() {
System.out.println("Mouse eating");
}
}
class Gerbil extends Rodent {
public void play() {
System.out.println("Gerbil playing");
}
public void eat() {
System.out.println("Gerbil eating");
}
}
class Hamster extends Rodent {
public void play() {
System.out.println("Hamster playing");
}
public void eat() {
System.out.println("Hamster eating");
}
}
public class Exercise9 {
public static void main(String[] args) {
Rodent[] rodents = { new Rodent(), new Mouse(), new Gerbil(),
new Hamster() };
for (Rodent rodent : rodents) {
rodent.play();
rodent.eat();
}
}
}
In Python:
class Rodent:
def play(self): print 'Rodent playing'
def eat(self): print 'Rodent eating'
class Mouse(Rodent):
def play(self): print 'Mouse playing'
def eat(self): print 'Mouse eating'
class Gerbil(Rodent):
def play(self): print 'Gerbil playing'
def eat(self): print 'Gerbil eating'
class Hamster(Rodent):
def play(self): print 'Hamster playing'
def eat(self): print 'Hamster eating'
rodents = (Rodent(), Mouse(), Gerbil(), Hamster())
for rodent in rodents:
rodent.play()
rodent.eat()
Chapter: Reusing Classes
Create a class called Amphibian. From this, inherit a class called Frog. Put appropriate methods in the base class. In main(), create a Frog and upcast it to Amphibian and demonstrate that all the methods will work.
In Java:
package chapter.reusingClasses;
class Amphibian {
private void move() {
System.out.println("Moving");
}
private void swim() {
System.out.println("Swimming");
}
static void travel(Amphibian a) {
a.move();
a.swim();
}
}
class Frog extends Amphibian {
}
public class Exercise16 {
public static void main(String[] args) {
Frog kermit = new Frog();
Amphibian.travel(kermit);
}
}
In Python:
class Amphibian:
def move(self):
print "Moving"
def swim(self):
print "Swimming"
def travel(self):
self.move()
self.swim()
class Frog(Amphibian):
pass
frog = Frog()
frog.travel()
Chapter: Reusing Classes
Create two classes, A and B, with default constructors (empty argument lists) that announce themselves. Inherit a new class called C from A, and create a member of class B inside C. Do not create a constructor for C. Create an object of class C and observe the results.
Notice the different output in the two solutions.
In Java:
package chapter.reusingClasses;
class A {
A() {
System.out.println("A");
}
}
class B {
B() {
System.out.println("B");
}
}
class C extends A {
B b = new B();
}
public class Exercise5 {
public static void main(String[] args) {
C c = new C();
}
} /* Output:
A
B
*///
In Python:
class A:
def __init__(self):
print "A"
class B:
def __init__(self):
print "B"
class C(A):
b = B()
C()
# Output:
# B
# A
Chapter: Initialization and Cleanup
Create an array of String objects and assing a String to each element. Print the array by using a for loop
I also demonstrate an alternative way to print the array.
In Java:
package chapter.initialization;
import java.util.*;
public class Exercise16 {
public static void main(String[] args) {
String[] stringArray = new String[] { "aaa", "bbb", "ccc", "ddd" };
for (String x : stringArray)
System.out.println(x);
System.out.println(Arrays.toString(stringArray));
}
}
In Python:
stringArray = ("aaa", "bbb", "ccc", "ddd")
for x in stringArray:
print x
print stringArrayIn Lisp:
(setq string-array '("aaa" "bbb" "ccc" "ddd"))
(loop for x in string-array do (print x))
(print string-array)
June 21, 2008
Chapter: Controlling Execution
Exercise 10: (5) A vampire number has an even number of digits and is formed by multiplying a pair of numbers containing half the number of digits of the result. The digits are taken from the original number in any order. Pairs of trailing zeroes are not allowed. Examples include:
1260 = 21 * 60
1827 = 21 * 87
2187 = 27 * 81
Write a program that finds all the 4-digit vampire numbers.
The straight foward way to solve this problem is through brute force: check every four digit number and test if it qualifies as a vampire number. If we write out all the ways to multiple two 2-digit numbers we can see a pattern that fits nicely into loops. Let a, b, c and d be the digits of a four-digit number. The possible vampire factors (called "fangs") are:
ab * cd
ab * dc
ba * cd
ba * dc
ac * bd
...
ad * bc
...
and so forth, for a total of 12 combinations. The solutions below use multiple for-loops to test all the combinations by swapping the digits. The inner for-loop swaps the third and fourth digits, the middle for-loop swaps the first and second digits, and the outer for-loop swaps the second digit with either the third or fourth digit. This tests all the combinations in the same sequence as the pattern above. (Note, I have not verified the results. See the bottom of this post for the numbers I got).
In Java:
package chapter.controllingExecution;
public class Exercise10 {
public static void main(String[] args) {
for (int i = 1000; i < 10000; i++)
if (isVampire(i))
System.out.println(i);
}
static boolean isVampire(int num) {
int temp;
int a = Integer.parseInt((String.valueOf(num)).substring(0, 1));
int b = Integer.parseInt((String.valueOf(num)).substring(1, 2));
int c = Integer.parseInt((String.valueOf(num)).substring(2, 3));
int d = Integer.parseInt((String.valueOf(num)).substring(3));
for (int i = 3; i <= 5; i++) {
for (int y = 1; y <= 2; y++) {
for (int z = 1; z <= 2; z++) {
if (num == combineNumbers(a, b) * combineNumbers(c, d))
return true;
temp = c;
c = d;
d = temp;
}
temp = a;
a = b;
b = temp;
}
if (i == 3) {
temp = b;
b = c;
c = temp;
} else {
temp = b;
b = d;
d = temp;
}
}
return false;
}
static int combineNumbers(int x, int y) {
return Integer.parseInt(Integer.toString(x) + Integer.toString(y));
}
}
In Python:
for i in range(1000, 10000):
if isVampire(i):
print i
def combineNumbers(a, b):
return int(str(a) + str(b))
def isVampire(num):
a = str(num)[0]
b = str(num)[1]
c = str(num)[2]
d = str(num)[3]
for i in 3,4,5:
for y in 1,2:
for z in 1,2:
if num == combineNumbers(a,b) * combineNumbers(c,d):
return True
c, d = d, c
a, b = b, a
if i == 3:
b, c = c, b
else:
b, d = d, b
return False
In Lisp:
(loop for i from 1000 to 10000 do
(if (vampire? i)
(print i)))
(defun combine-numbers (a b)
(+ (* a 10) b))
(defun vampire? (number)
(let* ((num (write-to-string number))
(a (parse-integer (subseq num 0 1)))
(b (parse-integer (subseq num 1 2)))
(c (parse-integer (subseq num 2 3)))
(d (parse-integer (subseq num 3 4)))
(temp 0)
(result nil))
(loop for i in '(3 4 5) while (eq result nil) do
(progn (loop for y in '(1 2) while (eq result nil) do
(progn (loop for z in '(1 2) while (eq result nil) do
(if (eq number
(* (combine-numbers a b)
(combine-numbers c d)))
(setq result t)
(setq temp c
c d
d temp)))
(setq temp a
a b
b temp)))
(if (eq i 3)
(setq temp b
b c
c temp)
(setq temp b
b d
d temp))))
result))
The python solution is my favorite because of the simple swapping feature. My results:
1260
1395
1435
1530
1827
2187
6880
June 8, 2008
Chapter: Operators
Exercise 5: (2) Create a class called Dog containing two Strings: name and says. In main( ), create two dog objects with names “spot” (who says, “Ruff!”) and “scruffy” (who says, “Wurf!”). Then display their names and what they say.
In Java:
public class Dog {
String name, says;
public Dog(String name, String says) {
this.name = name;
this.says = says;
}
public static void main(String[] args) {
Dog spot = new Dog("spot", "Ruff!");
Dog scruffy = new Dog("scruffy", "Wurf!");
System.out.println(spot.name + ": " + spot.says);
System.out.println(scruffy.name + ": " + scruffy.says);
}
}In Python:
class Dog:
def __init__(self, name, says):
self.name = name
self.says = says
spot = Dog("spot", "Ruff!")
scruffy = Dog("scruffy", "Wurf!")
print(spot.name, spot.says)
print(scruffy.name, scruffy.says)
In Lisp:
(defclass Dog ()
((name :accessor name :initarg :name)
(says :accessor says :initarg :says)))
(setf spot (make-instance 'Dog :name "spot" :says "Ruff!"))
(setf scruffy (make-instance 'Dog :name "scruffy" :says "Wurf!"))
(print (list (name spot)
(says spot)
(name scruffy)
(says scruffy)))
May 30, 2008
Chapter: Everything is an Object
Exercise 4: (1) Turn the DataOnly code fragments into a program that compiles and runs.
Again, not completely sure what they're after, but here is one that works:
public class Excercise4 {
public static void main(String[] args) {
DataOnly data = new DataOnly();
data.i = 20;
data.d = 1.23;
data.b = false;
System.out.println(data.i);
System.out.println(data.d);
System.out.println(data.b);
}
}
class DataOnly {
int i;
double d;
boolean b;
}In Lisp:
(defclass data-only ()
((i :accessor the-int :initform 20)
(d :accessor the-double :initform 1.23)
(b :accessor the-bool :initform nil)))
(setf data (make-instance 'data-only))
(print (list (the-int data)
(the-double data)
(the-bool data)))
In Python:
class DataOnly:
i = 20
d = 1.23
b = False
data = DataOnly()
print data.i
print data.d
print data.b
Chapter: Everything is an Object
Exercise 3: (1) Find the code fragments involving ATypeName and turn them into a program that compiles and runs.
Not exactly sure what they're looking for here, but here's a simple program in Java:
public class Exercise3 {
public static void main(String[] args) {
ATypeName x = new ATypeName();
System.out.println(x.i);
}
}
class ATypeName {
int i = 5;
}
Chapter: Everything is an Object
Exercise 2: (1) Following the HelloDate.java example in this chapter, create a “hello, world” program that simply displays that statement. You need only a single method in your class (the “main” one that gets executed when the program starts). Remember to make it static and to include the argument list, even though you don’t use the argument list. Compile the program with javac and run it using java. If you are using a different development environment than the JDK, learn how to compile and run programs in that environment.
The classic Hello World program in Java:
public class Exercise2 {
public static void main(String[] args) {
System.out.println("Hello Blog Readers!");
}
}In Lisp:
(print "Hello Blog Readers!")
In Python:
print "Hello Blog Readers!"
May 29, 2008
Chapter: Everything is an Object
Exercise 1: (2) Create a class containing an int and a char that are not initialized, and print their values to verify that Java performs default initialization.
Java code:
public class Exercise1 {
static int i;
static char c;
public static void main(String[] args) {
System.out.println("Int: " + i);
System.out.println("Char:" + c);
}
}Result:
Int: 0
Char:
Ints default to 0 and chars default to null. Note that you will get a complier error if you declare the variables within a method and try to use them without initializing them.
Bruce Eckel's Thinking in Java is considered one of the best books for learning Java and Object Oriented programming. To help keep my Java skills sharp, I will try to work through many of the problems, and also compare the Java solutions to solutions written in my favorite languages, Lisp and Python, where applicable. I hope that keeping a blog of my progress will motivate me to finish.