Euler #1: Multiples of 3 or 5
Let’s solve Euler #1 (https://projecteuler.net/problem=1) in
BQN.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
We can compute the remainder with 𝕨 | 𝕩: Modulus.
3|6
0
3|10
1
We can check if this remainder is 0 to see if the number is “divisible” by another with 𝕨 = 𝕩: Equal To.
0= 3|6
1
0= 3|10
0
We can combine values into an array with 𝕨 ⋈ 𝕩: Pair.
3|10 ⋈ 5|10
⟨ 1 0 ⟩
We can bind 3 to the modulus operator with 𝕗⊸𝔾 𝕩: Bind Left, then apply it to a value.
3⊸|
3⊸|
3⊸| 10
1
We can pair two of these bindings with 𝕨 ⋈ 𝕩: Pair.
3⊸| ⋈ 5⊸|
3⊸|⋈5⊸|
We can then apply it to a value.
(3⊸| ⋈ 5⊸|) 10
⟨ 1 0 ⟩
We can check if the values in the resulting array are 0.
0= (3⊸| ⋈ 5⊸|) 10
⟨ 0 1 ⟩
0 is false (10 is not divisible by three). 1 is true (10 is divisible by five).
You can create arrays with ‿: Strand. You can also use , or ⋄: Separator, but I like Strand.
1‿2‿3‿4
⟨ 1 2 3 4 ⟩
⟨ 1, 2, 3, 4 ⟩
⟨ 1 2 3 4 ⟩
⟨ 1 ⋄ 2 ⋄ 3 ⋄ 4 ⟩
⟨ 1 2 3 4 ⟩
We can use 𝔽¨ 𝕩, 𝕨 𝔽¨ 𝕩: Each to apply a function (such as √ 𝕩: Square root) to each item in a list.
√2
1.4142135623730951
√4
2
√10
3.1622776601683795
√¨ 2‿4‿10
⟨ 1.4142135623730951 2 3.1622776601683795 ⟩
We can use 𝔽¨ 𝕩, 𝕨 𝔽¨ 𝕩: Each to apply our divisibility checks to a list of numbers.
(3⊸| ⋈ 5⊸|)¨ 1‿2‿3‿4
⟨ ⟨ 1 1 ⟩ ⟨ 2 2 ⟩ ⟨ 0 3 ⟩ ⟨ 1 4 ⟩ ⟩
We can check for all the values that equal to 0.
0= (3⊸| ⋈ 5⊸|)¨ 1‿2‿3‿4
⟨ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 1 0 ⟩ ⟨ 0 0 ⟩ ⟩
1 is neither divisible by 3 nor 5 (⟨ 0 0 ⟩). 3 is divisible by 3 but not 5 (⟨ 1 0 ⟩).
We can gather all numbers from 0 up to a number with 𝕩: Range.
↕4
⟨ 0 1 2 3 ⟩
↕10
⟨ 0 1 2 3 4 5 6 7 8 9 ⟩
We can run our divisibility checks on all numbers less than 10.
0= (3⊸| ⋈ 5⊸|)¨ ↕10
⟨ ⟨ 1 1 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 1 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 1 ⟩ ⟨ 1 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 1 0 ⟩ ⟩
We can compute a OR b with 𝕨 ∨ 𝕩: Logical Or.
1 ∨ 0
1
0 ∨ 0
0
We can insert a function between items of an array with 𝔽´ 𝕩: Fold.
1 + 2
3
1 + 2 + 3
6
+´ 1‿2‿3
6
+´ 1‿2‿3‿4‿5‿6
21
We can insert 𝕨 ∨ 𝕩: Logical Or between a list of booleans.
∨´ 0‿0‿0‿0
0
∨´ 0‿0‿1‿0
1
∨´ 1‿0‿1‿0
1
We can insert 𝕨 ∨ 𝕩: Logical Or between a list of boolean lists with 𝔽´ 𝕩: Fold and 𝔽¨ 𝕩, 𝕨 𝔽¨ 𝕩: Each.
∨´¨ ⟨ ⟨0, 0⟩, ⟨0, 1⟩, ⟨1, 0⟩, ⟨1, 1⟩ ⟩
⟨ 0 1 1 1 ⟩
Our divisibility checks are a list of a list of booleans (for each number, whether that number is divisible by 3, and whether it is divisible by 5).
0= (3⊸| ⋈ 5⊸|)¨ ↕10
⟨ ⟨ 1 1 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 1 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 1 ⟩ ⟨ 1 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 1 0 ⟩ ⟩
We can check if the numbers less than 10 are divisible by 3 or 5.
∨´¨ 0= (3⊸| ⋈ 5⊸|)¨ ↕10
⟨ 1 0 0 1 0 1 1 0 0 1 ⟩
We can use the 0s and 1s to filter a list with 𝕨 / 𝕩: Replicate.
0‿1 / ⟨ 5, 6 ⟩
⟨ 6 ⟩
0‿1‿0‿1‿1 / ⟨ "hello", "this", "is", "a", "test" ⟩
⟨ "this" "a" "test" ⟩
We can filter the numbers less than 10 for those divisible by 3 or 5.
∨´¨ 0= (3⊸| ⋈ 5⊸|)¨ ↕10
⟨ 1 0 0 1 0 1 1 0 0 1 ⟩
(∨´¨ 0= (3⊸| ⋈ 5⊸|)¨ ↕10) / ↕10
⟨ 0 3 5 6 9 ⟩
(Extra credit) We can avoid repeating ourselves with 𝔽⊸𝔾 𝕩: Before.
(√ 10) + 10
13.16227766016838
√⊸+ 10 # apply √ and add it to the original
13.16227766016838
(∨´¨ 0= (3⊸| ⋈ 5⊸|)¨ ↕10) / ↕10
⟨ 0 3 5 6 9 ⟩
# apply divisibility checks, then Replicate
# against the original
(∨´¨ 0= (3⊸| ⋈ 5⊸|)¨) ⊸/ ↕10
⟨ 0 3 5 6 9 ⟩
We can use 𝔽´ 𝕩: Fold to sum the multiples of 3 or 5 below 10.
+´ (∨´¨ 0= (3⊸| ⋈ 5⊸|)¨) ⊸/ ↕10
23
We can sum the multiples of 3 or 5 below 1000.
+´ (∨´¨ 0= (3⊸| ⋈ 5⊸|)¨) ⊸/ ↕1000
233168
All together now:
3|6
3⊸| 6
(3⊸| ⋈ 5⊸|) 6
0= (3⊸| ⋈ 5⊸|) 6
0= (3⊸| ⋈ 5⊸|)¨ ↕1000
(∨´¨ 0= (3⊸| ⋈ 5⊸|)¨ ↕1000) / ↕1000
(∨´¨ 0= (3⊸| ⋈ 5⊸|)¨) ⊸/ ↕1000
+´ (∨´¨ 0= (3⊸| ⋈ 5⊸|)¨) ⊸/ ↕1000
(Bonus) We can rearrange a few terms and use blocks and arguments. I find it helps to sprinkle in 𝕩 two or three times instead of massaging everything to remove it.
+´ {(0=3|𝕩) ∨ (0=5|𝕩)}¨ ⊸/ ↕1000
233168
Author’s note: Don’t worry. BQN also supports more “familiar” programming principles like blocks, cases, and assignments.
Div3Or5 ← {
0=3|𝕩 ? 𝕩 ;
0=5|𝕩 ? 𝕩 ;
0
}
(function block)
+´ Div3or5¨ ↕1000
233168