La tour va-t-elle s'équilibrer?

36

introduction

À partir d'une tour ASCII et de la force du vent, écrivez un programme ou une fonction pour déterminer si la tour va s'équilibrer ou dans quel sens elle va tomber.

Par exemple, la première tour est en équilibre mais la seconde bascule vers la gauche.

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

Ceci est mon premier défi. J'espère que ça vous plait.

instructions

La tour se compose de blocs reliés représentés par #et forme un objet rigide . Chaque bloc est un carré avec une largeur et une hauteur d'une unité et une densité constante. Il y a deux forces qui agissent sur la tour, son poids et la force du vent. Toutes les forces agissent sur chaque bloc individuellement et passent au centre du bloc.

  • En raison de son poids, chaque bloc exerce une force descendante d'une unité.
  • De plus, chaque bloc qui n'a pas un autre bloc adjacent du côté au vent exerce une force qui agit horizontalement dans la direction du vent. La magnitude de cette force est donnée en entrée.
  • La direction du vent est indiquée par un drapeau ASCII quelque part dans l'entrée. Il y aura un drapeau dans l'entrée si et seulement si le vent n'est pas nul. Le drapeau n'affecte aucune force.

Le drapeau ressemblera exactement à ce qui apparaît ci-dessous.

Flag design and corresponding wind direction:

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

--->        <---

Pour clarifier, la tour est un objet solide qui ne se séparera pas et n’est pas attachée au sol. Cependant, votre programme doit calculer les forces pour chaque bloc individuellement afin de déterminer si la tour est équilibrée.

Exemple

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

Wind force: 1    Wind direction: --->

Le vent souffle à droite et poussera sur les blocs indiqués avec un >en haut à droite. Notez que le vent agit à l'intérieur des trous.

Supposons que le coin inférieur gauche de la tour a des coordonnées (0,0). Le moment autour de la base gauche de la tour (0,0)est de 71 unités dans le sens des aiguilles d'une montre pour que la tour ne tombe pas à gauche. Le moment autour de la base droite de la tour en (0,3) est de 8 unités dans le sens des aiguilles d'une montre pour que la tour tombe à droite.

Si le vent soufflait vers la gauche, les moments respectifs seraient de 2 unités dans le sens des aiguilles d'une montre et 61 unités dans le sens contraire des aiguilles d'une montre aux mêmes points, de sorte que la tour s'équilibrerait.

Contribution

  • Votre programme ou votre fonction doit prendre deux entrées, un nombre décimal et une chaîne séparée par une nouvelle ligne.
  • Le nombre décimal sera supérieur à zéro et représente la force exercée par le vent sur chaque bloc exposé, comme dans l'exemple.
  • La chaîne représente la tour de haut en bas et peut contenir des espaces, des #|o~caractères et des nouvelles lignes. Vous pouvez éventuellement supposer un retour à la ligne et / ou compléter la tour avec des espaces pour former un rectangle.
  • La tour aura au moins un #sur la rangée inférieure.
  • Vous pouvez entrer le nombre et la chaîne dans l'un ou l'autre ordre.
  • Si la force du vent est non nulle, il y aura un drapeau quelque part dans l'entrée, soit au sol, soit connecté à la tour. Le drapeau aura la forme exacte indiquée ci-dessus.
  • Les #blocs formeront une forme connectée pouvant contenir des trous. En d'autres termes, tous les blocs seront adjacents à un autre autre bloc sauf s'il n'y a qu'un seul bloc.

Sortie

  • L'un des personnages B, Lou R, selon que la tour va s'équilibrer, tombe vers la gauche (sens antihoraire) ou vers la droite (sens horaire).
  • La sortie peut avoir un retour à la ligne optionnel.

C'est du ; les règles standard et les échappatoires s'appliquent.

B Cas de test:

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 Cas de test:

Wind: 0
#####
   #


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

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

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

R Cas de test:

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

Wind: 2
o~~
|~~
#

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

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

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

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

Solution de référence (JavaScript)

Essayez-le en ligne.

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

Classement

Voici un extrait de pile permettant de générer un classement régulier et un aperçu des gagnants par langue.

Pour vous assurer que votre réponse apparaît, commencez votre réponse par un titre, en utilisant le modèle Markdown suivant:

# Language Name, N bytes

Nest la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores en les effaçant. Par exemple:

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

Si vous souhaitez inclure plusieurs numéros dans votre en-tête (par exemple, parce que votre score est la somme de deux fichiers ou si vous souhaitez répertorier séparément les pénalités d'indicateur d'interprétation), assurez-vous que le score réel est le dernier numéro de l'en-tête:

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

Vous pouvez également faire du nom de la langue un lien qui apparaîtra ensuite dans l'extrait de classement:

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

intrépide
la source
17
Bienvenue chez PPCG; C'est un premier défi parfaitement écrit! :)
Poignée de porte

Réponses:

2

JavaScript (ES6), 239 octets

J'ai joué au golf dans ma mise en œuvre de référence. J'ai pu économiser des octets en remplaçant la boucle for par une map, en utilisant &&et ||en court-circuitant des instructions if, et en utilisant l' ,opérateur pour tout insérer dans une instruction afin d'éviter un retour explicite dans la fonction.

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

Il serait peut-être encore possible de jouer au golf plus souvent. Les suggestions sont les bienvenues.

intrépide
la source
+1 bien meilleur que ma solution naïve
Conor O'Brien
1

JavaScript ES6, 297 293 octets

Fondamentalement, une version compressée de l'implémentation donnée.

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-expansé:

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
la source