|
57 | 57 | # (list:fill 4 nil) # [nil nil nil nil] |
58 | 58 | # =end |
59 | 59 | # @author https://github.com/SuperFola |
60 | | -(let fill (fun (_val _count) (builtin__list:fill _val _count))) |
| 60 | +(let fill (fun (_count _val) (builtin__list:fill _count _val))) |
61 | 61 |
|
62 | 62 | # @brief Function to call the `len` operator on a list |
63 | 63 | # @param _L list to get the size of |
|
843 | 843 | (if (= stopIteration (_f (select _L _indices))) |
844 | 844 | (set _continue false)) } |
845 | 845 | (set _continue false)) }) }) }) })) |
| 846 | + |
| 847 | +# @brief Compute permutations of length _r from a given list, allowing individual elements to be repeated more than once |
| 848 | +# @details The original list is not modified. |
| 849 | +# @param _L list to get values from |
| 850 | +# @param _r number of elements per permutation |
| 851 | +# @param _f function to call on each permutation. It can return list:stopIteration to stop iteration early |
| 852 | +# =begin |
| 853 | +# (let data [0 1 2]) |
| 854 | +# (list:permutations_with_replacement data 2 (fun (perm) (print perm))) |
| 855 | +# # [0 0] |
| 856 | +# # [0 1] |
| 857 | +# # [0 2] |
| 858 | +# # [1 1] |
| 859 | +# # [1 2] |
| 860 | +# # [2 2] |
| 861 | +# =end |
| 862 | +# @author https://github.com/SuperFola |
| 863 | +(let permutations_with_replacement (fun ((ref _L) _r _f) { |
| 864 | + (let _len (len _L)) |
| 865 | + (if (and (!= 0 _len) (> _r 0)) |
| 866 | + { |
| 867 | + (mut _indices (fill _r 0)) |
| 868 | + (if (!= stopIteration (_f (select _L _indices))) |
| 869 | + { |
| 870 | + (mut _continue true) |
| 871 | + (let _reversed_range (iterate (- _r 1) (fun (_x) (- _x 1)) _r)) |
| 872 | + (while _continue { |
| 873 | + (mut _i nil) |
| 874 | + (if |
| 875 | + (forEach _reversed_range (fun (_val) { |
| 876 | + (set _i _val) |
| 877 | + (if (!= (@ _indices _i) (- _len 1)) stopIteration) })) |
| 878 | + { |
| 879 | + (mut _j _i) |
| 880 | + (let _val (+ 1 (@ _indices _i))) |
| 881 | + (while (< _j _r) { |
| 882 | + (@= _indices _j _val) |
| 883 | + (set _j (+ 1 _j)) }) |
| 884 | + (if (= stopIteration (_f (select _L _indices))) |
| 885 | + (set _continue false)) } |
| 886 | + (set _continue false)) }) }) }) })) |
0 commit comments