/*****************************************************************************
Copyright (c) 2001 EDMGROUP
Project: CABLE_MASTER
FileName: CABLE_MASTER.PRO
Purpose: Cable master task solver
Written by: Serguei Penkov: spenkov@ozemail.com.au
Comments:
******************************************************************************/
global domains
SLIST = STRING*
ILIST = INTEGER*
FILE = input
BR_TREE = reference t(VAL,BR_TREE,BR_TREE)
VAL = INTEGER
predicates
predicates cable_master(SLIST INPUT_LINES)
predicates sort_integers(ILIST,ILIST) - (i,o)
procedure string_to_slist(STRING,STRING,SLIST) - (i,i,o)
procedure slist_to_integer_list(SLIST,ILIST) - (i,o)
procedure find_solution(ILIST CABLE_LENGTH_SORTED,INTEGER) - (i,i)
procedure total_length(ILIST,INTEGER LENGTH) - (i,o)
procedure min_number(ILIST,INTEGER,INTEGER MIN) - (i,i,o)
procedure max_number(ILIST,INTEGER,INTEGER MIN) - (i,i,o)
procedure max(INTEGER, INTEGER, INTEGER) - (i,i,o)
procedure min(INTEGER, INTEGER, INTEGER) - (i,i,o)
nondeterm for(INTEGER ,INTEGER Start,INTEGER Stop, INTEGER INCREMENT)
determ test_cable_length(INTEGER BEST_LENGTH,INTEGER REQUIRED_PIECES,ILIST CABLE_LENGTH_SORTED) - (i,i,i)
clauses
cable_master([FIRST_LINE|CABLE_LINES]):-
fronttoken(FIRST_LINE,TOTAL,PIECES),
str_int(TOTAL,TOTAL_CABLES),
str_int(PIECES,REQUIRED_PIECES),
slist_to_integer_list(CABLE_LINES,CABLE_LENGTH),
write("Total Cables - ",TOTAL_CABLES),nl,
write("Required Pieces - ",REQUIRED_PIECES),nl,
find_solution(CABLE_LENGTH,REQUIRED_PIECES),
!.
find_solution(CABLE_LENGTH,REQUIRED_PIECES):-
sort_integers(CABLE_LENGTH, CABLE_LENGTH_SORTED),
write("Cable Length sorted ",CABLE_LENGTH_SORTED),nl,
total_length(CABLE_LENGTH_SORTED,TOTAL_LENGTH),
write("Total Cable Length ",TOTAL_LENGTH),nl, % calculate total cable length
MAX_SEGMENT = TOTAL_LENGTH div REQUIRED_PIECES,
write("Max possible segment ",MAX_SEGMENT),nl,
% now - generate and test. Generate a cable length and test,
% if it can fit into current cables
% Simple approach - generate and test
for(BEST_LENGTH,MAX_SEGMENT,0,-1),
test_cable_length(BEST_LENGTH,REQUIRED_PIECES,CABLE_LENGTH_SORTED),
% here we are with solution
!.
find_solution(CABLE_LENGTH,REQUIRED_PIECES):-
write("No solution found\n"),
write("CABLES ",CABLE_LENGTH,", REQUIRED number of segments ",REQUIRED_PIECES),nl,
write("Max number of cables ",CABLE_LENGTH),nl,
!.
test_cable_length(_,_,[]):-!,fail. % THIS CABLE LENGTH DOESN'T FIT
test_cable_length(BEST_LENGTH,REQUIRED_PIECES,_):-
REQUIRED_PIECES = 0,
!, % OK - here we are - found best fit cable length
write("\tFound solution - ",BEST_LENGTH," is the maximum length\n").
test_cable_length(BEST_LENGTH,REQUIRED_PIECES,[CABLE_LENGTH|CABLE_LENGTH_SORTED]):-
HOW_MANY_PIECES_IN_THIS_CABLE = CABLE_LENGTH div BEST_LENGTH,
NEXT_REQUIRED_PIECES = REQUIRED_PIECES - HOW_MANY_PIECES_IN_THIS_CABLE,
NEXT_REQUIRED_PIECES > 0,!,
test_cable_length(BEST_LENGTH,NEXT_REQUIRED_PIECES,CABLE_LENGTH_SORTED).
test_cable_length(BEST_LENGTH,_,_):-
write("\tFound solution - ",BEST_LENGTH," is the maximum length\n"),
!.
% support predicates
for(I,I,_,_).
for(I,Start,Stop,INCREMENT):-
INCREMENT > 0,
Start < Stop,Next=Start+INCREMENT,
for(I,Next,Stop,INCREMENT).
for(I,Start,Stop,INCREMENT):-
INCREMENT < 0,
Start > Stop,Next=Start+INCREMENT,
for(I,Next,Stop,INCREMENT).
total_length([],0):-!.
total_length([LENGTH|ILIST],TOTAL_LENGTH):-!,
total_length(ILIST,TEMP),
TOTAL_LENGTH = TEMP + LENGTH.
string_to_slist(View,SEP,[Field|FieldList]):-
searchstring(View,SEP,FoundPos),
str_len(SEP,SEPLength),
Pos = FoundPos - 1,
frontstr(Pos,View,Field,RestString),
frontstr(SEPLength,RestString,_,Tail),!,
string_to_slist(Tail,SEP,FieldList).
string_to_slist(Field,_,[Field]).
slist_to_integer_list([],[]):-!.
slist_to_integer_list([LINE|DATA_LINES],[LENGTH_IN_CM|CABLE_LENGTH]):-
str_real(LINE,REAL),
LENGTH_IN_CM = val(INTEGER,REAL*100),!,
slist_to_integer_list(DATA_LINES,CABLE_LENGTH).
slist_to_integer_list([LINE|DATA_LINES],CABLE_LENGTH):-!,
write("Invalid input Data - length is not real - ",LINE),nl,
slist_to_integer_list(DATA_LINES,CABLE_LENGTH).
% min/max calculations
min_number([],MIN ,MIN):-!.
min_number([H|T],CURR_MIN ,MIN):-!,
min(H,CURR_MIN,TEMP),
min_number(T,TEMP,MIN).
max_number([],Max,Max):-!.
max_number([H|IndexList],Index,Max):-!,
max(H,Index,TempMax),
max_number(IndexList,TempMax,Max).
max(A,B,A):-A >= B,!.
max(_,B,B).
min(A,B,A):-A<=B,!.
min(_,B,B).
% sorting
PREDICATES
insert(INTEGER,BR_TREE)
instree(ILIST,BR_TREE)
nondeterm treemembers(INTEGER,BR_TREE)
CLAUSES
insert(Val,t(Val,_,_)):-!.
insert(NUMBER1,t(NUMBER2,Tree,_)):-
NUMBER1>NUMBER2,!,
insert(NUMBER1,Tree).
insert(Val,t(_,_,Tree)):-insert(Val,Tree).
instree([],_).
instree([H|T],Tree):-
insert(H,Tree),
instree(T,Tree).
treemembers(_,T):-free(T),!,fail.
treemembers(X,t(_,L,_)):-treemembers(X,L).
treemembers(X,t(NUMBER1,_,_)):-X=NUMBER1.
treemembers(X,t(_,_,R)):-treemembers(X,R).
sort_integers(L, L1) :-
instree(L,Tree),
findall(X,treemembers(X,Tree),L1).
goal
write("Cable master solution\n"),
syspath(ExeStartupPath,_),
filenamepath(FullName,ExeStartupPath,"input.txt"),
file_str(FullName,DATA_STRING),
string_to_slist(DATA_STRING,"\n",DATA_LINES),
cable_master(DATA_LINES).
Copyright 1999-2002 EDMGROUP, Australia