Функция буфера обмена: копировать

17

Эта проблема связана с некоторыми возможностями языка MATL в рамках мероприятия « Язык месяца», который состоится в мае 2018 года . Сопутствующий вызов : Функция буфера обмена: вставка .


Вступление

MATL имеет несколько буферов обмена , где вы можете хранить значения (копировать), которые будут получены позже (вставить). Некоторые буферы обмена являются автоматическими , что означает, что копирование автоматически инициируется определенными событиями. Эта задача фокусируется на одной из автоматических буферов обмена, называемых буфером ввода функций или просто буфером функций .

В этом буфере обмена хранятся входы для четырех самых последних вызовов обычных функций ввода. Нормальные функции - самый распространенный тип функций в MATL. Получение ввода означает, что функция принимает по крайней мере один вход (функции, которые не принимают никакого ввода, не рассматриваются буфером функций).

Это лучше всего объяснить с помощью следующих примеров, в которых используются две нормальные функции:

  • +, который извлекает два числа из стека и выталкивает их сумму.
  • U, который выскакивает одно число и толкает его квадрат.

Пример 1 :

3 2 + 6 + 12 4 U + +

дает результат 39. Код интерпретируется следующим образом:

  • Числовые литералы, такие как 3или 12выталкиваются в стек
  • Такие функции, как +выталкивание их входов и помещение их выходов в стек.

Вызовы функций в хронологическом порядке:

  1. 3 2 + дает 5
  2. 5 6 + дает 11
  3. 4 U дает 16
  4. 12 16 + 28
  5. 11 28 +дает 39.

Буфер обмена можно просматривать как список из четырех списков. Каждый внутренний список содержит входные данные для вызова функции, причем самые последние вызовы выполняются первыми . Внутри каждого внутреннего списка входы находятся в их первоначальном порядке .

Итак, после запуска кода содержимое буфера обмена (в нотации Python):

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

Пример 2 :

10 20 U 30 +

оставляет номера 10и 430в стеке. Стек отображается снизу вверх в конце программы.

Вызовы функций

  1. 20 U дает 400
  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 Нет, входные данные в каждом внутреннем списке должны быть в исходном порядке, то есть как при вызове функции
Луис Мендо
Хм, мы обескуражены, а, просто решить это в MATL? : P
Эрик Outgolfer
1
Это буфер обмена M?
Джузеппе
1
@Giussepe Точно! Я не упомянул это имя здесь, потому что мы не используем функцию M. Я сделаю это в вызове «вставить»
Луис Мендо

Ответы:

3

05AB1E , 20 байтов

A"D¸ˆn‚DˆO"4ô‡.V¯R4£

Попробуйте онлайн!

-4 спасибо Эмигне (а также -8 благодаря тому, что он сообщил мне о правилах).

  • U: a
  • +: b
Эрик Outgolfer
источник
4
:( ... Почему так много?
Луис Мендо
@LuisMendo Эта оценка настолько серьезна. :(
Эрик Outgolfer
Давайте продолжим эту дискуссию в чате .
Эрик Outgolfer
5

Баш , 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, где каждый +заменяется на rdnFPrp+, который в dc печатает второе число в стеке, за которым следует \ x0F, а затем верхнее число перед выполнением сложения. sed также заменяет каждый Uна p2^, печатает верхний элемент стека и возводит его в квадрат.

Первая команда замещения sзаменяет все, как обозначено флагом g lobal g, +на rdnFPrp+. В dc rменяются два верхних элемента стека, dдублируется верхний элемент, nпечатается его без новой строки, Fпомещается 15 в стек и Pпечатается как символ (который является разделителем), rснова выполняется свопинг, pпечатается верхний элемент стека, а затем +выполняется добавление в верхние два стека предметов.

У нас есть другая команда, и в sed команды отделяются точкой с запятой или новой строкой, из которых выбирается первая опция. Простое наличие ;заставит bash интерпретировать это как конец команды sed, так что оно экранируется с помощью a \.

В последней команде Uзамещения глобально заменяется на p2^. В dc pпечатает и 2^поднимает его до второй степени.

Результат sed оценивается как код постоянного тока, распечатывая весь буфер обмена.

Канал к dc заставляет dc интерпретировать это как код dc. Теперь самые последние звонки находятся внизу, а самые старые - вверху.

Поскольку линии расположены в обратном порядке, tac(обратное cat) используется для исправления этого.

И, наконец, sed выбирает первые 4 строки из TAC.

Это более короткий способ сделать head -4. sed выполняет команды для каждой строки ввода по одной за раз. Если нет команд, ничего не делается для ввода, и он возвращается как есть. 4qговорит sed выполнить команду qв строке 4. Когда sed обрабатывает строку 4 ввода, первые три ввода уже были напечатаны. Команда qвыходит из программы, поэтому печатает четвертую строку и выходит, выполняя, таким образом, эквивалент head -4.

Kritixi Lithos
источник
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 + +", и возвращает список списков целых чисел: [[11,28],[12,16],[4],[5,6]]. Попробуйте онлайн!

Laikoni
источник
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)

Попробуйте онлайн!

В классическом чистом стиле это решение Haskell, за исключением примерно на 50% длиннее.

Οurous
источник
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
Arnauld
источник
2

Go, 305 303 295 байт

Удалил 8 байтов благодаря @ovs

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])}

Попробуйте онлайн!

ollien
источник
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стек.

Sanchises
источник
не могли бы вы построить mи tнаоборот, добавив элементы вперед, а не в конец?
Джузеппе
178 байт с использованием стратегии, изложенной выше
Джузеппе
@Guiseppe Умный. У меня всегда есть чувство, что добавление обычно короче, чем добавление, но в этом случае большое количество «концов» должно было заставить меня пересмотреть
свое
1

Python 3 , 218 204 байта

-14 байт благодаря овсу

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])

Попробуйте онлайн!

Draconis
источник
1

Красный , 335 330 байт

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={}.

Giuseppe
источник
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");}

Попробуйте онлайн!

ErikF
источник