aboutsummaryrefslogtreecommitdiff
path: root/docs/doc/take.html
blob: bf54a147f3365b4ff65553e4a66bf15d9443bea9 (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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<head>
  <link href="../favicon.ico" rel="shortcut icon" type="image/x-icon"/>
  <link href="../style.css" rel="stylesheet"/>
  <title>BQN: Take and Drop</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="take-and-drop">Take and Drop</h1>
<svg viewBox='-156.8 -64 672 204.8'>
  <g fill='currentColor' stroke-linecap='round' text-anchor='middle' font-family='BQN,monospace'>
    <rect class='code' stroke-width='1.5' rx='12' x='-100.8' y='-40' width='560' height='156.8'/>
    <g font-size='25px'>
      <text dy='0.32em' x='-67.2' y='0'><tspan class='Value'>𝕩</tspan></text>
      <text dy='0.32em' x='112' y='80'><tspan class='Number'>5</tspan><tspan class='Function'>↑</tspan><tspan class='Value'>𝕩</tspan></text>
      <text dy='0.32em' x='336' y='80'><tspan class='Number'>5</tspan><tspan class='Function'>↓</tspan><tspan class='Value'>𝕩</tspan></text>
    </g>
    <g font-size='21px'>
      <text dy='0.32em' x='0' y='0'><tspan class='String'>'s'</tspan></text>
      <text dy='0.32em' x='56' y='0'><tspan class='String'>'t'</tspan></text>
      <text dy='0.32em' x='112' y='0'><tspan class='String'>'a'</tspan></text>
      <text dy='0.32em' x='168' y='0'><tspan class='String'>'r'</tspan></text>
      <text dy='0.32em' x='224' y='0'><tspan class='String'>'t'</tspan></text>
      <text dy='0.32em' x='280' y='0'><tspan class='String'>'e'</tspan></text>
      <text dy='0.32em' x='336' y='0'><tspan class='String'>'n'</tspan></text>
      <text dy='0.32em' x='392' y='0'><tspan class='String'>'d'</tspan></text>
    </g>
    <g class='bluegreen' stroke-width='3' style='fill:none' opacity='0.8'><path d='M-22.4 -15l-6 15l6 15M414.4 -15l6 15l-6 15'/></g>
    <g class='green' stroke-width='3' style='fill:none' opacity='0.8'>
      <path d='M201.6 31.2l25 12l-25 12M302.4 31.2l-25 12l25 12'/>
      <line x1='-16.8' x2='226.6' y1='43.2' y2='43.2'/>
      <line x1='277.4' x2='408.8' y1='43.2' y2='43.2'/>
    </g>
    <g class='red' stroke-width='2.5' stroke-dasharray='9 9' opacity='0.9'><line x1='252' x2='252' y1='-24' y2='96'/></g>
  </g>
</svg>

<p>The basic idea of Take (<code><span class='Function'>↑</span></code>) is to get the first few elements of a list, while Drop (<code><span class='Function'>↓</span></code>) removes those and returns the rest. Then they are extended in like a billion ways.</p>
<ul>
<li><code><span class='Value'>𝕩</span></code> can be an atom, or array of any rank (the result will be an array).</li>
<li><code><span class='Value'>𝕨</span></code> can be negative to take or drop from the end instead of the beginning.</li>
<li>For Take, if <code><span class='Value'>𝕨</span></code> is larger than the length of <code><span class='Value'>𝕩</span></code>, then fills are added.</li>
<li><code><span class='Value'>𝕨</span></code> can have multiple numbers corresponding to leading axes of <code><span class='Value'>𝕩</span></code>.</li>
<li><code><span class='Value'>𝕨</span></code> is allowed to be longer than the rank of <code><span class='Value'>𝕩</span></code>; <code><span class='Value'>𝕩</span></code> will be extended to fit.</li>
</ul>
<p>These extensions can be combined as well, so there are a lot of possibilities. A good picture to have in mind is cutting out a corner of the array <code><span class='Value'>𝕩</span></code>. This is because the result <code><span class='Value'>𝕨</span><span class='Function'>↑</span><span class='Value'>𝕩</span></code> or <code><span class='Value'>𝕨</span><span class='Function'>↓</span><span class='Value'>𝕩</span></code> always aligns with one side of <code><span class='Value'>𝕩</span></code> along each axis, so it aligns with the corner where those sides meet.</p>
<p>The result <code><span class='Value'>d</span><span class='Function'>↓</span><span class='Value'>𝕩</span></code> is always the same as <code><span class='Value'>t</span><span class='Function'>↑</span><span class='Value'>𝕩</span></code> for some other argument <code><span class='Value'>t</span></code>, but computing <code><span class='Value'>t</span></code> wouldn't be too convenient. The reverse isn't true: only Take can insert fills, so results that include them can't come from Drop.</p>
<h2 id="one-axis">One axis</h2>
<p>Let's start with a natural number <code><span class='Value'>𝕨</span></code>. Take gives the first <code><span class='Value'>𝕨</span></code> major cells of <code><span class='Value'>𝕩</span></code> (or elements of a list), while Drop gives all but the first <code><span class='Value'>𝕨</span></code>.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=NCDihpEgInRha2UgYW5kIGRyb3AiCjQg4oaTICJ0YWtlIGFuZCBkcm9wIgoKMSDihpMgPiJtYWoi4oC/Im9yYyLigL8iZWxsIg==">↗️</a><pre>    <span class='Number'>4</span> <span class='Function'>↑</span> <span class='String'>&quot;take and drop&quot;</span>
"take"
    <span class='Number'>4</span> <span class='Function'>↓</span> <span class='String'>&quot;take and drop&quot;</span>
" and drop"

    <span class='Number'>1</span> <span class='Function'>↓</span> <span class='Function'>&gt;</span><span class='String'>&quot;maj&quot;</span><span class='Ligature'>β€Ώ</span><span class='String'>&quot;orc&quot;</span><span class='Ligature'>β€Ώ</span><span class='String'>&quot;ell&quot;</span>
β”Œβ”€     
β•΅"orc  
  ell" 
      β”˜
</pre>
<p>If <code><span class='Value'>𝕨</span></code> is too large it's usually not a problem. For Take, fill elements are added to the end to bring <code><span class='Value'>𝕩</span></code> up to the required lengthβ€”although this <em>will</em> fail if <code><span class='Value'>𝕩</span></code> has no fill element. For Drop, the result is an empty array.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oaVNgoKMTAg4oaRIOKGlTYKCjEwIOKGkyDihpU2CgriiaIgNSDihpMg4oaVM+KAvznigL8y">↗️</a><pre>    <span class='Function'>↕</span><span class='Number'>6</span>
⟨ 0 1 2 3 4 5 ⟩

    <span class='Number'>10</span> <span class='Function'>↑</span> <span class='Function'>↕</span><span class='Number'>6</span>
⟨ 0 1 2 3 4 5 0 0 0 0 ⟩

    <span class='Number'>10</span> <span class='Function'>↓</span> <span class='Function'>↕</span><span class='Number'>6</span>
⟨⟩

    <span class='Function'>β‰’</span> <span class='Number'>5</span> <span class='Function'>↓</span> <span class='Function'>↕</span><span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>9</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span>
⟨ 0 9 2 ⟩
</pre>
<p>If <code><span class='Value'>𝕩</span></code> is an atom or unit array, it's converted to a list first. For Take this is useful to make an array of mostly fills; for Drop it's pretty much useless.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MTAg4oaRIDkKCjMg4oaTIDwiZWxlbWVudCI=">↗️</a><pre>    <span class='Number'>10</span> <span class='Function'>↑</span> <span class='Number'>9</span>
⟨ 9 0 0 0 0 0 0 0 0 0 ⟩

    <span class='Number'>3</span> <span class='Function'>↓</span> <span class='Function'>&lt;</span><span class='String'>&quot;element&quot;</span>
⟨⟩
</pre>
<h3 id="negative-argument">Negative argument</h3>
<p>If <code><span class='Value'>𝕨</span></code> is negative then wraps around the other side to take or drop from the end of <code><span class='Value'>𝕩</span></code>. It's a lot like negative indices in <a href="select.html">Select</a> (<code><span class='Function'>⊏</span></code>), but while negative indices are asymmetricβ€”<code><span class='Number'>0</span></code> is the first entry but <code><span class='Number'>Β―1</span></code> is the lastβ€”this case is symmetric. It's because the place to cut is always <em>before</em> the index <code><span class='Value'>𝕨</span></code>, cancelling out the negative index asymmetry.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MyDihpEgImFiY2RlRURDQkEiCgrCrzMg4oaRICJhYmNkZUVEQ0JBIiAgIyBMYXN0IHRocmVlCgrCrzMg4oaTICJhYmNkZUVEQ0JBIiAgIyBBbGwgYnV0IHRoZSBsYXN0IHRocmVl">↗️</a><pre>    <span class='Number'>3</span> <span class='Function'>↑</span> <span class='String'>&quot;abcdeEDCBA&quot;</span>
"abc"

    <span class='Number'>Β―3</span> <span class='Function'>↑</span> <span class='String'>&quot;abcdeEDCBA&quot;</span>  <span class='Comment'># Last three
</span>"CBA"

    <span class='Number'>Β―3</span> <span class='Function'>↓</span> <span class='String'>&quot;abcdeEDCBA&quot;</span>  <span class='Comment'># All but the last three
</span>"abcdeED"
</pre>
<p>What about <code><span class='Number'>0</span></code>? It behaves like it's both positive <em>and</em> negative. For Take, the first 0 and last 0 cells are indistinguishable, because they're both empty. For Drop, if you remove 0 cells it doesn't matter whether you start at the front or the back, because you're not going to do anything either way.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MCDihpEgNOKAvzPigL8yICAjIE5vdGhpbmcKCjAg4oaTIDTigL8z4oC/MiAgIyBFdmVyeXRoaW5n">↗️</a><pre>    <span class='Number'>0</span> <span class='Function'>↑</span> <span class='Number'>4</span><span class='Ligature'>β€Ώ</span><span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span>  <span class='Comment'># Nothing
</span>⟨⟩

    <span class='Number'>0</span> <span class='Function'>↓</span> <span class='Number'>4</span><span class='Ligature'>β€Ώ</span><span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span>  <span class='Comment'># Everything
</span>⟨ 4 3 2 ⟩
</pre>
<p>If <code><span class='Function'>|</span><span class='Value'>𝕨</span></code> is too large, then Take will insert fills at the beginning to keep the result aligned with <code><span class='Value'>𝕩</span></code> at the end. Drop returns an empty array as in the positive case. So unlike <a href="reverse.html">Rotate</a> (<code><span class='Function'>⌽</span></code>), which is completely cyclical, Take and Drop work cyclically only around 0.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=wq82IOKGkSAieHki">↗️</a><pre>    <span class='Number'>Β―6</span> <span class='Function'>↑</span> <span class='String'>&quot;xy&quot;</span>
"    xy"
</pre>
<h2 id="multiple-axes">Multiple axes</h2>
<p>In the general case <code><span class='Value'>𝕨</span></code> is a list of integers. They're matched with the leading axes of <code><span class='Value'>𝕩</span></code>, so that each affects one axis independently from the others.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIG0g4oaQICgxMMOX4oaVNSkgK+KMnCDihpU3CgrCrzTigL8yIOKGkSBtICAjIExhc3QgZm91ciByb3dzOyBmaXJzdCB0d28gY29sdW1ucwoKwq804oC/MiDihpMgbQ==">↗️</a><pre>    <span class='Function'>⊒</span> <span class='Value'>m</span> <span class='Gets'>←</span> <span class='Paren'>(</span><span class='Number'>10</span><span class='Function'>×↕</span><span class='Number'>5</span><span class='Paren'>)</span> <span class='Function'>+</span><span class='Modifier'>⌜</span> <span class='Function'>↕</span><span class='Number'>7</span>
β”Œβ”€                      
β•΅  0  1  2  3  4  5  6  
  10 11 12 13 14 15 16  
  20 21 22 23 24 25 26  
  30 31 32 33 34 35 36  
  40 41 42 43 44 45 46  
                       β”˜

    <span class='Number'>Β―4</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span> <span class='Function'>↑</span> <span class='Value'>m</span>  <span class='Comment'># Last four rows; first two columns
</span>β”Œβ”€       
β•΅ 10 11  
  20 21  
  30 31  
  40 41  
        β”˜

    <span class='Number'>Β―4</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span> <span class='Function'>↓</span> <span class='Value'>m</span>
β”Œβ”€           
β•΅ 2 3 4 5 6  
            β”˜
</pre>
<p>Now Take and Drop taken together don't include the whole array. Take includes the elements that are selected on <em>every</em> axis, while Drop excludes the ones selected on <em>any</em> axis. They are opposite corners that meet at some point in the middle of the array (here, at the spot between <code><span class='Number'>2</span></code> and <code><span class='Number'>11</span></code>).</p>
<p>Any integer values at all can be used, in any combination. Here one axis is shortened and the other's padded with fills. The result of Take has shape <code><span class='Function'>|</span><span class='Value'>𝕨</span></code>, maybe plus some trailing axes from <code><span class='Value'>𝕩</span></code>. Of course, if that's too big for your available memory, your BQN implementation probably can't compute it for you!</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=M+KAv8KvMTIg4oaRIG0KCuKJoiA54oC/wq80IOKGkSDihpU34oC/NuKAvzUgICMgVHJhaWxpbmcgc2hhcGUgZXhhbXBsZQ==">↗️</a><pre>    <span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>Β―12</span> <span class='Function'>↑</span> <span class='Value'>m</span>
β”Œβ”€                                
β•΅ 0 0 0 0 0  0  1  2  3  4  5  6  
  0 0 0 0 0 10 11 12 13 14 15 16  
  0 0 0 0 0 20 21 22 23 24 25 26  
                                 β”˜

    <span class='Function'>β‰’</span> <span class='Number'>9</span><span class='Ligature'>β€Ώ</span><span class='Number'>Β―4</span> <span class='Function'>↑</span> <span class='Function'>↕</span><span class='Number'>7</span><span class='Ligature'>β€Ώ</span><span class='Number'>6</span><span class='Ligature'>β€Ώ</span><span class='Number'>5</span>  <span class='Comment'># Trailing shape example
</span>⟨ 9 4 5 ⟩
</pre>
<p>If the rank of <code><span class='Value'>𝕩</span></code> is <em>smaller</em> than the length of <code><span class='Value'>𝕨</span></code>, then length-1 axes are added to the beginning until it's equal. Mostly this will be used with Take when <code><span class='Value'>𝕩</span></code> is a unit, producing an array that contains <code><span class='Value'>𝕩</span></code> and a lot of fills.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=M+KAvzQg4oaRIDwx4oC/MQ==">↗️</a><pre>    <span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>4</span> <span class='Function'>↑</span> <span class='Function'>&lt;</span><span class='Number'>1</span><span class='Ligature'>β€Ώ</span><span class='Number'>1</span>
β”Œβ”€                                 
β•΅ ⟨ 1 1 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩  
  ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩  
  ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩  
                                  β”˜
</pre>
<p>This property also enables a nice little trick with Drop. If <code><span class='Value'>𝕨</span></code> is a list of zeros, Drop won't do anythingβ€”except extend the rank of <code><span class='Value'>𝕩</span></code>. So <code><span class='Paren'>(</span><span class='Value'>r</span><span class='Function'>β₯Š</span><span class='Number'>0</span><span class='Paren'>)</span><span class='Function'>↓</span><span class='Value'>a</span></code>, or <code><span class='Value'>r</span> <span class='Function'>β₯Š</span><span class='Modifier2'>⟜</span><span class='Number'>0</span><span class='Modifier2'>⊸</span><span class='Function'>↓</span> <span class='Value'>a</span></code>, ensures <code><span class='Value'>a</span></code> is an array with rank at least <code><span class='Value'>r</span></code> but doesn't change any of the elements. As a special case, <code><span class='Bracket'>⟨⟩</span><span class='Function'>↓</span><span class='Value'>v</span></code> <a href="enclose.html">Encloses</a> an atom argument but otherwise has no effect.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omiICgz4qWKMCkg4oaTIDMKCuKJoiAoM+KlijApIOKGkyDihpUzCgriiaIgKDPipYowKSDihpMg4oaVNeKAvzTigL8z4oC/Mg==">↗️</a><pre>    <span class='Function'>β‰’</span> <span class='Paren'>(</span><span class='Number'>3</span><span class='Function'>β₯Š</span><span class='Number'>0</span><span class='Paren'>)</span> <span class='Function'>↓</span> <span class='Number'>3</span>
⟨ 1 1 1 ⟩

    <span class='Function'>β‰’</span> <span class='Paren'>(</span><span class='Number'>3</span><span class='Function'>β₯Š</span><span class='Number'>0</span><span class='Paren'>)</span> <span class='Function'>↓</span> <span class='Function'>↕</span><span class='Number'>3</span>
⟨ 1 1 3 ⟩

    <span class='Function'>β‰’</span> <span class='Paren'>(</span><span class='Number'>3</span><span class='Function'>β₯Š</span><span class='Number'>0</span><span class='Paren'>)</span> <span class='Function'>↓</span> <span class='Function'>↕</span><span class='Number'>5</span><span class='Ligature'>β€Ώ</span><span class='Number'>4</span><span class='Ligature'>β€Ώ</span><span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span>
⟨ 5 4 3 2 ⟩
</pre>