18
\$\begingroup\$

Background

J has trains similar to APL's. Given a sequence of verbs (functions), three rightmost verbs are grouped to form a derived verb (a fork) recursively, until one or two verbs remain. If the sequence has odd length, the entire train is a chain of forks. Otherwise, two verbs remain at the end, forming a hook.

    (F G H J K) x             5-train called monadically
->  (F G (H J K)) x
->  (F x) G ((H x) J (K x))   Function arities: 1, 2, 1, 2, 1

    x (F G H J K) y                 5-train called dyadically
->  x (F G (H J K)) y
->  (x F y) G ((x H y) J (x K y))   Function arities: 2, 2, 2, 2, 2

    (F G H J K L) x                 6-train called monadically
->  (F (G H (J K L))) x
->  x F ((G x) H ((J x) K (L x)))   Function arities: 2, 1, 2, 1, 2, 1

    x (F G H J K L) y               6-train called dyadically
->  x (F (G H (J K L))) y
->  x F ((G y) H ((J y) K (L y)))   Function arities: 2, 1, 2, 1, 2, 1

You don't need to fully understand J trains to solve this challenge. The pattern is pretty simple:

  • If the train length is even, the pattern is [2, 1, 2, 1, ..., 2, 1] regardless of the train's arity.
  • Otherwise (length is odd), if the train is called monadically, the pattern is [1, 2, 1, 2, ..., 2, 1]; if called dyadically, the pattern is all 2's.

Challenge

Given a train's length and arity (monadic is 1, dyadic is 2), output the arities of each function in the train.

Standard rules apply. The shortest code in bytes wins.

Test cases

length, arity -> answer
1,      1     -> [1]
1,      2     -> [2]
2,      1     -> [2, 1]
2,      2     -> [2, 1]
3,      1     -> [1, 2, 1]
3,      2     -> [2, 2, 2]
4,      1     -> [2, 1, 2, 1]
4,      2     -> [2, 1, 2, 1]
9,      1     -> [1, 2, 1, 2, 1, 2, 1, 2, 1]
9,      2     -> [2, 2, 2, 2, 2, 2, 2, 2, 2]
10,     1     -> [2, 1, 2, 1, 2, 1, 2, 1, 2, 1]
10,     2     -> [2, 1, 2, 1, 2, 1, 2, 1, 2, 1]
\$\endgroup\$
3
  • \$\begingroup\$ May we output a list or string with any two distinct values? \$\endgroup\$
    – chunes
    Nov 10, 2021 at 3:57
  • \$\begingroup\$ @chunes No, here 1 and 2 have specific meaning, so you need to specifically output those numbers. Outputting a string like "2121" is fine though. \$\endgroup\$
    – Bubbler
    Nov 10, 2021 at 4:05
  • \$\begingroup\$ Related: codegolf.stackexchange.com/questions/213877/… \$\endgroup\$
    – xigoi
    Nov 10, 2021 at 7:40

15 Answers 15

12
\$\begingroup\$

Python 2, 28 bytes

lambda l,a:(l*[2,l%a+1])[l:]

Try it online!

Python 2, 27 bytes

It saves one byte to output as a string.

lambda l,a:(l*`21+l%a`)[l:]

Try it online!

\$\endgroup\$
10
\$\begingroup\$

HBL 0.1, 10 bytes

<(0.(*(1(+(%.,))2?).

Try it at HBL Online!

HBL uses a half-byte codepage. Each character above represents one hex digit, two characters per byte. Here's a hexdump of the raw binary file:

00000000: 3c0a c5c1 c4c8 abdd 29da                 <.......).

Explanation

If we reverse the desired output, we can see some patterns emerge:

3 1  (1 2 1)
3 2  (2 2 2)
4 1  (1 2 1 2)
4 2  (1 2 1 2)
5 1  (1 2 1 2 1)
5 2  (2 2 2 2 2)
  • The output is some two-element list repeated a number of times and trimmed to a length equal to the first argument.
  • The second element of that list is always 2.
  • The first element of that list is 2 if the arguments are, respectively, an odd number and 2; otherwise, the first element is 1.

This leads to our initial solution, given here in Thimble, HBL's "ungolfed mode":

'(reverse           ; Reverse of
  (take arg1        ; The first (arg1) elements of
   (repeat          ; Repeat the following list...
    (cons           ;  Construct a list from the values...
     (cond          ;   If...
      (mul          ;    Multiply
       (odd? arg1)  ;    parity of arg1
       (dec arg2))  ;    by (arg2 - 1)
      2             ;   ... is nonzero, then 2
      1)            ;   else 1
     2              ;  ... and 2
     nil)           ;  prepended to the empty list
    arg1)))         ; ... (arg1) times

Translating this solution into HBL gives <(0.(*(1(?(*(%.)(-,))21)2?). (14 bytes). To get to our 10-byte solution, observe that there's a nice relationship between our two arguments and the number we want in our list:

 arg1 % 2 | arg2 | num | arg1 % arg2
----------|------|-----|-------------
 0        | 1    | 1   | 0
 0        | 2    | 1   | 0
 1        | 1    | 1   | 0
 1        | 2    | 2   | 1

So instead of the conditional, all we need is (inc (mod arg1 arg2)).

'(reverse
  (take arg1
   (repeat
    (cons
     (inc
      (mod arg1 arg2))
     2
     nil)
    arg1)))

Replacing the builtins with their HBL equivalents and removing the opening and closing parentheses (implicit in HBL), this solution maps directly onto the HBL solution given above.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice observation and explanation. \$\endgroup\$
    – Jonah
    Nov 10, 2021 at 22:27
4
\$\begingroup\$

Jelly, 7 bytes

%‘;2ṁḷU

Try it online!

Thanks to Unrelated String for making this work! Port of dingledooper's answer.

%‘ṭ2ṁḷU # Dyadic link taking two arguments
    ṁ   # Mold... 
  ;2    # 2 appended to...
%       # The modulo of the two inputs
 ‘      # Plus 1
    ṁ   # To length...
     ḷ  # Left argument (length input)
      U # Reversed
\$\endgroup\$
0
3
\$\begingroup\$

05AB1E, 10 bytes

%21+sиJs.$

Try it online!

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Fails for (1,9) and all odd-length inputs in general. \$\endgroup\$
    – Bubbler
    Nov 10, 2021 at 6:11
  • \$\begingroup\$ @Bubbler fixed though it ended up becoming dingledooper port \$\endgroup\$
    – Wasif
    Nov 10, 2021 at 6:27
  • \$\begingroup\$ иJ is the builtin ×. And here an alternative 9-byter: %T*12+²∍R \$\endgroup\$ Nov 10, 2021 at 11:09
  • \$\begingroup\$ My alternative 9-byter can actually be a 7-byter like this: %>2«²∍R (port of the Jelly answer) \$\endgroup\$ Nov 10, 2021 at 20:24
3
\$\begingroup\$

Factor + sequences.repeating, 50 bytes

[ dupd mod 1 + '[ 2 _ ] over 2 * cycle swap tail ]

Try it online!

This is a port of @dingledooper's excellent Python 2 answer.

There is a locals version that is the same length:

[| l a | 2 l a mod 1 + 2array l 2 * cycle l tail ]

Try it online!

Explanation:

It's a quotation (anonymous function) that takes the length and the arity (in that order) from the data stack as input and leaves a sequence on the data stack as output. Assuming 9 1 is on the data stack when this quotation is called...

Snippet Comment Data stack (the bottom is the top)
9   <--- NOS (next on stack)
1 <--- TOS (top of stack)
dupd
Duplicate NOS
9
9
1
mod
NOS % TOS
9
0
1
Push 1
9
0
1
+
NOS + TOS
9
1
'[ 2 _ ]
Slot TOS into the _
9
[ 2 1 ]
over
Copy NOS to TOS
9
[ 2 1 ]
9
2
Push 2
9
[ 2 1 ]
9
2
*
NOS * TOS
9
[ 2 1 ]
18
cycle
Repeat NOS until length of TOS
9
[ 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 ]
swap
Swap NOS and TOS
[ 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 ]
9
tail
Take NOS from index at TOS
[ 1 2 1 2 1 2 1 2 1 ]
\$\endgroup\$
3
\$\begingroup\$

Retina 0.8.2, 32 bytes

\d+
$*
r`11
21
T`1`2`21,1.*
.+,

Try it online! Link includes test cases. Takes input in the order arity, length. Explanation:

\d+
$*

Convert the length to unary, conveniently using 1s.

r`11
21

Working right-to-left, change every other 1 to a 2.

T`1`2`21,1.*

If the arity is two and the length is odd, change all the 1s to 2s.

.+,

Delete the arity.

\$\endgroup\$
2
\$\begingroup\$

Vyxal, 8 bytes

%21+S⁰*∷

Try it Online!

-1 thanks to emanresuA

Haha 05ab1e porting goes brrrr. When v2.6.0pre2 drops later this week, this'll be 7 bytes:

%21+⁰ẋ∷

Explained (old)

%21+S⁰*⁰ȯ # Full program, takes arity, length
%         # Push length mod arity,
 21+      # add 21 to that,
    S     # and cast to string. (This value will be called x)
     ⁰    # Push the length,
      *   # and repeat x that many times. (This value will be called y)
       ⁰  # Push the length again,
        ȯ # and push y[length:]
\$\endgroup\$
2
  • \$\begingroup\$ you ported me, and I ported dingledooper lol \$\endgroup\$
    – Wasif
    Nov 10, 2021 at 6:38
  • \$\begingroup\$ -1 with the first half \$\endgroup\$
    – emanresu A
    Nov 10, 2021 at 8:34
2
\$\begingroup\$

Ruby, 25 bytes

->l,a{([2,l%a+1]*l)[l,l]}

Try it online!

Another port of @dingledooper's Python answer.

\$\endgroup\$
2
\$\begingroup\$

J, 47 bytes

(".@,'~'''''}.~2&|)~'(',')',~,&'1&, :(,2&,)'&''

Try it online!

I would call this one a conscious un-golf, because ofc I could port dingledooper's Python answer to J for fewer bytes...

But it just didn't feel right for a J answer not to use J's train parsing code to compute the answer.

the idea

First, we construct a verb 1&, :(,2&,) that prepends 1 to its argument (say a b c) when called with 1 argument:

1 a b c

but plops 2 in the middle when called with 2 args:

a b c 2 a b c

Next we duplicate that verb length times to form a train, and then invoke the train on the empty list ''. More precisely, we call:

train ''

if our arity is 1, and:

'' train ''

if our arity is 2.

With that setup, J's train execution will do the required computation for us.

\$\endgroup\$
2
\$\begingroup\$

Jelly, 6 bytes

ḶU|%Ḃ‘

Try it online!

Like Dingledooper's answer, but a bit different.

ḶU       range [L-1..0]
  |%     bitwise OR by L%A
            (if L%A=0, this does nothing;
             if L%A=1, it makes the whole range odd)
    Ḃ‘   mod 2, add 1
\$\endgroup\$
1
\$\begingroup\$

R, 38 bytes

Or R>=4.1, 31 bytes by replacing the word function with \.

function(l,a)tail(rep(2:(l%%a+1),l),l)

Try it online!

Based od @dingledooper's idea.

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 46 bytes (44 using puts)

i;f(l,a){for(i=l;i--;)printf(L"122"+i%2+l%a);}

Try it online!

  • Based on @dingledooper answer
\$\endgroup\$
1
\$\begingroup\$

MathGolf, 9 bytes

\%J+░*h½≥

Port of @dingledooper's Python answer.

Try it online.

Explanation:

\          # Swap the two (implicit) input-integers
 %         # Modulo
  J+       # Add 21
    ░      # Convert it to a string
     *     # Repeat it the first (implicit) input-integer amount of times
      h    # Push the length of this string (without popping)
       ½   # Halve it
        ≥  # Remove that many leading digits from the string
           # (after which the entire stack is output implicitly as result)
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 12 bytes

Nθ↓I……⊕﹪θN³θ

Try it online! Link is to verbose version of code. Explanation:

Nθ              Input the length as an integer
     …          Range from
        θ       Input length
       ﹪        Reduced modulo
         N      Arity as an integer
      ⊕         Incremented
          ³     Until 3 (exclusive)
    …           Cycled to length
           θ    Input length
   I            Cast to string
  ↓             Output right-to-left

Instead of , either or can be used for vertical output.

\$\endgroup\$
1
\$\begingroup\$

Rust, 61 bytes

|l,a|->Vec<_>{(0..l).rev().map(move|x|(x|l%a)%2+1).collect()}

Try it online!

Port of @Lynn's Jelly answer.

Generates range l-1 .. 0, bitwise ORs each item with l modulo a, then modulos the result with 2 and adds 1

Range in rust ((start..stop)) must be ascending, as it returns an empty iterator if start >= stop, so we have to .rev() the range to reverse it before mapping. Thankfully though the stop of a range is exclusive, so (0..l) generates range 0 to l-1 inclusive.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.