diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-07-18 23:17:04 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-07-18 23:18:10 -0400 |
| commit | c63290ae05990f54619207ac6ee0b3fbf6f9c145 (patch) | |
| tree | 12951802a4190e69ae7edda9ed84fe4df735bca5 /doc | |
| parent | 6243dcd88bf70157d600e787a7c344541df98085 (diff) | |
Auto-generate results in some doc files
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/depth.md | 49 | ||||
| -rw-r--r-- | doc/group.md | 75 | ||||
| -rw-r--r-- | doc/join.md | 16 | ||||
| -rw-r--r-- | doc/logic.md | 11 | ||||
| -rw-r--r-- | doc/windows.md | 39 |
5 files changed, 0 insertions, 190 deletions
diff --git a/doc/depth.md b/doc/depth.md index 855ca6ab..8738e7ed 100644 --- a/doc/depth.md +++ b/doc/depth.md @@ -9,36 +9,25 @@ The depth of an array is the greatest level of array nesting it attains, or, put To find the depth of an array, use Depth (`≡`). For example, the depth of a list of numbers or characters is 1: ≡ 2‿3‿4 - 1 ≡ "a string is a list of characters" - 1 Depth is somewhat analogous to an array's rank `≠≢𝕩`, and in fact rank can be "converted" to depth by splitting rows with `<⎉1`, reducing the rank by 1 and increasing the depth. Unlike rank, Depth doesn't care at all about its argument's shape: ≡ 3‿4⥊"characters" - 1 ≡ (1+↕10)⥊"characters" - 1 Also unlike rank, Depth *does* care about the elements of its argument: in fact, to find the depth of an array, every element must be inspected. ≡ ⟨2,3,4,5⟩ - 1 ≡ ⟨2,<3,4,5⟩ - 2 ≡ ⟨2,<3,4,<<<5⟩ - 4 As the above expressions suggest, the depth of an array is the maximum of its elements' depths, plus one. The base case, a non-array (including a function or modifier), has depth 0. ≡'c' - 0 F←+⋄≡f - 0 ≡⟨'c',f,2⟩ - 1 ≡⟨5,⟨'c',f,2⟩⟩ - 2 If the function `IsArray` indicates whether its argument is an array, then we can write a recursive definition of Depth using the Choose modifier. @@ -47,9 +36,7 @@ If the function `IsArray` indicates whether its argument is an array, then we ca The minimum element depth of 0 implies that an empty array's depth is 1. ≡⟨⟩ - 1 ≡2‿0‿3⥊0 - 1 ## Testing depth for multiple-axis primitives @@ -63,82 +50,46 @@ Several primitive functions use the left argument to manipulate the right argume Functions such as Take and Drop use a single number per axis. When the left argument is a list of numbers, they apply to initial axes. But for convenience, a single number is also accepted, and applied to the first axis only. This is equivalent to ravelling the left argument before applying the function. ≢2↑7‿7‿7‿7⥊"abc" - [ 2 7 7 7 ] ≢2‿1‿1↑7‿7‿7‿7⥊"abc" - [ 2 1 1 7 ] In these cases the flexibility seems trivial because the left argument has depth 1 or 0: it is an array or isn't, and it's obvious what a plain number should do. But for the second row in the table, the left argument is always an array. The general case is that the left argument is a vector and its elements correspond to right argument axes: ⟨3‿2,1‿4‿1⟩ ⊏ ↕6‿7 - ┌ - [ 3 1 ] [ 3 4 ] [ 3 1 ] - [ 2 1 ] [ 2 4 ] [ 2 1 ] - ┘ This means the left argument is homogeneous of depth 2. What should an argument of depth 1, or an argument that contains non-arrays, do? One option is to continue to require the left argument to be a list, and convert any non-array argument into an array by enclosing it: ⟨3‿2,1⟩ <⍟(0=≡)¨⊸⊏ ↕6‿7 - [ [ 3 1 ] [ 2 1 ] ] While very consistent, this extension represents a small convenience and makes it difficult to act on a single axis, which for Replicate and [Group](group.md) is probably the most common way the primitive is used: 3‿2‿1‿2‿3 / "abcde" - [ aaabbcddeee ] With the extension above, every case like this would have to use `<⊸/` instead of just `/`. BQN avoids this difficulty by testing the left argument's depth. A depth-1 argument applies to the first axis only, giving the behavior above. For Select, the depth-1 case is still quite useful, but it may also be desirable to choose a single cell using a list of numbers. In this case the left argument depth can be increased from the bottom using `<¨`. 2‿1‿4 <¨⊸⊏ ↕3‿4‿5‿2 - [ [ 2 1 4 0 ] [ 2 1 4 1 ] ] ## The Depth modifier The Depth 2-modifier (`⚇`) is a generalization of Each that allows diving deeper into an array. To illustrate it we'll use a shape `4‿3` array of lists of lists. ⊢ n ← <⎉1⍟2 4‿3‿2‿2⥊↕48 - ┌ - [ [ 0 1 ] [ 2 3 ] ] [ [ 4 5 ] [ 6 7 ] ] [ [ 8 9 ] [ 10 11 ] ] - [ [ 12 13 ] [ 14 15 ] ] [ [ 16 17 ] [ 18 19 ] ] [ [ 20 21 ] [ 22 23 ] ] - [ [ 24 25 ] [ 26 27 ] ] [ [ 28 29 ] [ 30 31 ] ] [ [ 32 33 ] [ 34 35 ] ] - [ [ 36 37 ] [ 38 39 ] ] [ [ 40 41 ] [ 42 43 ] ] [ [ 44 45 ] [ 46 47 ] ] - ┘ ≡ n - 3 Reversing n swaps all the rows: ⌽ n - ┌ - [ [ 36 37 ] [ 38 39 ] ] [ [ 40 41 ] [ 42 43 ] ] [ [ 44 45 ] [ 46 47 ] ] - [ [ 24 25 ] [ 26 27 ] ] [ [ 28 29 ] [ 30 31 ] ] [ [ 32 33 ] [ 34 35 ] ] - [ [ 12 13 ] [ 14 15 ] ] [ [ 16 17 ] [ 18 19 ] ] [ [ 20 21 ] [ 22 23 ] ] - [ [ 0 1 ] [ 2 3 ] ] [ [ 4 5 ] [ 6 7 ] ] [ [ 8 9 ] [ 10 11 ] ] - ┘ Depth `¯1` is equivalent to Each, and reverses the larger vectors, while depth `¯2` applies Each twice to reverse the smaller vectors: ⌽⚇¯1 n - ┌ - [ [ 2 3 ] [ 0 1 ] ] [ [ 6 7 ] [ 4 5 ] ] [ [ 10 11 ] [ 8 9 ] ] - [ [ 14 15 ] [ 12 13 ] ] [ [ 18 19 ] [ 16 17 ] ] [ [ 22 23 ] [ 20 21 ] ] - [ [ 26 27 ] [ 24 25 ] ] [ [ 30 31 ] [ 28 29 ] ] [ [ 34 35 ] [ 32 33 ] ] - [ [ 38 39 ] [ 36 37 ] ] [ [ 42 43 ] [ 40 41 ] ] [ [ 46 47 ] [ 44 45 ] ] - ┘ ⌽⚇¯2 n - ┌ - [ [ 1 0 ] [ 3 2 ] ] [ [ 5 4 ] [ 7 6 ] ] [ [ 9 8 ] [ 11 10 ] ] - [ [ 13 12 ] [ 15 14 ] ] [ [ 17 16 ] [ 19 18 ] ] [ [ 21 20 ] [ 23 22 ] ] - [ [ 25 24 ] [ 27 26 ] ] [ [ 29 28 ] [ 31 30 ] ] [ [ 33 32 ] [ 35 34 ] ] - [ [ 37 36 ] [ 39 38 ] ] [ [ 41 40 ] [ 43 42 ] ] [ [ 45 44 ] [ 47 46 ] ] - ┘ While a negative depth tells how many levels to go down, a non-negative depth gives the maximum depth of the argument before applying the left operand. On a depth-3 array like above, depth `2` is equivalent to `¯1` and depth `1` is equivalent to `¯2`. A depth of `0` means to loop until non-arrays are reached, that is, apply [pervasively](https://aplwiki.com/wiki/Pervasion), like a scalar function. ⟨'a',"bc"⟩ ≍⚇0 ⟨2‿3,4⟩ - [ [ [ a 2 ] [ a 3 ] ] [ [ b 4 ] [ c 4 ] ] ] With a positive operand, Depth doesn't have to use the same depth everywhere. Here, Length is applied as soon as the depth for a particular element is 1 or less, including if the argument has depth 0. For example, it maps over `⟨2,⟨3,4⟩⟩`, but not over `⟨11,12⟩`, even though these are elements of the same array. ≠⚇1 ⟨1,⟨2,⟨3,4⟩⟩,⟨5,⟨6,7⟩,⟨8,9,10⟩⟩,⟨11,12⟩⟩ - [ 1 [ 1 2 ] [ 1 2 3 ] 2 ] diff --git a/doc/group.md b/doc/group.md index 2790a851..dcf13220 100644 --- a/doc/group.md +++ b/doc/group.md @@ -15,54 +15,25 @@ Once defined, the old BQN Key (dyadic) is `⍷⊸⊐⊸⊔` and Group (monadic) Group operates on a numeric list of indices and an array, treated as a list of its major cells or "values", to produce a list of groups, each of which is a selection from those cells. The two arrays have the same length, and each value cell is paired with the index at the same position. That index indicates the result group the cell should go into, with an "index" of ¯1 indicating that it should be dropped and not appear in the result. 0‿1‿2‿0‿1 ≍ "abcde" # Corresponding indices and values - ┌ - 0 1 2 0 1 - a b c d e - ┘ 0‿1‿2‿0‿1 ⊔ "abcde" # Values grouped by index - [ [ ad ] [ be ] [ c ] ] For example, we might choose to group a list of words by length. Within each group, cells maintain the ordering they had in the list originally. phrase ← "BQN"‿"uses"‿"notation"‿"as"‿"a"‿"tool"‿"of"‿"thought" ⥊˘ ≠¨⊸⊔ phrase - ┌ - [] - [ [ a ] ] - [ [ as ] [ of ] ] - [ [ BQN ] ] - [ [ uses ] [ tool ] ] - [] - [] - [ [ thought ] ] - [ [ notation ] ] - ┘ (Could we define `phrase` more easily? See [below](#partitioning).) If we'd like to ignore words of 0 letters, or more than 5, we can set all word lengths greater than 5 to 0, then reduce the lengths by 1. Two words end up with left argument values of ¯1 and are omitted from the result. 1 -˜ ≤⟜5⊸× ≠¨ phrase - [ 2 3 ¯1 1 0 3 1 ¯1 ] ⥊˘ {1-˜≤⟜5⊸×≠¨𝕩}⊸⊔ phrase - ┌ - [ [ a ] ] - [ [ as ] [ of ] ] - [ [ BQN ] ] - [ [ uses ] [ tool ] ] - ┘ Note that the length of the result is determined by the largest index. So the result never includes trailing empty groups. A reader of the above code might expect 5 groups (lengths 1 through 5), but there are no words of length 5, so the last group isn't there. When Group is called dyadically, the left argument is used for the indices and the right is used for values, as seen above. When it is called monadically, the right argument, which must be a list, gives the indices and the values grouped are the right argument's indices, that is, `↕≠𝕩`. ⥊˘ ⊔ 2‿3‿¯1‿2 - ┌ - [] - [] - [ [ 0 ] [ 3 ] ] - [ [ 1 ] ] - ┘ Here, the index 2 appears at indices 0 and 3 while the index 3 appears at index 1. @@ -73,16 +44,6 @@ Dyadic Group allows the right argument to be grouped along multiple axes by usin Here we split up a rank-2 array into a rank-2 array of rank-2 arrays. Along the first axis we simply separate the first pair and second pair of rows—a partition. Along the second axis we separate odd from even indices. ⟨0‿0‿1‿1,0‿1‿0‿1‿0‿1‿0⟩⊔(10×↕4)+⌜↕7 - ┌ - ┌ ┌ - 0 2 4 6 1 3 5 - 10 12 14 16 11 13 15 - ┘ ┘ - ┌ ┌ - 20 22 24 26 21 23 25 - 30 32 34 36 31 33 35 - ┘ ┘ - ┘ Each group `i⊑𝕨⊔𝕩` is composed of the cells `j<¨⊸⊏𝕩` such that `i≢j⊑¨𝕨`. The groups retain their array structure and ordering along each argument axis. Using multidimensional Replicate we can say that `i⊑𝕨⊔𝕩` is `(i=𝕨)/𝕩`. @@ -93,21 +54,16 @@ The monadic case works similarly: Group Indices always satisfies `⊔𝕩 ←→ Group is closely related to the inverse of Indices, `/⁼`. In fact, inverse Indices called on the index argument gives the length of each group: ≠¨⊔ 2‿3‿1‿2 - [ 0 1 2 1 ] /⁼∧ 2‿3‿1‿2 - [ 0 1 2 1 ] A related fact is that calling Indices on the result of Group sorts all the indices passed to Group (removing any ¯1s). This is a kind of counting sort. /≠¨⊔ 2‿3‿1‿¯1‿2 - [ 1 2 2 3 ] Called dyadically, Group sorts the right argument according to the left and adds some extra structure. If this structure is removed with Join, Group can be thought of as a kind of sorting. ∾ 2‿3‿1‿¯1‿2 ⊔ "abcde" - [ caeb ] 2‿3‿1‿¯1‿2 {F←(0≤𝕨)⊸/ ⋄ 𝕨⍋⊸⊏○F𝕩} "abcde" - [ caeb ] Group can even be implemented with the same techniques as a bucket sort, which can be branchless and fast. @@ -118,66 +74,35 @@ The obvious application of Group is to group some values according to a known or ln ← "Phelps"‿"Latynina"‿"Bjørgen"‿"Andrianov"‿"Bjørndalen" co ← "US" ‿"SU" ‿"NO" ‿"SU" ‿"NO" ⥊˘ co ⍷⊸⊐⊸⊔ ln - ┌ - [ [ Phelps ] ] - [ [ Latynina ] [ Andrianov ] ] - [ [ Bjørgen ] [ Bjørndalen ] ] - ┘ If we would like a particular index to key correspondence, we can use a fixed left argument to Index Of. countries ← "IT"‿"JP"‿"NO"‿"SU"‿"US" countries ∾˘ co countries⊸⊐⊸⊔ ln - ┌ - [ IT ] [] - [ JP ] [] - [ NO ] [ [ Bjørgen ] [ Bjørndalen ] ] - [ SU ] [ [ Latynina ] [ Andrianov ] ] - [ US ] [ [ Phelps ] ] - ┘ However, this solution will fail if there are trailing keys with no values. To force the result to have a particular length you can append that length as a dummy index to each argument, then remove the last group after grouping. countries ↩ "IT"‿"JP"‿"NO"‿"SU"‿"US"‿"ZW" countries ∾˘ co countries{𝕗⊸⊐⊸(¯1↓⊔○(∾⟜(≠𝕗)))} ln - ┌ - [ IT ] [] - [ JP ] [] - [ NO ] [ [ Bjørgen ] [ Bjørndalen ] ] - [ SU ] [ [ Latynina ] [ Andrianov ] ] - [ US ] [ [ Phelps ] ] - [ ZW ] [] - ┘ ### Partitioning In examples we have been using a list of strings stranded together. Often it's more convenient to write the string with spaces, and split it up as part of the code. In this case, the index corresponding to each word (that is, each letter in the word) is the number of spaces before it. We can get this number of spaces from a prefix sum on the boolean list which is 1 at each space. ' '(+`∘=⊔⊢)"BQN uses notation as a tool of thought" - [ [ BQN ] [ uses ] [ notation ] [ as ] [ a ] [ tool ] [ of ] [ thought ] ] To avoid including spaces in the result, we should change the result index at each space to ¯1. Here is one way to do that: ' '((⊢-˜¬×+`)∘=⊔⊢)"BQN uses notation as a tool of thought" - [ [ BQN ] [ uses ] [ notation ] [ as ] [ a ] [ tool ] [ of ] [ thought ] ] A function with structural Under, such as `` {¯1¨⌾(𝕩⊸/)+`𝕩} ``, would also work. In other cases, we might want to split on spaces, so that words are separated by any number of spaces, and extra spaces don't affect the output. Currently our function makes a new word with each space: ' '((⊢-˜¬×+`)∘=⊔⊢)" string with spaces " - [ [] [] [ string ] [ with ] [] [ spaces ] ] However, trailing spaces are ignored because Group never produces trailing empty groups (to get them back we would use a dummy final character in the string). To avoid empty words, we should increase the word index only once per group of spaces. We can do this by taking the prefix sum of a list that is 1 only for a space with no space before it. To make such a list, we can use the [Windows](windows.md) function. We will extend our list with an initial 1 so that leading spaces will be ignored. Then we take windows of the same length as the original list: the first includes the dummy argument followed by a shifted copy of the list, and the second is the original list. These represent whether the previous and current characters are spaces; we want positions where the previous wasn't a space and the current is. ≍⟜((<´<˘)≠↕1∾⊢) ' '=" string with spaces " # All, then filtered, spaces - ┌ - 1 1 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 - 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ≍⟜(⊢-˜¬×+`∘((<´<˘)≠↕1∾⊢))' '=" string with spaces " # More processing - ┌ - 1 1 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 - ¯1 ¯1 0 0 0 0 0 0 ¯1 1 1 1 1 ¯1 ¯1 2 2 2 2 2 2 ¯1 ¯1 ¯1 - ┘ ' '((⊢-˜¬×+`∘((<´<˘)≠↕1∾⊢))∘=⊔⊢)" string with spaces " # Final result - [ [ string ] [ with ] [ spaces ] ] diff --git a/doc/join.md b/doc/join.md index c7603628..5a58aaac 100644 --- a/doc/join.md +++ b/doc/join.md @@ -7,12 +7,10 @@ Join (`∾`) is an extension of the monadic function [Raze](https://aplwiki.com/ Join can be used to combine several strings into a single string, like `array.join()` in Javascript (but it doesn't force the result to be a string). ∾"time"‿"to"‿"join"‿"some"‿"words" - [ timetojoinsomewords ] To join with a separator in between, we might prepend the separator to each string, then remove the leading separator after joining. Another approach would be to insert the separator array as an element between each pair of array elements before calling Join. 1↓∾' '∾¨"time"‿"to"‿"join"‿"some"‿"words" - [ time to join some words ] Join requires each element of its argument to be an array, and their ranks to match exactly. No rank extension is performed. @@ -24,21 +22,7 @@ Join requires each element of its argument to be an array, and their ranks to ma However, Join has higher-dimensional uses as well. Given a rank-`m` array of rank-`n` arrays (requiring `m≤n`), it will merge arrays along their first `m` axes. For example, if the argument is a matrix of matrices representing a [block matrix](https://en.wikipedia.org/wiki/Block_matrix), Join will give the corresponding unblocked matrix as its result. ⊢ m ← (3‿1∾⌜4‿2‿5) ⥊¨ 2‿3⥊↕6 - ┌ - ┌ ┌ ┌ - 0 0 0 0 1 1 2 2 2 2 2 - 0 0 0 0 1 1 2 2 2 2 2 - 0 0 0 0 1 1 2 2 2 2 2 - ┘ ┘ ┘ - [ 3 3 3 3 ] [ 4 4 ] [ 5 5 5 5 5 ] - ┘ ∾ m # Join all that together - ┌ - 0 0 0 0 1 1 2 2 2 2 2 - 0 0 0 0 1 1 2 2 2 2 2 - 0 0 0 0 1 1 2 2 2 2 2 - 3 3 3 3 4 4 5 5 5 5 5 - ┘ Join has fairly strict requirements on the shapes of its argument elements—although less strict than those of Merge, which requires they all have identical shape. Suppose the argument to Join has rank `m`. Each of its elements must have the same rank, `n`, which is at least `m`. The trailing shapes `m↓⟜≢¨𝕩` must all be identical (the trailing shape `m↓≢∾𝕩` of the result will match these shapes as well). The other entries in the leading shapes need not be the same, but the shape of an element along a particular axis must depend only on the location of the element along that axis in the full array. For a list argument this imposes no restriction, since the one leading shape element is allowed to depend on position along the only axis. But for higher ranks the structure quickly becomes more rigid. diff --git a/doc/logic.md b/doc/logic.md index 13a9c3b2..1e25fd57 100644 --- a/doc/logic.md +++ b/doc/logic.md @@ -25,21 +25,10 @@ Note that `¬⁼ ←→ ¬`, since when applying `¬` twice the first added 1 wi We can form truth tables including the non-integer value one-half: ¬ 0‿0.5‿1 - [ 1 0.5 0 ] ∧⌜˜ 0‿0.5‿1 - ┌ - 0 0 0 - 0 0.25 0.5 - 0 0.5 1 - ┘ ∨⌜˜ 0‿0.5‿1 - ┌ - 0 0.5 1 - 0.5 0.75 1 - 1 1 1 - ┘ As with logical And and Or, any value and 0 is 0, while any value or 1 is 1. The other boolean values give the identity elements for the two functions: 1 and any value gives that value, as does 0 or the value. diff --git a/doc/windows.md b/doc/windows.md index e82b9e6b..a60e1ae0 100644 --- a/doc/windows.md +++ b/doc/windows.md @@ -11,20 +11,13 @@ The Window function replaces APL's Windowed Reduction, J's more general Infix op We'll start with the one-axis case. Here Window's left argument is a number between `0` and `1+≠𝕩`. The result is composed of slices of `𝕩` (contiguous sections of major cells) with length `𝕨`, starting at each possible index in order. 5↕"abcdefg" - ┌ - abcde - bcdef - cdefg - ┘ There are `1+(≠𝕩)-𝕨`, or `(≠𝕩)¬𝕨`, of these sections, because the starting index must be at least `0` and at most `(≠𝕩)-𝕨`. Another way to find this result is to look at the number of cells in or before a given slice: there are always `𝕨` in the slice and there are only `≠𝕩` in total, so the number of slices is the range spanned by these two endpoints. You can take a slice of an array `𝕩` that has length `l` and starts at index `i` using `l↑i↓𝕩` or `l↑i⌽𝕩`. The [Prefixes](prefixes.md) function returns all the slices that end at the end of the array (`(≠𝕩)=i+l`), and Suffixes gives the slices that start at the beginning (`i=0`). Windows gives yet another collection of slices: the ones that have a fixed length `l=𝕨`. Selecting one cell from its result gives you the slice starting at that cell's index: 2⊏5↕"abcdefg" - [ cdefg ] 5↑2↓"abcdefg" - [ cdefg ] Windows differs from Prefixes and Suffixes in that it doesn't add a layer of nesting (it doesn't enclose each slice). This is possible because the slices have a fixed size. @@ -33,26 +26,10 @@ Windows differs from Prefixes and Suffixes in that it doesn't add a layer of nes The above description applies to a higher-rank right argument. As an example, we'll look at two-row slices of a shape `3‿4` array. For convenience, we will enclose each slice. Note that slices always have the same rank as the argument array. <⎉2 2↕"0123"∾"abcd"≍"ABCD" - ┌ - ┌ ┌ - 0123 abcd - abcd ABCD - ┘ ┘ - ┘ Passing a list as the left argument to Windows takes slices along any number of leading axes. Here are all the shape `2‿2` slices: <⎉2 2‿2↕"0123"∾"abcd"≍"ABCD" - ┌ - ┌ ┌ ┌ - 01 12 23 - ab bc cd - ┘ ┘ ┘ - ┌ ┌ ┌ - ab bc cd - AB BC CD - ┘ ┘ ┘ - ┘ The slices are naturally arranged along multiple dimensions according to their starting index. Once again the equivalence `i⊏l↕x` ←→ `l↑i↓x` holds, provided `i` and `l` have the same length. @@ -69,46 +46,30 @@ Using [Group](group.md) we could also write `i⊑z` ←→ `𝕩⊑˜(𝕨∾○ Let's look at an earlier example, along with its transpose. {⟨𝕩,⍉𝕩⟩}5↕"abcdefg" - ┌ - ┌ ┌ - abcde abc - bcdef bcd - cdefg cde - ┘ def - efg - ┘ - ┘ Although the two arrays have different shapes, they are identical where they overlap. ≡○(3‿3⊸↑)⟜⍉5↕"abcdefg" - 1 In other words, the i'th element of slice j is the same as the j'th element of slice i: it is the `i+j`'th element of the argument. So transposing still gives a possible result of Windows, but with a different slice length. {(5↕𝕩)≡⍉(3↕𝕩)}"abcdefg" - 1 In general, we need a more complicated transpose—swapping the first set of `≠𝕨` axes with the second set. Note again the use of Span, our slice-length to slice-number converter. {((5‿6¬2‿2)↕𝕩) ≡ 2‿3⍉(2‿2↕𝕩)} ↕5‿6‿7 - 1 ## Applications Windows can be followed up with a reduction on each slice to give a windowed reduction. Here we take running sums of 3 values. +´˘3↕ ⟨2,6,0,1,4,3⟩ - [ 8 7 5 8 ] A common task is to pair elements, with an initial or final element so the total length stays the same. This can also be done with a pairwise reduction, but another good way (and more performant without special support in the interpreter) is to add the element and then use windows matching the original length. Here both methods are used to invert `` +` ``, which requires we take pairwise differences starting at initial value 0. -˜´˘2↕0∾ +` 3‿2‿1‿1 - [ 3 2 1 1 ] ((-˜´<˘)≠↕0∾⊢) +` 3‿2‿1‿1 - [ 3 2 1 1 ] This method extends to any number of initial elements. We can modify the running sum above to keep the length constant by starting with two zeros. ((+´<˘)≠↕(2⥊0)⊸∾) ⟨2,6,0,1,4,3⟩ - [ 2 8 8 7 5 8 ] |
