功能剪贴板:复制


17

作为2018年5月每月语言活动的一部分,此挑战与MATL语言的某些功能有关 相关挑战功能剪贴板:粘贴


介绍

MATL有几个剪贴板,您可以在其中存储值(副本)以供以后检索(粘贴)。某些剪贴板是自动的,这意味着某些事件会自动触发复制。这项挑战着眼于自动剪裁工具之一,称为功能输入剪贴板,或简称为功能剪贴板

该剪贴板将输入存储到最近四个对常规输入函数的调用。普通函数是MATL中最常见的函数类型。输入接受意味着该功能至少接受一个输入(功能剪贴板不考虑不接受任何输入的功能)。

最好使用以下示例解释这些示例,这些示例使用两个常规函数:

  • +,这会从堆栈中弹出两个数字并压入它们的和。
  • U,它会弹出一个数字并按其平方。

范例1

3 2 + 6 + 12 4 U + +

产生结果39。该代码解释如下:

  • 数字文字,例如3或被12压入堆栈
  • 诸如此类的功能会+弹出其输入,并将其输出推入堆栈。

按时间顺序排列的函数调用为:

  1. 3 2 +5
  2. 5 6 +11
  3. 4 U16
  4. 12 16 + 28
  5. 11 28 +39

剪贴板可以视为四个列表的列表。每个内部列表都包含函数调用的输入,最近的调用在前。在每个内部列表中,输入均按其原始顺序

因此,在运行代码之后,剪贴板的内容是(用Python表示法):

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

范例2

10 20 U 30 +

留下数字10430放在堆栈上。在程序结束时,堆栈从下至上显示。

函数调用是

  1. 20 U400
  2. 400 30 +430

由于只有两个函数调用,因此定义剪贴板的一些内部列表将为。还要注意如何10不用作任何功能的输入。

因此,运行代码后的剪贴板内容为:

[[400, 30], [20], [], []]

示例3(无效):

10 20 + +

被认为是无效的,因为+缺少第二个输入(在MATL中这将隐式触发用户输入)。

挑战

输入:一个字符串S,带有数字文字,+并且U用空格分隔。

输出:评估字符串S之后功能剪贴板的内容。

说明:

  • 您可以使用任何两个一致的符号来表示那些功能,而不是数字。另外,您可以使用任何一致的符号作为分隔符,而不是空格。
  • 仅考虑两个指示的功能。
  • 输入字符串将包含至少一个数字文字和至少一个函数。
  • 所有数字都是正整数,可能超过一个数字。
  • 如示例2所示,某些函数可能不使用某些数字文字。
  • 输入被保证是有效的代码,不需要其他数字。因此,示例3中的字符串将永远不会出现。
  • 输出中的尾随空内部列表可以忽略。因此,示例2中的结果可以是[[400, 30], [20]]
  • 任何合理,明确的输出格式都是可以接受的。例如,一个字符串,以逗号作为内部分隔符,以分号作为外部分隔符:400,30;20;;

附加规则:

测试用例

Input
Output

3 2 + 6 + 12 4 U + +
[[11, 28], [12, 16], [4], [5, 6]]

15 3 4 + 2 U 8 + U +
[[7, 144], [12], [4, 8], [2]]

3 6 9 12 + + 10 8 U 6
[[8], [6, 21], [9, 12], []]

8 41 12 25 4 5 33 7 9 10 + + + + + + + +
[[41, 105], [12, 93], [25, 68], [4, 64]]

10 1 1 + U U U U U
[[65536], [256], [16], [4]]

[[28, 11], [16, 12], [4], [6, 5]]第一个示例是否有效?
ovs '18年

@ovs否,每个内部列表中的输入必须按原始顺序进行,即,如函数调用中所示
Luis Mendo

嗯,我们不鼓励,只是在MATL中解决这个问题吗?:P
暴民埃里克(Erik the Outgolfer)'18年

1
这是剪贴板M吗?
朱塞佩

1
@朱塞佩没错!我在这里没有提到该名称,因为我们没有使用function M。我将在“粘贴”挑战中做到这一点
Luis Mendo,

Answers:



5

Bash,43个字节

sed s/+/rdnFPrp+/g\;s/U/p2^/g|dc|tac|sed 4q

在线尝试!

这将以以下格式打印剪贴板,请注意\ x0F作为分隔符的用法。

item_1\x0Fitem_2
item_3
.
.
item_m\x0Fitem_n

关键思想是将其传递给dc(一种基于堆栈的语言),以便将需要的堆栈项目打印出来。

输入通过管道传输到sed,在其中s +替换为rdnFPrp+,sd在dc中将在堆栈上打印第二个数字,然后是\ x0F,然后是在执行加法运算之前的第一个数字。sed的替换也每Up2^,打印栈顶元素,将其平方。

第一替换命令s替换所有,如由表示为叶形标志g+以s rdnFPrp+。在dc中,r交换顶部的两个堆栈项目,d复制顶部的项目,将其n打印而不用换行符,F将15推入堆栈,并将其P打印为字符(这是定界符),r再次交换,p打印顶部的堆栈项目,然后+执行顶部两个堆栈项上的加法。

我们有另一个命令,并且在sed中,命令之间用分号或换行符分隔,已选择了第一个选项。简单地;将使bash将其解释为sed命令的结尾,因此可以使用进行转义\

在最后一个替换命令中,U全局替换为p2^。以dc p打印,并将其2^提高到第二幂。

sed的结果被评估为dc代码,打印整个剪贴板。

通往dc的管道使dc将其解释为dc代码。现在,最近的通话在底部,较旧的通话在顶部。

由于这些行的顺序tac相反,cat因此使用(reverse )可以解决此问题。

最后,sed从tac中选择前4行。

这是一种较短的方法head -4。sed一次对输入的每一行执行命令。如果没有命令,则对输入不执行任何操作,并按原样返回。4q告诉sed q在第4行执行命令。当sed是输入的第4行处理时,前三个输入已经被打印。该命令q退出程序,因此它打印第四行并退出,从而执行的等效功能head -4


4

Python 2,126字节

s=[0];b=[]
for c in input().split():k='U+'.find(c)+1;b=[s[k-1::-1]][:k]+b;s=[int([c,s[0]**2,sum(s[:2])][k])]+s[k:]
print b[:4]

在线尝试!


4

Haskell中113个 109字节

take 4.([]#).words
x:y:s#"+":r=(x+y:s#r)++[[y,x]]
x:s#"U":r=(x*x:s#r)++[[x]]
s#n:r=read n:s#r
_#_=[]
infix 4#

第一行定义了一个匿名函数,该函数接受一个字符串,例如"3 2 + 6 + 12 4 U + +",并返回一个ints:列表[[11,28],[12,16],[4],[5,6]]在线尝试!


2

干净的 140字节

import StdEnv,Text
k[a,b:n]["+":s]=k[a+b:n]s++[[b,a]]
k[a:n]["U":s]=k[a^2:n]s++[[a]]
k n[v:s]=k[toInt v:n]s
k _[]=[]
$s=k[](split" "s)%(0,3)

在线尝试!

在经典的Clean风格中,它是Haskell解决方案,但要长大约50%。


2

JavaScript(ES6),107个字节

将输入作为由整数'+'和组成的列表'U'。返回另一个列表,该列表由整数,2个整数的数组以及'_'空插槽组成。

a=>a.map(x=>s.push(+x?x:(c=[x>[a=s.pop(),r=a*a]?a:[r=s.pop(),(r+=a,a)],...c],r)),s=[c='___'])&&c.slice(0,4)

在线尝试!

已评论

a =>                          // a[] = input array
  a.map(x =>                  // for each entry x in a[]:
    s.push(                   //   update the stack:
      +x ?                    //     if x is a positive integer:
        x                     //       push x onto the stack
      :                       //     else:
        ( c = [               //       update the clipboard:
            x > [             //         compare x with '['
              a = s.pop(),    //         a = first operand
              r = a * a       //         use a² as the default result
            ] ?               //         if x is 'U' (greater than '['):
              a               //           save the 1st operand in the clipboard
            :                 //         else:
              [ r = s.pop(),  //           r = 2nd operand
                (r += a, a)   //           add the 1st operand
              ],              //           save both operands in the clipboard
            ...c              //         append the previous clipboard entries
          ],                  //       end of clipboard update
          r                   //       push r onto the stack
        )                     //
    ),                        //     end of stack update
    s = [c = '___']           //   initialize the stack; start with c = '___'
  ) &&                        // end of map()
  c.slice(0, 4)               // return the last 4 entries of the clipboard

2

围棋,305个 303 295字节

@ovs减少了 8个字节

func e(s string){b,v,w,x,r:=[][]int{{},{},{},{}},[]int{},0,0,0;for _,d:=range Split(s," "){if d=="+"{w,x,v=v[0],v[1],v[2:];r=w+x;b=append([][]int{[]int{x,w}},b...)}else if d=="U"{w,v=v[0],v[1:];r=w*w;b=append([][]int{[]int{w}},b...)}else{n,_:=Atoi(d);r=n};v=append([]int{r},v...)};Print(b[0:4])}

在线尝试!


2

八度,206字节

s=strsplit(input(''));m=t=[];for z=s
if(q=str2num(p=z{1}))t=[t q];else
if(p-43)m{end+1}=(k=t(end));t(end)=k^2;else
m{end+1}=(k=t(end-1:end));t(end-1:end)=[];t(end+1)=sum(k);end
end
end
m(1:end-4)=[];flip(m)

在线尝试!

如果只有Octave有pop语法。m是内存剪贴板,t即堆栈。


你可以构建mt在倒车时,将元素添加到前面,而不是结束了吗?
朱塞佩

使用上述策略的178个字节
朱塞佩

@Guiseppe聪明。我总是有一种感觉,追加通常比前置短,但是在这种情况下,大量的“结束”应该让我重新考虑
Sanchises

1

Python 3中218个 204字节

-14字节归功于ovs

from collections import*
def f(s):
	a=deque(maxlen=4);z=a.appendleft;b=[];x=b.pop
	for i in s.split():
		if'+'==i:c=x(),x();z(c);r=sum(c)
		elif'U'==i:c=x();z(c);r=c*c
		else:r=int(i)
		b+=r,
	print([*a])

在线尝试!


1

红色335330字节

func[s][b: copy[]foreach c split s" "[append b either c >"+"and(c <"U")[do c][c]]r: copy[]until[t: 0 until[not parse
b[to copy c[2 integer!"+"](insert/only r reduce[c/1 c/2]replace b c c/1 + c/2 t: 1)to end]]until[not parse b[to copy
c[integer!"U"](insert/only r to-block c/1 replace b c c/1 ** 2 t: 1)to end]]t = 0]take/part r 4]

在线尝试!

更具可读性:

f: func[s] [
    s: split s " "
    b: copy []
    foreach c s [
        append b either (c > "+") and (c < "U")[do c] [c]
    ]
    r: copy []
    until [
        t: 0
        until [
            not parse b [to copy c[2 integer! "+"]
            (insert/only r reduce[c/1 c/2]
            replace b c c/1 + c/2
            t: 1)
            to end]
        ]
        until [
            not parse b [to copy c[integer! "U"]
            (insert/only r to-block c/1
            replace b c c/1 ** 2
            t: 1)
            to end]
        ]
        t = 0
    ]
    take/part r 4  
]

1

[R 205个 182字节

function(P){S=F
M=list()
for(K in el(strsplit(P," "))){if(is.na(x<-strtoi(K))){if(K>1){M=c(m<-S[1],M)
S[1]=m^2}else{M=c(list(m<-S[2:1]),M)
S=c(sum(m),S[-2:0])}}else S=c(x,S)}
M[1:4]}

在线尝试!

M是内存剪贴板,P是程序,S也是堆栈。

从技术上讲,它S被初始化为一个包含单个零的向量,但是由于我们从未收到无效的输入,因此它为我节省了一个字节S={}


1

C(gcc),264字节

我使用了递归,以便可以将函数堆栈用作数据堆栈:遍历输入列表并执行操作:结果以相反的顺序显示,不显示堆栈推入。

堆栈被实现为链接列表。运作方式如下:

  • 使用[指向值的指针,指向上一个节点的指针]设置当前节点
  • 要推送一个值,将存储该值,并使用当前节点再次调用该函数。
  • 要弹出值或修改堆栈顶部的值,将修改前一个节点的值,并使用前一个节点再次调用该函数。

最初,我为节点使用一种结构,但是为了节省空间,我切换到了裸指针。此链接列表的一个有趣功能是,当递归完成时,它会自行清理。

#define _ printf
f(char**s,int**p){int**w,v,*y[]={&v,p},m,n,t,z;w=y;z=1;return(*s?(**s-85?**s-43?(--z,t=14,v=atoi(*s)):(t=6,w=p[1],m=**w,**w+=n=**p):(t=0,w=p,**w*=m=**p),v=f(s+1,w),_(v<4?",[%d]\0,[%d,%d]\0"+t+!v:"",m,n),v+z):0);}g(char**s){_("[");f(s,0);_("]\n");}

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.