Zamień tablicę w problem matematyczny

35

Biorąc pod uwagę niepustą listę nieujemnych liczb całkowitych, rozważ przepisanie jej jako problemu arytmetycznego, gdy:

  • Znak plus ( +) jest wstawiany między parami liczb, które zwiększają się od lewej do prawej (czyli od początku listy do końca).
  • Znak minus ( -) jest wstawiany między pary liczb, które maleją od lewej do prawej.
  • *Pomiędzy parami liczb, które są równe, wstawiany jest znak mnożenia ( ).

Powiedziane w inny sposób: każda podlista a,bstaje się a+bjeśli a<b, a-bjeśli a>bi a*bjeśli a==b.

Na przykład lista

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

stałby się wyrazem

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

co ocenia na 75 .

Napisz program lub funkcję, która pobiera taką listę i ocenia ją, drukując lub zwracając wynik.

  • Kolejność operacji ma znaczenie. Przed dodaniem lub odjęciem należy wykonać pomnożenie.
  • Jeśli lista wejściowa ma jeden numer, powinno to być to, co ocenia. np. [64]powinien dać 64.
  • Użycie evallub execdopuszcza lub podobnej konstrukcji.

Oto kilka dodatkowych przykładów:

[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

Najkrótszy kod w bajtach wygrywa. Tiebreaker to wcześniejsza odpowiedź.

Hobby Calvina
źródło
5
Jeśli chodzi o „kolejność operacji ma znaczenie”, dobrze byłoby wyraźnie stwierdzić, że dodawanie i odejmowanie jest lewostronne i ma taki sam priorytet.
Martin Ender

Odpowiedzi:

15

Python 2, 63 bajty

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

Konstruuje i evals ciąg wyrażeń. Symbol arytmetyczny wybiera się przez porównanie poprzedniego numeru pz bieżącym x. Do symbolu dołącza się bieżący numer.

Pierwszy numer jest obsługiwany za pomocą sprytnej sztuczki ze Sp3000. Wartość początkowa parametru pjest ustawiona na ciąg znaków, który jest większy niż dowolna liczba, a zatem powoduje, że występuje -przed pierwszą liczbą. Ale sinicjowana jest print-w tym samym czasie, co powoduje, że wynik zaczyna się od print--(dzięki xsot za zapisanie 2 bajtów przez inicjalizację za pomocą print.)

xnor
źródło
Myślę, że możesz przejść printdo łańcucha i użyć execzamiast niego eval.
xsot
13

Pyth, 31 26 19 17 16 15 bajtów

Wyrażenia z *nie będą oceniać online, ale teoretycznie będą działać.

2 bajty dzięki Maltysen.

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

Zestaw testowy (z oceną).

Pozostałe przypadki (bez oceny).

Historia

  • 31 bajtów: M+G@"*-+"->GH<GHv+sgMC,JsMQtJ\x60e
  • 26 bajtów: M+G@"*-+"->GH<GHv+sgVQtQ\x60e
  • 19 bajtów: vtssVm@"*-+"->Zd<~Z
  • 17 bajtów: vtssVm@"*-+"._-~Z
  • 16 bajtów: vssVm@"*-+"._-~k
  • 15 bajtów: vsm+@"*-+"._-~k
Leaky Nun
źródło
Dlaczego mnożenie nie działa online? Jeśli nie masz pewności, czy to działa, najlepiej przetestować jeszcze trochę przed odpowiedzią.
Calvin's Hobbies
Ponieważ zabezpieczenia (ocena działa tylko +i -online)
Leaky Nun
@HelkaHomba Nie miałem jeszcze okazji wypróbować go offline, ale powinien działać. Tłumacz online korzysta z --safeprzełącznika, który zastępuje evalsię ast.literal_eval.
Dennis
Ok, w porządku.
Calvin's Hobbies
Potwierdzono, że działa z tłumaczem offline.
Dennis
12

Galaretka , 18 16 15 14 bajtów

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

Nie używa wbudowanego eval. Wypróbuj online! lub zweryfikuj wszystkie przypadki testowe .

Jak to działa

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.
Dennis
źródło
1
Ładnie wykonane. Powinienem dodać Python evaljako atom ...
Dennis
9
Wygrałem cię z golfa. : P
Dennis
Dobra robota, twoja kolej!
Leaky Nun
9

MATL , 12 bajtów

Y'^l6MdZSh*s

Wykorzystuje to bardzo fajny pomysł @ aditsu na kodowanie w czasie rzeczywistym.

Wypróbuj online!

Wyjaśnienie

       % 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
Luis Mendo
źródło
Haha właśnie napisał coś podobnego. RLE sprawdza się w tym przypadku
Suever
@Suever I see :-D
Luis Mendo
7

CJam, 20

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

Wypróbuj online

Wyjaśnienie:

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
aditsu
źródło
7

JavaScript (ES6), 54

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

eval otrzymuje listę wyrażeń oddzieloną przecinkami i zwraca wartość ostatniego.

Test

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>

edc65
źródło
4
To najgorsze nadużycie operatora przecinka, jakie pamiętam na tej stronie ...
Neil
5

Julia, 76 57 bajtów

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

Mój pierwszy raz grałem w golfa Julię, więc może są oczywiste ulepszenia. Wypróbuj online!

Dennis zaoszczędził mnóstwo bajtów.

Lynn
źródło
Dobra robota. Nie zdawałem sobie sprawy, że możesz zdefiniować niestandardową funkcję !.
Rɪᴋᴇʀ
@ Eᴀsᴛᴇʀʟʏ Iʀᴋ codegolf.stackexchange.com/a/81028/12012
Dennis
4

Pyth - 23 22 20 bajtów

Podobnie jak w przypadku Kenny'ego, mnożenie nie działa online.

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

Test Suite bez przeprowadzania oceny .

Maltysen
źródło
Kim jest Kevin?
Leaky Nun
@LeakyNun Po pewnym czasie zapomniałem twojego nazwiska> _>
Maltysen
@Maltysen Haha, myślisz o kevin-not-kenny Lau
DJMcMayhem
Przepraszam, jadłem, więc nie mogłem grać w golfa. Twoja kolej.
Leaky Nun
@LeakyNun prawie tam
Maltysen
3

R, 92 bajty

Prawdopodobnie nadal można tu grać w golfa.

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

Nie golfowany:

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.
rturnbull
źródło
Udało mi się zaoszczędzić tylko jeden bajt, stosując metodę indeksowania
JayCe,
2

TI-BASIC, 146 bajtów

Ładnie go sformatuję, gdy nie będzie mobilny. Sen mi ucieka, więc rozumiesz. Cieszyć się.

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
Conor O'Brien
źródło
2

JavaScript ES6, 64 62 znaków

a=>eval(a.map((x,i)=>x+('*+-'[x<a[++i]|(x>a[i])*2])).join``+1)
Qwertiy
źródło
3
Czy nie powinna to być funkcja i aparametr?
edc65
To jest nieprawidłowe jak jest.
Rɪᴋᴇʀ
@ edc65, tak, powinno. Ale w rzeczywistości został policzony (określono 61, ale rzeczywista długość kodu wynosiła 59), po prostu źle skopiowałem nowy kod (edycja powinna być a[i+1]...a[i+1]=> a[++i]...a[i]- 2 znaki krótsza, ale przez pomyłkę zastąpiłem cały upuszczany kod a=>).
Qwertiy,
@ EᴀsᴛᴇʀʟʏIʀᴋ, to po prostu zła pasta. Zobacz komentarz powyżej i edytuj historię, aby uzyskać więcej szczegółów.
Qwertiy,
@ Qwertiy ok fajnie. Niezła odpowiedź btw ..
Rɪᴋᴇʀ
1

Java, 384 bajty

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 spróbuj online

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;
}
Khaled.K
źródło
1
Kilka szybkich golfs: int a=l.length, &&=> &, umieścić int i=0na tej samej linii „jak” int n=l[0],m.
Leaky Nun
W 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;możesz po prostu zastąpić to zawartością wewnątrz elsebloku.
Leaky Nun
1

JavaScript ES6, 79 znaków

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

Perl, 49 bajtów

Kod 48 bajtów + 1 dla -p

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

Stosowanie

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

Notatki

Nauczyłem się tutaj, że możesz uchwycić spojrzenie w PCRE, chociaż jest to trochę nieintuicyjne ( (?=(\d+))zamiast ((?=\d+))). Ma to jednak sens po przeczytaniu, ponieważ przechwytujesz dopasowanie o zerowej długości (z wyprzedzeniem) z tym drugim, a zamiast tego przechwytujesz dopasowanie z pierwszym.

Dzięki @ninjalj za uratowanie 8 bajtów!

Dom Hastings
źródło
@LeakyNun Nigdy nie wiem dokładnie co liczyć na to, że nie może znaleźć odpowiedniego posta meta, jestem szczęśliwy do wpadać liczyć, ale pomyślałem, że skoro można uruchomić z -eza darmo, dodając pco -pebyło +1 ? Zaktualizuje się na razie, ale jeśli możesz znaleźć źródło, które mógłbym zacytować / link do dalszych działań, byłoby świetnie!
Dom Hastings,
3
@DomHastings 1 jest poprawny, z tego powodu, dla którego mówisz + ten meta post
Sp3000,
Dzięki @ Sp3000! Nie mogłem znaleźć tego postu na całe życie! @LeakyNun meta post dla +1 zgodnie z komentarzem od Sp3000
Dom Hastings
Zamiast korzystać z łańcuchowych operatorów warunkowych, możesz użyć operatora statku kosmicznego, aby wybrać z listy: $&.qw(* - +)[$&<=>$1]w zastępczej części s///operatora.
ninjalj
@ninjalj Oczywiście! niesamowite, dzięki! -8 z tym!
Dom Hastings,
1

Właściwie 30 bajtów

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

Niestety, ponieważ komenda eval ( ) ocenia tylko literały na TIO, ten program nie działa na TIO.

Wyjaśnienie:

;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
Mego
źródło
1

R , 120 44 bajtów

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

Wypróbuj online!

Algorytm jest podobny do tej odpowiedzi , ale zdałem sobie z tego sprawę dopiero po zakodowaniu mojej odpowiedzi. Znacznie lepiej niż moja pierwotna odpowiedź, która była używana eval(parse).

W pełni wykorzystuje wektoryzowane operacje R - czy *operacja najpierw używa rle(x)$values ^ rle(x)$lenghtsi kropkuje iloczyny tego wektora sign( diff( rle(x)$values ) )(poprzedza je 1).

JayCe
źródło
1

05AB1E (starsza wersja) , 17 16 15 bajtów

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

-2 bajty dzięki @Emigna .

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

ü                  # 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
Kevin Cruijssen
źródło
1
Ze względu na modułowe indeksowanie można usunąć >, przechodząc +na koniec ciągu.
Emigna
@Emigna Nie wiem, jak mi tego brakowało .. Dzięki!
Kevin Cruijssen
1
Możesz zapisać kolejny bajt, usuwając Ći ¨, jeśli używasz ‚ζzamiastø
Emigna
@Emigna Och, teraz to mądre! Dzięki. Wiedziałem, że załączenie było trochę dziwne, ale nie wiedziałem, jak to naprawić. ‚ζjest idealną alternatywą do obejścia, ponieważ przestrzeń jest ignorowana w ewaluacji. Dzięki jeszcze raz. :)
Kevin Cruijssen
0

PHP, 103 bajty

Zgrabne wyzwanie. Trwało to dłużej niż oczekiwano. Myślę, że użycie array_maplub podobne nie poprawi liczby bajtów, ponieważ anonimowe funkcje są wciąż drogie w PHP.

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

Działa z wiersza poleceń, wyświetli monit o listę oddzieloną przecinkami, na przykład:

php array_to_math.php
12, 0, 7, 7, 29, 10, 2, 2, 1
wstawić nazwę tutaj
źródło
0

PowerShell v2 +, 62 bajty

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

Pobiera dane wejściowe jako rozdzielone spacjami argumenty wiersza polecenia, które są konwertowane na tablicę automatyczną $args. Iterujemy przez każdy element, używając zmiennej pomocniczej $okażdej iteracji, aby zapamiętać, jaki był nasz poprzedni wpis. Używamy indeksowane ciąg wyciągnąć właściwego operatora, sporządzonej wykonując matematyki na niejawnie konwertowane wartości logicznych (na przykład wtedy, gdy poprzedni wpis jest mniejsze, []ma wartość 1+2*0tak '*+-'[1]oznacza, że +jest zaznaczone).

Połączone łańcuchy pozostawia się w rurociągu. My zbierać wszystkie te fragmenty ze sobą (na przykład 3-, 1+, 4-, itd.) Z -joineksploatacji, należy uszeregować w ostatecznej liczby (który ostatecznie przekształca się w ciągu) i rury IT iex(alias dla Invoke-Expressioni podobne do eval).

AdmBorkBork
źródło
Niepokojące jest to, że jeśli osoba dzwoniąca podała już wartość $ oa (powiedzmy $ o = 999), wówczas wyrażenie w tym wpisie nie obliczy poprawnej wartości. Do tego rozwiązania należy dodać inicjalizację $ o.
Bevo,
@Bevo To ma być pełny skrypt wykonywany za pomocą wiersza poleceń, a nie przez funkcję lub przez interaktywną powłokę. Zdecydowana większość moich zgłoszeń jest jako taka, ponieważ w takim scenariuszu nie ma żadnych predefiniowanych zmiennych, którymi można się martwić, a zatem kod może być nieco krótszy.
AdmBorkBork
0

Japt , 25 bajtów

Chciałbym skrócić go, ale nie mogłem sprawić, by wersja bez wersji działała.

S+Uä!- ®"*+-"gZÎì)íU
OxU

Wypróbuj online!

Gnida
źródło
Zmniejszono go do 22 bajtów, ale nadal uważam, że można to poprawić.
Kudłaty
0

Japt -x , 21 19 bajtów

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

Spróbuj


Wyjaśnienie

                        :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
Kudłaty
źródło