Wird der Turm balancieren?


36

Einführung

Wenn Sie einen ASCII-Turm und die Kraft des Windes voraussetzen, schreiben Sie ein Programm oder eine Funktion, um zu bestimmen, ob der Turm balanciert oder in welche Richtung er fällt.

Zum Beispiel gleicht der erste Turm aus, aber der zweite fällt nach links um.

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

Dies ist meine erste Herausforderung. Ich hoffe du genießt es.

Richtungen

Der Turm besteht aus verbundenen Blöcken, die durch #ein starres Objekt dargestellt werden . Jeder Block ist ein Quadrat mit einer Breite und Höhe von einer Einheit und hat eine konstante Dichte. Es gibt zwei Kräfte, die auf den Turm einwirken, sein Gewicht und die Windkraft. Alle Kräfte wirken einzeln auf jeden Block und durchlaufen die Mitte des Blocks.

  • Jeder Block wird aufgrund seines Gewichts von einer Einheit nach unten beaufschlagt.
  • Außerdem wirkt auf jeden Block , an dessen Luvseite kein anderer Block angrenzt, eine in Windrichtung horizontal wirkende Kraft. Die Größe dieser Kraft wird als Eingabe angegeben.
  • Die Windrichtung wird durch ein ASCII-Flag im Eingang angezeigt. In der Eingabe wird genau dann ein Flag angezeigt, wenn der Wind nicht Null ist. Die Flagge beeinflusst keine Kräfte.

Die Flagge sieht genau so aus, wie sie unten angezeigt wird.

Flag design and corresponding wind direction:

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

--->        <---

Zur Verdeutlichung ist der Turm ein fester Gegenstand und bricht nicht auseinander und ist nicht am Boden befestigt. Ihr Programm sollte jedoch die Kräfte für jeden Block einzeln berechnen, um festzustellen, ob sich der Turm im Gleichgewicht befindet.

Beispiel

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

Wind force: 1    Wind direction: --->

Der Wind weht nach rechts und drückt auf die Blöcke, >die oben rechts mit einem gekennzeichnet sind . Beachten Sie, dass der Wind auf die Innenseite der Löcher wirkt.

Angenommen, die linke untere Ecke des Turms hat Koordinaten (0,0). Der Moment um die linke Basis des Turms (0,0)beträgt 71 Einheiten im Uhrzeigersinn, damit der Turm nicht nach links fällt. Der Moment um die rechte Basis des Turms bei (0,3) beträgt 8 Einheiten im Uhrzeigersinn, so dass der Turm nach rechts fällt.

Wenn der Wind nach links weht, sind die jeweiligen Momente an denselben Punkten 2 Einheiten im Uhrzeigersinn und 61 Einheiten gegen den Uhrzeigersinn, sodass sich der Turm ausgleicht.

Eingang

  • Ihr Programm oder Ihre Funktion muss zwei Eingaben annehmen, eine Dezimalzahl und eine durch Zeilenumbrüche getrennte Zeichenfolge.
  • Die Dezimalzahl ist größer als Null und repräsentiert die Kraft, die der Wind wie im Beispiel auf jeden freiliegenden Block ausübt.
  • Die Zeichenfolge stellt den Turm von oben nach unten dar und kann Leerzeichen, #|o~Zeichen und Zeilenumbrüche enthalten. Sie können optional eine abschließende Newline annehmen und / oder den Turm mit abschließenden Leerzeichen auffüllen, um ein Rechteck zu bilden.
  • Der Turm wird mindestens eine #in der unteren Reihe haben.
  • Sie können die Nummer und die Zeichenfolge in beliebiger Reihenfolge eingeben.
  • Wenn die Stärke der Windstärke nicht Null ist, befindet sich irgendwo im Eingang eine Flagge, entweder auf dem Boden oder mit dem Turm verbunden. Die Flagge hat genau die oben gezeigte Form.
  • Die #Blöcke bilden eine zusammenhängende Form, die Löcher enthalten kann. Mit anderen Worten, alle Blöcke grenzen an einen anderen Block, es sei denn, es gibt nur einen Block.

Ausgabe

  • Eine der Figuren B, Loder R, abhängig davon, ob der Turm balanciert, fällt nach links (gegen den Uhrzeigersinn) oder nach rechts (im Uhrzeigersinn).
  • Die Ausgabe kann einen optionalen Zeilenumbruch enthalten.

Das ist ; Es gelten Standardregeln und Regelungslücken.

B Testfälle:

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 Testfälle:

Wind: 0
#####
   #


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

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

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

R Testfälle:

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

Wind: 2
o~~
|~~
#

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

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

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

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

Referenzlösung (JavaScript)

Probieren Sie es online aus.

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

Bestenliste

Hier ist ein Stack-Snippet, um sowohl eine reguläre Rangliste als auch eine Übersicht der Gewinner nach Sprache zu generieren.

Um sicherzustellen, dass Ihre Antwort angezeigt wird, beginnen Sie Ihre Antwort mit einer Überschrift. Verwenden Sie dazu die folgende Markdown-Vorlage:

# Language Name, N bytes

Wo Nist die Größe Ihres Beitrags? Wenn Sie Ihren Score zu verbessern, Sie können alte Rechnungen in der Überschrift halten, indem man sich durch das Anschlagen. Zum Beispiel:

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

Wenn Sie mehrere Zahlen in Ihre Kopfzeile aufnehmen möchten (z. B. weil Ihre Punktzahl die Summe von zwei Dateien ist oder wenn Sie die Strafen für Interpreter-Flags separat auflisten möchten), stellen Sie sicher, dass die tatsächliche Punktzahl die letzte Zahl in der Kopfzeile ist:

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

Sie können den Namen der Sprache auch als Link festlegen, der dann im Leaderboard-Snippet angezeigt wird:

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


17
Willkommen bei PPCG; Dies ist eine hervorragend geschriebene erste Herausforderung! :)
Türklinke

Antworten:


2

JavaScript (ES6), 239 Byte

Ich habe meine Referenzimplementierung heruntergespielt. Ich konnte Bytes speichern , indem die for - Schleife zu einem Wechsel map, mit &&und ||kurzzuschließen , wenn Anweisungen und mit dem ,Betreiber zu passen alles auf einer Anweisung , um eine explizite Rückkehr in der Funktion zu vermeiden.

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

Es könnte noch möglich sein, mehr Golf zu spielen. Vorschläge sind willkommen.


+1 viel besser als meine naive Lösung
Conor O'Brien

1

JavaScript ES6, 297 293 Bytes

Grundsätzlich eine komprimierte Version der gegebenen Implementierung.

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

Teilweise erweitert:

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"
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.