Перетворіть масив у математичну задачу


35

Враховуючи непорожній перелік неотримних цілих чисел, розглянемо його перезапис як арифметичну задачу, де:

  • Знак плюс ( +) вставляється між парами чисел, які збільшуються зліва направо (так само від початку списку до кінця).
  • Між мінусом ( -) вставляється між парами чисел, які зменшуються зліва направо.
  • Знак множення ( *) вставляється між парами чисел, рівних.

Інакше кажучи: будь подспісок a,bстає a+bякщо a<b, a-bякщо a>b, і a*bякщо a==b.

Наприклад, список

[12, 0, 7, 7, 29, 10, 2, 2, 1]

стане виразом

12 - 0 + 7*7 + 29 - 10 - 2*2 - 1

який оцінює до 75 .

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

  • Порядок операцій має значення. Множення слід робити перед будь-яким додаванням чи відніманням.
  • Якщо список вхідних даних має одне число, це має бути те, що він оцінює. наприклад, [64]повинні дати 64.
  • Використання evalабо execабо подібних конструкцій не допускається.

Ось кілька додаткових прикладів:

[list]
expression
value

[0]
0
0

[1]
1
1

[78557] 
78557
78557

[0,0]
0*0
0

[1,1]
1*1
1

[2,2]
2*2
4

[0,1]
0+1
1

[1,0]
1-0
1

[1,2]
1+2
3

[2,1]
2-1
1

[15,4,4]
15-4*4
-1

[9,8,1]
9-8-1
0

[4,2,2,4]
4-2*2+4
4

[10,9,9,12]
10-9*9+12
-59

[1,1,2,2,3,3]
1*1+2*2+3*3
14

[5,5,4,4,3,3]
5*5-4*4-3*3
0

[3,1,4,1,5,9,2,6,5,3,5,9]
3-1+4-1+5+9-2+6-5-3+5+9
29

[7637,388,389,388,387,12,0,0,34,35,35,27,27,2]
7637-388+389-388-387-12-0*0+34+35*35-27*27-2
7379

Виграє найкоротший код у байтах. Тирбейкер - це відповідь раніше.


5
Що стосується "порядку операцій, важливих питань", можливо, було б чітко сказати, що додавання і віднімання є ліво-асоціативними і мають однаковий пріоритет.
Мартін Ендер

Відповіді:


15

Python 2, 63 байти

p=s='print-'
for x in input():s+='*+-'[cmp(x,p)]+`x`;p=x
exec s

Конструює і evalвиражає рядок. Арифметичний символ вибирається порівнянням попереднього числа pз поточним x. Символ додається з подальшим поточним номером.

Перший номер обробляється спритним фокусом від Sp3000. Початкове значення параметра pвстановлюється на рядок, який більший за будь-яке число і тому викликає a -перед першим числом. Але, sініціалізується print-в той самий час, що робить результат починати з print--(завдяки xsot за збереження 2 байт шляхом ініціалізації з print.)


Я думаю, ви можете перейти printв рядок і використовувати execзамість eval.
xsot

13

Pyth, 31 26 19 17 16 15 байт

Вирази з *не оцінюватимуть в Інтернеті, але вони теоретично спрацюють.

2 байти завдяки Малтісену.

vsm+@"*-+"._-~k

Тестовий набір (з оцінкою).

Інші випадки (без оцінки).

Історія

  • 31 байт: M+G@"*-+"->GH<GHv+sgMC,JsMQtJ\x60e
  • 26 байт: M+G@"*-+"->GH<GHv+sgVQtQ\x60e
  • 19 байт: vtssVm@"*-+"->Zd<~Z
  • 17 байт: vtssVm@"*-+"._-~Z
  • 16 байт: vssVm@"*-+"._-~k
  • 15 байт: vsm+@"*-+"._-~k

Чому множення не працює в Інтернеті? Якщо ви не впевнені, що це працює, можливо, найкраще перевірити ще трохи, перш ніж відповісти.
Захоплення Кальвіна

Оскільки матеріали безпеки (оцінка працює лише для +та в -Інтернеті)
Leaky Nun

@HelkaHomba У мене ще не було можливості спробувати це в автономному режимі, але це має працювати. Онлайн перекладач використовує --safeперемикач, який замінює evalз ast.literal_eval.
Денніс

Гаразд, досить справедливо.
Захоплення Кальвіна

Підтверджено, це працює з офлайн-перекладачем.
Денніс

12

Желе , 18 16 15 14 байт

I0;ð1g×⁹⁸œṗP€S

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

Як це працює

I0;ð1g×⁹⁸œṗP€S  Main link. Input: A (list)

I               Increments; compute the deltas of all adjacent items of A.
 0;             Prepend a 0.
   ð            Begin a new, dyadic chain.
                Left argument: D (0 plus deltas). Right argument: A
    1g          Compute the GCD of 1 and each item in D.
                This yields 1 for non-negative items, -1 for negative ones.
      ×⁹        Multiply each 1 or -1 with the corresponding item of A.
                This negates every item in A that follows a - sign.
        ⁸œṗ     Partition the result by D. This splits at occurrences of non-zero
                values of D, grouping items with identical absolute value.
           P€   Take the product of each group.
             S  Sum; add the results.


1
Чудово зроблено. Я повинен додати Python evalяк атом ...
Денніс

9
Я тебе позаду гольфу. : P
Денніс

Чудово зроблено, ваша черга!
Leaky Nun

9

MATL , 12 байт

Y'^l6MdZSh*s

Це використовує дуже приємну ідею кодування довжиною пробігу @ aditsu .

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

Пояснення

       % Take input vector implicitly
Y'     % RLE. Produces two vectors: values and lengths
^      % Rise each value to the number of consecutive times it appears. This
       % realizes the product of consecutive equal values
l      % Push 1
6M     % Push vector of values again
d      % Consecutive differences
ZS     % Sign function. Gives 1 or -1 (no 0 in this case)
h      % Concatenate horizontally with previous 1
*      % Multiply. This gives plus or minus depending on increasing character
s      % Sum of vector. This realizes the additions or subtractions
       % Display implicitly

Ха-ха щойно написав щось подібне. RLE добре
справляється

@Suever Я бачу :-D
Луїс Мендо

7

CJam, 20

q~e`{~_W-g\:W@#*}%:+

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

Пояснення:

q~       read and evaluate the input (array of numbers)
e`       RLE encode, obtaining [count number] pairs
{…}%     map each pair
  ~_     dump the count and number on the stack, and duplicate the number
  W-     subtract the previous number (W is initially -1 by default)
  g      get the sign of the result
  \      swap with the other copy of the number
  :W     store it in W (for next iteration)
  @#     bring the count to the top, and raise the number to that power
  *      multiply with the sign
:+       add all the results together

7

JavaScript (ES6), 54

p=>eval(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

eval отримує відокремлений комою список виразів і повертає значення останнього.

Тест

f=p=>eval(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

t=p=>(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

function Test() {
  var a=I.value.match(/\d+/g).map(x=>+x) // convert input to a numeric array
  
  var x=f(a),y=t(a)
  O.textContent='Value '+x+'\n(no eval '+y+')'
}  

Test()
#I { width:80%}
<input value='12, 0, 7, 7, 29, 10, 2, 2, 1' id=I>
<button onclick='Test()'>Test</button>
<pre id=O></pre>


4
Це найгірше зловживання оператором комами, яке я пам'ятаю, бачивши на цьому сайті ...
Ніл

5

Джулія, 76 57 байт

!x=[[" ""-*+"[2+sign(diff(x))]...] x]'|>join|>parse|>eval

Я вперше займався гольфу Юлією, тому, можливо, є очевидні поліпшення. Спробуйте в Інтернеті!

Денніс врятував тонну байтів.


Хороша робота. Я не розумів, що ви можете визначити спеціальну функцію для !.
Rɪᴋᴇʀ


4

Pyth - 23 22 20 байт

Як і у Кені, множення не працює в Інтернеті.

vs.i+\+@L"*+-"._M-Vt

Тестовий сюїт, не роблячи eval .


Хто такий Кевін?
Leaky Nun

@LeakyNun Я забув ваше ім’я через деякий час> _>
Maltysen

@Maltysen Haha, ти думаєш про кевін-не-
кенні

Вибачте, я їв, тому не міг розіграти своє рішення. Твоя черга.
Лина монашка

@LeakyNun майже там
Мальтісен

3

R, 92 байти

Тут, мабуть, ще є хороший гольф, який можна зробити.

eval(parse(t=paste(i<-scan(),c(ifelse(d<-diff(i),ifelse(d>0,"+","-"),"*"),""),collapse="")))

Безголівки:

i = scan()                # Read list from stdin
d = diff(i)               # Calculate difference between each element of list
s = ifelse(d,             # If d!=0
             ifelse(d>0,  # And if d>1
                    "+",  # Return plus
                    "-"), # Else return minus
             "*")         # Else (i.e. d==0) return multiply.
s = c(s,"")               # Pad the list s with an empty string, so it's the same
                          # length as i
p = paste(i,s,collapse="")# Paste the elements of i and s into one long string.
eval(parse(t=p))          # Evaluate the string as a language object.

Мені вдалося зберегти лише один байт, використовуючи підхід до індексування
JayCe


2

TI-BASIC, 146 байт

Я добре відформатую його, коли не на мобільному пристрої. Сон рятується від мене, тож ви це отримуєте. Насолоджуйтесь.

Prompt L₁
"(→Str1
For(A,1,dim(L₁
{0,1→L₂
{0,L₁(A→L₃
LinReg(ax+b) L₁,L₃,Y₁
Equ►String(Y₁,Str2
sub(Str2,1,-1+inString(Str2,"X→Str2
If A>1
Then
L₁(A-1
2+(Ans>L₁(A))-(Ans<L₁(A
Str1+sub("+*-",Ans,1→Str1
End
Str1+Str2→Str2
End
expr(Str1

2

Javascript ES6, 64 62 символів

a=>eval(a.map((x,i)=>x+('*+-'[x<a[++i]|(x>a[i])*2])).join``+1)

3
Це не повинно бути функцією та aпараметром?
edc65

Це недійсне як є.
Rɪᴋᴇʀ

@ edc65, так, так і повинно. Але насправді це було підраховано (вказано 61, але реальна довжина коду - 59), я просто погано скопіював новий код (правка повинна бути a[i+1]...a[i+1]=> a[++i]...a[i]- на 2 символи коротше, але я помилково замінив весь відкинутий код a=>).
Qwertiy

@ EᴀsᴛᴇʀʟʏIʀᴋ, це просто неправильна паста. Дивіться коментар вище та відредагуйте історію, щоб отримати більше деталей.
Qwertiy

@Qwertiy гаразд круто. Приємна відповідь btw ..
Rɪᴋᴇʀ

1

Java, 384 байти

int s(int[]l){int n=l[0],m;for(int i=0;i<l.length-1;i++)if(l[i]<l[i+1])if(i<l.length-2&&l[i+1]!=l[i+2])n+=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n+=m;}else if(l[i]>l[i+1])if(i<l.length-2&&l[i+1]!=l[i+2])n-=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n-=m;}else{m=l[i];while(i<l.length-1&&l[i]==l[i+1])m*=l[i++];n+=m;}return n;}

Ungolfed спробуйте онлайн

int s(int[] l)
{
    int n=l[0], m;

    for(int i=0; i<l.length-1; i++)
    {
        if(l[i] < l[i+1])
        {
            if (i<l.length-2 && l[i+1]!=l[i+2])
            {
                n += l[i+1];
            }
            else
            {
                m = l[i+1];
                while(i<l.length-2 && l[i+1]==l[i+2]) m *= l[(i++)+1];
                n += m;
            }
        }
        else if(l[i] > l[i+1])
        {
            if (i<l.length-2 && l[i+1]!=l[i+2])
            {
                n -= l[i+1];
            }
            else
            {
                m = l[i+1];
                while(i<l.length-2 && l[i+1]==l[i+2]) m *= l[(i++)+1];
                n -= m;
            }
        }
        else
        {
            m = l[i];
            while(i<l.length-1 && l[i]==l[i+1]) m *= l[i++];
            n += m;
        }
    }

    return n;
}

1
Деякі швидко гольфи: int a=l.length, &&=> &, поставити int i=0на одній і тій же «лінії» , як int n=l[0],m.
Лина монашка

В if(i<l.length-2&&l[i+1]!=l[i+2])n+=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n+=m;, ви можете просто замінити це з вмістом всередині elseблоку.
Leaky Nun

1

Javascript ES6, 79 символів

a=>eval(`${a}`.replace(/(\d+),(?=(\d+))/g,(m,a,b)=>a+('*+-'[+a<+b|(+a>+b)*2])))

1

Perl, 49 байт

48 байт коду + 1 для -p

s/\d+ (?=(\d+))/$&.qw(* - +)[$&<=>$1]/ge;$_=eval

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

perl -pe 's/\d+ (?=(\d+))/$&.qw(* - +)[$&<=>$1]/ge;$_=eval' <<< '12 0 7 7 29 10 2 2 1'
75

Примітки

Тут я дізнався, що ви можете зафіксувати пошук у PCRE, хоча це трохи неінтуїтивно ( (?=(\d+))замість ((?=\d+))). Це має сенс після прочитання, хоча як би ви фіксували збіг нульової довжини (lookahead) з останнім, а замість цього фіксуйте збіг з першим).

Дякуємо @ninjalj за збереження 8 байт!


@LeakyNun Я ніколи не знаю, на що точно розраховувати, я не можу знайти відповідну мета-посаду, я радий підбити кількість, але я подумав, що оскільки ви можете працювати з -eбезкоштовно, додавши, pщо це -peбуло +1 ? Буде оновлено зараз, але якщо ви зможете знайти джерело, я можу процитувати / посилатись, щоб рухатися вперед, це було б приголомшливо!
Дом Гастінгс

3
@DomHastings 1 є правильним, з тієї причини, яку ви говорите + цей мета-пост
Sp3000

Дякую @ Sp3000! Я не міг знайти цю посаду за все життя! Мета-повідомлення @LeakyNun для +1 за коментарем від Sp3000
Дом Гастінгс

Замість використання ланцюгових умовних операторів ви можете використовувати оператора космічного корабля для вибору зі списку: $&.qw(* - +)[$&<=>$1]у замінній частині s///оператора.
ніндзя

@ninjalj Звичайно! дивовижно, дякую! -8 з цим!
Дом Гастінгс

1

Власне, 30 байт

;2@VpXdX`i-su"+*-"E`M' @o♀+εj≡

На жаль, оскільки команда eval ( ) оцінює лише літерали на TIO, ця програма не працює в TIO.

Пояснення:

;2@VpXdX`i-su"+*-"E`M' @o♀+εj≡
;                               duplicate input
 2@V                            overlapping sublists of length <= 2
    pXdX                        discard first and last element (length-1 sublists)
        `i-su"+*-"E`M           map: for each pair of elements
         i-su                     flatten, subtract, sign, increment (results in a 0 if b < a, 1 if b == a, and 2 if b > a)
             "+*-"E               select the correct operation
                     ' @o       put a space at the beginning of the list to pad it properly
                         ♀+     pairwise addition (since addition is not defined for strings and integers, this just zips the lists and flattens the result into a single flat list)
                           εj   join with empty string
                             ≡  eval

1

R , 120 44 байт

r=rle(scan());c(1,sign(diff(r$v)))%*%r$v^r$l

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

Алгоритм подібний до цієї відповіді , але я зрозумів це лише після кодування своєї відповіді. Набагато краще, ніж моя оригінальна відповідь, яку я використовував eval(parse).

Повністю використовує векторизовані операції R - робить *операцію першим, використовуючи rle(x)$values ^ rle(x)$lenghtsта крапкові продукти, з цим вектором sign( diff( rle(x)$values ) )(попередньо 1).


1

05AB1E (спадщина) , 17 16 15 байт

ü.S…*-+sè‚ζJJ.E

-2 байти завдяки @Emigna .

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

Пояснення:

ü                  # Pair-wise loop over the (implicit) input-list
                   #  i.e. [12,0,7,7] → [[12,0],[0,7],[7,7]]
 .S                # Calculate the signum of the pair (-1 for a<b; 0 for a==b; 1 for a>b)
                   #  i.e. [[12,0],[0,7],[7,7]] → [1,-1,0]
   …*-+sè          # Index over "*-+" (with wrap-around)
                   #  i.e. [1,-1,0] → ['-','+','*']
         ‚ζ        # Zip the two lists together (appending the operands to the numbers)
                   #  i.e. [12,0,7,7] and ['-','+','*','+']
                   #   → [[12,'-'],[0,'+'],[7,'*'],[7,' ']]
           JJ      # Join them together
                   #  [[12,'-'],[0,'+'],[7,'*'],[7,' ']] → '12-0+7*7 '
             .E    # Evaluate as Python code
                   #  i.e. '12-0+7*7' → 61

1
Завдяки модульній індексації можна видалити >, перемістившись +до кінця рядка.
Емінья

@Emigna Не впевнений, як я пропустив це .. Дякую!
Кевін Круїйсен

1
Ви можете зберегти ще один байт, видаливши, Ćа ¨якщо ‚ζзамість цьогоø
Emigna

@Emigna О, тепер це розумно! Спасибі. Я знав, що додаток було дещо дивною обробкою, але не знав, як це виправити. ‚ζє ідеальною альтернативною обробкою, оскільки простір ігнорується в евалі. Знову дякую. :)
Кевін Кройсейсен

0

PHP, 103 байти

Охайний виклик. Це стало довше, ніж очікувалося. Я думаю, що використання array_mapабо подібне не покращить кількість байтів, оскільки анонімні функції все ще дорогі в PHP.

foreach(fgetcsv(STDIN)as$v)(0<=$p?$o.=$p.('*-+'[($p>$v)+2*($p<$v)]):_)&&$p=$v;echo eval("return$o$v;");

Запускається з командного рядка, підкаже список відокремлених комами, наприклад:

php array_to_math.php
12, 0, 7, 7, 29, 10, 2, 2, 1

0

PowerShell v2 +, 62 байти

-join($args|%{"$o"+'*+-'[($o-lt$_)+2*($o-gt$_)];$o=$_})+$o|iex

Вводить дані як аргументи командного рядка, розділені пробілом, який перетворюється в автоматичний масив $args. Ми повторюємо кожен елемент, використовуючи помічну змінну $oкожної ітерації, щоб пам'ятати, яким був наш попередній запис. Ми використовуємо проіндексовану рядок витягнути відповідний оператор, укладений виконуючи математику на неявно перетворюються булевих значеннях (наприклад, якщо попередній запис менше, то має []значення , 1+2*0так '*+-'[1]значить , +вибрано).

З’єднані струни залишаються на трубопроводі. Ми збираємо всі ці фрагменти разом (наприклад, 3-, 1+, 4-і т.д.) з -joinроботою, можна зчепити на кінцевому числі (неявно перетвориться в рядок), а також через канал, iex(псевдонім для Invoke-Expressionі подібного eval).


Побоювання полягає в тому, що якщо абонент вже дав значення $ oa (скажімо, $ o = 999), то вираз у цьому записі не обчислить правильне значення. До цього рішення потрібно додати ініціалізацію $ o.
Бево

@Bevo Це призначений для повного сценарію, який виконується за допомогою командного рядка, а не функції або через інтерактивну оболонку. Переважна більшість моїх матеріалів є такими, оскільки в такому сценарії немає заздалегідь визначених змінних, про які слід турбуватися, і, таким чином, код може бути трохи коротшим.
AdmBorkBork


0

Japt -x , 21 19 байт

änJ f mÎí*Uò¦ ®ÎpZÊ

Спробуй це


Пояснення

                        :Implicit input of array U
  J                     :Prepend -1
än                      :Get deltas
    f                   :Filter (remove 0s)
      m                 :Map
       Î                : Signs
        í               :Interleave
          U             :  Original input
           ò            :  Partition on
            ¦           :   Inequality
              ®         :  Map each sub-array Z
               Î        :    Get first element
                p       :    Raise to the power of
                 ZÊ     :     Length of Z
         *              :Reduce each pair of elements by multiplcation
                        :Implicitly reduce by addition and output
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.