((«¬∘∧⊢)' '=⊢)⊸/
This works by building a boolean mask of spaces, and converting it to a mask of 'is a space, preceded by a space', negates that, and replicates out by that inverted mask (i.e. is not a space preceded by a space):Here's stepping through it with some input.
(' '=⊢) "this is a sentence with many spaces"
⟨ 0 0 0 0 1 1 0 0 1 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 ⟩
(«' '=⊢) "this is a sentence with many spaces"
⟨ 0 0 0 1 1 0 0 1 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 ⟩
((«∧⊢)' '=⊢) "this is a sentence with many spaces"
⟨ 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 ⟩
((«¬∘∧⊢)' '=⊢) "this is a sentence with many spaces"
⟨ 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 1 1 1 1 1 1 1 ⟩
((«¬∘∧⊢)' '=⊢)⊸/ "this is a sentence with many spaces"
"this is a sentence with many spaces" (¬∘∧⟜«' '=⊢)⊸/
(¬·«⊸∧' '=⊢)⊸/
{¬«⊸∧' '=x}⊸/ # should have double-struck x here (U+1D569), but hn removes it (1 ∾˜ " "⊸(¬∘⍷))⊸/
which removes the first space of each occurrence of double spacingIt's also worth thinking through how all 16 boolean operators work on boolean masks. E.g. what do msk≠msk2, msk<msk2, msk≤msk2 etc. mean? In my experience, the important part is to find crisp domain-specific meanings for these patterns. In general, really, that's how you gain APL fluency. In the same way that reading fluency requires chunking so that letters "disappear", APL fluency requires familiarity with semantic phrases, so you stop thinking in the individual symbols.
[0]:https://blog.wilsonb.com/posts/2023-07-24-suggestivity-and-i...
- ⍪⍤2 add padding on top of surface of bit mask of water
- 2>⌿⍤2 identify where surface is exposed by seeing if air comes after water vertically
- ⍉l⊤⍸∊ collapse and get where water is in chunk position format row-by-row
s:"this is a sentence with many spaces"
s@&~0&':s=" "