Generate self-avoiding loops of a specific length
APL (Dyalog Extended), 39 bytes
{∧'LURD'⊇⍨m⌿⍨(⍲∘⍧=⊢/)⍤1+\0J1*m←⍉4⊤⍳4*⍵}
Try it online!
The output is a matrix of characters, one path on a line.
How it works
{∧'LURD'⊇⍨m⌿⍨(⍲∘⍧=⊢/)⍤1+\0J1*m←⍉4⊤⍳4*⍵} ⍝ Input ⍵←n
m←⍉4⊤⍳4*⍵ ⍝ A matrix of all length-n combinations of 0..3
⍳4*⍵ ⍝ 0..4^n-1
4⊤ ⍝ Convert each to base 4 (each goes to a column)
m←⍉ ⍝ Transpose and assign to m
∧'LURD'⊇⍨m⌿⍨(⍲∘⍧=⊢/)⍤1+\0J1*m
0J1*m ⍝ Power of i (directions on complex plane)
+\ ⍝ Cumulative sum; the path of the robot
( )⍤1 ⍝ Test each row:
⊢/ ⍝ the last number (real+imag is always even)
= ⍝ equals
⍲∘⍧ ⍝ NAND of the nub-sieve
⍝ (0 if all numbers are unique, 1 otherwise)
⍝ The condition is satisfied only if both are 0
m⌿⍨ ⍝ Extract the rows that satisfy the above
'LURD'⊇⍨ ⍝ Index each number into the string 'LURD'
∧ ⍝ Ascending sort
Python 2, 119 106 104 bytes
def f(n,s="",p=0,*v):
if p==n<1:print s
for d in"DLRU":p in v or 0<n<f(n-1,s+d,p+1j**(ord(d)%15),p,*v)
Try it online!
Same idea in Python 3:
Python 3, 102 100 bytes
-2 bytes thanks to @ovs!
def f(n,s="",p=0,*v):p==n<1==print(s);p in v or[f(n-1,s+d,p+1j**(ord(d)%15),p,*v)for d in"DLRU"if n]
Try it online!
A recursive function that prints the results to STDOUT
. Keep track of s, p, v
which are the current sequence, the current position (as a complex number), and the list of visited positions respectively.
The sequence is printed when n == 0
and the position is back to 0
, aka p==n<1
.
Otherwise, if there is still moves and no self-intersection (n > 0 and p not in v
), the function tries to move the current position in 4 directions, and recurs. Given the character d
that is one of the 4 character D, L, R, U
, the direction is determined as
1j ** (ord(d) % 15)
since
d ord(d) ord(d)%15 1j**...
D 68 8 1
L 76 1 1j
R 82 7 -1j
U 85 10 -1
Husk, 21 bytes
fS=oḟȯE½M#₁Q`π₁
"RULD
Try it online!
Explanation
A string over RULD
encodes a self-avoiding loop if and only if the only contiguous substring with an equal number of R and L, and of U and D, is the entire string.
I loop over all strings of the given length and check this condition by brute force.
fS=oḟȯE½M#₁Q`π₁ Implicit input n
`π₁ Length-n words over string "RULD" (from second line).
f Keep those that satisfy this:
Q List of substrings
oḟ Get the first one that satisfies this:
M#₁ Counts of each letter in "RULD"
½ Split in half
ȯE The halves (counts of R,U vs counts of L,D) are equal
S= That equals the string, which is the last substring in the list