Gere um ponto aleatório fora de um determinado retângulo dentro de um mapa


15

Introdução

Dada esta visualização de um campo de jogo:

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

O mapa inteiro em que o jogo é jogado é o retângulo com as coordenadas dos cantos (0,0) e (map_width, map_height). Os pontos elegíveis para desovar inimigos são a União

S=(A,B,C,D)

O desafio

Escreva um código que retorne um ponto aleatório (x, y) com garantia de estar dentro de S. Seu código não pode introduzir nenhum viés adicional, o que significa que a probabilidade de cada coordenada é distribuída uniformemente, considerando que sua escolha de gerar aleatoriedade (por exemplo, função | library | dev / urandom) é imparcial.

As soluções mais curtas em bytes ganham!

Entrada

Você será dado um total de 6 variáveis de entrada inteiro positivo na ordem: map_width, map_height, W_top_left_x, W_top_left_y, W_width, W_height. Você pode assumir que a área de superfície (calculada) de todas as regiões (A, B, C, D, W) é cada> 10, portanto, não há espaços / regiões vazios.

Exemplo de entrada: 1000, 1000, 100, 100, 600, 400

A entrada deve conter os 6 valores descritos acima, mas pode ser passada como menor número de argumentos e em qualquer ordem. Por exemplo, passar (map_width, map_height)como tupla python é permitido. O que não é permitido, é claro, são parâmetros calculados, como o ponto inferior direito do W.

Resultado

2 inteiros gerados aleatoriamente (x, y) em que

(0x<map_width)¬(W_top_left_xx<W_top_left_x+view_width)

OU

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

ou seja, pelo menos uma das expressões lógicas acima deve ser verdadeira.

Exemplos

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 detalhes e limitações para entrada / saída, consulte as regras padrão de entrada / saída


Eu acho que você deveria declarar explicitamente que as coordenadas de saída são números inteiros (que eu deduzo como sua intenção implícita).
agtoever 6/08/19


1
@agtoever diz isso na seção "output"; 2 randomly generated integers (x, y)
Giuseppe

1
podemos receber informações em uma ordem diferente (consistente)?
attinat 7/08/19

@agtoever yes, a saída deve ser um número inteiro, conforme indicado na seção "saída".
jaaq

Respostas:


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*

Experimente online!


Não tenho certeza, mas acho que deve ser [i%w, i/w] porque o intervalo, w*h/w=hmas x, está vinculado à largura neste exemplo, não à altura.
jaaq

@jaaq Sim, você está certo. Fixas agora, graças :)
TFeld

Acabei de verificar o conteúdo da lista que você gera e parece que sua solução está incorreta. A plotagem dos pontos mostra que todos os valores estão ao longo de uma linha e não preenchem toda a região de S conforme planejado. Além disso, a lista que você gera contém valores não inteiros.
jaaq

@jaaq Não sei ao certo o que você quer dizer? As coordenadas são sempre números inteiros, e não em uma linha ( por exemplo )
TFeld

1
@jaaq No Python 2, a/bjá é a divisão do piso, se ae bsão inteiros (que estão aqui).
precisa saber é

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}

Experimente online!

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

Amostras de [0 0,W]×[0 0,h] uniformemente até encontrar um ponto fora do retângulo interno.


4

05AB1E , 23 21 20 18 17 bytes

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

A entrada está no formato [map_width, map_height], [W_top_left_x, W_top_left_y], [W_width, W_height].

Graças ao @Grimy por -1 byte, e também por me fazer perceber que introduzi um bug após minha última edição.

Experimente on-line , produza 10 saídas possíveis ao mesmo tempo ou verifique todas as coordenadas possíveis . (Observação secundária: reduzi o exemplo de entrada em um fator 10, porque o filtro e a escolha aleatória incorporados são muito lentos para grandes listas.)

Explicação:

As entradas map_width, map_height, [W_top_left_x, W_top_left_y], [W_width, W_height]são referidas [Wm, Hm], [x, y], [w, h]abaixo:

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)

1
Obrigado por adicionar a parte de verificação :) ótima solução!
jaaq

1
@jaaq Thanks! Eu mesmo usei o verificador após a minha versão inicial, que foi quando notei um bug que precisava corrigir, pois estava incluindo coordenadas [map_height, 0]como possível saída aleatória sem o ¨. :)
Kevin Cruijssen 7/08/19

*ݨ¹‰poderia ser L`â<pegando as duas primeiras entradas como [map_height, map_width]. Também IIpoderia ser Š, a menos que eu perdesse alguma coisa.
Grimmy

@ Grimy Obrigado pela L`â<. Quanto ao II+to Š+, você está realmente certo de que seria o mesmo .. Infelizmente eu cometi um erro e deveria ter sido, em ²³+vez de II+, pois ele usaria a terceira entrada para ambos I(assim como levaria duas vezes a terceira entrada com Š) após a primeira iteração do filtro .. Então, implicitamente, obrigado por me fazer perceber que eu tinha um bug. :)
Kevin Cruijssen 08/08/19


3

PowerShell , 85 73 bytes

-12 bytes graças ao mazzy

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

Experimente online!

Resposta simples e agradável, que reúne uma matriz composta pelo intervalo de valores para cada dimensão e, em seguida, seleciona uma aleatoriamente para xe y. Consegue reutilizar a maior parte do código processando primeiro x, depois substituindo $x-o $ye executando-o novamente.


1
você pode economizar alguns bytes Experimente online!
Mazzy

1
@mazzy Na verdade, eu tropecei na otimização de faixa, mas a apliquei para trás, economizando 0 bytes.
Veskah 6/08/19


1

Gelatina , 11 bytes

p/’$€+2¦ḟ/X

Experimente online!

Um link dyadic que leva dois argumentos, [map_width, map_height], [W_width, W_height]e W_left, W_tope retorna um ponto selecionado aleatoriamente atender aos requisitos.

Explicação

   $€       | 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

1

Python 2 , 100 bytes

A entrada deve estar na forma de ((map_width, W_top_left_x, W_width),(map_height, W_top_left_y, W_height))

A saída é fornecida no formato: [[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

Experimente online!

Saídas aleatórias obtidas a partir da entrada de exemplo:

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



0

Carvão , 55 43 bytes

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

Experimente online! Link é a versão detalhada do código. Explicação:

NθNη

Insira o tamanho do mapa. (Se eles fossem os últimos, eu poderia inserir a altura em linha para economizar 1 byte.)

FE²N⊞υ⟦ιN⟧

Insira o retângulo interno. (Se eu pudesse inserir o pedido left, width, top, height, poderia usá-lo F²⊞υE²Npara economizar 3 bytes.)

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

Gere uma lista de todas as coordenadas no campo.

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

Filtre as entradas em que as duas coordenadas estão dentro do retângulo.

I‽...

Imprima um elemento aleatório daqueles que restam.



0

Scala , 172 bytes

Aleatoriedade? Peguei vocês.

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

Uma implementação divertida em que pude pensar.
Como funciona : gere um par aleatório no mapa. Se estiver no retângulo interno, tente novamente.
Experimente online!


0

J , 54 47 45 39 bytes

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

Experimente online!

Tome entrada como uma grade 3 x 2 como:

grid_height  grid_width
inner_top    inner_left
inner_height inner_width
  • Escolha um ponto aleatório em toda a grade: 0?@{[
  • Desloque-o para a esquerda e para baixo pelo ponto superior esquerdo do retângulo interno: (-1&{)~
  • Volte à etapa 1 se o ponto escolhido estiver dentro (<*/@,0<:[)do retângulo interno com a mesma alteração 2{[. Caso contrário, retorne o ponto aleatório original, sem deslocamento.
  • Propague todo o processo com um ponto que sabemos ser inválido, ou seja, o ponto superior esquerdo do retângulo interno, definido pelos elementos 2 e 3 da lista de entrada: {~&1

Outra abordagem, 45 bytes

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

Experimente online!

Este é conceitualmente mais simples e não se preocupa com o loop. Em vez disso, construímos uma matriz de todos os números de 0 a (wxh), deslocamos-a pelo ponto inicial interno, agarramos apenas os pontos da sub-grade (0, 0) a (interna w, inn h) e os removemos do conjunto geral grade após achatar os dois, escolha um aleatoriamente do restante e converta o número inteiro novamente em um ponto usando divmod<.@% , |~

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.