g | x | w | all
Bytes Lang Time Link
183C GCC in a terminal240915T110538Zmatteo_c
079C in an xterm240914T140341ZG. Sliep
141Zsh extendedglob in xterm240914T222714ZGammaFun
039Z80 Machine Code240914T055429Zv-rob
033Charcoal240913T163742ZNeil
035Perl 5 + pF M5.10.0240913T150923ZDom Hast

C (GCC) in a terminal, 185 183 bytes

h;w;d;W;i;p;main(m,v)char**v,*m;{for(W=strlen(*++v)+1,m=calloc(W*3,W);w[*v];m[(++h+d+!d+W)*W+w++]="\\_/"[d])h-=d=w[*v]-100>>3;for(;i<3*W*W;putchar(++i%W?w?:32:p?p=0,10:13))p|=w=m[i];}

Attempt This Online!

C (GCC) with many empty lines, 171 169 bytes

h;w;d;W;i;main(m,v)char**v,*m;{for(W=strlen(*++v)+1,m=calloc(W*3,W);w[*v];m[(++h+d+!d+W)*W+w++]="\\_/"[d])h-=d=w[*v]-100>>3;for(;i<3*W*W;putchar(++i%W?w?:32:10))w=m[i];}

Attempt This Online!

In ATO, both versions output many empty lines. The first version does not print empty lines when run in a terminal.

C (in an xterm), 80 79 bytes

l(char*s){for(puts("\e[2J\e[99B");*s;)printf("/\e[A\0\e[B\\\0_"+(1^*s++&3)*5);}

Clears the terminal and draws a landscape at the bottom of the screen: enter image description here

Zsh --extendedglob in xterm, 141 bytes

Inspired by G. Sliepen's C answer, but fixed to follow us/‾ and make ud/du not unnecessarily switch lines.

For fairness, this also sends \e[2J\e[99B to clear screen and move cursor down 99 lines, just as in their answer.

<<<$'\e[2J\e[99B'
m=(u '\e[A' d '\e[B')
for c
printf ${${c#[^$v]}:+$m[1+m[(i)$c]]}${${${c/u//}/d/\\}/s/${${${v#d}:+‾}:-_}}&&v=${${c#s}:-$v}

Don't try it online, it doesn't work there!


Zsh --extendedglob in xterm, 78 bytes

Same idea as G. Sliepen's C answer, both of our answers don't follow spec for us/‾. ~~I think I have an idea to fix it though. EDIT: See above.

m=(u $'/\e[A' d $'\e[B\\' s _)
<<<$'\e[2J\e[99B'${1//(#m)?/$m[m[(i)$MATCH]+1]}

Don't try it online, it doesn't work there!

Z80 Machine Code, 39 bytes

1AB7C81323FE552005362F250600FE44200524365C065FFE5320E5A0200624367E2518DC7018D9

Without the requirement for the s character being different based on whether it follows a u or d, the code can be gotten down to 27 bytes.

Explanation of disassembled code:

; de = Pointer to input string. Hitting a null character causes the subroutine
;      to return. Characters other than 's', 'u', 'd' cause undefined behavior.
; hl = Pointer to starting location within output array, minus 1. The width of
;      the array must be 256 bytes.
DrawLandscape:
    ld a, (de)                  ; Get the character from the input string. If
    or a                        ; it's the null character, return.
    ret z

    inc de                      ; Increment both input and output pointers.
    inc hl

    cp 'u'                      ; If the character is 'u', draw a '/', move the
    jr nz, noUp                 ; pointer up a row, and set the lower straight
    ld (hl), '/'                ; value to 0, indicating a '~' will be drawn one
    dec h                       ; position below the pointer.
    ld b, 0
noUp:

    cp 'd'                      ; If the character is 'd', move the pointer down
    jr nz, noDown               ; a row, draw a '\', and set the lower straight
    inc h                       ; value to '_', which we draw later.
    ld (hl), '\'
    ld b, '_'
noDown:

    cp 's'                      ; If the character is 's', we need to draw a
    jr nz, DrawLandscape        ; straight character.

    and b                       ; If the lower straight value is not set, we
    jr nz, drawLower            ; need to draw a '~' below the pointer.

    inc h
    ld (hl), '~'
    dec h
    jr DrawLandscape
drawLower:

    ld (hl), b                  ; Otherwise, draw the lower straight value
    jr DrawLandscape            ; directly.

There's no portable way to print stuff in Z80, but here's an example of the code in action:

screenshot of printed landscape

Charcoal, 33 bytes

≔_θFS≡ιsθd«M⁼θ_↓\≔_θ»«M⌕θ_↓/≔‾θ

Try it online! Link is to verbose version of code. Explanation:

≔_θ

Start by mapping s to _.

FS≡ι

Loop through and switch on each character of the input.

For an s just output its current mapping.

d«M⁼θ_↓\≔_θ»

For a d, move down if the mapping is _, then print a \ and set the mapping to _.

«M⌕θ_↓/≔‾θ

Otherwise, move up unless the mapping is _, then print a / and set the mapping to (which costs 3 bytes to represent in Charcoal).

Had it been acceptable to print an underline on the line above instead of an overline, then for 14 bytes:

FS≡ιd¦¶\¦s¦_↗/

Try it online! Link is to verbose version of code. Explanation: Depending on each input letter, the program either d) moves down a line, then prints a \ s) prints a _ or u) prints a /, then moves up a line. Annoyingly I can't seem to do anything about the multiple separators required between the strings which take up over 20% of my bytes.

Perl 5 + -pF -M5.10.0, 35 bytes

say$/x@F;s/d/.\\/g;s!u!/.[A!g;y;s;_

Try it online!