¿Se equilibrará la torre?


36

Introducción

Dada una torre ASCII y la fuerza del viento, escriba un programa o función para determinar si la torre se equilibrará o de qué manera caerá.

Por ejemplo, la primera torre se equilibra pero la segunda cae hacia la izquierda.

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

Este es mi primer desafío. Espero que lo disfruten.

Direcciones

La torre consta de bloques conectados representados por #y forma un objeto rígido . Cada bloque es un cuadrado con un ancho y alto de una unidad y tiene una densidad constante. Hay dos fuerzas que actúan sobre la torre, su peso y la fuerza del viento. Todas las fuerzas actúan sobre cada bloque individualmente y pasan por el centro del bloque.

  • Debido a su peso, cada bloque tiene una fuerza hacia abajo de una unidad que actúa sobre él.
  • Además, cada bloque que no tiene otro bloque adyacente a él en su lado de barlovento tiene una fuerza que actúa horizontalmente en la dirección del viento. La magnitud de esta fuerza se da como una entrada.
  • La dirección del viento se indica mediante una bandera ASCII en algún lugar de la entrada. Habrá una bandera en la entrada si y solo si el viento no es cero. La bandera no afecta a ninguna fuerza.

La bandera se verá exactamente como aparece a continuación.

Flag design and corresponding wind direction:

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

--->        <---

Para aclarar, la torre es un objeto sólido y no se romperá y no está unida al suelo. Sin embargo, su programa debe calcular las fuerzas para cada bloque individualmente para determinar si la torre se equilibra.

Ejemplo

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

Wind force: 1    Wind direction: --->

El viento sopla a la derecha y empujará los bloques que se muestran con un >a la derecha arriba. Tenga en cuenta que el viento actúa en el interior de los agujeros.

Suponga que la esquina inferior izquierda de la torre tiene coordenadas (0,0). El momento alrededor de la base izquierda de la torre (0,0)es de 71 unidades en el sentido de las agujas del reloj para que la torre no caiga a la izquierda. El momento alrededor de la base derecha de la torre en (0,3) es de 8 unidades en el sentido de las agujas del reloj, por lo que la torre caerá a la derecha.

Si el viento soplara hacia la izquierda, los momentos respectivos serían 2 unidades en sentido horario y 61 unidades en sentido antihorario en los mismos puntos, por lo que la torre se equilibraría.

Entrada

  • Su programa o función debe tomar dos entradas, un número decimal y una cadena separada por una nueva línea.
  • El número decimal será mayor que cero y representa la fuerza ejercida por el viento en cada bloque expuesto como en el ejemplo.
  • La cadena representará la torre de arriba a abajo y puede contener espacios, #|o~caracteres y líneas nuevas. Opcionalmente, puede suponer una nueva línea posterior y / o rellenar la torre con espacios finales para formar un rectángulo.
  • La torre tendrá al menos uno #en la fila inferior.
  • Puede ingresar el número y la cadena en cualquier orden.
  • Si la magnitud de la fuerza del viento no es cero, habrá una bandera en algún lugar de la entrada, ya sea en el suelo o conectada a la torre. La bandera tendrá la forma exacta que se muestra arriba.
  • Los #bloques formarán una forma conectada que puede contener agujeros. En otras palabras, todos los bloques serán adyacentes a otro bloque a menos que solo haya un bloque.

Salida

  • Uno de los personajes B, Lo R, dependiendo de si la torre se equilibrará, caerá hacia la izquierda (en sentido antihorario) o caerá hacia la derecha (en sentido horario).
  • La salida puede tener una nueva línea final opcional.

Este es el ; se aplican reglas estándar y lagunas.

B Casos de prueba:

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 Casos de prueba:

Wind: 0
#####
   #


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

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

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

R Casos de prueba:

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

Wind: 2
o~~
|~~
#

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

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

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

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

Solución de referencia (JavaScript)

Pruébalo en línea.

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

Tabla de clasificación

Aquí hay un fragmento de pila para generar una tabla de clasificación regular y una descripción general de los ganadores por idioma.

Para asegurarse de que su respuesta se muestre, comience con un título, usando la siguiente plantilla de Markdown:

# Language Name, N bytes

¿Dónde Nestá el tamaño de su envío? Si mejora su puntaje, puede mantener los puntajes antiguos en el título, tachándolos. Por ejemplo:

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

Si desea incluir varios números en su encabezado (por ejemplo, porque su puntaje es la suma de dos archivos o desea enumerar las penalizaciones de la bandera del intérprete por separado), asegúrese de que el puntaje real sea el último número en el encabezado:

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

También puede hacer que el nombre del idioma sea un enlace que luego aparecerá en el fragmento de la tabla de clasificación:

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


17
Bienvenido a PPCG; ¡Este es un primer desafío excelentemente escrito! :)
Pomo de la puerta

Respuestas:


2

JavaScript (ES6), 239 bytes

Disminuí mi implementación de referencia. Pude guardar bytes cambiando el bucle for a map, usando &&y ||para hacer un cortocircuito en las declaraciones if, y usando el ,operador para ajustar todo en una declaración a fin de evitar un retorno explícito en la función.

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

Todavía podría ser posible jugar golf más. Las sugerencias son bienvenidas.


+1 mucho mejor que mi solución ingenua
Conor O'Brien

1

JavaScript ES6, 297 293 bytes

Básicamente, una versión comprimida de la implementación dada.

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-expandido:

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"
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.