Создать случайную точку за пределами данного прямоугольника на карте


15

Вступление

Учитывая эту визуализацию игрового поля:

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

Вся карта, на которой играется, представляет собой прямоугольник с угловыми координатами (0,0) и (map_width, map_height). Очки, имеющие право на порождение врагов - Союз

S=(A,B,C,D)

Соревнование

Напишите код, который возвращает случайную точку (x, y), которая, как гарантированно, находится внутри S. Ваш код не может вводить никакого дополнительного смещения, означающего, что вероятность каждой координаты равномерно распределена с учетом предположения о том, что вы выбираете генерацию случайности (например, функция). | библиотека | dev / urandom) беспристрастна.

Самые короткие решения в байтах выигрывают!

вход

Вам будет предоставлена в общей сложности 6 положительных целое число входных переменных в следующем порядке: map_width, map_height, W_top_left_x, W_top_left_y, W_width, W_height. Можно предположить, что (расчетная) площадь поверхности всех областей (A, B, C, D, W) составляет> 10, поэтому пустых пространств / областей нет.

Пример ввода: 1000, 1000, 100, 100, 600, 400

Входные данные должны содержать 6 значений, описанных выше, но они могут передаваться как меньшее количество аргументов и в любом порядке. Например, (map_width, map_height)допускается передача в виде кортежа Python. Что не допускается, конечно, рассчитанные параметры, такие как нижняя правая точка W.

Выход

2 случайно сгенерированных целых числа (x, y) где

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

ИЛИ

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

значение хотя бы одного из приведенных выше логических выражений должно быть истинным.

Примеры

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

Для получения подробной информации и ограничений для ввода / вывода, пожалуйста, обратитесь к стандартным правилам ввода / вывода


Я думаю, что вы должны явно указать, что выходные координаты являются целыми числами (что я предполагаю как ваше неявное намерение).
19


1
@ всегда так сказано в разделе «вывод»; 2 randomly generated integers (x, y)
Джузеппе

1
Можем ли мы принять входные данные в другом (последовательном) порядке?
attinat

@agtoever yes output должен быть целым числом, как указано в разделе «output».
Jaaq

Ответы:


7

Python 2 , 114 106 102 101 байт

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*

Попробуйте онлайн!


Я не уверен, но я думаю, что это должно быть, [i%w, i/w] потому что диапазон, w*h/w=hно x привязан к ширине в этом примере, а не к высоте.
Яак

@jaaq Да, ты прав. Исправлено, спасибо :)
TFeld

Я только что проверил содержимое созданного вами списка, и кажется, что ваше решение неверно. Построение точек показывает, что все значения расположены вдоль линии и не заполняют всю область S, как предполагалось. Также генерируемый вами список содержит нецелые значения.
Яак

@jaaq Я не уверен, что ты имеешь в виду? Координаты всегда целые, а не в строке ( например )
TFeld

1
@jaaq В Python 2, a/bэто уже деление по полу, если aи bявляются целыми числами (которые они здесь).
TFeld


4

05AB1E , 23 21 20 18 17 байт

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

Ввод в формате [map_width, map_height], [W_top_left_x, W_top_left_y], [W_width, W_height].

Спасибо @Grimy за -1 байт, а также за то, что я понял, что я внес ошибку после моего последнего редактирования.

Попробуйте онлайн , выведите 10 возможных выходов одновременно или проверьте все возможные координаты . (Небольшое примечание: я уменьшил входные данные примера в 10 раз, потому что встроенный фильтр и случайный выбор довольно медленны для больших списков.)

Объяснение:

Входы map_width, map_height, [W_top_left_x, W_top_left_y], [W_width, W_height]упоминаются как [Wm, Hm], [x, y], [w, h]ниже:

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
Спасибо за добавленную часть проверки :) отличное решение!
Jaaq

1
@jaaq Спасибо! Я сам использовал верификатор после моей первоначальной версии, когда я заметил ошибку, которую мне пришлось исправить, поскольку в нее были включены координаты [map_height, 0]как возможный случайный вывод без ¨. :)
Кевин Круйссен

*ݨ¹‰может быть L`â<, принимая первые два входа как [map_height, map_width]. Также IIможет быть Š, если я что-то пропустил.
Grimmy

@ Грими Спасибо за L`â<. Что же касается II+до Š+, вы действительно правы , что это будет такой же .. К сожалению , я сделал ошибку , и сам он должен был ²³+вместо II+, так как он будет использовать третий вход для обоих I(так же , как это заняло бы в два раза третий ввод с Š) после первой итерации фильтра .. Так что неявно спасибо, что заставили меня понять, что у меня была ошибка. :)
Кевин Круйссен


3

PowerShell , 85 73 байта

-12 байт благодаря маззи

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

Попробуйте онлайн!

Хороший простой ответ, который объединяет массив, составленный из диапазона значений для каждого измерения, а затем выбирает один случайным образом для xи y. Руководит повторно большую часть кода на первой обработке x, а затем перезаписать $xс $yи запустить его снова.


1
Вы можете сэкономить несколько байтов. Попробуйте онлайн!
Маззи

1
@mazzy Я действительно наткнулся на оптимизацию диапазона, но применил ее в обратном направлении, сохранив 0 байтов.
Веска


1

Желе , 11 байт

p/’$€+2¦ḟ/X

Попробуйте онлайн!

Двоичное звено , которое принимает два аргумента [map_width, map_height], [W_width, W_height]и W_left, W_topвозвращает случайно выбранную точку отвечающих требований.

объяснение

   $€       | 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 байт

Вход должен быть в форме ((map_width, W_top_left_x, W_width),(map_height, W_top_left_y, W_height))

Выход дается в виде: [[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

Попробуйте онлайн!

Случайные результаты, полученные из входных данных примера:

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

1

Java (OpenJDK 8) , 100 байт

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

Попробуйте онлайн!

Использует в java.awt.Rectangleкачестве держателя некоторых параметров. Естественно, те используют intполя, а не floatили double.


1
О, хороший способ принять вызов буквально со Rectangle#containsвстроенным! : D
Кевин Круйссен


0

Древесный уголь , 55 43 байта

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

Попробуйте онлайн! Ссылка на подробную версию кода. Объяснение:

NθNη

Введите размер карты. (Если бы они были последними, я мог бы ввести встроенную высоту для 1-байтового сохранения.)

FE²N⊞υ⟦ιN⟧

Введите внутренний прямоугольник. (Если бы я мог ввести в порядке, left, width, top, heightто я мог бы использовать F²⊞υE²Nдля 3-байтового сохранения.)

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

Создайте список всех координат в поле.

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

Отфильтруйте записи, где обе координаты лежат внутри прямоугольника.

I‽...

Выведите случайный элемент из тех, которые остались.



0

Scala , 172 байта

Случайность? Попался.

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

Веселая реализация, о которой я мог подумать.
Как это работает : Генерация случайной пары на карте. Если это во внутреннем прямоугольнике, попробуйте еще раз.
Попробуйте онлайн!


0

J , 54 47 45 39 байт

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

Попробуйте онлайн!

Возьмите входные данные в виде сетки 3 x 2, например:

grid_height  grid_width
inner_top    inner_left
inner_height inner_width
  • Выберите случайную точку на всей сетке: 0?@{[
  • Сдвиньте его влево и вниз на верхнюю левую точку внутреннего прямоугольника: (-1&{)~
  • Вернитесь к шагу 1, если выбранное место находится внутри (<*/@,0<:[)смещенного аналогично внутреннего прямоугольника 2{[. В противном случае верните исходную несмещенную случайную точку.
  • Заполнить весь процесс недопустимой точкой, а именно левой верхней точкой внутреннего прямоугольника, определенного элементами 2 и 3 входного списка: {~&1

Другой подход, 45 байтов

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

Попробуйте онлайн!

Этот концептуально проще и не связан с циклом. Вместо этого мы строим матрицу из всех чисел от 0 до (wxh), сдвигаем ее на внутреннюю начальную точку, берем только точки в подсетке (0, 0) - (inner w, innner h), удаляем их из общего сетка после сглаживания обоих, выберите один случайным образом из остатка, и преобразовать целое число обратно в точку, используя divmod<.@% , |~

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.