Czy wieża się wyrówna?

36

Wprowadzenie

Biorąc pod uwagę wieżę ASCII i siłę wiatru, napisz program lub funkcję, aby ustalić, czy wieża wyrówna się lub w którą stronę spadnie.

Na przykład pierwsza wieża równoważy się, a druga przewraca się w lewo.

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

To jest moje pierwsze wyzwanie. Mam nadzieję, że ci się spodoba.

Kierunki

Wieża składa się z połączonych bloków reprezentowanych przez #i tworzy sztywny obiekt . Każdy blok jest kwadratem o szerokości i wysokości jednej jednostki i ma stałą gęstość. Na wieżę działają dwie siły, jej ciężar i siła wiatru. Wszystkie siły działają na każdy blok indywidualnie i przechodzą przez środek bloku.

  • Ze względu na swoją wagę, każdy blok ma siłę skierowaną w dół o jedną jednostkę działającą na niego.
  • Ponadto, każdy blok , który nie ma innego bloku sąsiadującego z nim po jego stronie wietrznej, ma na niego siłę działającą poziomo w kierunku wiatru. Wielkość tej siły podano jako dane wejściowe.
  • Kierunek wiatru jest wskazywany gdzieś na wejściu flagą ASCII. Na wejściu pojawi się flaga wtedy i tylko wtedy, gdy wiatr nie będzie zerowy. Flaga nie wpływa na żadne siły.

Flaga będzie wyglądać dokładnie tak, jak pokazano poniżej.

Flag design and corresponding wind direction:

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

--->        <---

Aby wyjaśnić, wieża jest solidnym przedmiotem i nie rozpadnie się i nie jest przymocowana do podłoża. Jednak twój program powinien obliczyć siły dla każdego bloku indywidualnie, aby ustalić, czy wieża się równoważy.

Przykład

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

Wind force: 1    Wind direction: --->

Wiatr wieje w prawo i będzie naciskał na pokazane bloki z symbolem >powyżej po prawej stronie. Pamiętaj, że wiatr działa na wnętrze otworów.

Załóżmy, że lewy dolny róg wieży ma współrzędne (0,0). Moment wokół lewej podstawy wieży (0,0)wynosi 71 jednostek zgodnie z ruchem wskazówek zegara, więc wieża nie spadnie w lewo. Moment wokół prawej podstawy wieży w (0,3) wynosi 8 jednostek zgodnie z ruchem wskazówek zegara, więc wieża spadnie w prawo.

Gdyby wiatr wiał w lewo, odpowiednie momenty wynosiłyby 2 jednostki w kierunku zgodnym z ruchem wskazówek zegara i 61 jednostek w kierunku przeciwnym do ruchu wskazówek zegara w tych samych punktach, więc wieża byłaby zrównoważona.

Wkład

  • Twój program lub funkcja musi przyjmować dwa dane wejściowe, liczbę dziesiętną i ciąg oddzielony znakiem nowej linii.
  • Liczba dziesiętna będzie większa od zera i reprezentuje siłę wywieraną przez wiatr na każdy odsłonięty blok, jak w przykładzie.
  • Ciąg będzie reprezentował wieżę od góry do dołu i może zawierać spacje, #|o~znaki i znaki nowej linii. Opcjonalnie możesz założyć końcową linię i / lub uzupełnić wieżę końcowymi spacjami, aby utworzyć prostokąt.
  • Wieża będzie miała co najmniej jeden #w dolnym rzędzie.
  • Możesz wprowadzić liczbę i ciąg znaków w dowolnej kolejności.
  • Jeśli wielkość siły wiatru jest różna od zera, gdzieś na wejściu będzie flaga, albo na ziemi, albo podłączona do wieży. Flaga będzie miała dokładną formę pokazaną powyżej.
  • Te #bloki tworzą połączoną postać, która może zawierać otwory. Innymi słowy, wszystkie bloki będą przylegały do ​​innego innego bloku, chyba że będzie tylko jeden blok.

Wydajność

  • Jedna z postaci B, Llub R, w zależności od tego, czy wieża się wyrówna, spadnie w lewo (przeciwnie do ruchu wskazówek zegara) lub spadnie w prawo (zgodnie z ruchem wskazówek zegara).
  • Dane wyjściowe mogą mieć opcjonalny końcowy znak nowej linii.

To jest ; obowiązują standardowe zasady i luki.

B Przypadki testowe:

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 Przypadki testowe:

Wind: 0
#####
   #


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

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

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

R Przypadki testowe:

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

Wind: 2
o~~
|~~
#

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

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

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

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

Referencyjne rozwiązanie (JavaScript)

Wypróbuj 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';
}

Tabela liderów

Oto fragment kodu, który pozwala wygenerować zarówno zwykłą tabelę wyników, jak i przegląd zwycięzców według języka.

Aby upewnić się, że twoja odpowiedź się pojawi, zacznij od nagłówka, korzystając z następującego szablonu Markdown:

# Language Name, N bytes

gdzie Njest rozmiar twojego zgłoszenia. Jeśli poprawić swój wynik, to może zachować stare porachunki w nagłówku, uderzając je przez. Na przykład:

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

Jeśli chcesz umieścić w nagłówku wiele liczb (np. Ponieważ twój wynik to suma dwóch plików lub chcesz osobno wymienić kary za flagi tłumacza), upewnij się, że rzeczywisty wynik jest ostatnią liczbą w nagłówku:

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

Możesz także ustawić nazwę języka jako link, który pojawi się we fragmencie tabeli wyników:

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

intrepidcoder
źródło
17
Witamy w PPCG; to świetnie napisane pierwsze wyzwanie! :)
Klamka

Odpowiedzi:

2

JavaScript (ES6), 239 bajtów

Grałem w golfa moją referencyjną implementację. Byłem w stanie zaoszczędzić bajty, zmieniając pętlę for na a map, używając &&i ||zwierając instrukcje if, i używając ,operatora, aby dopasować wszystko do jednej instrukcji, aby uniknąć jawnego powrotu funkcji.

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

Być może nadal będzie można grać w golfa. Sugestie są mile widziane.

intrepidcoder
źródło
+1 znacznie lepiej niż moje naiwne rozwiązanie
Conor O'Brien
1

JavaScript ES6, 297 293 bajtów

Zasadniczo skompresowana wersja danej implementacji.

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

Częściowo rozszerzone:

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