RE: Sorts API: A collection of sort functions
Version 0.1 collects together the Sort functions previously contained in my List program (including Sortn from the forum), with minor implementation changes.
http://www.hpmuseum.org/forum/thread-9411.html
Requires List which should be compiled first.
Code:
Code
LOCAL CRID:="Sorts API V0.1 © 2018 StephenG1CMZ";
LOCAL MORETEXT:="A collection of sort routines brought to you by StephenG1CMZ,\n with some from the forum.";
LOCAL MN:="Sorts.";//Name
//IMPORT({List}); //Required
LOCAL TYPELST:=TYPE({});
LOCAL TYPEFLOAT:=TYPE(3.1);
LOCAL TYPEINT:=TYPE(#3);
LOCAL TYPESTR:=TYPE(" ");
//Customise
EXPORT SortableTypes:={TYPEFLOAT,TYPEINT,TYPESTR};
LOCAL UNK0:=0;//EMPTY IS UNKNOWN,DEFAULT FALSE
LOCAL UNK1:=1;//EMPTY IS UNKNOWN,DEFAULT TRUE
//LOCAL SL:=1;
//NB To test: sort >1 item
//End
//Forward
IsSortablePortable(LST);
SortL(LST);
SortN(LST,NN);
LOCAL NL:="\n";
LOCAL ListANS;//OUTPUT LIST(WHEN NOT RETURNED)
//ERR
LOCAL ListErrK:=1;
LOCAL PyErrK:=3;
EXPORT ListLastError:=0;
LOCAL ERRKIND:={"","Error","","Py Error"};
EXPORT EL:={
"(/0) DivideBy0",
"IndexOutofBoundsException",
"ListIsEmptyError",
"ListIsFullError",
"ListSortError",
"ListStatisticsError",
"ItemNotFoundError",
"ValueError"
};
//ERRNO IS ARBITRARY:INDEXES ERRLST
EXPORT DivBy0Error:=1;
LOCAL IndexOutOfBoundsException:=2;//List J
EXPORT ListIsEmptyError:=3;
LOCAL ListIsFullError:=4;//UNUSED YET
LOCAL SortError:=5;
EXPORT ListStatisticsError:=6;
EXPORT ItemNotFoundError:=7;//List Py
EXPORT ValueError:=8; // Py
EXPORT ABOUT()
BEGIN
MSGBOX(CRID);
MSGBOX(MORETEXT);
END;
TBD()
BEGIN
MSGBOX(MN+"TBD");
END;
EXPORT IsSortable(LST)
//For now use Portable
//Later: as SORT
BEGIN
RETURN IsSortablePortable(LST);
END;
EXPORT IsSortablePortable(LST)
//0.Is parameter a list
//1.Is TYPE of contents OF ORDERABLE DATA
//2.Is SORTL implemented on that type yet
//NOTE:
//IsSORTABLE({Real})=1 AND IsSORTABLE({INT})=1 AND IsSORTABLE({string})=1 but
//do not assume SORT({mixed}) will deliver your expectations
//NB The current algorithm reports {1,"4"} as sortable
//But native sort wont
//The Portable variant assumes strings and numerics are sortable.
BEGIN
IF TYPE(LST)==TYPELST THEN
IF SIZE(LST) THEN
RETURN ListIsTYPE(LST,SortableTypes);
END;
RETURN UNK0;//EMPTY
END;
RETURN 0;//NOT LIST:CANNOT BE SORTED
END;
EXPORT IsSortedEQ(LST)
//Tells whether a list is sorted...inefficiently
//By sorting it and checking equality
//(Useful for testing)
BEGIN
ListANS:=SortL(LST);
RETURN EQ(ListANS,LST);
END;
EXPORT IsSorted(LST)
//Looping until 1st descending will/may be quicker TBD
BEGIN
RETURN IsSortedEQ(LST);
END;
EXPORT SortByKey(SORTS,KeyNum)
//Sort lists by list number KeyNum (with some input guards)
BEGIN
IF 0<KeyNum≤SIZE(SORTS) THEN
IF SIZE(SORTS)>1 AND SORTS(1)≠{} AND SORTS(2)≠{} THEN
RETURN SortN(SORTS,KeyNum);
END;
ELSE
//Potential:not all checked
//List small, not containing lists, key out of range, key list unsortable
RAISE(MN+"SortByKey",EL,SortError,KeyNum,ListErrK);
END;
RETURN SORTS;
END;
EXPORT SortByOccurrences(LST)
//Returns {LSTV,LSTF} sorted by frequency of occurrence
//reverse so most popular is 1st and index is approx rank
BEGIN
TBD();
//ListANS:=ListOCCURRENCES(LST);
RETURN REVERSE(SortByKey(ListANS,2));
END;
EXPORT SortL(LST)
//This implementation uses native SORT
BEGIN
IF TYPE(LST)≠TYPELST THEN
RAISE(MN+"SortL",EL,SortError,"",ListErrK);
END;
RETURN SORT(LST);
END;
EXPORT SortN(list,n)
// From http://www.hpmuseum.org/forum/thread-6179.html?highlight=sort+two+lists
//Call via ListSORTBYKEY to guard parameters...or call directly with good inputs
BEGIN
LOCAL li,ma;
ma:=list2mat(list) ;
li:=SORT(MAKELIST(mat2list(col(ma,I)),I,1,colDim(ma)),n);
RETURN MAKELIST(mat2list(col(list2mat(li),I)),I,1,rowDim(ma));
//For example:
//SORTN({{3,2,1},{15,20,18}},1);// -> {{1,2,3},{18,20,15}}
//SORTN({{3,2,1},{15,20,18},{32,35,27}},1);// -> {{1,2,3},{18,20,15},{27,35,32}}
END;
EXPORT SortsVERSION()
BEGIN
RETURN CRID;
END;
EXPORT Pyreverse(LST)
//Python analogue
BEGIN
RETURN REVERSE(LST);
END;
EXPORT Pysort(LST,KeyFunc,RReverse)
//Python analogue SORT
//TBD: KeyFunc: Selects sort key from item
BEGIN
IF TYPE(KeyFunc)==TYPEFLOAT AND KeyFunc==0 THEN
//0=None=NO FUNC
ELSE
TBD();
RAISE(MN+"Pysort",EL,ValueError,"",1);//TBD
END;
RETURN IFTE(RReverse,SORT(Pyreverse(LST)),SORT(LST));
END;
EXPORT ListPuzzles()
//SEE http://www.hpmuseum.org/forum/thread-8209.html?highlight=challenge
BEGIN
LOCAL VR;
LOCAL LST:=MAKELIST("",VR,1,5);//40
LST(2):="31. ListOCCURRENCESWITHSORT";
CHOOSE(VR,MN+"Puzzles (See thread)",LST);
END;
EXPORT SortSeeAlso ()
BEGIN
LOCAL KK;
LOCAL CatFuns:={
"REVERSE",
"reverse",
"revlist",
"SORT",
"sort"
};
//Just Listed as a reminder:not Selectable
CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)
END;
EXPORT SortsExamples()
//In real use, use XXX:=Sort...()
BEGIN
LOCAL LL:={1,2,3,4,5,6,7,8,9};
PRINT();
PRINT(SortsVERSION);
PRINT("Is");
PRINT(IsSortable(0));
PRINT(IsSortable({}));
PRINT(IsSortable(LL));
//PRINT(IsSortable(LL+{3.1}));
PRINT(IsSorted(LL));
//PRINT(ListIsTYPE({3.4},1-1));
PRINT("Sort");
//SortByABS
//SortByKey
//SortByOccurrences
//TBD PRINT(SortByOccurrences({1,2,2,3,3,3}));
//SortL
PRINT(SortL(LL));
//SortN
PRINT(SortN({{3,2,1},{15,20,18}},1));// -> {{1,2,3},{18,20,15}}
PRINT(SortN({{3,2,1},{15,20,18},{32,35,27}},1));// -> {{1,2,3},{18,20,15},{27,35,32}}
PRINT("Exampled");
//RETURN 0;
END;
EXPORT SORTS()
BEGIN
ABOUT();
//SortExamples();
END;
Version 0.2 is reworked to minimise the need for my "List" program.
I had hoped it would now only be needed for error handling, but in fact there is still a dependency on ListIsTYPE too..
New routines ReverseLOL, SortByCount, SortByABS.
Code:
LOCAL CRID:="Sorts API V0.2 © 2018 StephenG1CMZ";
LOCAL MORETEXT:="A collection of sort routines brought to you by StephenG1CMZ,\n with some from the forum.";
LOCAL MN:="Sorts.";//Name
//Also includes REVERSE functions
//IMPORT({List}); //for error handling
LOCAL TYPELST:=TYPE({});
LOCAL TYPEFLOAT:=TYPE(3.1);
LOCAL TYPEINT:=TYPE(#3);
LOCAL TYPESTR:=TYPE(" ");
//Customise
EXPORT SortableTypes:={TYPEFLOAT,TYPEINT,TYPESTR};
LOCAL UNK0:=0;//EMPTY IS UNKNOWN,DEFAULT FALSE
LOCAL UNK1:=1;//EMPTY IS UNKNOWN,DEFAULT TRUE
//LOCAL SL:=1;
//NB To test: sort >1 item
//End
//Forward
IsSortablePortable(LST);
SortByKeyTBD(SORTS,Keynum);
SortL(LST);
SortN(LST,NN);
LOCAL NL:="\n";
LOCAL ListANS;//OUTPUT LIST(WHEN NOT RETURNED)
//ERR
LOCAL ListErrK:=1;
LOCAL PyErrK:=3;
EXPORT ListLastError:=0;
LOCAL ERRKIND:={"","Error","","Py Error"};
EXPORT EL:={
"(/0) DivideBy0",
"IndexOutofBoundsException",
"ListIsEmptyError",
"ListIsFullError",
"ListSortError",
"ListStatisticsError",
"ItemNotFoundError",
"ValueError"
};
//ERRNO IS ARBITRARY:INDEXES ERRLST
EXPORT DivBy0Error:=1;
LOCAL IndexOutOfBoundsException:=2;//List J
EXPORT ListIsEmptyError:=3;
LOCAL ListIsFullError:=4;//UNUSED YET
LOCAL SortError:=5;
EXPORT ListStatisticsError:=6;
EXPORT ItemNotFoundError:=7;//List Py
EXPORT ValueError:=8; // Py
EXPORT ABOUT()
BEGIN
MSGBOX(CRID);
MSGBOX(MORETEXT);
END;
TBD()
BEGIN
MSGBOX(MN+"TBD");
END;
EXPORT IsSortable(LST)
//For now use Portable
//Later: as native SORT
BEGIN
RETURN IsSortablePortable(LST);
END;
EXPORT IsSortablePortable(LST)
//0.Is parameter a list
//1.Is TYPE of contents OF ORDERABLE DATA
//2.Is SORTL implemented on that type yet
//NOTE:
//IsSORTABLE({Real})=1 AND IsSORTABLE({INT})=1 AND IsSORTABLE({string})=1 but
//do not assume SORT({mixed}) will deliver your expectations
//NB The current algorithm reports {1,"4"} as sortable
//But native sort wont
//The Portable variant assumes strings and numerics are sortable.
BEGIN
IF TYPE(LST)==TYPELST THEN
IF SIZE(LST) THEN
RETURN ListIsTYPE(LST,SortableTypes);
END;
RETURN UNK0;//EMPTY
END;
RETURN 0;//NOT LIST:CANNOT BE SORTED
END;
EXPORT IsSortedEQ(LST)
//Tells whether a list is sorted...inefficiently
//By sorting it and checking equality
//(Useful for testing)
BEGIN
ListANS:=SortL(LST);
RETURN EQ(ListANS,LST);
END;
EXPORT IsSorted(LST)
//Looping until 1st descending will/may be quicker TBD
BEGIN
RETURN IsSortedEQ(LST);
END;
EXPORT ReverseLOL(LSTS)
//Reverse a list of lists
//EG {{1,2},{3,4}} -> {{2,1},{4,3}}
//NONRECURSIVE:TOP LISTS ONLY
//ALL LISTS MUST BE REVERSIBLE
BEGIN
LOCAL II;
ListANS:={};
IF SIZE(LSTS) THEN
//REVERSE EACH LST
FOR II FROM 1 TO SIZE(LSTS) DO
ListANS(II):=REVERSE(LSTS(II));
END;//FOR
END;
RETURN ListANS;
END;
EXPORT SortByABS(LST)
BEGIN
LOCAL TMP:={};
IF SIZE(LST) THEN
TMP:=SortN({ABS(LST),SIGN(LST)},1);
RETURN TMP(1)*TMP(2);
END;
RETURN {};
END;
EXPORT SortByCount(LSTS,Keynum)
//LSTS is {LSTV,LSTF} as returned by
//ListOCCURRENCES(LST);
//but additional fields are allowed
//Returns {LSTV,LSTF} sorted by frequency of occurrence
//EG {{1,2,3},{10,30,20}} -> {{2,3,1},{10,20,30}}
BEGIN
IF SIZE(LSTS)≥Keynum THEN
IF SIZE(LSTS(1))>1 AND SIZE(LSTS(Keynum))>1 THEN
RETURN SortN(LSTS,K);
END;
END;
RETURN {};
//To reverse sequence call ReverseLOLS()
END;
//These routines are similar
//Why does one fail TBD
EXPORT SortByKeyTBD(LSTS,KeyNum)
//Sort lists by list number KeyNum (with some input guards)
//Hint: If this gives a data type error call SORTN directly (WHY?)
BEGIN
IF 0<KeyNum≤SIZE(LSTS) AND SIZE(LSTS)>1 THEN
IF LSTS(1)≠{} AND LSTS(2)≠{} THEN
RETURN SortN(LSTS,KeyNum);
END;
ELSE
//Potential:not all checked
//List small, not containing lists, key out of range, key list unsortable
RAISE(MN+"SortByKey",EL,SortError,KeyNum,ListErrK);
END;
RETURN {};
END;
EXPORT SortL(LST)
//This implementation uses native SORT
BEGIN
IF TYPE(LST)≠TYPELST THEN
RAISE(MN+"SortL",EL,SortError,"",ListErrK);
END;
RETURN SORT(LST);
END;
EXPORT SortN(list,n)
// From http://www.hpmuseum.org/forum/thread-6179.html?highlight=sort+two+lists
//Call via ListSORTBYKEY to guard parameters...or call directly with good inputs
BEGIN
LOCAL li,ma;
ma:=list2mat(list) ;
li:=SORT(MAKELIST(mat2list(col(ma,I)),I,1,colDim(ma)),n);
RETURN MAKELIST(mat2list(col(list2mat(li),I)),I,1,rowDim(ma));
//For example:
//SORTN({{3,2,1},{15,20,18}},1);// -> {{1,2,3},{18,20,15}}
//SORTN({{3,2,1},{15,20,18},{32,35,27}},1);// -> {{1,2,3},{18,20,15},{27,35,32}}
END;
EXPORT SortsVERSION()
BEGIN
RETURN CRID;
END;
EXPORT Pyreverse(LST)
//Python analogue
BEGIN
RETURN REVERSE(LST);
END;
EXPORT Pysort(LST,KeyFunc,RReverse)
//Python analogue SORT
//TBD: KeyFunc: Selects sort key from item
BEGIN
IF TYPE(KeyFunc)==TYPEFLOAT AND KeyFunc==0 THEN
//0=None=NO FUNC
ELSE
TBD();
RAISE(MN+"Pysort",EL,ValueError,"",1);//TBD
END;
RETURN IFTE(RReverse,SORT(Pyreverse(LST)),SORT(LST));
END;
EXPORT ListPuzzles()
//SEE http://www.hpmuseum.org/forum/thread-8209.html?highlight=challenge
BEGIN
LOCAL VR;
LOCAL LST:=MAKELIST("",VR,1,5);//40
LST(2):="31. ListOCCURRENCESWITHSORT";
CHOOSE(VR,MN+"Puzzles (See thread)",LST);
END;
EXPORT SortSeeAlso ()
BEGIN
LOCAL KK;
LOCAL CatFuns:={
"REVERSE",
"reverse",
"revlist (slower)",
"SORT",
"sort"
};
//Just Listed as a reminder:not Selectable
CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)
END;
EXPORT SortsExamples()
//In real use, use XXX:=Sort...()
BEGIN
LOCAL LL:={1,2,3,4,5,6,7,8,9};
PRINT();
PRINT(SortsVERSION);
PRINT("Is");
PRINT(IsSortable(0));
PRINT(IsSortable({}));
PRINT(IsSortable(LL));
PRINT(IsSortablePortable(LL));
PRINT(IsSorted(LL));
PRINT(IsSortedEQ(LL));
PRINT("Reverse");
PRINT(ReverseLOL({{1,2},{3,4},{5,6}}));
PRINT("Sort");
//SortByABS
PRINT(SortByABS({1,2,3,−2})); // -> {1,2,−2,3}
//SortByCount
PRINT(SortByCount({{1,2,3},{10,30,20}},2)); // -> {{2,3,1},{10,20,30}}
//SortByKey
//SortL
PRINT(SortL(LL));
//SortN
PRINT(SortN({{3,2,1},{15,20,18}},1));// -> {{1,2,3},{18,20,15}}
PRINT(SortN({{3,2,1},{15,20,18},{32,35,27}},1));// -> {{1,2,3},{18,20,15},{27,35,32}}
//SortByOccurrences
PRINT(SortByCount({{1,2,3},{1,22,3}},2));
PRINT(ReverseLOL(SortByCount({{1,2,3},{1,22,3}},2)));
PRINT("Py");
PRINT(Pyreverse({1,2,3}));
PRINT(Pysort({1,22,3},0,0));
PRINT("Exampled");
//RETURN 0;
END;
EXPORT SORTS()
BEGIN
ABOUT();
//SortExamples();
END;
Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
|