Зброя з математики


44

Минулого разу, коли я намагався придумати щось легке, що не було дублікатом, це виявилося занадто важким. Тож, сподіваємось, цього разу справді щось теж може спробувати новачок.

Вхід:

Масив / список із цілими числами / десятковими знаками. (Або рядок, що представляє масив з цілими числами / десятковими знаками.)

Вихід:

Проведіть цикл через числа та застосуйте наступні п'ять математичних операндів у цьому порядку:

  • Доповнення ( +);
  • Віднімання ( );
  • Множення ( *або ×або ·);
  • Відділ реального / калькулятора ( /або ÷);
  • Експоненція ( ^або **).

(ПРИМІТКА. Символи між дужками просто додаються як уточнення. Якщо ваша мова програмування використовує зовсім інший символ для математичної операції, ніж приклади, то це, звичайно, цілком прийнятно.)

Продовжуйте продовжувати, поки ви не досягнете кінця списку, а потім дайте результат суми.

Правила виклику:

  • Експоненція на 0 ( n ^ 0) повинна спричинити 1 (це також стосується 0 ^ 0 = 1).
  • Немає тестових випадків для поділу на 0 ( n / 0), тому вам не доведеться турбуватися про цей крайній випадок.
  • Якщо масив містить лише одне число, ми повертаємо це як результат.

Загальні правила:

  • Це , тому найкоротша відповідь у байтах виграє.
    Не дозволяйте мовам коду-гольфу відштовхувати вас від публікації відповідей з не кодовими гольф-мовами. Спробуйте придумати якомога коротшу відповідь на "будь-яку" мову програмування.
  • Стандартні правила діють для вашої відповіді, тому вам дозволяється використовувати STDIN / STDOUT, функції / метод з відповідними параметрами, повноцінні програми. Твій дзвінок.
  • Лазівки за замовчуванням заборонені.
  • Якщо можливо, додайте посилання з тестом для вашого коду.

Тестові приклади:

[1,2,3,4,5] -> 0
-> 1 + 2 = 3
  -> 3 - 3 = 0
    -> 0 * 4 = 0
      -> 0 / 5 = 0 

[5,12,23,2,4,4,2,6,7] -> 539
-> 5 + 12 = 17
  -> 17 - 23 = -6
    -> -6 * 2 = -12
      -> -12 / 4 = -3
        -> -3 ^ 4 = 81
          -> 81 + 2 = 83
            -> 83 - 6 = 77
              -> 77 * 7 -> 539

[-8,50,3,3,-123,4,17,99,13] -> -1055.356...
-> -8 + 50 = 42
  -> 42 - 3 = 39
    -> 39 * 3 = 117
      -> 117 / -123 = -0.9512...
        -> -0.9512... ^ 4 = 0.818...
          -> 0.818... + 17 = 17.818...
            -> 17.818... - 99 -> -81.181...
              -> -81.181... * 13 = -1055.356...

[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] -> 256
-> 2 + 2 = 4
  -> 4 - 2 = 2
    -> 2 * 2 = 4
      -> 4 / 2 = 2
        -> 2 ^ 2 = 4
          -> 4 + 2 = 6
            -> 6 - 2 = 4
              -> 4 * 2 = 8
                -> 8 / 2 = 4
                  -> 4 ^ 2 = 16
                    -> 16 + 2 = 18
                      -> 18 - 2 = 16
                        -> 16 * 2 = 32
                          -> 32 / 2 = 16
                            -> 16 ^ 2 = 256

[1,0,1,0,1,0] -> 1
-> 1 + 0 = 1
  -> 1 - 1 = 0
    -> 0 * 0 = 0
      -> 0 / 1 = 0
        -> 0 ^ 0 = 1

[-9,-8,-1] -> -16
  -> -9 + -8 = -17
    -> -17 - -1 = -16

[0,-3] -> -3
  -> 0 + -3 = -3

[-99] -> -99

Не ціле ділення?
Ліна монашка

@LeakyNun Ні. Можливо, мені слід змінити вхід до списку з десятковою комою замість цілих чисел через поділ (і тестовий випадок 3)?
Кевін Круїйсен

Це було в пісочниці?
Балінт

9
У математиці є два суперечливих "правила":, n ^ 0 = 1але 0 ^ n = 0. Конфлікт вирішується шляхом встановлення n != 0обох правил, але потім він залишається 0 ^ 0невизначеним. Однак є багато речей, які непогано стають на місці в математиці, якщо 0 ^ 0це визначено 1. Детальну інформацію див. У Вікіпедії .
Mego

1
@ Bálint Правила вказують, що ніколи не буде дійсного вводу з діленням на нуль. Вам не доведеться турбуватися про цей крайній випадок.
Mego

Відповіді:


7

Желе , 13 байт

“+_×÷*”ṁṖ⁸żFV

Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Як це працює

“+_×÷*”ṁṖ⁸żFV  Main link. Argument: A (list of integers)

“+_×÷*”        Yield the list of operations as a string.
        Ṗ      Yield A popped, i.e., with its last element removed.
       ṁ       Mold; reshape the string as popped A.
               This repeats the characters of the string until it contains
               length(A)-1 characters.
         ⁸ż    Zipwith; pairs the integers of A with the corresponding characters.
           F   Flatten the result.
            V  Eval the resulting Jelly code.
               Jelly always evaluates left-to-right (with blatant disregard towards
               the order of operations), so this returns the desired result.

Приємно, що на 8 балів нижче , ніж у Pyke , який наразі лідирував.
Кевін Круїйсен

3
Ніхто не перевершує Денніса. Ніколи.
Синій

1
Лише запитання: чи насправді він рахує 13 байт з усіма цими символами, які не є ascii?
Ксав'є Дарі

3
@XavierDury Так. Посилання байтів у заголовку призводить до власної кодової сторінки Jelly, яка кодує 256 символів, які Jelly розуміє як один байт кожен.
Денніс

@Dennis Дякую за точність!
Ксав'є Дюрі

19

Javascript ES7 49 байт

a=>a.reduce((c,d,e)=>[c**d,c+d,c-d,c*d,c/d][e%5])

Збережено 9 байт завдяки Дому Гастінгсу, ще 6 завдяки Лекі Монахині

Використовується новий оператор експоненції.


@LeakyNun це не просто призведе Infinity, а не помилка?
Дом Гастінгс

Спробуйте використовувати eval, можливо, це буде коротше
Downgoat

@Upgoat Спочатку він використовував eval, потім Leaky Nun показав мені, що краще, так робити
Bálint

@ Bálint, ти, як, використовуючи стільки коми?
Rɪᴋᴇʀ

1
@ EᴀsᴛᴇʀʟʏIʀᴋ Немовна спікерка. Часто так робить Балінт. Англійська граматика нерозумна в найкращі часи.
wizzwizz4

11

Haskell, 76 65 64 62 байт

Дякуємо @Damien за видалення ще двох байтів =)

f(u:v)=foldl(\x(f,y)->f x y)u(zip(v>>[(+),(-),(*),(/),(**)])v)

Тут використовується те, >>що тут просто додає список [(+),...]до себе length vразів. Решта як і раніше працює так само, як і старі версії.

Старі версії:

Ці рішення використовують нескінченні списки, оскільки cycle[...]просто повторюють даний список нескінченно. Тоді він в основному zipредагується зі списком чисел, і ми просто fold( скорочуємо іншими мовами) список зіштовхується через лямбда, що застосовує операторів до елемента списку акумулятора / поточного.

f(u:v)=foldl(\x(f,y)->f x y)u(zip(cycle[(+),(-),(*),(/),(**)])v)

f(u:v)=foldl(\x(y,f)->f x y)u(zip v(cycle[(+),(-),(*),(/),(**)]))

f l=foldl(\x(y,f)->f x y)(head l)(zip(drop 1l)(cycle[(+),(-),(*),(/),(**)]))

Ви можете замінити цикл на: v >>
Дамієн

@Damien Дуже дякую!
flawr

Гм foldl(&)u$zipWith(&)v(flip<$>v>>[…]),?
Бергі

@Bergi я чесно не можу читати те , що це робить більше =) У будь-якому випадку, нам потрібно importдля &, так що буде більше разів, але все одно спасибі!
недолік

@flawr: Насправді моя ідея була зовсім такою ж, як і Лазерсмоке, яку я опублікував як відповідь , я просто не прочитав її. Я дістався до цього, намагаючись спростити цю свою ламду чимось подібним uncurry. Не вийшло, але я помітив, що ви повинні мати можливість зберегти ще один байт, використовуючи $замість дужок.
Бергі


7

Хаскелл, 61 байт

foldl(flip id)0.zipWith flip((+):cycle[(+),(-),(*),(/),(**)])

Створює ряд перетворень у списку, як у [додавання 1, додавання 2, віднімання 3, ...], починаючи з 2 додавань, тому що ми починаємо з 0 у складці. Далі ми робимо те, що я називаю список додатків Fold, або foldl (flip id), до якого послідовно застосовується список гомоморфізмів. Це починається з нуля, додає початкове значення, потім виконує всі перераховані вище обчислені перетворення, щоб отримати кінцевий результат.

Зауважте, що (flip id) те саме, що (\ x y-> yx), лише коротше.

Використання зразка:

f = foldl(flip id)0.zipWith flip((+):cycle[(+),(-),(*),(/),(**)])
f [1,2,3,4,5] -- Is 0.0

Замість цього flip idви можете просто використовувати &. Або flip($). Ого, я так і не зрозумів($) = id
Бергі

1
@Bergi: &визначено в Data.Function, тому вам також потрібен import. Можливо, якийсь інтернет-перекладач імпортує його за замовчуванням, але тоді вам потрібно вказати, який ви використовуєте.
nimi

7

TSQL 116 115 88 байт

Завдяки пропозиції Росса Пресера, я зміг переграти це на 88 символів

-- In Try-it code, this must be DECLARE @y TABLE 
CREATE TABLE T(a real, i int identity)
INSERT T values(5),(12),(23),(2),(4),(4),(2),(6),(7)

DECLARE @ REAL SELECT @=CHOOSE(i%5+1,@/a,ISNULL(POWER(@,a),a),@+a,@-a,@*a)FROM T
PRINT @

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


1
На 1 байт менше: вимагайте, щоб таблицю введення було названо T замість @y. У PL / SQL було таке рішення, то чому б не TSQL.
Росс Прессер

@RossPresser так, звичайно. як я пропустив це. У тестовому посиланні неможливо, немає дозволів на створення таблиць, і воно запуститься правильно лише перший раз у базі даних. Але що це має значення, коли персонаж може бути в гольфі. Дякуємо за підказку, ваше покращення додано
t-clausen.dk

Поставили ще 12 байт: використовуйте CHOOSE замість вкладеного IIF, залишаючи один IIF для i = 1 випадку. З вашого дозволу я відредагую відповідь.
Росс Пресер

відповідь відредагована. Ось посилання пробування
Ross

1
@RossPresser Я не знав ВИБІР. включив вашу пропозицію та пограв нею трохи далі
t-clausen.dk

6

Pyth, 27 26 25 байт

.v+>tlQ*lQ"^c*-+":jdQ\-\_

Тестовий набір.

Pyth використовує позначення префікса: 1+2пишеться як +1 2(простір, необхідний для розділення чисел).

Тому для першої тестової виразки буде вираз (((1+2)-3)*4)/5, який у позначеннях префікса буде записаний як /*-+ 1 2 3 4 5.

У Pyth поділ поплавця є c замість/ , так воно стає c*-+ 1 2 3 4 5.

Також у Pyth -100 написано як _100замість цього.

Таким чином, для третього випадку випробування, яке ((((((((-8+50)-3)*3)/-123)^4)+17)-99)*13), вона стає: *-+^c*-+ _8 50 3 3 _123 4 17 99 13.

.v+>tlQ*lQ"^c*-+":jdQ\-\_
                  jdQ       Join input by space.
                 :   \-\_   Replace "-" with "_".
   >tlQ*lQ"^c*-+"           Generate the string "...^c*-+" of suitable length.
  +                         Join the two strings above.
.v                          Evaluate as a Pyth expression.

Історія


Ви швидко! Здається, мені вдалося зробити легший виклик. Або ти просто ТОЙ хороший. ;)
Кевін Круїссен



6

Власне, 23 байти

;l"+-*/ⁿ"*@R':j':+'?o+ƒ

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

Насправді використовується позначення постфіксу для математики, і оператори, які коли-небудь беруть два аргументи (такі як оператори для додавання, віднімання, множення, ділення та експоненціації), нічого не роблять, коли на стеку є лише один елемент. Таким чином, перетворення вводу в фактично код є таким же простим, як і повернення вводу, форматування його як числових знаків та додавання операцій. Потім отриманий код можна виконати, даючи бажаний вихід.

Пояснення:

;l"+-*/ⁿ"*@R':j':+'?o+ƒ
;l"+-*/ⁿ"*               repeat the operations a number of times equal to the length of the input
                            (since extraneous operations will be NOPs, there's no harm in overshooting)
          @R             reverse the input
            ':j          join on ":" (make a string, inserting ":" between every pair of elements in the list)
               ':+       prepend a ":" (for the first numeric literal)
                  '?o    append a "?"
                           (this keeps the poor numeric parsing from trying to gobble up the first + as part of the numeric literal, since ? isn't interpreted as part of the literal, and is a NOP)
                     +   append the operations string
                      ƒ  cast as a function and call it

Приклад перекладеного коду для введення 1,2,3,4,5:

:5:4:3:2:1?+-*/ⁿ+-*/ⁿ+-*/ⁿ+-*/ⁿ+-*/ⁿ

3
Любіть те, як назва мови зливається з кількістю байтів
user6245072

3
s/Actually uses postfix notation/Actually actually uses postfix notation/
Лина монашка


5

J, 40 байт

^~`(%~)`*`(-~)`+/@(|.@,7#:~#&2)(5-5|4+#)

Знаходить кількість значень, необхідних для використання кратного 5 операторів, ніж колодки зі значеннями ідентичності цих операторів. Для того, щоб +це 0, -це 0, *це 1, %це 1, і ^це 1, що може бути бітовим значенням 00111, або 7 в базі 10. Потім працює над цим списком під час переходу через операторів.

Використання

   f =: ^~`(%~)`*`(-~)`+/@(|.@,7#:~#&2)(5-5|4+#)
   f 1 2 3 4 5
0
   f 5 12 23 2 4 4 2 6 7
539
   f _8 50 3 3 _123 4 17 99 13
_1055.36
   f 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
256
   f 1 0 1 0 1 0
1
   f _9 _8 _1
_16
   f 0 _3
_3
   f _99
_99

Пояснення

^~`(%~)`*`(-~)`+/@(|.@,7#:~#&2)(5-5|4+#) Input: A
                                      #  Get length of A
                                    4+   Add four to it
                                  5|     Take it mod 5
                                5-       Find 5 minus its value, call it x
                           #&2           Create x copies of 2
                       7#:~              Convert 7 to base 2 and take the last x digits
                      ,                  Append those x digits to the end of A
                   |.@                   Reverse it, call it A'
^~                                       Power, reversed operators
    %~                                   Division, reversed operators
       *                                 Multiplication
         -~                              Subtraction, reversed operators
            +                            Addition
             /@                          Insert the previous operations, separated by `,
                                         into A' in order and cycle until the end
                                         Then evaluate the equation from right-to-left
                                         and return

5

Python 2, 81 67 64 байт

i=10
for n in input():exec'r%s=n'%'*+-*/*'[i::5];i=-~i%5
print r

Вхід - це масив поплавків. Перевірте це на Ideone .

Як це працює

'*+-*/*'[i::5]вибирає кожен п'ятий символ рядка, починаючи з символу в індексі i , так що виходить, **якщо i = 0 , +якщо i = 1 , -якщо i = 2 , *якщо i = 3 і /якщо i = 4 . Оскільки рядок має довжину 6 , вираз дасть порожній рядок, якщо i> 5 .

Ініціалізуємо змінну i до 10 . Для кожного числа n у вхідному масиві будуємо рядок r<op>=n, якийexec виконується.

Спочатку i = 10 , так <op>це порожній рядок, і він ініціалізує r з r+=n. Після кожного кроку ми збільшуємо i modulo 5 сi=-~i%5 , тому наступним кроком буде відновлення належного оператора.

Коли всі вхідні числа були оброблені, ми друкуємо r , що містить потрібний вихід.


5

Матлаб - 95 91 85 байт / Октава - 81 байт

Введення здійснюється у такій формі: a = ['1' '2' '3' '4' '5']; я сподіваюся, що це охоплене "рядком, що представляє масив з цілими числами / десятковими знаками", ще є 2 num2str, необхідні додатково.

Кожен проміжний результат друкується на консолі, оскільки це зекономить мені крапки з комою. a(1)виконується, тому його значення зберігається в ans. Також звичайно використання ansв коді є поганою практикою.

b='+-*/^'
a(1)
for i=2:length(a)
  ['(',ans,')',b(mod(i-2,5)+1),a(i)]
end
eval(ans)

В Octave '+-*/^'(mod(i+2,5)+1)також працює, що зберігає ще 4 байти, завдяки Адаму та Луїсу Мендо:

a(1)
for i=2:length(a)
  strcat('(',ans,')','+-*/^'(mod(i-2,5)+1),a(i))
end
eval(ans)

Журнал змін:

  • Видалено пробіли, де це можливо
  • додали розчин Октава
  • замінено strcat () на []

Привіт, Ласкаво просимо до PPCG! Вхід є таким добре, оскільки це все ще легко відрізнити, що таке вхід. Хм, я ніколи не використовував Matlab, так що, може бути , я говорю ідіотські речі тут, але не може b = '+-*/^'бути golfed до b='+-*/^'і for i = 2:length(a)до for i=2:length(a)(видалення пробілів)? Також, можливо, Поради щодо гольфу в MATLAB можуть бути цікавими для вас. :)
Кевін Круїйсен

Чи '+-*/^'(mod(i+2,5)+1)дійсно?
Адам

@ Adám Ні, але це, мабуть, в Октаві
Луїс Мендо

@ Adám: це працює в Octave, я додав його.
Лукаш К.

4

Математика, 67 66 65 байт

Fold[{+##,#-#2,#2#,#/#2,If[#2==0,1,#^#2]}[[i++~Mod~5+1]]&,i=0;#]&

Простий Foldзі змінною, що iтримає індекс.


Байт можна зберегти, +##замість#+#2
LLlAMnYP

4

CJam, 18 байт

q~{"+-*/#"W):W=~}*

Вхід - це масив поплавків. Спробуйте в Інтернеті!

Як це працює

q~                  Read and evaluate all input.
  {             }*  Reduce:
   "+-*/#"            Push the string of operators.
          W           Push W (initially -1).
           ):W        Increment and save in W.
              =       Retrieve the character at that index.
               ~      Evaluate.

4

R , 87 78 70 байт

i=0
Reduce(function(a,j)get(substr("+-*/^",i<<-i%%5+1,i))(a,j),scan())

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


в якийсь момент мені дійсно потрібно навчитися користуватися do.call... Я, мабуть, не повинен вважати себе програмістом R, поки не стану!
Джузеппе

1
@Giuseppe Advanced Rвід Hadley Wickam - це чудовий пляж, прочитаний :)
JayCe

Дякую @Giuseppe за вказівку do.call- дав мені зрозуміти, що шукаю get.
JayCe

3

Хаскелл - 74

f(x:xs)=foldl(\x(o,y)->o x y)x(zip(cycle[(+),(-),(*),(/),flip(^).floor])xs)

Тестові приклади:

λ> f[1,2,3,4,5] -> 0.0
λ> f[5,12,23,2,4,4,2,6,7] -> 539.0
λ> f[-8,50,3,3,-123,4,17,99,13] -> -1055.356943846277
λ> f [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] -> 256.0

Можливо, це може бути коротше; Підтримка Haskell для нескінченних списків та функцій вищого порядку робить пряме рішення досить приємним. Версія^ :: Double -> Double -> Double була б приємнішою для гольфу, але я не зміг її знайти. На щастя, мені не потрібна була повна лямбда, тому безглуздий стиль виголив кілька байтів.


2
Ви можете випереджати сингл (+)до списку операторів і почати foldlз 0йти повністю pointfree і зберегти ім'я функції і параметри: foldl(\x(o,y)->o x y)0.zip((+):cycle[(+),(-),(*),(/),(**)]).
німі

3

PowerShell v2 +, 124 байти

param($n)$o=$n[0];if($y=$n.count-1){1..$y|%{$o=if(($x=$i++%5)-4){"$o"+'+-*/'[$x]+$n[$_]|iex}else{[math]::pow($o,$n[$_])}}}$o

Довго, тому що PowerShell не має ^ або **оператора, тому нам доведеться враховувати окремий випадок і використовувати .NET-виклик.

Приймає введення $nяк масив, встановлює наш вихід $oпершою цифрою. Потім ми перевіряємо.count масив і до тих пір, поки він більше, ніж один, ми входимо в if. В іншому випадку ми пропускаємо if.

Всередині ifми пробираємося через масив, 1..$y|%{...}і кожну ітерацію ми знову встановлюємо $oна нове значення, результат іншого if/elseтвердження. Поки наш лічильник $i++не є модулем-5 рівним 4 (тобто ми не в ^операторі), ми просто беремо $oі з'єднуємо його з відповідним символом '+-*/'[$x]і наступним номером у вхідному масиві $n[$_]. Ми передаємо це iex(псевдонім для Invoke-Expressionта подібне до eval), і це буде повторно збережено $o. Якщо ми перебуваємо на ^операторі, ми знаходимось у else, тому ми виконуємо [math]::Pow()дзвінок та цей результат знову зберігається$o .

У будь-якому випадку ми просто виводимо $oна трубопровід і виходимо, з висновком неявним.


3

Іржа, 123 , 117 байт

Оригінальна відповідь:

fn a(v:&[f32])->f32{v.iter().skip(1).enumerate().fold(v[0],|s,(i,&x)|match i%5{0=>s+x,1=>s-x,2=>s*x,3=>s/x,_=>s.powf(x)})}

дурні довгі назви методів ^^ ах набагато краще

fn f(v:&[f32])->f32{v[1..].iter().zip(0..).fold(v[0],|s,(&x,i)|match i%5{0=>s+x,1=>s-x,2=>s*x,3=>s/x,_=>s.powf(x)})}

неозорий

fn f(values : &[f32]) -> f32 {
    values[1..].iter().zip(0..)
    .fold(values[0], |state,(&x,i)|
        match i%5 {
            0=>state+x,
            1=>state-x,
            2=>state*x,
            3=>state/x,
            _=>state.powf(x)
        }
    )
}

3

Perl 6 ,  70 68 65   62 байт

{$/=[(|(&[+],&[-],&[*],&[/],&[**])xx*)];.reduce: {$/.shift.($^a,$^b)}}
{(@_ Z |(&[+],&[-],&[*],&[/],&[**])xx*).flat.reduce: {&^b($^a,$^c)}}
{(@_ Z |(*+*,*-*,&[*],*/*,&[**])xx*).flat.reduce: {&^b($^a,$^c)}}
{reduce {&^b($^a,$^c)},flat @_ Z |(*+*,*-*,&[*],*/*,&[**])xx*}

Пояснення:

-> *@_ {
  reduce
    -> $a, &b, $c { b($a,$c) },

    flat       # flatten list produced from zip
      zip
        @_,    # input

        slip(  # causes the list of operators to flatten into the xx list

          # list of 5 infix operators
          &infix:<+>, &infix:<->, &infix:<*>, &infix:</>, &infix:<**>

        ) xx * # repeat the list of operators infinitely
}

Технічно * + *це лямбда, що б там не було, але фактично така ж, як &[+]і коротка для &infix:<+>набору підпрограм, які обробляють додавання числових інфіксів.
Я не використовував це для множення чи експоненції як способів їх написання, як мінімум, до тих пір, як у мене є ( *×*або* * * і * ** *)

Тест:

Перевірте це на ideone.com
(після оновлення до версії Rakudo, яка не пройшла за півтора року до офіційного випуску спектаклів Perl 6 )

#! /usr/bin/env perl6

use v6.c;
use Test;

my @tests = (
  [1,2,3,4,5] => 0,
  [5,12,23,2,4,4,2,6,7] => 539,
  [-8,50,3,3,-123,4,17,99,13] => -1055.35694385, # -2982186493/2825761
  [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] => 256,
  [1,0,1,0,1,0] => 1,
  [-9,-8,-1] => -16,
  [0,-3] => -3,
  [-99] => -99,
);

plan +@tests;

my &code = {reduce {&^b($^a,$^c)},flat @_ Z |(*+*,*-*,&[*],&[/],&[**])xx*}

for @tests -> $_ ( :key(@input), :value($expected) ) {
  is code(@input), $expected, .gist
}
1..8
ok 1 - [1 2 3 4 5] => 0
ok 2 - [5 12 23 2 4 4 2 6 7] => 539
ok 3 - [-8 50 3 3 -123 4 17 99 13] => -1055.35694385
ok 4 - [2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2] => 256
ok 5 - [1 0 1 0 1 0] => 1
ok 6 - [-9 -8 -1] => -16
ok 7 - [0 -3] => -3
ok 8 - [-99] => -99


3

Python 3, 88 93 байт

f=lambda x:eval('('*(len(x)-1)+'){}'.join(map(str,x)).format(*['+','-','*','/','**']*len(x)))

Це почалося набагато коротше, але тоді пріоритет оператора переміг мене, і я повинен був включити багато дужок ...


3

Oracle PL / SQL, 275 254 байт

declare r number;begin for x in (select n,mod(rownum,5)r from t) loop if r is null then r:=x.n;elsif x.r=2then r:=r+x.n;elsif x.r=3then r:=r-x.n;elsif x.r=4then r:=r*x.n;elsif x.r=0then r:=r/x.n;else r:=r**x.n;end if;end loop;DBMS_OUTPUT.PUT_LINE(r);end;

Дані повинні бути вставлені в таблицю, яку називають Tстовпцем NтипуNUMBER

Використання:

drop table t;
create table t (n number);
insert into t values (-8);
insert into t values (50);
insert into t values (3);
insert into t values (3);
insert into t values (-123);
insert into t values (4);
insert into t values (17);
insert into t values (99);
insert into t values (13);

declare r number;begin for x in (select n,mod(rownum,5)r from t) loop if r is null then r:=x.n;elsif x.r=2then r:=r+x.n;elsif x.r=3then r:=r-x.n;elsif x.r=4then r:=r*x.n;elsif x.r=0then r:=r/x.n;else r:=r**x.n;end if;end loop;DBMS_OUTPUT.PUT_LINE(r);end;

Вихід:

-1055,356943846277162152071601242992595623

Версія 275 байт:

declare r number;cursor c is select n,mod(rownum,5) r from t;begin for x in c loop if r is null then r:=x.n;else case x.r when 2 then r:=r+x.n;when 3 then r:=r-x.n;when 4 then r:=r*x.n;when 0 then r:=r/x.n;else r:=r**x.n; end case;end if;end loop;DBMS_OUTPUT.PUT_LINE(r);end;

3

Java 8, 173 172 167 138 137 118 113 байт

a->{double r=a[0],t;for(int i=1;i<a.length;r=new double[]{Math.pow(r,t),r+t,r-t,r*t,r/t}[i++%5])t=a[i];return r;}

Пояснення:

Спробуйте тут.

a->{                     // Method with double-array parameter and double return-type
  double r=a[0],         //  Result-double, starting at the first item of the input
         t;              //  Temp double
  for(int i=1;           //  Index-integer, starting at the second item
      i<a.length;        //  Loop over the input-array
      r=new double[]{    //    After every iteration, change `r` to:
         Math.pow(r,t),  //      If `i%5` is 0: `r^t`
         r+t,            //      Else-if `i%5` is 1: `r+t`
         r-t,            //      Else-if `i%5` is 2: `r-t`
         r*t,            //      Else-if `i%5` is 3: `r*t`
         r/t}[i++%5])    //      Else-if `i%5` is 4: `r/t`
                         //      And increase `i` by 1 afterwards with `i++`
    t=a[i];              //   Change `t` to the next item in the array
  return r;}             //  Return result-double

2
Тому що, ви знаєте, java в 1,5 рази довший за найдовший відповідь .... що є в SQL
Bálint

1
Ви можете змінити , double r=a[0];щоб double r=a[0],b;зберегти деякі байти.
Leaky Nun

1
@LeakyNun Спочатку у мене був float, але немає Math.powплавців, отже, doubleзамість цього. Дякую за ,b. І з цим i++<a.lengthя отримую ArrayOutOfBoundsException у b=a[i];(якщо тільки не робити це i++<a.length-1, який на один байт довший, а не коротший).
Kevin Cruijssen

1
Ви можете змінити , == 4щоб > 3і == 0в < 1. Я не впевнений, але я думаю, ви могли б трохи заощадити, створивши змінну для i % 5.
Фрозн

1
Я подумав, що ти можеш змінити всю справу на об'єднання тернаріїв. У всіх порівняннях ви можете використовувати <xтрюк, зменшуючи всю функцію до 137 символів.
Фрозн

3

Кілька хитрощів можуть зменшити підхід @ Вілмора на 23-1174 байт (потрібно php 5.6 або пізнішої версії). Найбільш економічною частиною є видалення непотрібних дужок (-10 байт).

функція f ($ a) {while (count ($ a)> 1) {$ l = array_shift ($ a); $ r = array_shift ($ a); array_unshift ($ a, ($ j = $ i ++% 5) ? ($ j == 1? $ l- $ r: ($ j == 2? $ l * $ r: ($ j == 3? $ l / $ r: $ l ** $ r))): $ l + $ r);} повернення кінця ($ a);}

Але використання **оператора замість pow()також дозволяє використовуватиeval з масивом для операцій; і ще з трьома хитрощами ...

PHP> = 5,6, 82 байти

while(--$argc)eval('$x'.['/','**','+','-','*'][$i++?$i%5:2]."=$argv[$i];");echo$x;

приймає список з параметрів командного рядка. Виконати з php -nr '<code>'або спробуйте в Інтернеті .

стара версія, 161 157 151 145 144 140 137 117 байт

function f($a){while(count($a)>1)eval('$a[0]=array_shift($a)'.['+','-','*','/','**'][$i++%5].'$a[0];');return$a[0];}

Найефективніший гольф був результатом написання проміжного результату безпосередньо на перший елемент - після зміщення попереднього результату з масиву.

зламатися

function f($a)
{
    while(count($a)>1)  // while array has more than one element ...
        eval('$a[0]='                           // future first element :=
            . 'array_shift($a)'                 // = old first element (removed)
            . ['+','-','*','/','**'][$i++%5]    // (operation)
            .'$a[0];'                           // new first element (after shift)
        );
    return$a[0];        // return last remaining element
}

тестовий набір

$cases = array (
    0=>[1,2,3,4,5],
    539=>[5,12,23,2,4,4,2,6,7],
    '-1055.356...' => [-8,50,3,3,-123,4,17,99,13],
    256 => [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
    1 => [1,0,1,0,1,0],
    -16 => [-9,-8,-1],
    -3 => [0, -3],
    -99 => [-99]
);
echo '<table border=1><tr><th>values</th><th>expected</th><th>actual result</th></tr>';
foreach ($cases as $expect=>$a)
{
    $result=f($a);
    echo "<tr><td>[", implode(',',$a),"]</td><td>$expect</td><td>$result</td></tr>";
}
echo '</table>';

Чудово зроблено. Ви можете видалити ще 3 байти, повернувши останнє значення у вигляді масиву (змінити 'return $ a [0]' на 'return $ a'), яке, я не бачу, суперечить правилам. :)
640 Кб

@gwaugh Imo If the array contains just a single number, we return that as the result.досить зрозумілий. Але дякую, що дозволили мені переглянути це.
Тит

Можна було б зробити семантичний аргумент, що "те" у реченні може означати "масив". Незважаючи на те, ваша відповідь - це найкоротший PHP. Дуже добре зроблено, і знову за покажчики на моїй тривалій подачі.
640 Кб

3

PHP ,135 130 байт

Дякую @titus, -5 байт, плюс 0 виправлених випадків!

function f($z){return array_reduce($z,function($c,$x)use(&$i){eval('$c'.['/','**','+','-','*'][$i++?$i%5:5].'=$x;');return$c;});};

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

Менш гофрований:

function f( $t ) {
    return array_reduce( $t,
        function( $c, $x ) use( &$i ) {
            eval('$c'.['/','**','+','-','*'][$i++?$i%5:5].'=$x;');
            return $c;
        }
    );
};

Дійсно вкорінювалося, щоб array_reduce () працював для цього, але потрібно занадто багато символів, щоб перемогти поточний найнижчий показник PHP.

Опублікуйте його в будь-якому випадку, якщо хтось має якісь пропозиції!


1
Гарний підхід; але я вважаю, що не вдасться кожного разу, коли $cпотрапить 0. Збережіть два байти з анонімною функцією замість w. eval('$c'.['/','**','+','-','*'][$i++?$i%5:5].'=$x');return$c;на шість байтів коротше і має вирішити нульову проблему.
Тит

Дякую @Titus! Ви абсолютно праві щодо справи 0. Мені довелося додати ще; після = $ x, тому що eval не буде працювати без нього. Якби я зробив це функцією anon, я повинен був би призначити йому змінну або запустити її в тестовому коді, правда? Не хотіло б викликати підрахунок байтів під сумнів. : D
640 КБ

2

Брахілог , 68 байт

hI,?bL,1:+:-:*:/:^b:L:I{bhv?t.|[O:L:I]h$(P,LbM,OhA,Lh:Ir:A&:M:Pr&.}.

Це довго ... але він не використовує присудок оцінювання.

Пояснення

  • Основний присудок

    hI,                                  Unify I with the first element of the input
       ?bL,                              L is the input minus the first element
           1:+:-:*:/:^b                  Construct the list of predicates [+:-:*:/:^]
                       :L:I{...}.        Call predicate 1 with [[+:-:*:/:^]:L:I] as input
    
  • Присудок 1

    bhv?t.                               If the second element of Input is empty (i.e. L),
                                         unify Output with the last element of Input
    |                                    Or
    [O:L:I]                              Input = [O:L:I]
           h$(P,                         P is O circularly permutated to the left
                LbM,                     M is L minus the first element
                    OhA,                 A is the first element of O
                        Lh:Ir:A&         Call predicate A on [I:First element of L]
                                :M:Pr&.  Call predicate 1 recursively with P:M:
    

Збийте вас 1̶ ̶b̶y̶t̶e̶ 2 байти;)
LegionMammal978

2

IBM PC 8087 FPU, 66 82 байти

Для розрахунків використовується лише математичний копроцесор Intel 8087 IBM PC.

Спробуйте це в автономному режимі! (у DOSBox чи іншому). Дайте нудному мікросхемі 8087 вашого нужденного ПК, окрім усіх електронних таблиць Lotus 1-2-3, які ви робили в 80-х.

9bdf 0783 c302 499b de07 83c3 0249 e342 9bde 2783 c302 49e3 399b de0f 83c3 0249 
e330 9bde 3783 c302 49e3 2751 8b0f 9bd9 e883 f900 7413 9c7f 02f7 d99b d8c9 e2fb 
9d7d 069b d9e8 9bd8 f159 83c3 0249 e302 ebb5 c3

Необолочені (не зібрані):

START: 
    ; RUN TESTS  
    MOV  BX, OFFSET TST     ; 5, 12, 23, 2, 4, 4, 2, 6, 7
    MOV  CX, CTST           ; input array length
    CALL WOMI               ; calculate sequence
    CALL PRINT_FLT          ; output to console

    MOV  BX, OFFSET TST1    ; 5, 12, 23, 2, 4, -4, 2, 6, 7
    MOV  CX, CTST1
    CALL WOMI
    CALL PRINT_FLT

    MOV  BX, OFFSET TST2    ; -8, 50, 3, 3, -123, 4, 17, 99, 13
    MOV  CX, CTST2
    CALL WOMI
    CALL PRINT_FLT

    MOV  BX, OFFSET TST3    ; 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
    MOV  CX, CTST3
    CALL WOMI
    CALL PRINT_FLT

    MOV  BX, OFFSET TST4    ; 1,0,1,0,1,0
    MOV  CX, CTST4
    CALL WOMI
    CALL PRINT_FLT

    MOV  BX, OFFSET TST5    ; -9, -8, -1
    MOV  CX, CTST5
    CALL WOMI
    CALL PRINT_FLT

    MOV  BX, OFFSET TST6    ; 0, -3
    MOV  CX, CTST6
    CALL WOMI
    CALL PRINT_FLT

    MOV  AX, 4C00H          ; exit to DOS
    INT  21H

;  TEST DATA

TST   DW  5, 12, 23, 2, 4, 4, 2, 6, 7
CTST  EQU ($-TST)/(SIZE TST)    ; count of items on list

TST1  DW  5, 12, 23, 2, 4, -4, 2, 6, 7
CTST1 EQU ($-TST1)/(SIZE TST1)  ; count of items on list

TST2  DW -8, 50, 3, 3, -123, 4, 17, 99, 13
CTST2 EQU ($-TST2)/(SIZE TST2)  ; count of items on list

TST3  DW 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
CTST3 EQU ($-TST3)/(SIZE TST3)  ; count of items on list

TST4  DW 1,0,1,0,1,0
CTST4 EQU ($-TST4)/(SIZE TST4)  ; count of items on list

TST5  DW -9, -8, -1
CTST5 EQU ($-TST5)/(SIZE TST5)  ; count of items on list

TST6  DW 0, -3
CTST6 EQU ($-TST6)/(SIZE TST6)  ; count of items on list

; 8087 exponent: ST(0) = ST(0) ^ EXP
FIEXP   MACRO   EXP
        LOCAL   REPEAT, DONE
        PUSH CX
        MOV  CX, EXP        ; Exponent is count for loop
        FLD1                ; load 1 into ST
        CMP  CX, 0          ; is exponent pos, neg or 0?
        JZ   DONE           ; exit (with value 1) if exponent is 0
        PUSHF               ; save result flags for later
        JG   REPEAT         ; if exp > 1 start calculation
        NEG  CX             ; make exponent positive for loop
REPEAT:
        FMUL ST(0), ST(1)   ; multiply ST0 = ST0 * ST1
        LOOP REPEAT
        POPF                ; retrieve flags from earlier
        JGE  DONE           ; if exponent was negative, divide 1 by result
        FLD1                ; push 1 into numerator
        FDIV ST(0), ST(1)   ; ST0 = 1 / ST1
DONE:
        POP  CX
        ENDM

; Function WOMI: (Weapons of Math Instruction)
; input: BX - address of start of input array
;       CX - length of input array
; output: ST - result on top of 8087 register stack
WOMI PROC
    FILD WORD PTR [BX]      ; load first item
    ADD  BX, 2              ; move to next
    DEC  CX
CALC:
    FIADD WORD PTR [BX]     ; add
    ADD  BX, 2              ; move to next
    DEC  CX                 ; decrement counter
    JCXZ OUTPUT             ; check if done

    FISUB WORD PTR [BX]     ; subtract
    ADD  BX, 2
    DEC  CX
    JCXZ OUTPUT

    FIMUL WORD PTR [BX]     ; multiply
    ADD  BX, 2
    DEC  CX
    JCXZ OUTPUT

    FIDIV WORD PTR [BX]     ; divide
    ADD  BX, 2
    DEC  CX
    JCXZ OUTPUT

    FIEXP [BX]              ; exponent
    ADD  BX, 2
    DEC  CX
    JCXZ OUTPUT
    JMP CALC                ; start again

OUTPUT:
    RET 
WOMI ENDP

PRINT_FLT PROC
; print top of 8087 stack
; scaling: 14 digits, 4 decimal places
; input: BX = address of a TBYTE (BCD) output buffer
;       ST = value to display on top of 8087 stack  
    LEA   BX, BUFF                  ; set BX to BCD output buffer
    MOV   AH, 2
    MOV   WORD  PTR[BX], 10000      ; ten thousand (scale factor)
    FIMUL WORD  PTR[BX]             ; scale up by 10000
    FBSTP TBYTE PTR[BX]             ; store as BCD
    FWAIT                           ; sync 8088 and 8087
    TEST  BYTE  PTR[BX+9], 80H      ; check sign bit
    JE    PF_1                      ; 0, goto PF_1
    MOV   DL, '-'                   ; output '-'
    INT   21H
PF_1:
    ADD   BX, 8                     ; point to high byte
    MOV   CH, 7                     ; 14 digits before decimal point
    MOV   CL, 4                     ; 4 shifts (8 bytes / 2 = 4 = 1 nibble)
    MOV   DH, 2                     ; 2 times (8 bytes / 4)
PF_LOOP:
    MOV   DL, [BX]                  ; get BCD digits
    SHR   DL, CL                    ; move high digit to low nibble
    OR    DL, 30H                   ; convert to ASCII
    INT   21H
    MOV   DL, [BX]                  ; get byte again
    AND   DL, 0FH                   ; mask out high digit
    OR    DL, 30H                   ; convert to ASCII
    INT   21H                       ; output
    DEC   BX                        ; next byte
    DEC   CH                        ; decrement byte
    JG    PF_LOOP                   ; repeat if more bytes
    DEC   DH                        ; second time?
    JE    PF_DONE                   ; yes, done
    MOV   DL, '.'                   ; no, output decimal point
    INT   21H
    MOV   CH, 2                     ; 4 more digits after decimal point
    JMP   PF_LOOP                   ; go print digits
PF_DONE:
    MOV  DL, 0DH                    ; display newline CRLF
    MOV  AH, 2
    INT  21H
    MOV  DL, 0AH
    INT  21H
    RET 
PRINT_FLT ENDP

BUFF DT 0   ; output buffer for floating point digit string

_TEXT ENDS
END START

Вихід:

A>WOMI.COM
00000000000539.0000
-00000000000027.9136
-00000000001055.3569
00000000000256.0000
00000000000001.0000
-00000000000016.0000
-00000000000003.0000

Введення здійснюється через PROC (x86, найбільш еквівалентний функції), при цьому BX є вказівником на масив WORDs в пам'яті, а CX - кількість елементів у ньому та повертає результат у ST.

* Примітка. Фактичний код функції 6682 байти. Звичайно, код просто для запису на консоль номер з плаваючою комою (код кулінарної книги) становить 83 байти. Програма тестування та дані є183215 байт, що робить .COM виконуваним 305 380 байт загалом.


1
Це чудово! Я написав подібне рішення для x86-64 (linux), але я ще не так багато гольфував, що, ймовірно, змінить багато логіки навколо. Для вашого обчислення експонентів, хоча тести, які не дають тестування, не отримують негативний показник, я вважав, що це необхідна частина логіки програми, тим більше, що це так просто, як натиснути 1 на st0, а потім зробити дів між st0 і st1 (принаймні на x86 це дві інструкції).
Дейв

Дякую @davey - дуже хороший момент! Я оновив код для обробки негативних показників і додав ще один тестовий випадок для нього.
640 Кб

2

APL (Dyalog Unicode) , 29 27 байт SBCS

Анонімна негласна префіксальна функція. Зауважимо, що *це експоненція в APL.

≢{⍎3↓⍕⌽⍵,¨⍨⍺⍴'+-×÷*''⍨'}⊢

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

Оскільки APL виконує право наліво, ми можемо просто змінити порядок аргументів вставлених операцій і повернути весь вираз. Postfix скасовує аргументи. Зробивши ідеальну перестановку чисел і операцій, нам просто потрібно просто повернути назад, вирівняти та оцінити:

≢{}⊢ Викличте наступну функцію з підрахунком та фактичними номерами як і :

'⍨' цей персонаж

'+-×÷*',¨ додайте до цього кожного з цих символів; ["+⍨","-⍨","×⍨","÷⍨","*⍨"]

⍺⍴ використовувати лівий аргумент (кол - сть номерів) циклічно г eshape , що

 реверс

 формату як плоский рядок

3↓краплі, що ведуть 3 символи (пробіл та символ та )

 виконати як APL-код


2

Japt , 16 байт

r@[XY]r"p+-*/"gZ

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

Пояснення:

r@                  #Reduce the input list:
       "p+-*/"      # The list of functions to apply (offset by one due to the behavior of Z)
              gZ    # Choose the one at the current index, wrapping
  [  ]r             # Apply that function to:
   X                #  The result of the previous step
    Y               #  and the current number
                    #Implicitly return the result of the final step

Ах, фейк, я просто працював над цим, намагаючись зрозуміти, чому це дає мені неправильні результати - я пропустив підказку підробки! : \
Кудлатий

1

c #, 238 , 202 байти

double d(double[]a){Array.Reverse(a);var s=new Stack<double>(a);int i=0,j;while(s.Count>1){double l=s.Pop(),r=s.Pop();j=i++%5;s.Push(j==0?l+r:j==1?l-r:j==2?l*r:j==3?l/r:Math.Pow(l,r));}return s.Peek();}

Я не бачив жодного рішення c #, тому дам його. Це мій перший кодегольф. Я почав писати в c # "два місяці тому" (хоча я певною мірою знаю Java).

Він використовує Stack

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

Невикористані і тестові справи

using System;
using System.Collections.Generic;

class M 
{
    double d(double[]a) {
        Array.Reverse(a);
        var s = new Stack<double>(a);
        int i=0,j;
        while (s.Count>1)
        {
            double l=s.Pop(),r=s.Pop();
            j=i++%5;
            s.Push(j==0?l+r:j==1?l-r:j==2?l*r:j==3?l/r:Math.Pow(l, r));
        }
        return s.Peek();
    }

    public static void Main()
    {
        int[][] a = new int[][]{
            new int[]{1,2,3,4,5},
            new int[]{5,12,23,2,4,4,2,6,7},
            new int[]{-8,50,3,3,-123,4,17,99,13},
            new int[]{2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
            new int[]{1,0,1,0,1,0},
            new int[]{-9,-8,-1},
            new int[]{0,-3},
            new int[]{-99}
        };

        for (int i = 0; i < a.Length; i++)
        {
            Console.WriteLine(new M().d(Array.ConvertAll(a[i], e => Convert.ToDouble(e))));
        }
        Console.ReadKey();
    }
}

Вихід:

0
539
-1055,35694384628
256
1
-16
-3
-99

Привіт, і ласкаво просимо до PPCG! Це може бути приємною темою для перегляду: Поради щодо кодового гольфу в C # . Деякі речі, які можна заграти у ваш код: пробіли ( a, Double.Parse-> a,Double.Parse; while (s.Count-> while(s.Count; Pow(l, r)-> Pow(l,r)). Також ви можете зняти int перед j=і поставити його позаду int i=0,j;. Чудова перша відповідь, хоча, і ще раз вітається. :)
Кевін Кройсейсен

@KevinCruijssen Привіт! Ти! Пробіли видалено, і j перемістилося, як ви запропонували :)
display_name

1

PHP, 206 , 198 , 197 байт

function f($a){while(count($a)>1){$l=array_shift($a);$r=array_shift($a);array_unshift($a,($j=$i++%5)==0?($l+$r):($j==1?($l-$r):($j==2?($l*$r):($j==3?($l/$r):(pow($l,$r))))));}return array_pop($a);}

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

Безумовно

<?php

function f($a)
{
    while(count($a)>1)
    {
        $l = array_shift($a); $r = array_shift($a);
        array_unshift($a,($j=$i++%5)==0?($l+$r):($j==1?($l-$r):($j==2?($l*$r):($j==3?($l/$r):(pow($l,$r))))));
    }
    return array_pop($a);
}

echo f([1,2,3,4,5])."\n";
echo f([5,12,23,2,4,4,2,6,7])."\n";
echo f([-8,50,3,3,-123,4,17,99,13])."\n";
echo f([2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])."\n";
echo f([1,0,1,0,1,0])."\n";
echo f([-9,-8,-1])."\n";
echo f([0,-3])."\n";
echo f([-99])."\n";

У PHP логіка схожа на мій C # відповіді ( 202 байт ) :).

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