Apakah menara akan seimbang?

36

pengantar

Diberi menara ASCII dan kekuatan angin, tulislah sebuah program atau fungsi untuk menentukan apakah menara itu akan seimbang atau ke arah mana ia akan jatuh.

Misalnya menara pertama menyeimbangkan tetapi yang kedua jatuh ke kiri.

  # #            # #
  ###            ### 
 ###            ### 
 # #            # # 
#####          ##### 
 ###            ### 
 ###              #

Ini tantangan pertama saya. Kuharap kamu menikmatinya.

Petunjuk arah

Menara ini terdiri dari blok-blok terhubung yang diwakili oleh #dan membentuk objek yang kaku . Setiap blok berbentuk bujur sangkar dengan lebar dan tinggi satu unit dan memiliki kerapatan konstan. Ada dua kekuatan yang bekerja pada menara, beratnya dan kekuatan angin. Semua gaya bekerja pada setiap blok secara individual dan melewati bagian tengah blok.

  • Karena beratnya, setiap blok memiliki kekuatan ke bawah dari satu unit yang bekerja di atasnya.
  • Juga, setiap blok yang tidak memiliki blok lain di sebelahnya di sisi anginnya memiliki gaya di atasnya yang bekerja secara horizontal ke arah angin. Besarnya gaya ini diberikan sebagai input.
  • Arah angin ditunjukkan oleh bendera ASCII di suatu tempat di input. Akan ada bendera di input jika dan hanya jika angin tidak nol. Bendera tidak memengaruhi kekuatan apa pun.

Bendera akan terlihat persis seperti yang ditampilkan di bawah ini.

Flag design and corresponding wind direction:

 o~~        ~~o
 |~~        ~~|

--->        <---

Untuk memperjelas, menara adalah benda padat dan tidak akan pecah dan tidak melekat ke tanah. Namun, program Anda harus menghitung kekuatan untuk setiap blok secara individual untuk menentukan apakah menara seimbang.

Contoh

  o~~
  |~~
  # #              > > 
  ###              >## 
 ###              >##  
 # #              > >  
#####            >#### 
 ###              >##  
 ###              >##  

Wind force: 1    Wind direction: --->

Angin bertiup ke kanan dan akan mendorong pada blok yang ditunjukkan dengan >di kanan atas. Perhatikan bahwa angin beraksi di bagian dalam lubang.

Asumsikan sudut kiri bawah menara memiliki koordinat (0,0). Momen di sekitar dasar kiri menara di (0,0)adalah 71 unit searah jarum jam sehingga menara tidak akan jatuh ke kiri. Momen di sekitar dasar kanan menara di (0,3) adalah 8 unit searah jarum jam sehingga menara akan jatuh tepat.

Jika angin bertiup ke arah kiri, momen masing-masing akan menjadi 2 unit searah jarum jam dan 61 unit berlawanan arah jarum jam pada titik yang sama, sehingga menara akan menyeimbangkan.

Memasukkan

  • Program atau fungsi Anda harus mengambil dua input, angka desimal dan string yang dipisahkan baris baru.
  • Angka desimal akan lebih besar dari nol dan mewakili gaya yang diberikan oleh angin pada setiap blok yang terbuka seperti pada contoh.
  • String akan mewakili menara dari atas ke bawah dan dapat berisi spasi, #|o~karakter, dan baris baru. Anda dapat secara opsional mengambil garis baru dan / atau mengisi menara dengan spasi tambahan untuk membentuk persegi panjang.
  • Menara ini akan memiliki setidaknya satu #di baris bawah.
  • Anda dapat memasukkan nomor dan string dalam urutan apa pun.
  • Jika besarnya kekuatan angin bukan nol, akan ada bendera di suatu tempat di input, baik di darat atau terhubung ke menara. Bendera akan memiliki bentuk persis seperti yang ditunjukkan di atas.
  • The #blok akan membentuk bentuk terhubung yang mungkin berisi lubang. Dengan kata lain, semua blok akan berdekatan dengan blok lainnya kecuali jika hanya ada satu blok.

Keluaran

  • Salah satu karakter B,, Latau R, tergantung pada apakah menara akan menyeimbangkan, jatuh ke kiri (berlawanan arah jarum jam), atau jatuh ke kanan (searah jarum jam).
  • Output mungkin memiliki baris tambahan opsional.

Ini adalah ; aturan standar dan celah berlaku.

B Kasus uji:

Wind: 1
    ~~o
    ~~|
      # #
      ###
     ###
     # #
    #####
     ###
     ###

Wind: 0
##
# ##
###

Wind: 1.7
o~~
|~~
#
##

Wind: 0.768
      o~~
      |~~
      # #
      ###
     ###
     # #
    #####
     ###
     ###

Wind: 0.1
#
#
#
#
#
# o~~
# |~~

Wind: 0
#

Wind: 0
############

Wind: 144
               o~~
############   |~~

Wind: 0
#######
 ##
 #
 ##

Wind: 0
                ############
           ############
       ############
    ############
   ############
 ############
############

Wind: 41
                 ############
            ############
        ############
     ############
    ############
  ############     ~~o
 ############      ~~|

L Kasus uji:

Wind: 0
#####
   #


Wind: 42
                 ############
            ############
        ############
     ############
    ############
  ############     ~~o
 ############      ~~|

Wind: 4
########
    ###
 ~~o# ##
 ~~|#  #

Wind: 3
########
    ###
 o~~# ##
 |~~   #

R Kasus uji:

Wind: 1
      o~~
      |~~
      # #
      ###
     ###
     # #
    #####
     ###
     ###

Wind: 2
o~~
|~~
#

Wind: 0.001
                 ############
            ############
        ############
     ############
    ############
  ############     o~~
 ############      |~~

Wind: 145
               o~~
############   |~~

Wind: 1
#
#
#
#
#
# o~~
# |~~

Wind: 0.26
#######
 ##
 #   o~~
 ##  |~~

Solusi Referensi (JavaScript)

Cobalah online.

function balanced(tower, wind) {
    var rows = tower.split('\n').reverse(); // Reverse so row index matches height of row.
    var height = rows.length;
    var leftEdge = rows[0].indexOf('#'); // Find bottom left corner of tower.
    var rightEdge = rows[0].lastIndexOf('#') + 1; // Find bottom right corner of tower.
    var leftMoment = 0, rightMoment = 0; // Moments around the bottoms corners of tower.
    wind *= tower.indexOf('~o')>-1 ? -1 : 1; // Find direction of the wind.

    // Sum the moments for each block in the tower.
    for (var i = height - 1; i >= 0; i--) {
        rows[i].split('').map(function(ch, index, arr) {
            if (ch=='#') {
                // If there's not a block toward the windward side of the current one.
                if ((wind < 0 && arr[index-1] != '#') || (wind > 0 && arr[index+1]!='#')) {
                    // Add moments from wind.
                    leftMoment += (i+0.5)*-wind;
                    rightMoment += (i+0.5)*-wind; 
                }

                leftMoment += leftEdge - (index + 0.5);
                rightMoment += rightEdge - (index + 0.5);
            }
        }, 0);
    }
    if (leftMoment > 0) return 'L';
    else if (rightMoment < 0) return 'R';
    else return 'B';
}

Papan peringkat

Berikut ini adalah Stack Snippet untuk menghasilkan leaderboard biasa dan gambaran umum pemenang berdasarkan bahasa.

Untuk memastikan bahwa jawaban Anda muncul, silakan mulai jawaban Anda dengan tajuk utama, menggunakan templat Penurunan harga berikut:

# Language Name, N bytes

di mana Nukuran kiriman Anda. Jika Anda meningkatkan skor Anda, Anda dapat menyimpan skor lama di headline, dengan mencoretnya. Contohnya:

# Ruby, <s>104</s> <s>101</s> 96 bytes

Jika Anda ingin memasukkan beberapa angka dalam tajuk Anda (mis. Karena skor Anda adalah jumlah dari dua file atau Anda ingin membuat daftar hukuman penterjemah secara terpisah), pastikan bahwa skor sebenarnya adalah angka terakhir di tajuk:

# Perl, 43 + 2 (-p flag) = 45 bytes

Anda juga dapat membuat tautan nama bahasa yang kemudian akan muncul di cuplikan papan peringkat:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes

intrepidcoder
sumber
17
Selamat datang di PPCG; ini adalah tantangan pertama yang ditulis dengan sangat baik! :)
Gagang Pintu

Jawaban:

2

JavaScript (ES6), 239 byte

Saya menurunkan implementasi referensi saya. Saya dapat menyimpan byte dengan mengubah loop for menjadi map, menggunakan &&dan ||untuk hubungan pendek jika pernyataan, dan menggunakan ,operator untuk memasukkan semuanya pada satu pernyataan sehingga untuk menghindari pengembalian eksplisit dalam fungsi.

(a,b)=>((c=a.split`
`.reverse(),d=c[f=g=0].indexOf`#`,e=c[0].lastIndexOf`#`+1),a.match`o~`&&(b*=-1),c.map((h,i)=>h.replace(/#/g,(j,k,l)=>(b>0&l[k-1]!='#'|b<0&l[k+1]!='#'&&(f+=(i+=0.5)*b,g+=i*b),f+=d-k-0.5,g+=e-k-0.5))),f>0?'L':g<0?'R':'B')

Mungkin masih bisa bermain golf ini lebih banyak. Saran diterima.

intrepidcoder
sumber
+1 jauh lebih baik daripada solusi naif saya
Conor O'Brien
1

JavaScript ES6, 297 293 byte

Pada dasarnya versi terkompresi dari implementasi yang diberikan.

b=(n,e)=>{r=n.split`
`.reverse(),t=r.length,a=r[0].indexOf`#`,f=r[i=l=0].lastIndexOf`#`+1;e*=n.indexOf`~o`>-1?-1:1;for(d=t-1;d>=0;d--)r[d].split``.map((n,r,t)=>{(j="#")==n&&((0>e&&j!=t[r-1]||e>0&&j!=t[r+1])&&(i+=(d+.5)*-e,l+=(d+.5)*-e),i+=a-(r+.5),l+=f-(r+.5))},0);return i>0?"L":0>l?"R":"B"}

Semi diperluas:

b = (n, e) => {
    r = n.split `
`.reverse(), t = r.length, a = r[0].indexOf `#`, f = r[i = l = 0].lastIndexOf `#` + 1;
    e *= n.indexOf `~o` > -1 ? -1 : 1;
    for (d = t - 1; d >= 0; d--) r[d].split ``.map((n, r, t) => {
        (j = "#") == n && ((0 > e && j != t[r - 1] || e > 0 && j != t[r + 1]) && (i += (d + .5) * -e, l += (d + .5) * -e), i += a - (r + .5), l += f - (r + .5))
    }, 0);
    return i > 0 ? "L" : 0 > l ? "R" : "B"
}
Conor O'Brien
sumber