Skip to content

Instantly share code, notes, and snippets.

@mndrix
Created January 1, 2010 21:30
Show Gist options
  • Save mndrix/267260 to your computer and use it in GitHub Desktop.
Save mndrix/267260 to your computer and use it in GitHub Desktop.
% Variable naming convention:
% T - town in which to snowbird
% Cs - choices made
% E - expense incurred
%
% t(T,Cs,E) represents a specific snowbirding trip. Standing at home
% and having decided to snowbird in Las Vegas is represented as
% t(vegas, Cs, 0). That is, I've decided on Vegas and incurred no cost yet,
% but haven't made any choices about how I'll get there.
main :-
findall( How, snowbird( t(_,[],0), How ), Trips ),
predsort( by_cost, Trips, Sorted ),
forall( member(How, Sorted), show_t(How) ).
snowbird -->
travel_there,
/* housing, food */
temple,
transportation,
travel_back.
travel_there --> airport_city, vehicle_storage, fly.
travel_there --> drive.
travel_back --> fly, airport_city.
travel_back --> drive.
vehicle_storage --> airport_parking.
vehicle_storage --> long_term_parking.
vehicle_storage --> airport_taxi.
transportation --> own_car.
transportation --> rent_car.
transportation --> public_transit.
transportation --> zip_car.
drive( t(T,Cs,E0), t(T,[drive|Cs],E1) ) :-
\+ memberchk( fly, Cs ), % can't drive if we've decided to fly
distance( T, Miles ),
drive_miles( Miles, DriveCost ),
E1 is E0 + DriveCost.
fly( t(T,Cs,E0), t(T,[fly|Cs],E1) ) :-
\+ memberchk( drive, Cs ), % can't fly if we've decided to drive
flight_cost( T, Flight ),
flight_duration( T, FlightMinutes ),
TotalHours is FlightMinutes/60+2, % security, check-in, etc.
lost_work( TotalHours, Time ),
meals( TotalHours, Meals ),
E1 is E0+6*Flight/2+Time+Meals. % Flight is round-trip
% getting to/from the city with an airport
airport_city( t(T,Cs,E0), t(T,Cs,E1) ) :-
distance( denver, Miles ),
drive_miles( Miles, DriveCost ),
E1 is E0+DriveCost.
% vehicle storage choices
airport_parking( t(T,Cs,E0), t(T,[park(airport)|Cs],E1) ) :-
cold_duration(Days),
E1 is E0+Days*10. % $10/day
long_term_parking( t(T,Cs,E0), t(T,[park(long)|Cs],E1) ) :-
cold_duration(Days),
E1 is E0+Days*6. % $6/day
airport_taxi( t(T,Cs,E0), t(T,[taxi|Cs],E1) ) :-
E1 is E0+25*6*2. % $25/person flat fee each way
% what's the total cost of driving a certain distance?
drive_miles( Miles, E ) :-
fuel( Miles, Fuel ),
Duration is Miles/75,
lost_work( Duration, Time ),
meals( Duration, Meals ),
hotel( Duration, Hotel ),
E is Fuel+Time+Meals+Hotel.
fuel( Miles, E ) :-
E is Miles/15*2.40.
lost_work( Hours, E ) :-
E is Hours*65.
meals( Hours, E ) :-
E is 20*(round(Hours) // 3).
hotel( Hours, E ) :-
E is 100*(round(Hours) // 10).
own_car( t(T,Cs,E0), t(T,Cs,E0) ) :-
memberchk( drive, Cs ).
rent_car( t(T,Cs,E0), t(T,[rent_car|Cs], E1) ) :-
\+ memberchk( drive, Cs ),
cold_duration(Days),
car_rental_cost(T, RentPerDay),
% TODO add fuel costs
E1 is E0+Days*RentPerDay.
zip_car( t(T,Cs,E0), t(T,[zip_car|Cs], E1) ) :-
\+ memberchk( drive, Cs ),
zip_car(T),
cold_duration(Days),
E1 is E0+50+65*(Days*3/7).
public_transit( t(T,Cs,E0), t(T,[buses|Cs],E1) ) :-
\+ memberchk( drive, Cs ),
bus_pass(T, BusPass),
E1 is E0+6*BusPass.
% how much is an unlimited bus pass?
bus_pass(T, E) :-
cold_duration(Days),
buses( T, FareSchedule ),
bus_pass( T, FareSchedule, Days, E ).
bus_pass( _, _, 0, 0 ).
bus_pass( _, [1-Price], DaysLeft, E ) :-
E is Price*DaysLeft.
bus_pass( T, [Days-Price|Schedule], DaysLeft0, E ) :-
BigPass is Price*(DaysLeft0//Days),
DaysLeft1 is DaysLeft0 rem Days,
bus_pass( T, Schedule, DaysLeft1, SmallPasses ),
!,
E is BigPass+SmallPasses.
temple( t(T,Cs,E0), t(T,Cs,E1) ) :-
temple_distance(T, Miles),
RoundtripMiles is Miles*2, % accounts for meals better than Cost*2
drive_miles(RoundtripMiles, Cost),
cold_duration(Days),
E1 is E0+round(Days/14)*Cost. % to/from the temple each fortnight
% compare two trips by cost
by_cost( Order, t(_, _, E1), t(_,_,E2) ) :-
compare(Order, E1, E2).
% convert a trip into text
show_t( t( T, Cs, E ) ) :-
reverse( Cs, Chronological ),
format('~w ~w ~w~n', [ E, T, Chronological ]).
% for how many days would we snowbird?
cold_duration( 90 ).
% for how many consecutive winters would we snowbird?
winters(5).
% facts about the various towns
about( Town, [Fact] ) :-
Fact =.. [ Functor | Args ],
Full =.. [ Functor, Town | Args ],
assert(Full).
about( Town, [H|T] ) :-
about( Town, [H] ),
about( Town, T ).
:- about( amarillo, [
car_rental_cost(100),
distance(626),
flight_cost(368),
flight_duration(390),
temple_distance(124)
]).
:- about( denver, [
airport_shuttle_cost(50),
distance(215)
]).
:- about( mesquite, [
distance(662),
temple_distance(40)
]).
:- about( miami, [
buses([ 30-102, 7-28, 1-7 ]), % bus pass Days-Cost
car_rental_cost(65),
distance(2256),
flight_cost(296),
flight_duration(390),
temple_distance(235),
zip_car
]).
:- about( st_george, [
buses([ 30-30, 7-10, 1-2.5 ]), % bus pass Days-Cost
distance(624),
temple_distance(0)
]).
:- about( tucson, [
buses([ 90-94, 30-35, 1-3 ]), % bus pass Days-Cost
car_rental_cost(75),
distance(1100),
flight_cost(120),
flight_duration(120),
temple_distance(117)
]).
:- about( vegas, [
buses([ 30-55, 3-15, 1-7 ]), % bus pass Days-Cost
car_rental_cost(59),
distance(747),
flight_cost(130),
flight_duration(120),
temple_distance(0)
]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment