Будет ли башня балансировать?

36

Введение

Учитывая ASCII башню и силу ветра, напишите программу или функцию, чтобы определить, будет ли башня балансировать или каким образом она упадет.

Например, первая башня балансирует, а вторая падает влево.

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

Это мой первый вызов. Я надеюсь, тебе это нравится.

Направления

Башня состоит из соединенных блоков, представленных #и образующих жесткий объект . Каждый блок представляет собой квадрат шириной и высотой в одну единицу и имеет постоянную плотность. На башню действуют две силы: ее вес и сила ветра. Все силы действуют на каждый блок индивидуально и проходят через центр блока.

  • Из-за своего веса каждый блок имеет усилие, направленное вниз, действующее на него.
  • Кроме того, каждый блок , который не имеет другого блока, смежного с ним на его наветренной стороне, имеет силу, действующую горизонтально в направлении ветра. Величина этой силы дается в качестве входных данных.
  • Направление ветра указано флагом ASCII где-то на входе. На входе будет флаг, если и только если ветер не нулевой. Флаг не влияет ни на какие силы.

Флаг будет выглядеть именно так, как он выглядит ниже.

Flag design and corresponding wind direction:

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

--->        <---

Чтобы уточнить, башня является твердым объектом и не будет разрываться на части и не прикреплена к земле. Тем не менее, ваша программа должна рассчитать силы для каждого блока в отдельности, чтобы определить, балансирует ли башня.

пример

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

Wind force: 1    Wind direction: --->

Ветер дует вправо и будет толкать блоки, показанные >справа вверху. Обратите внимание, что ветер действует на внутренние отверстия.

Предположим, в нижнем левом углу башни есть координаты (0,0). Момент вокруг левого основания башни (0,0)составляет 71 единицу по часовой стрелке, поэтому башня не упадет влево. Момент вокруг правого основания башни в точке (0,3) составляет 8 единиц по часовой стрелке, поэтому башня упадет вправо.

Если ветер дует влево, соответствующие моменты будут равны 2 единицам по часовой стрелке и 61 единице против часовой стрелки в тех же точках, поэтому башня будет сбалансирована.

вход

  • Ваша программа или функция должны принимать два ввода: десятичное число и строку, разделенную символом новой строки.
  • Десятичное число будет больше нуля и представляет силу, оказываемую ветром на каждый открытый блок, как в примере.
  • Строка будет представлять башню сверху вниз и может содержать пробелы, #|o~символы и символы новой строки. При желании вы можете использовать завершающий символ новой строки и / или заполнить башню завершающими пробелами, чтобы сформировать прямоугольник.
  • У башни будет хотя бы один #в нижнем ряду.
  • Вы можете ввести число и строку в любом порядке.
  • Если величина силы ветра не равна нулю, где-то на входе будет флаг, либо на земле, либо на башне. Флаг будет иметь точную форму, показанную выше.
  • Эти #блоки будут образовывать связную форму , которая может содержать отверстия. Другими словами, все блоки будут смежными с другим другим блоком, если только не один блок.

Выход

  • Один из персонажей B, Lили R, в зависимости от того, будет ли башня балансировать, падает влево (против часовой стрелки) или падает вправо (по часовой стрелке).
  • Вывод может иметь дополнительный завершающий перевод строки.

Это ; применяются стандартные правила и лазейки.

B Тестовые случаи:

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 Тестовые случаи:

Wind: 0
#####
   #


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

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

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

R Тестовые случаи:

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

Wind: 2
o~~
|~~
#

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

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

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

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

Справочное решение (JavaScript)

Попробуйте онлайн.

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

Leaderboard

Вот фрагмент стека, который генерирует как регулярную таблицу лидеров, так и обзор победителей по языкам.

Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:

# Language Name, N bytes

где Nразмер вашего представления. Если вы улучшите свой счет, вы можете сохранить старые результаты в заголовке, вычеркнув их. Например:

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

Если вы хотите включить в заголовок несколько чисел (например, потому что ваш результат равен сумме двух файлов или вы хотите перечислить штрафы за флаг интерпретатора отдельно), убедитесь, что фактический результат является последним числом в заголовке:

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

Вы также можете сделать название языка ссылкой, которая затем будет отображаться во фрагменте списка лидеров:

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

intrepidcoder
источник
17
Добро пожаловать в PPCG; это отлично написанная первая задача! :)
Дверная ручка

Ответы:

2

JavaScript (ES6), 239 байт

Я проиграл свою контрольную реализацию. Я смог сохранить байты, изменив цикл for на a map, используя &&и ||замкнув операторы if и используя ,оператор, чтобы поместить все в один оператор, чтобы избежать явного возврата в функцию.

(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')

Возможно, все еще возможно играть в гольф больше. Предложения приветствуются.

intrepidcoder
источник
+1 намного лучше, чем мое наивное решение
Конор О'Брайен
1

JavaScript ES6, 297 293 байта

В основном сжатая версия данной реализации.

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

Полувспененный:

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"
}
Конор О'Брайен
источник