aboutsummaryrefslogtreecommitdiff
path: root/docs/doc/reverse.html
blob: 4fc5165a759716e714c331443132996cdbf9c62d (plain)
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<head>
  <link href="../favicon.ico" rel="shortcut icon" type="image/x-icon"/>
  <link href="../style.css" rel="stylesheet"/>
  <title>BQN: Reverse and Rotate</title>
</head>
<div class="nav"><a href="https://github.com/mlochbaum/BQN">BQN</a> / <a href="../index.html">main</a> / <a href="index.html">doc</a></div>
<h1 id="reverse-and-rotate">Reverse and Rotate</h1>
<p>The symbol <code><span class='Function'>⌽</span></code> indicates two different array transformations: with no left argument, it reverses the major cells of the array, but with a left argument, it rotates or cycles them around. These two possibilities, first put together in very early versions of APL, can't be considered restrictions or different views of some unifying function, but there are connections between them. Each returns an array with the same <a href="shape.html">shape</a> and all the same elements as <code><span class='Value'>𝕩</span></code>, possibly in a different arrangement. And elements that start out next to each other in <code><span class='Value'>𝕩</span></code> generally stay next to each otherβ€”always, if we consider an element on one edge to be next to the one opposite to it. One might think of them as <a href="https://en.wikipedia.org/wiki/Isometry">isometries</a> preserving a discrete subgroup of the torus, if one were inclined to think such things. On major cells, the two functions decompose the <a href="https://en.wikipedia.org/wiki/Dihedral_group">dihedral group</a> okay I'll stop.</p>
<p>Many uses of Rotate in APL are better handled by <a href="shift.html">shift</a> functions in BQN. If there's no reason to treat the data as cyclic or periodic, it's best to avoid Rotate.</p>
<h2 id="reverse">Reverse</h2>
<p>There's not too much to say about Reverse. It puts the elements of a list the other way around, or more generally the major cells of an array.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oy9ICJhYmNkZWZnIgoK4oy9ID4iYWIi4oC/ImNkIuKAvyJlZiIKCuKMvSAnYyc=">↗️</a><pre>    <span class='Function'>⌽</span> <span class='String'>&quot;abcdefg&quot;</span>
"gfedcba"

    <span class='Function'>⌽</span> <span class='Function'>&gt;</span><span class='String'>&quot;ab&quot;</span><span class='Ligature'>β€Ώ</span><span class='String'>&quot;cd&quot;</span><span class='Ligature'>β€Ώ</span><span class='String'>&quot;ef&quot;</span>
β”Œβ”€    
β•΅"ef  
  cd  
  ab" 
     β”˜

    <span class='Function'>⌽</span> <span class='String'>'c'</span>
'c'
</pre>
<p>You can't reverse an atom or rank-0 array because it has no axes to reverse along, or it could be said no ordering to reverse.</p>
<p>To reverse along an axis other than the first, use Cells (<code><span class='Modifier'>˘</span></code>) or Rank (<code><span class='Modifier2'>βŽ‰</span></code>).</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oy9y5ggPiJhYiLigL8iY2Qi4oC/ImVmIg==">↗️</a><pre>    <span class='Function'>⌽</span><span class='Modifier'>˘</span> <span class='Function'>&gt;</span><span class='String'>&quot;ab&quot;</span><span class='Ligature'>β€Ώ</span><span class='String'>&quot;cd&quot;</span><span class='Ligature'>β€Ώ</span><span class='String'>&quot;ef&quot;</span>
β”Œβ”€    
β•΅"ba  
  dc  
  fe" 
     β”˜
</pre>
<p>Reverse is useful for <a href="fold.html">folding</a> left to right instead of right to left.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omN4peLPCDCtCAgICJhYmNkIiAgIyBSaWdodCB0byBsZWZ0CgriiY3il4s8y5zCtCDijL0gImFiY2QiICAjIExlZnQgdG8gcmlnaHQ=">↗️</a><pre>    <span class='Function'>≍</span><span class='Modifier2'>β—‹</span><span class='Function'>&lt;</span> <span class='Modifier'>Β΄</span>   <span class='String'>&quot;abcd&quot;</span>  <span class='Comment'># Right to left
</span>⟨ 'a' ⟨ 'b' "cd" ⟩ ⟩

    <span class='Function'>≍</span><span class='Modifier2'>β—‹</span><span class='Function'>&lt;</span><span class='Modifier'>˜´</span> <span class='Function'>⌽</span> <span class='String'>&quot;abcd&quot;</span>  <span class='Comment'># Left to right
</span>⟨ ⟨ "ab" 'c' ⟩ 'd' ⟩
</pre>
<p>Reverse is its own <a href="undo.html">inverse</a> <code><span class='Function'>⌽</span><span class='Modifier'>⁼</span></code>. As a result, <code><span class='Function'>𝔽</span><span class='Modifier2'>⌾</span><span class='Function'>⌽</span></code> reverses the argument, applies <code><span class='Function'>𝔽</span></code>, and reverses again. It's a particularly useful pattern with <a href="scan.html">Scan</a>, as it allows scanning from the end rather than the beginning of the array. For example, <code><span class='Function'>∨</span><span class='Modifier'>`</span></code> on a list of booleans changes all bits after the first <code><span class='Number'>1</span></code> to <code><span class='Number'>1</span></code>, but <code><span class='Function'>∨</span><span class='Modifier'>`</span><span class='Modifier2'>⌾</span><span class='Function'>⌽</span></code> does this to all bits before the last <code><span class='Number'>1</span></code>.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oioYCAgIDDigL8w4oC/MeKAvzDigL8w4oC/MeKAvzAKCuKIqGDijL7ijL0gMOKAvzDigL8x4oC/MOKAvzDigL8x4oC/MA==">↗️</a><pre>    <span class='Function'>∨</span><span class='Modifier'>`</span>   <span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>1</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>1</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span>
⟨ 0 0 1 1 1 1 1 ⟩

    <span class='Function'>∨</span><span class='Modifier'>`</span><span class='Modifier2'>⌾</span><span class='Function'>⌽</span> <span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>1</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>1</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span>
⟨ 1 1 1 1 1 1 0 ⟩
</pre>
<h2 id="rotate">Rotate</h2>
<p>Rotate moves elements in a list around cyclically. It can also rotate any number of axes of the argument array by different amounts at once. That's discussed in the next section; for now we'll stick to a single number for <code><span class='Value'>𝕨</span></code>. It has to be an integer, and <code><span class='Value'>𝕩</span></code> has to be an array with at least one axis.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MiDijL0gInJvdGF0ZSIKCjIgKOKKoiDiiY3il4s8IOKMvSkgNeKAvzLipYoicm90YXRlQ0VMTCIKCjIg4oy9ICdjJyAgIyBObyBheGVzIHRvIHJvdGF0ZQ==">↗️</a><pre>    <span class='Number'>2</span> <span class='Function'>⌽</span> <span class='String'>&quot;rotate&quot;</span>
"tatero"

    <span class='Number'>2</span> <span class='Paren'>(</span><span class='Function'>⊒</span> <span class='Function'>≍</span><span class='Modifier2'>β—‹</span><span class='Function'>&lt;</span> <span class='Function'>⌽</span><span class='Paren'>)</span> <span class='Number'>5</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span><span class='Function'>β₯Š</span><span class='String'>&quot;rotateCELL&quot;</span>
β”Œβ”€               
Β· β”Œβ”€     β”Œβ”€      
  β•΅"ro   β•΅"te    
    ta     CE    
    te     LL    
    CE     ro    
    LL"    ta"   
       β”˜      β”˜  
                β”˜

    <span class='Number'>2</span> <span class='Function'>⌽</span> <span class='String'>'c'</span>  <span class='Comment'># No axes to rotate
</span>ERROR
</pre>
<p>Elements are always rotated to the left, so that entry <code><span class='Value'>i</span></code> of the result is entry <code><span class='Value'>𝕨</span><span class='Function'>+</span><span class='Value'>i</span></code> of the argumentβ€”or rather, entry <code><span class='Paren'>(</span><span class='Function'>β‰ </span><span class='Value'>𝕩</span><span class='Paren'>)</span><span class='Function'>|</span><span class='Value'>𝕨</span><span class='Function'>+</span><span class='Value'>i</span></code> to enable elements to cycle around. This can be seen directly by using the <a href="range.html">range</a> <code><span class='Function'>↕</span><span class='Value'>n</span></code> as an argument: then the value of <code><span class='Value'>𝕩</span></code> at index <code><span class='Value'>i</span></code> is just <code><span class='Value'>i</span></code>.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MiDijL0g4oaVNg==">↗️</a><pre>    <span class='Number'>2</span> <span class='Function'>⌽</span> <span class='Function'>↕</span><span class='Number'>6</span>
⟨ 2 3 4 5 0 1 ⟩
</pre>
<p>The rotation <code><span class='Paren'>(</span><span class='Function'>β‰ </span><span class='Value'>𝕩</span><span class='Paren'>)</span><span class='Function'>⌽</span><span class='Value'>𝕩</span></code> moves each element the entire <a href="shape.html">length</a> of <code><span class='Value'>𝕩</span></code>, which just places it back where it started. In fact, adding <code><span class='Function'>β‰ </span><span class='Value'>𝕩</span></code> to the rotation amount never changes the behavior or the rotation. In terms of indices, this is because <code><span class='Paren'>(</span><span class='Function'>β‰ </span><span class='Value'>𝕩</span><span class='Paren'>)</span><span class='Function'>|</span><span class='Paren'>(</span><span class='Function'>β‰ </span><span class='Value'>𝕩</span><span class='Paren'>)</span><span class='Function'>+</span><span class='Value'>a</span></code> is <code><span class='Value'>a</span></code>.</p>
<p>To rotate the other way, use a negative left argument (so <code><span class='Function'>-</span><span class='Modifier2'>⊸</span><span class='Function'>⌽</span></code> is a simple way to write &quot;reverse rotate&quot;). This will always be the same as some leftwards rotation, since <code><span class='Paren'>(</span><span class='Function'>-</span><span class='Value'>r</span><span class='Paren'>)</span><span class='Function'>⌽</span><span class='Value'>𝕩</span></code> is <code><span class='Paren'>((</span><span class='Function'>β‰ </span><span class='Value'>𝕩</span><span class='Paren'>)</span><span class='Function'>-</span><span class='Value'>r</span><span class='Paren'>)</span><span class='Function'>⌽</span><span class='Value'>𝕩</span></code>, but could be more convenient.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=wq8yIOKMvSAicm90YXRlIg==">↗️</a><pre>    <span class='Number'>Β―2</span> <span class='Function'>⌽</span> <span class='String'>&quot;rotate&quot;</span>
"terota"
</pre>
<h3 id="multiple-axes">Multiple axes</h3>
<p>The easiest way to rotate a later array axis is usually to use the Cells (<code><span class='Modifier'>˘</span></code>) or Rank (<code><span class='Modifier2'>βŽ‰</span></code>) modifier.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIHRhYiDihpAgM+KAvzTipYoiYWJjZEFCQ0QwMTIzIgoKMSDijL3LmCB0YWIgICMgUm90YXRlIHRoZSBzZWNvbmQgYXhpcw==">↗️</a><pre>    <span class='Function'>⊒</span> <span class='Value'>tab</span> <span class='Gets'>←</span> <span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>4</span><span class='Function'>β₯Š</span><span class='String'>&quot;abcdABCD0123&quot;</span>
β”Œβ”€      
β•΅"abcd  
  ABCD  
  0123" 
       β”˜

    <span class='Number'>1</span> <span class='Function'>⌽</span><span class='Modifier'>˘</span> <span class='Value'>tab</span>  <span class='Comment'># Rotate the second axis
</span>β”Œβ”€      
β•΅"bcda  
  BCDA  
  1230" 
       β”˜
</pre>
<p>Rotate also allows <code><span class='Value'>𝕨</span></code> to be a list (or unit array) of integers, in which case they're matched with <a href="leading.html">leading axes</a> of <code><span class='Value'>𝕩</span></code>. This means the length of <code><span class='Value'>𝕨</span></code> can't be larger than the rank of <code><span class='Value'>𝕩</span></code>, or there wouldn't be enough axes to match. This rule also explains why <code><span class='Value'>𝕩</span></code> has to have rank one or more when <code><span class='Value'>𝕨</span></code> is an atom, because <code><span class='Value'>𝕨</span></code> is treated as the one-element list <code><span class='Function'>β₯Š</span><span class='Value'>𝕨</span></code> in that case.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=M+KAvzTigL8yIOKMvSAianVzdCBhIGxpc3Qi">↗️</a><pre>    <span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>4</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span> <span class='Function'>⌽</span> <span class='String'>&quot;just a list&quot;</span>
ERROR
</pre>
<p>The expression below rotates the first (vertical) axis of <code><span class='Value'>tab</span></code> by one element, and second by two. So the line of capital letters goes from being one away from the top, up to the top, and the column with <code><span class='String'>'2'</span></code> goes from horizontal index 2 to index 0.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MeKAvzIg4oy9IHRhYg==">↗️</a><pre>    <span class='Number'>1</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span> <span class='Function'>⌽</span> <span class='Value'>tab</span>
β”Œβ”€      
β•΅"CDAB  
  2301  
  cdab" 
       β”˜
</pre>
<p>The vertical and horizontal rotations are independent, and could also be done with two <code><span class='Function'>⌽</span></code>s and a <code><span class='Modifier'>˘</span></code>. The multi-axis form is more convenient, and can potentially be evaluated faster that multiple separate rotations in the cases where it shows up.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MSDijL0gMiDijL3LmCB0YWI=">↗️</a><pre>    <span class='Number'>1</span> <span class='Function'>⌽</span> <span class='Number'>2</span> <span class='Function'>⌽</span><span class='Modifier'>˘</span> <span class='Value'>tab</span>
β”Œβ”€      
β•΅"CDAB  
  2301  
  cdab" 
       β”˜
</pre>