Функція буфера обміну: копія


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
Ерік Атголфер

1
Це буфер обміну M?
Джузеппе

1
@Giussepe Рівно! Я не згадував це ім'я тут, тому що ми не використовуємо функцію M. Я зроблю це у виклику "вставити"
Луїс Мендо

Відповіді:


3

05AB1E , 20 байт

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

Спробуйте в Інтернеті!

-4 подяки Еміньї (а також -8 завдяки йому оновлення мене щодо правил).

  • U: a
  • +: b

4
:( ... Чому так seRïõS?
Луїс Мендо

@LuisMendo Ця оцінка настільки seRïõSly £ arge. :(
Ерік Аутгольфер


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, +s rdnFPrp+. У постійному струмі rпідміняє два найпопулярніших елемента стека, dдублює верхній елемент, nдрукує його без нового рядка, Fнатискає 15 на стек і Pдрукує його як символ (який є роздільником), rзнову поміняє місцями, pдрукує верхній елемент стека і потім +виконує додаток у двох перших елементах стеку.

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

В останній команді підстановки Uзамінюється глобально на p2^. У постійному струмі pдрукується та 2^піднімає його на другу потужність.

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

Труба до постійного струму змушує dc інтерпретувати це як код dc. Тепер найсвіжіші дзвінки внизу, а старіші вгорі.

Оскільки лінії розташовані у зворотному порядку, для їх фіксації використовується tac(зворотний cat).

І нарешті, sed вибирає перші 4 рядки від tac.

Це коротший спосіб виконання head -4. sed виконує команди для кожного вхідного рядка по одному. Якщо немає команд, нічого не робиться на вхід, і він повертається як є. 4qповідомляє sed виконувати команду qв рядку 4. Коли sed обробляє лінію 4 входу, перші три входи вже надруковані. Команда qвиходить з програми, тому вона друкує четвертий рядок і закриває, виконуючи таким чином еквівалент head -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 + +", і повертає список списків цілих чисел: [[11,28],[12,16],[4],[5,6]]. Спробуйте в Інтернеті!



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 байт

Упав 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])}

Спробуйте в Інтернеті!


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)

Спробуйте в Інтернеті!

Якби тільки Октав мав popсинтаксис. m- буфер обміну пам'яті, tстек.


Ви могли б сконструювати mі tв зворотному порядку, додаючи елементи спереду, а не до кінця?
Джузеппе

178 байт, використовуючи стратегію, викладену вище
Джузеппе

@Guiseppe Clever. У мене завжди таке відчуття, що додавання, як правило, коротше, ніж попереднє, але в цьому випадку велика кількість "кінцевих" повинно було змусити мене переглянути
Санчіз


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


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");}

Спробуйте в Інтернеті!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.