20
\$\begingroup\$

This challenge is related to some of the MATL language's features, as part of the May 2018 Language of the Month event. Associated challenge: Function clipboard: copy.


Introduction

MATL's function clipboard stores ("copies") the inputs to the four most recent calls to normal, input-taking functions. Normal functions are the most common type of functions in MATL. Input-taking means that the function takes at least one input. The stored clipboard contents can be pushed onto the stack ("pasted").

This challenge will take the clipboard contents as input. It will be assumed that all functions that have produced that clipboard state took one or more positive integers as inputs. So the clipboard state can be represented by a list of lists of numbers. (For more information on how the clipboard is actually filled see the related challenge; but that's not necessary for the current one).

Interpreting the clipboard contents

Example 1

The first inner list refers to the most recent function call, and so on, Thus the clipboard state

[[11, 28], [12, 16], [4], [5, 6]]

indicates that the last function call took two inputs, namely 11, 28; the second-last call took inputs 12, 16; etc. (This clipboard state is produced by the code in the first example of the related challenge).

Example 2

If there have not been enough function calls, some trailing inner lists in the clipboard will be empty:

[[7, 5], [], [], []]

(This is produced by a program that simply adds 7 and 5).

Example 3

Function calls can have any number of inputs, but always at least 1 (functions taking no inputs do not change the clipboard state). So the following is also possible.

[[3], [2, 40, 34], [7, 8, 15], []]

Accessing the clipboard contents

The contents of the function clipboard are pushed onto the stack using MATL's function M (which, by the way, is not a normal function, but a clipboard function). This function takes a positive integer as input, and pushes some of the clipboard contents onto the stack, as follows. With reference to the clipboard state in example 1:

[[11, 28], [12, 16], [4], [5, 6]]
  • 1M returns all inputs to the most recent function call. So, for the considered example, it gives 11, 28.
  • Similarly, 2M, 3M and 4M return all inputs to the second, third and fourth most recent function calls. So 2M gives 12, 16; 3M gives 4; and 4M gives 5, 6.
  • Numbers beyond 4 select individual inputs to function calls that took more than one input. So 5M returns the last input to the most recent such call. In our case this gives 28. 6M returns the preceding individual input, which is 11. 7M returns the last input of the second-last call, that is, 16, and 8M gives 12. Now, 9M gives 6. Note how input 4 is skipped because it was the only input in its function call. Lastly, 10M gives 5.

For the clipboard state in example 3:

[[3], [2, 40, 34], [7, 8, 15], []]
  • 1M gives 3. 2M gives 2, 40, 34. 3M gives 7, 8, 15.
  • 4M has undefined behaviour (for the purposes of this challenge), because there have only been three function calls.
  • 5M gives 34. 6M gives 40. 7M gives 2. 8M gives 15. 9M gives 8, 10M gives 7.
  • 11M, 12M, ... also have undefined behaviour.

The challenge

Input:

  • the clipboard state, as a list of lists, or any other reasonable format;
  • a positive integer n.

Output: the result of calling function M with n as input. The output will be one or several numbers with an unambiguous separator, or in any reasonable format such as a list or array.

Clarifications:

  • The clipboard state consists of four lists of numbers. Some of the trailing lists may be empty, as in examples 2 and 3. If preferred, you can input the clipboard without those trailing empty lists. So example 3 would become [[3], [2, 40, 34], [7, 8, 15]].
  • All numbers in the clipboard will be positive integers, possibly with more than one digit.
  • The number n is guaranteed to be valid. So for example 3 above, n cannot be 4 or 11.

Additional rules:

Test cases

Clipboard state
Number
Output(s)

[[11, 28], [12, 16], [4], []]
2
12, 16

[[11, 28], [12, 16], [4], []]
5
28

[[7, 144], [12], [4, 8], [3, 4, 6]]
1
7, 144

[[7, 144], [12], [4, 8], [3, 4, 6]]
10
4

[[30], [40], [50, 60], [70, 80, 90]]
2
40

[[30], [40], [50, 60], [80, 90]]
7
90

[[15], [30], [2, 3, 5], [4, 5, 10]]
3
2, 3, 5

[[15], [30], [2, 3, 5], [4, 5, 10]]
7
2
\$\endgroup\$
  • \$\begingroup\$ Can we take a 0-indexed n? \$\endgroup\$ – Arnauld May 20 '18 at 18:28
  • 3
    \$\begingroup\$ @Arnauld I’m going to say no, as this is based on MATL’s actual behaviour \$\endgroup\$ – Luis Mendo May 20 '18 at 18:34

15 Answers 15

3
\$\begingroup\$

Jelly, 8 bytes

ḊƇUẎ⁸;⁹ị

Try it online!

\$\endgroup\$
  • 2
    \$\begingroup\$ Do you mind adding an explanation? \$\endgroup\$ – LordColus May 20 '18 at 21:17
  • \$\begingroup\$ @LordColus ḊƇ select all non-singletons, U reverse and flatten. For input [[11, 28], [12, 16], [4], []] this gets [16, 12, 28, 11], the values of 5M through 8M. Now prepend the original input to this list ⁸; and index into the resulting list by the other input ⁹ị. \$\endgroup\$ – Lynn May 20 '18 at 22:08
  • \$\begingroup\$ @LordColus Ah, sorry, I only add explanations on request (because ninja), but I was asleep. Lynn pretty much explained it, however I would like to add that U doesn't reverse the result of ḊƇ, but rather each of its elements. Only if I could somehow reduce ḊƇUẎ⁸;... \$\endgroup\$ – Erik the Outgolfer May 21 '18 at 11:48
4
\$\begingroup\$

Haskell, 56 51 47 bytes

-5-9 bytes thanks to Laikoni (pattern match to ensure length > 1 and using do-notation over list comprehension)!

c!n=([]:c++do l@(_:_:_)<-c;reverse$pure<$>l)!!n

Try it online!

Pointfree, 58 55 bytes

-3 bytes thanks to Laikoni (moving ([]:) and replacing id)!

Alternatively we could use this pointfree version

(!!).(([]:)<>map pure.(>>=reverse).filter((1<).length)).

\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Unicode), 17 bytes

{⍺⊃⍵⍪∊⊖¨⍵⌿⍨1<≢¨⍵}

Try it online!

\$\endgroup\$
3
\$\begingroup\$

JavaScript (Node.js), 57 bytes

a=>n=>a.map(e=>e[1]&&a.push(...[...e].reverse()))&&a[n-1]

Try it online!

This is an anonymous, curried function. Run it with ( function code )(clipboard)(n)

Explanation

a=>n=>{
    // The strategy is to append the individual clipboard inputs to the end of a,
    // after the function calls (lists). We then return a[n-1] to offset JavaScript's
    // zero indexing.
    a.map(e=>{
        e[1]&& // if this list has more than one element...
            a.push(...[...e].reverse()) // add each element to a, in reverse order.
            // reverse() modifies the original array, so we have to use [...e] to "clone" e
    })
    return a[n-1]
}
\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 72 bytes

Takes input in currying syntax (clipboard)(n).

a=>m=>a[m-1]||(g=r=>(r=r|a[k][1]&&a[k].pop())?--m<5?r:g(1):g(!++k))(k=0)

Try it online!

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

Python 2, 60 56 bytes

thanks to Jonathan Allan for -4 bytes.

lambda l,n:(l+sum([b[::-1]for b in l if b[1:]],[]))[n-1]

Try it online!

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

Java 8, 110 bytes

A lambda (curried) taking the clipboard state as an int[][] and the number as an int and returning int or int[] (a single number may be returned through either type).

s->n->{if(--n<4)return s[n];else{int i=0,l;for(n-=4;(l=s[i].length)<=n|l<2;i++)n-=l>1?l:0;return s[i][l+~n];}}

Try It Online

Ungolfed

s ->
    n -> {
        if (--n < 4)
            return s[n];
        else {
            int i = 0, l;
            for (
                n -= 4;
                (l = s[i].length) <= n | l < 2;
                i++
            )
                n -= l > 1 ? l : 0;
            return s[i][l + ~n];
        }
    }
\$\endgroup\$
2
\$\begingroup\$

05AB1E, 12 bytes

Díʒg<Ā}˜«s<è

Try it online!

Explanation

D              # duplicate input list
 í             # reverse each
  ʒg<Ā}        # filter, keep only elements that are longer than 1
       ˜       # flatten
        «      # append to original list
         s<    # decrement the second input
           è   # get the element in the list at that index
\$\endgroup\$
2
\$\begingroup\$

Husk, 12 bytes

!S+(m;ṁ↔f(¬ε

Try it online!

Explanation

Pretty much a direct port of the Haskell answer:

!S+(m;ṁ↔f(¬ε  -- example inputs: [[1],[2,3],[4],[5,6,7],[]] 7
 S+           -- concatenate itself with itself modified by
        f(    -- | filter
           ε  -- | | length 1
          ¬   -- | | not
              -- | : [[2,3],[5,6,7],[]]
      ṁ       -- | map and flatten
       ↔      -- | | reverse
              -- | : [3,2,7,6,5]
              -- | map
              -- | | pure
              -- | : [[3],[2],[7],[6],[5]]
              -- : [[1],[2,3],[4],[5,6,7],[],[3],[2],[7],[6],[5]]
!             -- index into it: [2]
\$\endgroup\$
2
\$\begingroup\$

R, 58 bytes

function(M,n)c(M,unlist(lapply(M[lengths(M)>1],rev)))[[n]]

Try it online!

Takes M as a list of vectors c(); so replacing [[ with list(, [ with c( and ] with ) should transform the test cases into R test cases.

For inputs n<=4 with "undefined behavior", returns NULL and for other invalid inputs, throws a "subscript out of bounds" error.

function(M,n)
                                        [[n]]	# take the nth element of
c(M,                                   )	# M concatenated with:
    unlist(                           )		# the individual elements of
           lapply(               ,rev)		# in-place reversals of
                  M[lengths(M)>1]		# elements of M with length > 1
\$\endgroup\$
  • \$\begingroup\$ Could probably get away with using [n] instead of [[n]]. \$\endgroup\$ – JAD May 21 '18 at 15:28
2
\$\begingroup\$

Stax, 12 14 13 bytes

àJ├∙ε╝F▀ÿi☻Ia

Run and debug it

Explanation:

vsc{%vfr$r+@]|u Full program, unpacked, implicit input
vs              Decrement the number and get the list
  c{  f         Copy and filter:
    %v            Length not equal to 1?
       r$r      Reverse, flatten, and reverse again
          +     Concat orig array and and modified array
           @]|u Index, wrap into array, uneval

Stax, 12 bytes

Å{b≈\☼╣Δ@░ ‼

Unpacked:

{vsc{%vfr$r+@}

This is a block, so I can get rid of the ]|u, but I don't know if this is valid as it's packing a block.

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

J, 33 22 bytes

-11 bytes (1/3 shorter) thanks to FrownyFrog's solution!

{0;],|.&.>;/@;@#~1<#&>

Try it online!

My initial solution:

J, 33 bytes

<:@[{(,[:<"0@;[:|.&.>(1<#)&>#])@]

Not happy - I'm pretty sure it can be golfed much further.

Explanation:

A dyadic function, taking the clipboard state as its rigth argument, the left argument is n

<:@[ subtract 1 from the left argument

{ selects the ith element (calculated above) from the list on its right

(...) the entire list

# copy

] from the list of clipboard state

(1<#) the sublists with length greater than 1

|.&.> rotate each copied sublist

<"0@; raze and box - puts each number into a separate box

, append the new list to the list of clipboard state

@] makes the entire verb in (...) monadic

Try it online!

\$\endgroup\$
  • \$\begingroup\$ @FrownyFrog I like 0; the most. Thanks! \$\endgroup\$ – Galen Ivanov May 22 '18 at 14:25
  • \$\begingroup\$ That’s entirely your solution, just golfed :) \$\endgroup\$ – FrownyFrog May 22 '18 at 14:35
2
\$\begingroup\$

V + coreutils, 53 45 43 42 40 bytes

-9 bytes thanks to DJMcMayhem (using VGÇ /d over :,$g/^[^ ]*$/d, D@"dd over "aDÀdd and !! over :.!)!

My very first attempt at V (tips welcome!), the below code is using circled characters (eg. for \xf) for readability:

jäGⓞVGÇ /d
ⓞò!!tr \  \\n|tac
jòHD@"ddjdG

Try it online!

Hexdump

00000000: 6ae4 470f 5647 c720 2f64 0a0f f221 2174  j.G.VG. /d...!!t
00000010: 7220 5c20 205c 5c6e 7c74 6163 0a6a f248  r \  \\n|tac.j.H
00000020: 4440 2264 646a 6447                      D@"ddjdG

Explanation

The first line contains n and the lines below contain the entries of the clipboard, each entry is separated by spaces if there were multiple inputs:

j                        " move to the beginning of the clipboard entries
 äG                      " duplicate the clipboard
   ⓞ                    " <C-o> move cursor to the beginning of the 2nd copy
     VG                  " select everything from cursor to the end of buffer and ..
       Ç /d              " .. delete every line that doesn't contain a space

ⓞ                       " <C-o> move cursor to the beginning of the 2nd copy (now without single arguments)
  ò                   ò  " do the following until the end of buffer
   !!                    "   on the current line execute the shell command
     tr \  \\n           "   replace spaces with newlines
              |tac⮠     "   and reverse the lines
                    j    "   move to next line

H                        " go to the beginning of buffer (where n is)
 D                       " delete n (stores it in register ")
  @"                     " that many times ..
    dd                   " .. remove the line
      j                  " move cursor to next line
       dG                " delete everything from here to the end of buffer
\$\endgroup\$
1
\$\begingroup\$

Red, 91 bytes

func[b n][a: copy[]foreach c b[if 1 < length? c[append a reverse copy c]]pick append b a n]

Try it online!

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

C (gcc), 176 bytes

#define p printf("%d ",
int*_,i;f(x,n)int**x;{if(n<5){for(_=x[2*n-2];_-x[2*n-1];++_)p*_);}else{n-=4;for(i=0;i<8;i+=2)if(n&&x[i]+1-x[i+1])for(_=x[i+1];_-x[i]&&n;--_,--n);p*_);}}

Try it online!

Takes the array as a list of 4 start/end pointer pairs, then n.

Description:

#define p printf("%d ",  // This gives us the short-hand for printing
int*_,                   // This defines _ as a pointer to int
i;                       // This defines i as an integer
f(x,n)int**x;{           // This defines f as a function taking int **x and int n
                         // NOTE: x is {start, end, start, end, start, end, start, end}
if (n<5) {               // This is for the 1-4 case
  for(_=x[2*n-2];        // Loop _ from the 'end pointer' 
  _-x[2*n-1];++_)        // Until the 'start pointer'
  p*_);                  // Using the short-hand, print *_
}else{                   // This is for the 5+ case
  n-=4;                  // Cut n to improve indexing
  for(i=0;i<8;i+=2)      // Loop over each 'start pointer index'
    for(_=x[i+1];        // Loop _ from the 'end pointer'
        _-x[i]&&n;       // Until the 'start pointer' or n becomes 0
        --_,--n);        // Decreasing n each time
  p*_);}}                // _ now points to the 'correct' index, so print it
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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