| Bytes | Lang | Time | Link |
|---|---|---|---|
| 044 | Uiua | 241229T175801Z | lolad |
| 074 | Wolfram Language Mathematica | 241220T092939Z | att |
| 176 | Wolfram Language Mathematica | 241219T151623Z | Introduc |
| 1926 | Jelly | 241206T074200Z | Jonathan |
| nan | Python | 241205T090829Z | 138 Aspe |
| 101 | Ruby | 241205T101649Z | Doorknob |
| 106 | Python 3 | 241205T100906Z | tsh |
| 089 | JavaScript V8 | 241205T081953Z | l4m2 |
| 033 | 05AB1E | 241205T080054Z | Kevin Cr |
| 100 | APL+WIN | 241205T085408Z | Graham |
| 046 | Charcoal | 241204T234459Z | Neil |
Uiua, 45 44 bytes
▽⤚≡⌟(××>₀⊣:/×⊸≥₀\+:=₀/+∩-°⊟₄≡=¤)⊸⧅⋅⋅1:"WESN"
Edit: shaved off a byte using experimental sided subscripts.
Explanation
Take all k-permutations of the directions, then test if they are valid: they should have equal numbers of W and E; at any time have >= counts of N to S as well as > counts at the end.
▽⤚≡⌟(××>₀⊣:/×⊸≥₀\+:=₀/+∩-°⊟₄≡=¤)⊸⧅⋅⋅1:"WESN"
⧅⋅⋅1:"WESN" # generate all k-perms
▽⤚≡⌟( ) # filter by
≡=¤ # compare string to each direction
∩-°⊟₄ # for each char, E-W and N-S
×× # valid iff:
=₀/+ # - overall E-W = 0
/×⊸≥₀\+: # - at each step, N-S >= 0
>₀⊣: # - at last step, N-S > 0
Wolfram Language (Mathematica), 74 bytes
{E,S,W,N}[[#]]&/@Select[Range@4~Tuples~#,Tr[I^#]>0Re@Accumulate[I^#]&]&
Returns a list of lists containing {E,S,W,N}. For output without delimiters, prepend Print@@ (+7 bytes): Try it online!.
is \[VectorLessEqual].
Range@4~Tuples~# paths of given length
Select[ , &] filter by:
0Re@Accumulate[I^#] path stays in the right half-plane
Tr[I^#]>0 path ends directly right of start
{E,S,W,N}[[#]]&/@ % translate to letters
x>0 is only True if x is a noncomplex, positive value, and remains unevaluated otherwise (non-True values are falsy).
Wolfram Language (Mathematica), 176 bytes
f[n_]:=(s={"N","S","E","W"}~Tuples~n;StringJoin/@Pick[s,#[[-1]][[1]]==0&&#[[-1]][[2]]>0&&Min[#[[All,2]]]>=0&/@Accumulate/@(s/.{"N"->{0,1},"S"->{0,-1},"E"->{1,0},"W"->{-1,0}})])
Explanation
Create all possible paths with Tuples then convert them into a coordinate system. Use Pick with the three restricitons imposed (finish vertically above,finish above the starting point, do not ever go below the starting point) to select the allowed paths. Finally convert into a concatenated string.
Jelly, (19?) 26 bytes
19 bytes using the integers \$[1,4]\$ as the directions WSEN, respectively.
4ṗµı*ÄḞAƑa$aĊ¬$ƲṪµƇị“WSEN”
A monadic Link that accepts an integer and yields a list of lists of characters.
Try it online! Or see the test-suite.
How?
4ṗµı*ÄḞAƑa$aĊ¬$ƲṪµƇị“WSEN” - Link: integer, Steps
4ṗ - [1..4] Cartesian power {Steps}
-> all lists of [1..4] of length Steps
µ µƇ - keep those Potentials for which:
ı* - -1 exponentiate {Potential} (vectorises)
Ä - cumulative sums -> "Stops" (Gaussian integers)
Ʋ - last four links as a monad - f(Stops):
Ḟ - Real parts {Stops} -> "Heights"
$ - last two links as a monad - f(Heights):
Ƒ - is invariant under?:
A - absolute values
a - logical AND {Heights} (vectorises)
-> "HeightsOrZeros" (Zeros if went below start)
$ - last two links as a monad - f(Stops):
Ċ - imaginary parts {Stops} -> "Laterals"
¬ - logical NOT (vectorises) -> isCentredForEach
a - {HeightsOrZeros} logical AND {isCentredForEach} (vectorises)
Ṫ - tail
ị“WSEN” - index into "WSEN" (vectorises)
Python, 259 96 bytes
Python port of @l4m2's JavaScript answer.
Saved 163 bytes thanks to @Unrelated String
Golfed version. Attempt This Online!
def g(z,v=1,h=0,c='',d=2):
for x in'ENWS'*(z>(1>h==z!=print(c))):d-=1;g(z-1,v+d%2,h+~d%2,c+x,d)
Ungolfed version. Attempt This Online!
# Counter for tracking printed paths
cnt = 0
# Function to print path and increment counter
def print_path(path):
global cnt
cnt += 1
print(path, cnt)
# Main recursive function to find valid paths
def find_paths(length, vertical_pos=1, horizontal_pos=0, current_path='', direction=2):
global cnt
# Base case: if we've used all steps
if vertical_pos * length == 0:
# Only print if we're at position (2, 0)
if vertical_pos > 1 and horizontal_pos == 0:
print_path(current_path)
return
# Try all four directions: East, North, West, South
for dir in ['E', 'N', 'W', 'S']:
# Calculate new positions based on direction
new_direction = direction - 1
direction-=1
new_vertical_move = 1 if new_direction % 2 else 0 # 1 for N/S
new_horizontal_move = 0 if new_direction % 2 else 1 # 1 for E/W
# Recursive call with updated positions
find_paths(
length - 1, # Decrease remaining steps
new_vertical_move + vertical_pos, # New vertical position
new_horizontal_move + horizontal_pos, # New horizontal position
current_path + dir, # Add direction to path
new_direction # Update direction counter
)
# Start the path finding with length 4
find_paths(4)
Ruby, 101 bytes
->n{((a=?E*-~n)..?E+a).map{|x|x[0,n]if/^((N\g<1>S?|E*W*)+)(?<=S)$/=~x&&x.count(?W)==x.count(?E)}-[p]}
This is very slow, but it manages to finish for n=4 eventually on my machine. Try it for n=3 (it times out for n=4, lol)
Whoever said regex can't find matching parentheses? :D
Explanation:
((a=?E*-~n)..?E+a)generates the list of strings['EEEEE', 'EEEEF', 'EEEEG', ..., 'EEEEEC', 'EEEEED', 'EEEEEE'](for n=4). This is obviously extreme overkill but does contain all of the 5-length strings with alphabet NSEW, and then some. (Why 5? You'll see later.)We map over that list and test for two conditions.
The first is the regex
/^((N\g<1>S?|E*W*)+)(?<=S)$/. This is a recursive regex that tests the N/S part. It does this by matching 1 or more of the following:Nfollowed by a recursive call to itself (\g<1>, technically a recursive call to the first capture group because we want to omit the^and$) followed by an optionalS, or any number ofEandW.We also tack on a positive lookbehind
(?<=S)at the end to make sure the string ends withS. Instead of generating 4-length strings that end at 1 or higher, we generate 5-length strings that end at 0 or higher and then chop off theSat the end.The second is just
x.count(?W)==x.count(?E). It feels like this should be shorter but I can't find anything.
Note that the original list contained a few unwanted 6-length strings, but all of them have at least one non-NSEW character except for
EEEEEE, which doesn't pass either condition.If both conditions hold, evaluate to
x[0,n](take the firstncharacters, i.e. remove the extraneousS). Otherwise, implicitly evaluate tonil.Remove the
nilelements by performing-[p].pis a function that prints and returns its argument. In this case the argument is nil, so it prints nothing and returns nil.
A bonus solution, which I think is super slick but is sadly much longer:
->n{(i=4**n).upto(2*i){puts$&.chop.tr'0-3','NSEW'if/^((0\g<1>1?|2*3*)+)$/=~_1.digits(4)*''&&$&.count(?2)==$&.count(?3)}}
Python 3, 106 bytes
f=lambda n,N=0,E=0,*p:sum([f(n-1,i%2*i+N,~i%2*~-i+E,*p,'WNES'[i])for i in[-1,0,1,2]if~N*n],(1>E==n<N)*[p])
JavaScript (V8), 89 bytes
f=(n,y=1,x=0,s='',i=2)=>y*n--?[...'ENWS'].map(c=>f(n,i--%2+y,i%2+x,s+c)):y>1&!x&&print(s)
From my Nice
05AB1E, 35 33 bytes
'€Ã©Iãʒ®À2ôδÃÇ`È·<ηO¤0›sd`r6b-O_P
Based on my answer for the Walks in Nice (Nizza) challenge. The difference is that the _ (==0, aka no vertical change) is replaced with 0› (>0, aka climbed), and a horizontal filter is added (6b-O_, aka not wondered east/west, but went straight up).
Explanation:
'€Ã '# Push dictionary string "news"
© # Store it in variable `®` (without popping)
Iã # Cartesian product with the input
ʒ # Filter this list by:
®À2ôδà # Split the "ew" and "sn" in loose groups:
®À # Push "news" from `®`, and rotate it once: "ewsn"
2ô # Split into pairs: ["ew","sn"]
δ # Using the current string and this pair as arguments:
à # Keep only those characters
Ç # Convert it to a pair of codepoint-integer lists
` # Pop and push both lists separately to the stack
È·< # IsEven *2 -1 (North is now 1; South is -1)
η # Get the prefixes
O # Sum each prefix
¤ # Get the last sum (without popping the list)
0› # Check whether it's positive (>0)
# (aka, there are more "n" than "s" and we've climbed)
s # Swap to get the list of cumulative sums again
d # Check for each whether it's non-negative (>=0)
# (aka for every "s" there should have been at least one
# preceding "n")
` # Dump all those >=0 checks to the stack
r # Reverse the stack
6b # Push 6, and convert it to binary: 110
- # Subtract (East is now -9; West is 9)
O # Sum them together
_ # Check that this sum is 0
# (aka, an equal amount of "e" and "w")
P # Check if everything on the stack is truthy
# (after which the filtered list is output implicitly)
See this 05AB1E tip of mine (section How to use the dictionary?) to understand why '€Ã is "news".
APL+WIN, 100 bytes
Prompts for n
(0=↑¨m='s')/m←((+/¨m='s')<+/¨m='n')/m←((+/¨m='e')=+/¨m='w')/m←,⍎∊((¯1+⎕)⍴⊂'''nsew''∘.,'),⊂'''nsew'''
Charcoal, 46 bytes
Nθ⊞υωFυ«≔⁼№ιN№ιSη¿‹LιθF✂SNWEη⊞υ⁺ικ¿›⁼№ιW№ιEη⟦ι
Try it online! Link to verbose version of code. Explanation: Based on my answer to Walks in Nice (Nizza) but instead of printing walks whose vertical distance is zero prints walks whose vertical distance is not zero but whose horizontal distance is zero.