Uiua: Weekly challenge 242

memark

Magnus Markling

Posted on November 11, 2023

Uiua: Weekly challenge 242

Table of contents

  1. Introduction
  2. Task 2
  3. Task 1

Introduction

Uiua is an interesting new language. Strongly influenced by APL and BQN, it's array-oriented and stack-based. To explore it briefly, I will walk through my solutions to this week's Perl weekly challenge (242).

Uiua has an excellent language tour as well as a tutorial on its own site, which I'd recommend you go through if you're just starting out. I'm going to assume you have at least some syntactic familiarity with the language already.

Task 2

We'll actually start with Task 2 this week, since it's way easier.

Here is the problem description:

You are given `n x n` binary matrix.

Write a script to flip the given matrix as below.

1 1 0
0 1 1
0 0 1

a) Reverse each row

0 1 1
1 1 0
1 0 0

b) Invert each member

1 0 0
0 0 1
0 1 1
Enter fullscreen mode Exit fullscreen mode

We'll start by putting the example matrix on the stack, in Uiua notation

[[1 1 0] [0 1 1] [0 0 1]]
Enter fullscreen mode Exit fullscreen mode

giving

╭─
╷ 1 1 0
  0 1 1
  0 0 1
        ╯
Enter fullscreen mode Exit fullscreen mode

Reversing each row can by done by a combination of the ≡ rows and ⇌ reverse functions. Like this:

[[1 1 0] [0 1 1] [0 0 1]]
≡⇌
Enter fullscreen mode Exit fullscreen mode

giving

╭─
╷ 0 1 1
  1 1 0
  1 0 0
       ╯
Enter fullscreen mode Exit fullscreen mode

That takes care of part a). What we need to do now is just reverse each element. Since most simple functions in Uiua are pervasive, this is as simple as calling the ¬ not function on our previous result. Like this:

[[1 1 0] [0 1 1] [0 0 1]]
¬ ≡⇌
Enter fullscreen mode Exit fullscreen mode

giving

╭─
╷ 1 0 0
  0 0 1
  0 1 1
        ╯
Enter fullscreen mode Exit fullscreen mode

which is the expected answer. In the task there were two additional examples:

Example 1

Input: @matrix = ([1, 1, 0], [1, 0, 1], [0, 0, 0])
Output: ([1, 0, 0], [0, 1, 0], [1, 1, 1])
Enter fullscreen mode Exit fullscreen mode

Example 2

Input: @matrix = ([1, 1, 0, 0], [1, 0, 0, 1], [0, 1, 1, 1], [1, 0, 1, 0])
Output: ([1, 1, 0, 0], [0, 1, 1, 0], [0, 0, 0, 1], [1, 0, 1, 0])
Enter fullscreen mode Exit fullscreen mode

Let's put our logic in a function:

FlipMatrix ← ¬≡⇌
Enter fullscreen mode Exit fullscreen mode

and add these examples as unit tests by combining ⍤ assert and ≍ match in a --- test scope:

---
FlipMatrix [[1 1 0] [1 0 1] [0 0 0]]
⍤.        ≍[[1 0 0] [0 1 0] [1 1 1]]

FlipMatrix [[1 1 0 0] [1 0 0 1] [0 1 1 1] [1 0 1 0]]
⍤.        ≍[[1 1 0 0] [0 1 1 0] [0 0 0 1] [1 0 1 0]]
---
Enter fullscreen mode Exit fullscreen mode

Both unit tests pass, so we are done with Task 2.

Task 1

Let's move on to the more challenging task of the two. Here is the problem description:

You are given two arrays of integers.

Write a script to find out the missing members in each other arrays.
Enter fullscreen mode Exit fullscreen mode

Let's start with the first example.

Example 1

Input: @arr1 = (1, 2, 3)
       @arr2 = (2, 4, 6)
Output: ([1, 3], [4, 6])

(1, 2, 3) has 2 members (1, 3) missing in the array (2, 4, 6).
(2, 4, 6) has 2 members (4, 6) missing in the array (1, 2, 3).
Enter fullscreen mode Exit fullscreen mode

Since we'll be working with these example arrays a lot, let's start by putting them into variables a and b:

a ← [1 2 3]
b ← [2 4 6]
Enter fullscreen mode Exit fullscreen mode

To get what members are common between the two arrays we can use ∊ member like this:

∊ a b
Enter fullscreen mode Exit fullscreen mode

which gives us a filter mask with 1s corresponding to the common elements:

[0 1 0]
Enter fullscreen mode Exit fullscreen mode

We want the missing ones (i.e. the not common elements), so we invert this array with ¬ not:

¬∊ a b
Enter fullscreen mode Exit fullscreen mode

giving

[1 0 1]
Enter fullscreen mode Exit fullscreen mode

We can now apply this inverted mask to our original array using ▽ keep to get the missing members

¬∊ a b
▽: a
Enter fullscreen mode Exit fullscreen mode

giving

[1 3]
Enter fullscreen mode Exit fullscreen mode

which is correct. Note that this could also be put on a single line like this:

▽: a ¬∊ a b
Enter fullscreen mode Exit fullscreen mode

We also need to do the opposite by reversing the arrays in our input

▽: b ¬∊ b a
Enter fullscreen mode Exit fullscreen mode

giving

[4 6]
Enter fullscreen mode Exit fullscreen mode

which is also correct. Since the output should be in the form of a single 2d array

Output: ([1, 3], [4, 6])
Enter fullscreen mode Exit fullscreen mode

we could do it like this (variable names are case sensitive)

A = ▽: a ¬∊ a b
B = ▽: b ¬∊ b a
[A B]
Enter fullscreen mode Exit fullscreen mode

or by using ⊟ couple like this

A = ▽: a ¬∊ a b
B = ▽: b ¬∊ b a
⊟ A B
Enter fullscreen mode Exit fullscreen mode

both giving the expected 2d array

╭─
╷ 1 3
  4 6
      ╯
Enter fullscreen mode Exit fullscreen mode

Let's try to do away with some repetition. We'll start by creating a single function that gets us the missing members in one direction between two arrays:

F ← ▽¬∊,
Enter fullscreen mode Exit fullscreen mode

And combining them with ⊟ couple

⊟  F b a  F a b
Enter fullscreen mode Exit fullscreen mode

Note that this is equal to

⊟  F : a b  F a b
Enter fullscreen mode Exit fullscreen mode

Now things start to get interesting. Notice the symmetry, where we do two different operations to the same set of values. Uiua has a couple interesting functions for doing that, in this case we'll use ⊃ fork:

⊟ ⊃(F∶)(F) a b
Enter fullscreen mode Exit fullscreen mode

still giving us what we want

╭─
╷ 1 3
  4 6
      ╯
Enter fullscreen mode Exit fullscreen mode

So far so good.

Example 2

Input: @arr1 = (1, 2, 3, 3)
       @arr2 = (1, 1, 2, 2)
Output: ([3])

(1, 2, 3, 3) has 2 members (3, 3) missing in the array (1, 1, 2, 2). Since they are same, keep just one.
(1, 1, 2, 2) has 0 member missing in the array (1, 2, 3, 3).
Enter fullscreen mode Exit fullscreen mode

If we try our last function on this new data

a ← [1 2 3 3]
b ← [1 1 2 2]
F ← ▽¬∊,
⊟⊃(F∶)(F) a b
Enter fullscreen mode Exit fullscreen mode

we get an error

Error: Cannot couple arrays with shapes [2] and [0]  
at 4:1  
4 | ⊟ ⊃(F∶)(F) a b  
    ─
Enter fullscreen mode Exit fullscreen mode

This is because arrays in Uiua must have a uniform shape, i.e. the same number of elements/rows/subarrays at each level. The solution is to □ box the result of F:

⊟⊃(□F∶)(□F) a b
Enter fullscreen mode Exit fullscreen mode

giving

[⟦3 3⟧ ⟦⟧]
Enter fullscreen mode Exit fullscreen mode

Notice the ⟦⟧ meaning it's a boxed array. There are two problems left to solve here though. First we want to get rid of the duplicate 3 in the first box. We'll use ⊝ deduplicate for that:

⊟⊃(□⊝F∶)(□⊝F) a b
Enter fullscreen mode Exit fullscreen mode

which works as expected

[⟦3⟧ ⟦⟧]
Enter fullscreen mode Exit fullscreen mode

We also want to get rid of the empty second box altogether. We can do that by taking the ⧻ length of each row and then ▽ keep the ones >0:

▽>0≡⧻. ⊟ ⊃(□⊝F∶)(□⊝F) a b
Enter fullscreen mode Exit fullscreen mode

giving us

[⟦3⟧]
Enter fullscreen mode Exit fullscreen mode

which is correct! Putting it altogether, we can inline F for brevity and add our two examples as unit tests:

MissingMembers ← ▽>0≡⧻. ⊟⊃(□⊝▽¬∊,∶)(□⊝▽¬∊,)

---
⍤. ≍{[1 3][4 6]} MissingMembers [1 2 3]   [2 4 6]
⍤. ≍{[3]}        MissingMembers [1 2 3 3] [1 1 2 2]
---
Enter fullscreen mode Exit fullscreen mode

The unit tests pass and we're happy once again!

Was it hard or easy to follow along? Do you want more content like this? Leave a comment!

💖 💪 🙅 🚩
memark
Magnus Markling

Posted on November 11, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Uiua: Weekly challenge 242
uiua Uiua: Weekly challenge 242

November 11, 2023