Write {(+/3<?⍵⍴6)×100÷⍵}1000 tacitly
Asked Answered
M

1

6

Inspired by some Conor Hoekstra YouTube videos, I tried doing some baby steps in APL and also convert my small lines to point-free style. But for this (percentage of rolls of 4, 5, or 6 in 1000 die-6 rolls) I can't wrap my head around how to eliminate the omega before the reshape.

{(+/3<?⍵⍴6)×100÷⍵}1000

Marcusmarcy answered 22/11, 2021 at 2:13 Comment(1)
To the uninitiated, this question may look like it is lacking in details or clarity, but rest assured that for the APLer with experience in tacit programming, the stated problem ("how to eliminate the omega before the reshape") is perfectly clear, and a common issue.Sheik
R
9

Let's take it step by step:

{(+/3<?⍵⍴6)×100÷⍵}

First we need to express every part of the function that uses the argument, as a function of the argument. The multiplication combines the two main parts:

{+/3<?⍵⍴6}×{100÷⍵}

In the rightmost part, {100÷⍵}, we need the argument. There are a couple of ways we can deal with this:

  1. We can use an identity function to represent it: 100÷⊢
  2. We can bind (a.k.a. curry) the left argument, 100, to the function ÷ yielding a monadic function: 100∘÷

Let's take the last approach:

{+/3<?⍵⍴6}×100∘÷

In the left part, {+/3<?⍵⍴6}, we can do the same, but need to watch out for two things, and each can be dealt with in a few different ways:

  1. We have a constant, 6, as the rightmost part of our function.
    1. We can change the constant into a constant function: 6⍨
    2. We can commute (a.k.a. swap or switch) the arguments of and use an identity function: 6⍴⍨⊢
    3. We can bind the right argument, 6, to the function yielding a monadic function: ⍴∘6
  2. We have a monadic function, ?, in the middle.
    1. We can compose ? atop : ?⍤⍴
    2. We can compose ? beside <: <∘?

Let's take the last approach for each problem:

(+/3<∘?⍴∘6)×100∘÷

This is a fully tacit equivalent to the monadic function {(+/3<?⍵⍴6)×100÷⍵}. However, there's one more trick we can use to eliminate the parenthesis. Since × is commutative, we can swap its arguments to put the more involved expression on the right:

100∘÷×(+/3<∘?⍴∘6)

However, now we have the problem of the monadic +/ in the middle. Observe that < sees a vector on the right and a scalar on the left. In the case of F/s G v for scalar functions F and G with scalar s and vector v the inner product s F.G v is equivalent, so we can combine the summation with the comparison as follows:

100∘÷×3+.<∘?⍴∘6

Alternatively, we can observer that summation is equivalent to evaluation in base 1 because the place values in base 1 are (…,12, 11, 10) = (…, 1, 1, 1) so if we have the list (…, c, b, a) and evaluate it as a number in base 1, we get:

(… + c×12 + b×11 + a×10) =
(… + c×1 + b×1 + a×10) =
(… + c + b×1 + a×1) =
(… + c + b + a)

That is, the sum of our list. We can write this as:

100∘÷×1⊥3<∘?⍴∘6

Ruperto answered 22/11, 2021 at 8:42 Comment(4)
I would personally prefer the ?⍤⍴ to <∘⍴ since that creates the "roll six-sided dice" function ?⍤⍴∘6. The inner product +.< is already chunking the "how many values greater than" part of the solution. (100∘÷× ⍝ As a percentage) (3+.< ⍝ Count of values greater than 3) (?⍤⍴∘6 ⍝ Of ⍵ 6-sided dice rolls) I personally think it's important to try and tie the meaning of the compositions to the meaning of the solution in the problem domain where possible, although I understand it's almost always up to interpretation.Miscegenation
@Miscegenation Good point, and I thought of that too, but since ?⍤⍴ doesn't work in all supported versions, I opted for F∘G.Sheik
Wow, thanks for this overview of ideas! I believe in 1.3, ⍴∘⍵ should be ⍴∘6.Marcusmarcy
@FelixDombek Oops. I've fixed that typo.Sheik

© 2022 - 2024 — McMap. All rights reserved.