1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-30 22:14:58 +03:00

Sort lists with a custom phrase (I7-2392)

This commit is contained in:
Dannii Willis 2023-07-18 12:36:44 +10:00
parent 097d74b62d
commit 3b6794a14c
8 changed files with 69 additions and 30 deletions

View file

@ -1213,19 +1213,22 @@ To rotate (L - a list of values) backwards
(- LIST_OF_TY_Rotate({-lvalue-by-reference:L}, 1); -).
To sort (L - a list of values)
(documented at ph_sortlist):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, 1); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_ASCENDING); -).
To sort (L - a list of values) in/into reverse order
(documented at ph_sortlistreverse):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, -1); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_DESCENDING); -).
To sort (L - a list of values of kind K) with (cf - phrase (K, K) -> number)
(documented at ph_sortlistphrase):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_ASCENDING, 0, 0, {cf}-->1); -).
To sort (L - a list of values) in/into random order
(documented at ph_sortlistrandom):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, 2); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_LIST_RANDOM); -).
To sort (L - a list of objects) in/into (P - property) order
(documented at ph_sortlistproperty):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, 1, {P}, {-property-holds-block-value:P}); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_ASCENDING, {P}, {-property-holds-block-value:P}); -).
To sort (L - a list of objects) in/into reverse (P - property) order
(documented at ph_sortlistpropertyreverse):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, -1, {P}, {-property-holds-block-value:P}); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_DESCENDING, {P}, {-property-holds-block-value:P}); -).
Section 6 - Relations

View file

@ -232,7 +232,7 @@ phs_listbraced phs_listdef phs_listindef _ doc352 "21.3" "21.3. Saying lists of
ph_islistedin ph_isnotlistedin ph_repeatlist _ doc353 "21.4" "21.4. Testing and iterating over lists"
ph_addtolist ph_addlisttolist ph_addatentry ph_addlistatentry ph_remfromlist ph_remlistfromlist ph_rementry ph_rementries _ doc354 "21.5" "21.5. Building lists"
ph_listofdesc _ doc355 "21.6" "21.6. Lists of objects"
ph_reverselist ph_sortlist ph_sortlistreverse ph_sortlistrandom ph_sortlistproperty ph_sortlistpropertyreverse ph_rotatelist ph_rotatelistback _ doc357 "21.8" "21.8. Sorting, reversing and rotating lists"
ph_reverselist ph_sortlist ph_sortlistreverse ph_sortlistphrase ph_sortlistrandom ph_sortlistproperty ph_sortlistpropertyreverse ph_rotatelist ph_rotatelistback _ doc357 "21.8" "21.8. Sorting, reversing and rotating lists"
ph_numberentries _ doc358 "21.9" "21.9. Accessing entries in a list"
ph_changelength ph_truncate ph_truncatefirst ph_truncatelast ph_extend _ doc359 "21.10" "21.10. Lengthening or shortening a list"
kind_description ph_valuematch _ doc362 "22.2" "22.2. Descriptions as values"

View file

@ -123,11 +123,6 @@ use the list's own preferred comparison function to judge the items in turn,
stopping as soon as a pair of corresponding items differs: thus we sort
lists of equal size in lexicographic order.
Since the comparison function depends only on the KOV, it may seem wasteful
of a word of memory to store it in the list, given that we are already storing
the KOV in any case. But we do this because comparisons have to be fast: we
don't want to incur the overhead of translating KOV to comparison function.
=
[ LIST_OF_TY_Compare listleft listright delta no_items i cf;
delta = BlkValueRead(listleft, LIST_LENGTH_F) - BlkValueRead(listright, LIST_LENGTH_F);
@ -687,13 +682,19 @@ the list, unless the optional argument |prop| is supplied, in which case
we sort based not on the item values but on their values for the property
|prop|. (This only makes sense if the list contains objects.)
|LIST_OF_TY_Sort(list, dir, 0, 0, cf)| sorts the given |list| with the custom
comparison function |cf|, which must behave as any standard comparison function
would.
=
Constant SORT_LIST_RANDOM = 2;
Global LIST_OF_TY_Sort_cf;
[ LIST_OF_TY_Sort list dir prop cf i j no_items v;
[ LIST_OF_TY_Sort list dir prop prop_is_bv cf i j no_items v;
BlkMakeMutable(list);
no_items = BlkValueRead(list, LIST_LENGTH_F);
if (dir == 2) {
if (dir == SORT_LIST_RANDOM) {
if (no_items < 2) return;
for (i=1:i<no_items:i++) {
j = random(i+1) - 1;
@ -704,8 +705,20 @@ Global LIST_OF_TY_Sort_cf;
return;
}
SetSortDomain(ListSwapEntries, ListCompareEntries);
if (cf) LIST_OF_TY_Sort_cf = BlkValueCompare;
else LIST_OF_TY_Sort_cf = 0;
if (cf) {
LIST_OF_TY_Sort_cf = cf;
}
else if (prop) {
if (prop_is_bv) {
LIST_OF_TY_Sort_cf = BlkValueCompare;
}
else {
LIST_OF_TY_Sort_cf = 0;
}
}
else {
LIST_OF_TY_Sort_cf = LIST_OF_TY_ComparisonFn(list);
}
SortArray(list, prop, dir, no_items, 0);
];
@ -716,21 +729,17 @@ Global LIST_OF_TY_Sort_cf;
BlkValueWrite(list, LIST_ITEM_BASE+j-1, v);
];
[ ListCompareEntries list col i j d cf;
[ ListCompareEntries list col i j d;
if (i==j) return 0;
i = BlkValueRead(list, LIST_ITEM_BASE+i-1);
j = BlkValueRead(list, LIST_ITEM_BASE+j-1);
if (I7S_Col) {
if (i provides I7S_Col) i=i.I7S_Col; else i=0;
if (j provides I7S_Col) j=j.I7S_Col; else j=0;
cf = LIST_OF_TY_Sort_cf;
} else {
cf = LIST_OF_TY_ComparisonFn(list);
}
if (cf == 0) {
if (i > j) return 1;
if (i < j) return -1;
return 0;
} else
return cf(i, j);
if (LIST_OF_TY_Sort_cf == 0) {
return i - j;
} else {
return LIST_OF_TY_Sort_cf(i, j);
}
];

View file

@ -13,6 +13,9 @@ avoid filling the stack with copies, but otherwise we will hardly need any
auxiliary storage.
=
Constant SORT_ASCENDING = 1;
Constant SORT_DESCENDING = -1;
Global I7S_Tab; ! The array to be sorted, which can have almost any format
Global I7S_Col; ! The "column number" in the array, if any
Global I7S_Dir; ! The direction of sorting: ascending (1) or descending (-1)

View file

@ -4,6 +4,9 @@ An apple, a pear and an orange are fruits. A fruit has a number called size.
The size of a fruit is usually 4. The size of the apple is 7. The size of the pear is 6.
To decide which number is the comparison of (X - a number) and (Y - a number) (this is numerical comparison):
decide on X - Y;
To begin:
let L be { 16, 3, 5, -7, 11, -7, 0, 2 };
say "L is [L in brace notation].";
@ -21,6 +24,9 @@ To begin:
say "L sorts randomly to [L in brace notation].";
sort L in reverse order;
say "L sorts in reverse order to [L in brace notation].";
sort L in random order;
sort L with numerical comparison;
say "L sorts with a custom comparison phrase to [L in brace notation].";
let F be the list of fruits;
showme F;
sort F in size order;

View file

@ -6,6 +6,7 @@
L then rotates backwards to {16, 11, 5, 3, 2, 0, -7, -7}.
L sorts randomly to {16, 5, 3, 0, 2, -7, -7, 11}.
L sorts in reverse order to {16, 11, 5, 3, 2, 0, -7, -7}.
L sorts with a custom comparison phrase to {-7, -7, 0, 2, 3, 5, 11, 16}.
"F" = list of fruits: {apple, pear, orange}
F sorts in size order to {orange, pear, apple}.
F sorts in reverse size order to {apple, pear, orange}.

View file

@ -1459,19 +1459,22 @@ To rotate (L - a list of values) backwards
(- LIST_OF_TY_Rotate({-lvalue-by-reference:L}, 1); -).
To sort (L - a list of values)
(documented at ph_sortlist):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, 1); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_ASCENDING); -).
To sort (L - a list of values) in/into reverse order
(documented at ph_sortlistreverse):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, -1); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_DESCENDING); -).
To sort (L - a list of values of kind K) with (cf - phrase (K, K) -> number)
(documented at ph_sortlistphrase):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_ASCENDING, 0, 0, {cf}-->1); -).
To sort (L - a list of values) in/into random order
(documented at ph_sortlistrandom):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, 2); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_LIST_RANDOM); -).
To sort (L - a list of objects) in/into (P - property) order
(documented at ph_sortlistproperty):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, 1, {P}, {-property-holds-block-value:P}); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_ASCENDING, {P}, {-property-holds-block-value:P}); -).
To sort (L - a list of objects) in/into reverse (P - property) order
(documented at ph_sortlistpropertyreverse):
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, -1, {P}, {-property-holds-block-value:P}); -).
(- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_DESCENDING, {P}, {-property-holds-block-value:P}); -).
@ Relations are the final data structure given here. In some ways they are
the most fundamental of all, but they're not either set or tested by

View file

@ -14813,6 +14813,20 @@ This phrase puts the list into descending order. Example:
results in L being {6 PM, 4:21 PM, 11:13 AM, 9:01 AM}.
{end}
{defn ph_sortlistphrase}sort (list of values) with (phrase (value, value) -> number)
This phrase sorts the list with a custom comparison phrase. A comparison phrase must accept two list elements, and then return a number which indicates the relative order of the two list elements: negative if the left value should come before the right, zero if they are equal, and positive if the left value should come after the right. For example to sort numbers you would use this phrase:
To decide which number is the comparison of (X - a number) and (Y - a number) (this is numerical comparison):
decide on X - Y;
You could then sort a list of numbers using the numerical comparison phrase:
let L be {5, 1, 7, 2, 3};
sort L with numerical comparison;
Which results in L being {1, 2, 3, 5, 7}.
{end}
{defn ph_sortlistrandom}sort (list of values) in random order
This phrase puts the list into a uniformly random order, shuffling it as if it were a pack of cards. Example: