Given some input array a = [a1, a2, ..., an]
and a positive integer k
, shuffle the input array a
such that no entry is farther than k
from its initial position.
Example
Given the array [1, 2, 3, 4, 5, 6]
and k = 1
, this means the entry 3
can be at following positions:
[*, 3, *, *, * ,*]
[*, *, 3, *, *, *] (original position)
[*, *, *, 3, *, *]
Details
- Uniform randomness over all permissible permutations is not required, but
- You can assume the input array is limited to the range
[1, n]
(or[0, n-1]
, wheren
is the length). - all permissible permutations must have a nonzero probability of occurring.
- Instead of shuffling an input array, you can also just take
k
and the length of the arrayn
(orn+-1
alternatively) as an input, and output a permutation in a suitable encoding (i.e as a list of indices etc). For this you can use 0 or 1 based indexing. - Instead of
k
you can also takek-1
ork+1
as an input if it is more suitable. - You can assume that
0 < k < [length of array]
. - Alternatively to sampling one random permutation you can also output all permissible permutations.
-
1\$\begingroup\$ Is the input a possible output or do we have to force each element to change? \$\endgroup\$chunes– chunes2022年04月04日 19:31:14 +00:00Commented Apr 4, 2022 at 19:31
-
\$\begingroup\$ @chunes The input is a possible output: All permissible permutations must be able to occur! \$\endgroup\$flawr– flawr2022年04月04日 19:35:46 +00:00Commented Apr 4, 2022 at 19:35
-
2\$\begingroup\$ We can't guarantee that the input has no duplicates, correct? \$\endgroup\$naffetS– naffetS2022年04月04日 22:19:46 +00:00Commented Apr 4, 2022 at 22:19
-
1\$\begingroup\$ @KevinCruijssen Under the current rules yes it can be arbitrary, but I think we can add this assumption as it leads to no loss of generality. \$\endgroup\$flawr– flawr2022年04月05日 07:09:36 +00:00Commented Apr 5, 2022 at 7:09
-
1\$\begingroup\$ @Steffan Yes the input may contain duplicates. \$\endgroup\$flawr– flawr2022年04月05日 07:12:36 +00:00Commented Apr 5, 2022 at 7:12
13 Answers 13
R, 47 bytes
\(n,k){while(any(abs((a=sample(n))-1:n)>k))0
a}
Takes the length n
and the maximum distance allowed k
and returns a permutation on 1:n
by rejection sampling.
Footer computes 10000 iterations of f(6,1)
and tabulates the results for each index to give a rough distribution.
05AB1E, (削除) 9 (削除ここまで) (削除) 7 (削除ここまで) 6 bytes
œʒāα@P
1-based input-list, and outputs all possible permutations. Outputting a random one would be 2 bytes longer by adding a trailing }Ω
.
Explanation:
œ # Push a list of permutations of the first (implicit) input-list
ʒ # Filter this list of permutations by:
ā # Push a list in the range [1,length] (without popping)
α # Get the absolute difference between the values at the same positions
@ # Check for each whether the second (implicit) input is >= the value
P # Product to check if all are truthy
# (after which the filtered list is output implicitly)
JavaScript (ES6), (削除) 89 (削除ここまで) 87 bytes
Expects (array)(k)
.
a=>g=k=>a.every((v,i)=>!(1/b[j=i+Math.random()*(k-~k)-k|0])/a[j]&&[b[j]=v],b=[])?b:g(k)
Commented
a => // a[] = input array
g = k => // k = max. distance
a.every((v, i) => // for each value v at position i in a[]:
!( // abort if:
1 / b[ // - b[j] is already defined
j = i + // where j is randomly chosen in
Math.random() * // [i-k .. i+k]
(k - ~k) - k | 0 //
] // or:
) / a[j] && // - a[j] is not defined
[ // otherwise:
b[j] = v // set b[j] to v and keep going
], //
b = [] // start with b[] = empty array
) ? // end of every; if sucessful:
b // return b[]
: // else:
g(k) // try again
Jelly, 9 bytes
Œ!ạJ{Ṁ<ʋƇ
A dyadic Link that accepts the length, n
, on the left and the minimum illegal distance, k+1
, on the right and yields a list of all permutations as 1-indexed indices.
How?
Œ!ạJ{Ṁ<ʋƇ - Link: n; k+1
Œ! - all permutations of [1..n]
Ƈ - filter keep those for which:
ʋ - last four links as a dyad - f(P, k+1):
{ - use k+1 with:
J - range of length -> I = [1..k+1]
ạ - P absolute difference I (vectorises) -> distances
Ṁ - maximum
< - is less than k+1?
Ruby, (削除) 72 (削除ここまで) (削除) 64 (削除ここまで) (削除) 63 (削除ここまで) 62 bytes
Lambda that accepts length of array minus one n-1
, and minimum illegal distance for an element to be moved k+1
.
->n,k{a=*0..n;a.shuffle!.all?{(a.index(_1)-_1).abs<k}||redo;a}
-8 bytes thanks to @Dingus
Python 3, (削除) 104 (削除ここまで) (削除) 94 (削除ここまで) 92 bytes
Code
lambda l,k:[p for p in permutations(l)if all(-k<p[i]-i<k for i in l)]
from itertools import*
Takes as input:
- The list
[0, 1, ..., n-2, n-1]
wheren
is the length of the list k+1
Outputs all possible permutations.
Explanation
- Uses
itertools.permutations
to get all permutations of the list. - Only adds each one to the output list if
-k<p[i]-i<k
isTrue
for every indexi
and valuep[i]
in the permutation.
Vyxal r
, (削除) 17 (削除ここまで) (削除) 13 (削除ここまで) 11 bytes
ʁṖ'→ƛ←ḟε;G≥
-4 bytes thanks to emanresu A
-1 byte thanks to Aaroneous Miller
-
\$\begingroup\$ Nice! The Both
:
are unnecessary, and you can use the nameless variable for -2 bytes. (Or the register) \$\endgroup\$emanresu A– emanresu A2022年04月08日 21:34:16 +00:00Commented Apr 8, 2022 at 21:34 -
\$\begingroup\$ FYI, there's a Vyxal chat if you need help with anything, and there's a deadlineless bounty for five Vyxal answers if you want that. \$\endgroup\$emanresu A– emanresu A2022年04月09日 01:22:52 +00:00Commented Apr 9, 2022 at 1:22
-
\$\begingroup\$ Thanks, I knew about both, actually. \$\endgroup\$naffetS– naffetS2022年04月09日 01:25:38 +00:00Commented Apr 9, 2022 at 1:25
-
\$\begingroup\$ You can use the
r
flag for -1 byte (Also you need to use≥
or≤
at the end instead of>
or<
) \$\endgroup\$Aaroneous Miller– Aaroneous Miller2022年04月14日 00:50:51 +00:00Commented Apr 14, 2022 at 0:50 -
\$\begingroup\$
<
was fine because I was takingk+1
, but I guessk
works fine. \$\endgroup\$naffetS– naffetS2022年04月14日 17:26:34 +00:00Commented Apr 14, 2022 at 17:26
Python3, 178 bytes:
lambda a,k:f([*enumerate(a)],k,a,0,[])
def f(a,k,l,j,c):
if len(a)==j:yield c;return
for x,y in a:
if abs(x-j)<=k and(C:=list.count)(l,y)>C(c,y):yield from f(a,k,l,j+1,c+[y])
Charcoal, 29 bytes
NθFN⊞υ0W⊙υ∨⊖Noυλ‹θ↔−κλUMυ‽LυIυ
Try it online! Link is to verbose version of code. Outputs a random permissible permutation. Explanation:
Nθ
Input k
.
FN⊞υ0
Input n
and create an illegal permutation (unless n=1
, in which case there is only one permutation).
W⊙υ∨⊖Noυλ‹θ↔−κλ
Repeat until the permutation is both legal and permissible...
UMυ‽Lυ
... randomise the permutation.
Iυ
Output the permissible permutation.
Python, 106 bytes
from random import* f=lambda L,k:(shuffle(Z:=L[::])or all([k>abs(s-n)for n,s in zip(L,Z)])and Z or f(L,k))
Returns a new list. Requires the input list to be in the format [1,2,...,n-1,n]
where n
is the length of the list. Taking k+1
as an input
-
\$\begingroup\$ -5 bytes... \$\endgroup\$naffetS– naffetS2022年04月05日 02:54:24 +00:00Commented Apr 5, 2022 at 2:54
-
\$\begingroup\$
k>Z[n]-n>-k for n in L
for -7 bytes if you switch to 0-indexing forL
\$\endgroup\$Tipping Octopus– Tipping Octopus2022年04月05日 05:50:17 +00:00Commented Apr 5, 2022 at 5:50
Factor + math.combinatorics math.unicode
, 66 bytes
[ iota dup [ v- vabs [ >= ] with ∀ ] 2with filter-permutations ]
Takes \$k\$ and a length \$l\$ and outputs all zero-indexed sets of indices of length \$l\$ that satisfy the distance constraint given by \$k\$.
Haskell (Lambdabot), 72 bytes
Operator #
that accepts length of array minus one n-1
, and minimum illegal distance for an element to be moved k+1
.
n#k=[x|x<-permutations[0..n],all(\y->abs(fromJust(elemIndex y x)-y)<k)x]
Vyxal, 8 bytes
Ṗ'ż-ȧ0≤A
Port of 05AB1E.
How?
Ṗ'ż-ȧ0≤A
Ṗ # All permutations of the (implicit) first input
' # Filter by:
ż # Length range [1, length]
-ȧ # Absolute differences of values in the same positions
0≤ # For each, is it less than or equal to the second input?
A # Are they all truth?
```
Explore related questions
See similar questions with these tags.