Skip to content

Instantly share code, notes, and snippets.

@xyos
Created June 28, 2013 18:19
Show Gist options
  • Save xyos/5886830 to your computer and use it in GitHub Desktop.
Save xyos/5886830 to your computer and use it in GitHub Desktop.
package pf;
import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Boat {
private static final PersonType Adult = PersonType.Adult;
private static final PersonType Child = PersonType.Child;
private static final Location Oahu = Location.Oahu;
private static final Location Molokai = Location.Molokai;
private static final ArrayList<Person> boat = new ArrayList<Person>();
private static BoatGrader grader;
private static Location boatLocation;
private static int adultsO;
private static int childrenO;
private static int adultsM;
private static int childrenM;
private static Lock boatLock;
private static Lock finishLock;
private static Condition isEmptyAndNoChildOnO;
private static Condition isEmptyAndOneChildOnO;
private static Condition hasPilot;
private static Condition isOnLand;
private static Condition isEmptyM;
private static Condition isFinished;
private static boolean debug;
private static boolean childOnO;
private static boolean finished;
public static void main(String[] args) throws InterruptedException {
System.out.println("\nprobando:\n2 niños oahu;\n2 adultos , 1 niño molokai\n\n ");
begin(100, 220, 20, 13, true);
/* System.out.println("\nprobando: 1 niño , 2 adultos oahu;\n1 adulto, 2 niños molokai n ");
begin(1, 2, 2, 1, false);
System.out.println("\nprobando: 5 niños , 3 adultos oahu;\n1 adulto, 2 niños molokai n ");
begin(5, 3, 1, 2, false);*/
System.out.println("\nTerminando");
System.out.println("Adultos, Niños Oahu:" + adultsO + "," + childrenO + " Molokai:" + adultsM + "," + childrenM);
System.exit(0);
}
private static void begin(int adults_o, int children_o, int adults_m, int children_m, boolean dbg) throws InterruptedException {
debug = dbg;
assert (adults_o >= 0 && children_o >= 2);
grader = new BoatGrader();
adultsO = childrenO = adultsM = childrenM = 0;
adultsM = adults_m;
childrenM = children_m;
if (debug) {
if (adultsM > 0) {
System.out.println("Creando Adultos en Molokai");
debug();
}
if (childrenM > 0) {
System.out.println("Creando niños en Molokai");
debug();
}
}
childOnO = finished = false;
boatLocation = Oahu;
boatLock = new ReentrantLock();
isEmptyAndNoChildOnO = boatLock.newCondition();
isEmptyAndOneChildOnO = boatLock.newCondition();
isEmptyM = boatLock.newCondition();
hasPilot = boatLock.newCondition();
isOnLand = boatLock.newCondition();
finishLock = new ReentrantLock();
isFinished = finishLock.newCondition();
finishLock.lock();
for (int i = 0; i < adults_o; i++) {
Thread adultThread = new Thread(new Person(Adult));
adultThread.setName("Adulto_" + i);
adultThread.start();
}
for (int i = 0; i < children_o; i++) {
Thread childThread = new Thread(new Person(Child));
childThread.setName("Niño_" + i);
childThread.start();
}
while (!finished) {
isFinished.await();
if (childrenM + adultsM == adults_o + children_o + adults_m + children_m)
finished = true;
else {
System.out.println("aun no hemos terminado");
isEmptyM.signal();
}
}
finishLock.unlock();
System.out.println("terminado");
}
private static void debug() {
if (debug) {
System.out.println("Adultos, Niños Oahu:" + adultsO + "," + childrenO + " Molokai:" + adultsM + "," + childrenM);
}
}
private static void AdultItinerary(Person adult) throws InterruptedException {
/*
* This is where you should put your solutions. Make calls to the
* BoatGrader to show that it is synchronized. For example:
* bg.AdultRowToMolokai(); indicates that an adult has rowed the boat
* across to Molokai
*/
assert (adult.location == Oahu);
adultsO++;
if (debug) {
System.out.print("creando " + Thread.currentThread().getName() + " en Oahu\n ");
debug();
}
loadAdult(adult);
grader.AdultRowToMolokai();
adultGoToM(adult);
}
private static void ChildItinerary(Person child) throws InterruptedException {
childrenO++; // could just do this in Person constructor but maybe cheating?
if (debug) {
System.out.print("creando " + Thread.currentThread().getName() + " en Oahu\n ");
debug();
}
while (!finished) {
if (child.location == Oahu) {
if (loadTwoChildren(child)) {
grader.ChildRowToMolokai();
childGoToM(child);
} else {
grader.ChildRideToMolokai();
ChildTravelToM(child);
}
} else if (child.peopleLastIsland != 0) { // go back to Oahu
loadChild(child);
grader.ChildRowToOahu();
childGoToO(child);
}
Thread.yield();
}
}
private static void loadAdult(Person adult) throws InterruptedException {
boatLock.lock();
while (childrenO != 1 || boatLocation != Oahu || !boat.isEmpty() || !childOnO) {
isEmptyAndOneChildOnO.await();
}
if (debug) {
System.out.println(Thread.currentThread() + " se subió al bote");
}
boat.add(adult);
boatLock.unlock();
}
private static void loadChild(Person child) throws InterruptedException {
boatLock.lock();
while (boatLocation != Molokai || !boat.isEmpty() || finished) {
isEmptyM.await();
}
System.out.println("el " + Thread.currentThread().getName() + " es piloto");
boat.add(child);
boatLock.unlock();
}
private static boolean loadTwoChildren(Person child) throws InterruptedException {
boatLock.lock();
if (!childOnO)
childOnO = true;
else
while (childrenO == 1 || boatLocation != Oahu || boat.size() >= 2) {
isEmptyAndNoChildOnO.await();
}
boat.add(child);
if (boat.size() == 2) {
if (debug) {
System.out.println("el " + Thread.currentThread().getName() + " es pasajero");
}
hasPilot.signal();
while (boat.size() == 2)
isOnLand.await();
boatLock.unlock();
return false;
} else { //child is rower
if (debug) {
System.out.println("el " + Thread.currentThread().getName() + " es piloto");
}
while (boat.size() != 2)
hasPilot.await();
boatLock.unlock();
return true;
}
}
private static void unload(Person person) {
boatLock.lock();
if (debug) {
System.out.println("el " + Thread.currentThread().getName() + " se bajo del bote");
debug();
}
boat.remove(person);
if (boat.isEmpty()) {
if (boatLocation == Molokai) {
if (person.peopleLastIsland == 0) {
finishLock.lock();
isFinished.signal();
finishLock.unlock();
} else
isEmptyM.signal();
} else if (childrenO == 1)
isEmptyAndOneChildOnO.signal();
else
isEmptyAndNoChildOnO.signal();
}
boatLock.unlock();
}
private static void adultGoToM(Person adult) {
adult.peopleLastIsland = childrenO + adultsO - 1;
adultsO--;
adultsM++;
boatLocation = Molokai;
unload(adult);
adult.location = Molokai;
}
private static void childGoToM(Person child) {
child.peopleLastIsland = childrenO + adultsO - 2;
childrenO--;
childrenM++;
boatLocation = Molokai;
unload(child);
child.location = Molokai;
boatLock.lock();
isOnLand.signal();
boatLock.unlock();
}
private static void ChildTravelToM(Person child) {
child.peopleLastIsland = childrenO + adultsO - 1;
childrenO--;
childrenM++;
boatLocation = Molokai;
unload(child);
child.location = Molokai;
}
private static void childGoToO(Person child) {
child.peopleLastIsland = childrenM + adultsM - 1;
childrenM--;
childrenO++;
boatLocation = Oahu;
unload(child);
child.location = Oahu;
}
enum PersonType {Adult, Child}
enum Location {Oahu, Molokai}
static class Person implements Runnable {
final PersonType type;
Location location;
int peopleLastIsland;
Person(PersonType t) {
location = Oahu;
type = t;
}
public void run() {
if (type == Adult)
try {
AdultItinerary(this);
} catch (InterruptedException e) {
e.printStackTrace();
}
else
try {
ChildItinerary(this);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package pf;
public class BoatGrader {
/**
* BoatGrader consists of functions to be called to show that your solution
* is properly synchronized. This version simply prints messages to standard
* out, so that you can watch it. You cannot submit this file, as we will be
* using our own version of it during grading.
*
* Note that this file includes all possible variants of how someone can get
* from one island to another. Inclusion in this class does not imply that
* any of the indicated actions are a good idea or even allowed.
*/
/*
* ChildRowToMolokai should be called when a child pilots the boat from Oahu
* to Molokai
*/
public void ChildRowToMolokai() {
System.out.println("**Child rowing to Molokai.");
}
/*
* ChildRowToOahu should be called when a child pilots the boat from Molokai
* to Oahu
*/
public void ChildRowToOahu() {
System.out.println("**Child rowing to Oahu.");
}
/*
* ChildRideToMolokai should be called when a child not piloting the boat
* disembarks on Molokai
*/
public void ChildRideToMolokai() {
System.out.println("**Child arrived on Molokai as a passenger.");
}
/*
* ChildRideToOahu should be called when a child not piloting the boat
* disembarks on Oahu
*/
public void ChildRideToOahu() {
System.out.println("**Child arrived on Oahu as a passenger.");
}
/*
* AdultRowToMolokai should be called when a adult pilots the boat from Oahu
* to Molokai
*/
public void AdultRowToMolokai() {
System.out.println("**Adult rowing to Molokai.");
}
/*
* AdultRowToOahu should be called when a adult pilots the boat from Molokai
* to Oahu
*/
public void AdultRowToOahu() {
System.out.println("**Adult rowing to Oahu.");
}
/*
* AdultRideToMolokai should be called when an adult not piloting the boat
* disembarks on Molokai
*/
public void AdultRideToMolokai() {
System.out.println("**Adult arrived on Molokai as a passenger.");
}
/*
* AdultRideToOahu should be called when an adult not piloting the boat
* disembarks on Oahu
*/
public void AdultRideToOahu() {
System.out.println("**Adult arrived on Oahu as a passenger.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment