Generar un punto aleatorio fuera de un rectángulo dado dentro de un mapa

15

Introducción

Dada esta visualización de un campo de juego:

(0,0)
+----------------------+(map_width, 0)
|           A          |
|-----+-----------+----|
|  D  |     W     | B  |
|-----+-----------+----|
|           C          |
+----------------------+(map_width, map_height)
(0, map_height)

El mapa completo en el que se juega es el rectángulo con las coordenadas de las esquinas (0,0) y (map_width, map_height). Los puntos elegibles para generar enemigos es la Unión

S=(A,B,C,D)

El reto

Escriba el código que devuelve un punto aleatorio (x, y) que se garantiza que está dentro de S. Su código no puede introducir ningún sesgo adicional, lo que significa que la probabilidad de cada coordenada se distribuye uniformemente dado el supuesto de que su elección de generar aleatoriedad (por ejemplo, función | biblioteca | dev / urandom) es imparcial.

¡Las soluciones más cortas en bytes ganan!

Entrada

Se le dará un total de 6 variables de entrada de enteros positivos en orden: map_width, map_height, W_top_left_x, W_top_left_y, W_width, W_height . Puede suponer que el área de superficie (calculada) de todas las regiones (A, B, C, D, W) es cada una> 10, por lo que no hay espacios / regiones vacíos.

Entrada de ejemplo: 1000, 1000, 100, 100, 600, 400

La entrada tiene que contener los 6 valores descritos anteriormente, pero se puede pasar como un menor número de argumentos y en cualquier orden. Por ejemplo, pasar (map_width, map_height)como python tuple está permitido. Lo que no está permitido, por supuesto, son parámetros calculados como el punto inferior derecho de la W.

Salida

2 enteros generados aleatoriamente (x, y) donde

(0 0X<ancho_mapa)¬(W_top_left_xX<W_top_left_x+view_width)

O

(0 0y<altura_mapa)¬(W_top_left_yy<W_top_left_y+view_height)

lo que significa que al menos una de las expresiones lógicas anteriores tiene que ser verdadera.

Ejemplos

Input                                    Output(valid random samples)

1000 1000 100 100 600 400                10 10
1000 1000 100 100 600 400                800 550
1000 1000 100 100 600 400                800 10
1000 1000 100 100 600 400                10 550

Para obtener detalles y limitaciones para la entrada / salida, consulte las reglas predeterminadas de entrada / salida

jaaq
fuente
Creo que debería indicar explícitamente que las coordenadas de salida son enteros (lo que infiero como su intención implícita).
agtoever
1
¿Podemos usar las reglas de entrada / salida predeterminadas ?
Nick Kennedy el
1
@agtoever lo dice en la sección "salida"; 2 randomly generated integers (x, y)
Giuseppe
1
¿podemos tomar entradas en un orden diferente (consistente)?
attinat
@agtoever yes output tiene que ser un número entero como se indica en la sección "output".
jaaq

Respuestas:

7

Python 2 , 114 106 102 101 bytes

lambda w,h,X,Y,W,H:choice([(i%w,i/w)for i in range(w*h)if(W>i%w-X>-1<i/w-Y<H)<1])
from random import*

Pruébalo en línea!

TFeld
fuente
No estoy seguro, pero creo que debería ser [i%w, i/w] porque el rango w*h/w=hpero x está vinculado al ancho en este ejemplo, no a la altura.
jaaq
@jaaq Sí, tienes razón. Reparado ahora, gracias :)
TFeld
Acabo de comprobar el contenido de la lista que genera y parece que su solución es incorrecta. El trazado de los puntos muestra que todos los valores están a lo largo de una línea y no completan toda la región de S como se esperaba. Además, la lista que genera contiene valores no enteros.
jaaq
@jaaq No estoy seguro de lo que quieres decir? Las coordenadas son siempre enteras, y no en una línea ( p . Ej. )
TFeld
1
@jaaq En Python 2, a/bya es división de piso, si ay bson enteros (que están aquí).
TFeld
4

R , 89 73 bytes

function(w,h,K,D,`*`=sample){while(all((o<-c(0:w*1,0:h*1))<=K+D&o>K))0
o}

Pruébalo en línea!

Toma entrada como width,height,c(X,Y),c(W,H).

Muestras de [0 0,w]×[0 0,h] uniformemente hasta que encuentre un punto fuera del rectángulo interno.

Giuseppe
fuente
4

05AB1E , 23 21 20 18 17 bytes

L`â<ʒ²³+‹y²@«P≠}Ω

La entrada está en el formato [map_width, map_height], [W_top_left_x, W_top_left_y], [W_width, W_height].

Gracias a @Grimy por -1 byte, y también por darme cuenta de que introduje un error después de mi última edición.

Pruébelo en línea , envíe 10 salidas posibles al mismo tiempo o verifique todas las coordenadas posibles . (Nota menor: he disminuido la entrada de ejemplo en un factor 10, porque el filtro y la selección aleatoria incorporada son bastante lentos para las listas grandes).

Explicación:

Las entradas map_width, map_height, [W_top_left_x, W_top_left_y], [W_width, W_height]se denominan a [Wm, Hm], [x, y], [w, h]continuación:

L          # Convert the values of the first (implicit) input to an inner list in
           # the range [1, n]: [[1,2,3,...,Wm],[1,2,3,....,Hm]]
 `         # Push both inner lists separated to the stack
  â        # Get the cartesian product of both lists, creating each possible pair
   <       # Decrease each pair by 1 to make it 0-based
           # (We now have: [[0,0],[0,1],[0,2],...,[Wm,Hm-2],[Wm,Hm-1],[Wm,Hm]])
    ʒ      # Filter this list of coordinates [Xr, Yr] by:
     ²³+   #  Add the next two inputs together: [x+w, y+h]
          #  Check for both that they're lower than the coordinate: [Xr<x+w, Yr<y+h]
     y     #  Push the coordinate again: [Xr, Yr]
      ²    #  Push the second input again: [x, y]
       @   #  Check for both that the coordinate is larger than or equal to this given 
           #  input: [Xr>=x, Yr>=y] (the w,h in the input are ignored)
     «     #  Merge it with the checks we did earlier: [Xr<x+w, Yr<y+h, Xr>=x, Yr>=y]
      P   #  And check if any of the four is falsey (by taking the product and !=1,
           #  or alternatively `ß_`: minimum == 0)
         # After the filter: pick a random coordinate
           # (which is output implicitly as result)
Kevin Cruijssen
fuente
1
Gracias por agregar la parte de verificación :) ¡gran solución!
jaaq
1
@jaaq ¡Gracias! Yo mismo utilicé el verificador después de mi versión inicial, que es cuando noté un error que tenía que corregir, ya que incluía coordenadas [map_height, 0]como salida aleatoria posible sin el ¨. :)
Kevin Cruijssen
*ݨ¹‰podría ser L`â<tomando las dos primeras entradas como [map_height, map_width]. También IIpodría ser Š, a menos que me haya perdido algo.
Grimmy
@ Grimy Gracias por el L`â<. En cuanto al II+to Š+, tienes razón en que sería lo mismo ... Desafortunadamente, cometí un error y debería haber sido en ²³+lugar de II+, ya que usaría la tercera entrada para ambos I(al igual que tomaría dos veces el tercera entrada con Š) después de la primera iteración del filtro. Así que, implícitamente, gracias por hacerme darme cuenta de que tenía un error. :)
Kevin Cruijssen
3

PowerShell , 85 73 bytes

-12 bytes gracias a mazzy

param($a,$b,$x,$y,$w,$h)$a,$b|%{0..--$x+($x+$w+2)..$_|random
$x,$w=$y,$h}

Pruébalo en línea!

Buena respuesta simple que improvisa una matriz hecha del rango de valores para cada dimensión y luego elige uno al azar para xy y. Se las arregla para reutilizar la mayor parte del código por primera transformación x, a continuación, sobrescribir $xcon $yy funcionando de nuevo.

Veskah
fuente
1
puedes guardar algunos bytes ¡ Pruébalo en línea!
mazzy
1
@mazzy En realidad tropecé con la optimización del rango, pero la apliqué al revés, ahorrando 0 bytes.
Veskah
1

Jalea , 11 bytes

p/’$€+2¦ḟ/X

Pruébalo en línea!

Un enlace diádico que toma dos argumentos, [map_width, map_height], [W_width, W_height] y W_left, W_topy devuelve un punto seleccionado al azar el cumplimiento de los requisitos.

Explicación

   $€       | For each of member of the left argument, do the following as a monad:
p/          | - Reduce using Cartesian product (will generate [1,1],[1,2],... up to the width and height of each of the rectangles)
  ’         | - Decrease by 1 (because we want zero-indexing)
     +2¦    | Add the right argument to the second element of the resulting list
        ḟ/  | Reduce by filtering members of the second list from the first
          X | Select a random element
Nick Kennedy
fuente
1

Python 2 , 100 bytes

La entrada debe estar en forma de ((map_width, W_top_left_x, W_width),(map_height, W_top_left_y, W_height))

La salida se da en la forma: [[x],[y]]

lambda C:[c(s(r(i[0]))-s(r(i[1],i[1]+i[2])),1)for i in C]
from random import*;c=sample;r=range;s=set

Pruébalo en línea!

Salidas aleatorias obtenidas de la entrada de ejemplo:

[[72], [940]]
[[45], [591]]
[[59], [795]]
[[860], [856]]
[[830], [770]]
[[829], [790]]
[[995], [922]]
[[23], [943]]
[[761], [874]]
[[816], [923]]
Ioannes
fuente
1

Java (OpenJDK 8) , 100 bytes

W->H->r->{int x=0,y=0;for(;r.contains(x+=W*Math.random(),y+=H*Math.random());x=y=0);return x+","+y;}

Pruébalo en línea!

Usos java.awt.Rectanglecomo titular de algunos de los parámetros. Naturalmente, esos usan intcampos, y no floato double.

Olivier Grégoire
fuente
1
¡Oh, buena manera de asumir el desafío literalmente con el Rectangle#containsincorporado! : D
Kevin Cruijssen
0

Carbón , 55 43 bytes

NθNηFE²N⊞υ⟦ιN⟧I‽ΦE×θη⟦﹪ιθ÷ιθ⟧⊙υ∨‹§ιμ§λ⁰¬‹§ιμΣλ

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

NθNη

Ingrese el tamaño del mapa. (Si fueran los últimos, podría ingresar la altura en línea para un ahorro de 1 byte).

FE²N⊞υ⟦ιN⟧

Ingrese el rectángulo interno. (Si pudiera ingresar en el orden left, width, top, height, podría usarlo F²⊞υE²Npara un ahorro de 3 bytes).

E×θη⟦﹪ιθ÷ιθ⟧

Genere una lista de todas las coordenadas en el campo.

Φ...⊙υ∨‹§ιμ§λ⁰¬‹§ιμΣλ

Filtre las entradas donde ambas coordenadas se encuentran dentro del rectángulo.

I‽...

Imprima un elemento aleatorio de los que quedan.

Neil
fuente
0

Scala , 172 bytes

Aleatoriedad? Gotcha

(a:Int,b:Int,c:Int,d:Int,e:Int,f:Int)=>{var r=new scala.util.Random
var z=(0,0)
do{z=(r.nextInt(a),r.nextInt(b))}while((c to e+c contains z._1)|(d to e+d contains z._2))
z}

Una implementación divertida que se me ocurre.
Cómo funciona : genera un par aleatorio en el mapa. Si está en el rectángulo interno, intente nuevamente.
Pruébalo en línea!

V. Courtois
fuente
0

J , 54 47 45 39 bytes

(0?@{[)^:((-1&{)~(<*/@,0<:[)2{[)^:_{~&1

Pruébalo en línea!

Tome la entrada como una cuadrícula de 3 x 2 como:

grid_height  grid_width
inner_top    inner_left
inner_height inner_width
  • Elija un punto aleatorio en toda la cuadrícula: 0?@{[
  • Desplácese hacia la izquierda y hacia abajo por el punto superior izquierdo del rectángulo interior: (-1&{)~
  • Regrese al paso 1 si el lugar elegido está dentro (<*/@,0<:[)del rectángulo interior desplazado de manera similar2{[ . De lo contrario, devuelva el punto aleatorio original no desplazado.
  • Siembre todo el proceso con un punto que sabemos que no es válido, es decir, el punto superior izquierdo del rectángulo interior, definido por los elementos 2 y 3 de la lista de entrada: {~&1

Otro enfoque, 45 bytes

{.#:i.@{.(?@#{])@-.&,([:<@;&i./{:){1&{|.i.@{.

Pruébalo en línea!

Este es conceptualmente más simple y no se molesta con el bucle. En su lugar, construimos una matriz de todos los números 0 a (wxh), la desplazamos por el punto de inicio interno, tomamos solo los puntos en la subcuadrícula (0, 0) a (interior w, innner h), los eliminamos del total cuadrícula después de aplanar ambos, elija uno al azar del resto y convierta el entero de nuevo en un punto usando divmod<.@% , |~

Jonás
fuente