Ubah Array menjadi Masalah Matematika


35

Diberikan daftar kosong dari bilangan bulat non-negatif, pertimbangkan menulis ulang itu sebagai masalah aritmatika di mana:

  • Tanda plus ( +) disisipkan di antara pasangan angka yang meningkat dari kiri ke kanan (alias dari awal daftar hingga akhir).
  • Tanda minus ( -) disisipkan di antara pasangan angka yang menurun dari kiri ke kanan.
  • Tanda multiplikasi ( *) disisipkan di antara pasangan angka yang sama.

Mengatakan dengan cara lain: setiap sublist a,bmenjadi a+bjika a<b, a-bjika a>b, dan a*bjika a==b.

Misalnya, daftarnya

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

akan menjadi ungkapan

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

yang dievaluasi menjadi 75 .

Tulis program atau fungsi yang mengambil dalam daftar tersebut dan mengevaluasinya, mencetak atau mengembalikan hasilnya.

  • Urutan operasi penting. Perkalian harus dilakukan sebelum penambahan atau pengurangan.
  • Jika daftar input memiliki satu nomor, itu yang harus dievaluasi. misalnya [64]harus memberi 64.
  • Penggunaan evalatau execatau konstruksi serupa diizinkan.

Berikut ini beberapa contoh tambahan:

[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

Kode terpendek dalam byte menang. Tiebreaker adalah jawaban sebelumnya.


5
Mengenai "urutan operasi," mungkin baik untuk menyatakan secara eksplisit bahwa penambahan dan pengurangan adalah asosiatif kiri dan memiliki prioritas yang sama.
Martin Ender

Jawaban:


15

Python 2, 63 byte

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

Membangun dan evals string ekspresi. Simbol aritmatika dipilih dengan membandingkan angka sebelumnya pdengan yang sekarang x. Simbol ditambahkan diikuti oleh nomor saat ini.

Nomor pertama ditangani dengan trik pintar dari Sp3000. Nilai awal dari pdiatur ke string, yang lebih besar dari angka apa pun dan karena itu menyebabkan -sebelum angka pertama. Tetapi, sdiinisialisasi print-pada saat yang sama yang membuat hasil dimulai dengan print--(terima kasih kepada xsot untuk menyimpan 2 byte dengan menginisialisasi dengan print.)


Saya pikir Anda bisa pindah printke string dan menggunakan execalih-alih eval.
xsot

13

Pyth, 31 26 19 17 16 15 byte

Ekspresi dengan *tidak akan mengevaluasi online, tetapi mereka secara teoritis akan berfungsi.

2 byte, terima kasih kepada Maltysen.

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

Test suite (dengan evaluasi).

Kasus-kasus lain (tanpa evaluasi).

Sejarah

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

Mengapa multiplikasi tidak berfungsi secara online? Jika Anda tidak yakin itu berhasil, mungkin lebih baik untuk menguji sedikit sebelum menjawab.
Calvin Hobbies

Karena hal-hal keamanan (evaluasi hanya berfungsi +dan -online)
Leaky Nun

@HelkaHomba Saya belum punya kesempatan untuk mencobanya secara offline, tetapi harus bekerja. Penafsir secara online menggunakan --safeswitch, yang menggantikan evaldengan ast.literal_eval.
Dennis

OK cukup adil.
Calvin Hobi

Dikonfirmasi, ini berfungsi dengan penerjemah offline.
Dennis

12

Jelly , 18 16 15 14 byte

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

Tidak menggunakan eval bawaan. Cobalah online! atau verifikasi semua kasus uji .

Bagaimana itu bekerja

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
Bagus sekali. Saya harus menambahkan Python evalsebagai atom ...
Dennis

9
Aku bermain golf di luarmu. : P
Dennis

Dilakukan dengan baik, giliran Anda!
Leaky Nun

9

MATL , 12 byte

Y'^l6MdZSh*s

Ini menggunakan ide yang sangat bagus dari @ aditsu untuk run-length encoding.

Cobalah online!

Penjelasan

       % 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

Haha baru saja menulis sesuatu yang serupa. RLE bekerja dengan baik untuk ini
Suever

@Suever Saya melihat :-D
Luis Mendo

7

CJam, 20

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

Cobalah online

Penjelasan:

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 menerima daftar ekspresi yang dipisahkan koma dan mengembalikan nilai yang terakhir.

Uji

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
Itu penyalahgunaan terburuk dari operator koma yang saya ingat pernah lihat di situs ini ...
Neil

5

Julia, 76 57 byte

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

Pertama kali saya bermain golf Julia, jadi mungkin ada perbaikan yang jelas. Cobalah online!

Dennis menghemat satu ton byte.


Pekerjaan yang baik. Saya tidak menyadari Anda dapat menentukan fungsi khusus untuk !.
R

@ Eᴀsᴛᴇʀʟʏ Iʀᴋ codegolf.stackexchange.com/a/81028/12012
Dennis


3

R, 92 byte

Kemungkinan masih ada beberapa golf bagus yang bisa dilakukan di sini.

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

Tidak Disatukan:

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.

Saya berhasil menyelamatkan hanya satu byte menggunakan pendekatan pengindeksan
JayCe


2

TI-BASIC, 146 byte

Saya akan memformatnya dengan baik ketika tidak di ponsel. Tidur luput dari saya, jadi Anda dapatkan ini. Nikmati.

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 karakter

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

3
Bukankah ini seharusnya sebuah fungsi dan aparameter?
edc65

Ini tidak valid apa adanya.
R

@ edc65, ya, seharusnya. Tapi sebenarnya itu dihitung (61 ditentukan, tetapi panjang kode sebenarnya adalah 59), saya hanya menyalin kode baru (edit harus a[i+1]...a[i+1]=> a[++i]...a[i]- 2 karakter lebih pendek, tapi saya keliru mengganti seluruh kode yang dijatuhkan a=>).
Qwertiy

@ EᴀsᴛᴇʀʟʏIʀᴋ, ini hanya salah tempel. Lihat komentar di atas dan edit riwayat untuk detail lebih lanjut.
Qwertiy

@ Bersyukur oke keren. Jawaban yang bagus btw ..
R

1

Java, 384 byte

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

Tidak dicoba coba 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;
}

1
Beberapa golfs cepat: int a=l.length, &&=> &, menempatkan int i=0pada "garis" yang sama seperti int n=l[0],m.
Leaky Nun

Di 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;, Anda bisa mengganti ini dengan konten di dalam elseblokir.
Leaky Nun

1

Javascript ES6, 79 karakter

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

1

Perl, 49 byte

48 byte kode +1 untuk -p

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

Pemakaian

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

Catatan

Saya belajar di sini bahwa Anda dapat menangkap lookahead di PCRE, meskipun sedikit tidak intuitif ( (?=(\d+))bukan ((?=\d+))). Masuk akal setelah membaca meskipun karena Anda akan menangkap pertandingan panjang nol (lookahead) dengan yang terakhir, dan bukannya menangkap pertandingan dengan yang pertama).

Terima kasih kepada @ninjalj karena telah menghemat 8 byte!


@LeakyNun Saya tidak pernah tahu persis apa yang harus dihitung untuk itu, saya tidak dapat menemukan pos meta yang relevan, saya senang untuk menghitungnya, tapi saya pikir karena Anda dapat menjalankannya dengan -egratis, menambahkan pmembuatnya -pemenjadi +1 ? Akan diperbarui untuk saat ini, tetapi jika Anda dapat menemukan sumber saya bisa mengutip / menautkan untuk maju, itu akan luar biasa!
Dom Hastings

3
@HomHastings 1 benar, sesuai alasan Anda mengatakan + pos meta ini
Sp3000

Terima kasih @ Sp3000! Saya tidak dapat menemukan pos itu seumur hidup saya! @LeakyNun posting meta untuk +1 sesuai komentar dari Sp3000
Dom Hastings

Alih-alih menggunakan operator kondisional berantai, Anda dapat menggunakan operator pesawat ruang angkasa untuk memilih dari daftar: $&.qw(* - +)[$&<=>$1]di bagian pengganti s///operator.
ninjalj

@ninjalj Tentu saja! luar biasa, terima kasih! -8 dengan itu!
Dom Hastings

1

Sebenarnya, 30 byte

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

Sayangnya, karena perintah eval ( ) hanya mengevaluasi literal pada TIO, program ini tidak berfungsi pada TIO.

Penjelasan:

;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 byte

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

Cobalah online!

Algoritma ini mirip dengan jawaban ini , tetapi saya baru menyadarinya setelah mengkode jawaban saya. Jauh lebih baik daripada jawaban asli saya yang digunakan eval(parse).

Sepenuhnya memanfaatkan operasi vektor R - melakukan *operasi pertama menggunakan rle(x)$values ^ rle(x)$lenghtsdan dot-produk dengan vektor ini sign( diff( rle(x)$values ) )(didahului dengan 1).


1

05AB1E (warisan) , 17 16 15 byte

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

-2 byte terima kasih kepada @Emigna .

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

ü                  # 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
Karena pengindeksan modular, Anda dapat menghapus >dengan memindahkan +ke ujung string.
Emigna

@Emigna Tidak yakin bagaimana saya melewatkannya .. Terima kasih!
Kevin Cruijssen

1
Anda dapat menyimpan byte lain dengan menghapus Ćdan ¨, jika Anda menggunakannya ‚ζsebagai gantinyaø
Emigna

@ Emigna Oh, sekarang itu pintar! Terima kasih. Saya tahu bahwa penutupnya sedikit aneh, tetapi tidak tahu bagaimana cara memperbaikinya. ‚ζadalah alternatif penyelesaian yang sempurna, karena ruang diabaikan dalam eval. Terima kasih lagi. :)
Kevin Cruijssen

0

PHP, 103 byte

Tantangan yang rapi. Ini jadi lebih lama dari yang diharapkan. Saya pikir menggunakan array_mapatau serupa tidak akan meningkatkan jumlah byte, karena fungsi anonim masih mahal di PHP.

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

Berjalan dari baris perintah, akan meminta daftar yang dipisahkan koma, seperti:

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

0

PowerShell v2 +, 62 byte

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

Mengambil input sebagai argumen baris perintah yang dipisahkan oleh ruang, yang akan dikonversi menjadi array otomatis $args. Kami beralih melalui setiap elemen, menggunakan variabel pembantu $osetiap iterasi untuk mengingat apa entri kami sebelumnya. Kami menggunakan diindeks-string untuk menarik keluar operator yang tepat, dilakukan dengan melakukan matematika pada nilai-nilai Boolean secara implisit-dikonversi (misalnya, jika entry sebelumnya lebih kecil, yang []mengevaluasi ke 1+2*0sehingga '*+-'[1]berarti +dipilih).

Senar bersambung dibiarkan di atas pipa. Kami mengumpulkan semua orang potongan bersama-sama (misalnya, 3-, 1+, 4-, dll) dengan -joinoperasi, concatenate pada jumlah akhir (implisit dikonversi ke string), dan pipa untuk iex(alias untuk Invoke-Expressiondan mirip dengan eval).


Kekhawatiran adalah bahwa jika penelepon telah memberikan nilai $ oa (katakanlah $ o = 999) maka ekspresi dalam entri ini tidak akan menghitung nilai yang benar. Inisialisasi $ o perlu ditambahkan ke solusi ini.
Bevo

@Bevo Ini dimaksudkan untuk menjadi skrip penuh, dieksekusi melalui baris perintah, dan bukan fungsi atau melalui shell interaktif. Sebagian besar kiriman saya adalah seperti itu, karena dalam skenario seperti itu, tidak ada variabel yang telah ditentukan untuk dikhawatirkan dan dengan demikian kode bisa sedikit lebih pendek.
AdmBorkBork

0

Japt , 25 byte

Ingin memotongnya lebih pendek, tapi saya tidak bisa membuat versi eval-less bekerja.

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

Cobalah online!


Turun ke 22 byte tetapi masih berpikir itu bisa ditingkatkan.
Shaggy

0

Japt -x , 21 19 byte

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

Cobalah


Penjelasan

                        :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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.