# ASCII Art “Flight Simulator”

EDIT

It appears that there has been some confusion following my typo in the original post which used a lowercase o to define the plane and then an uppercase later. Unfortunately this bug did not get picked up in the Sandbox. Since many members have written answers with both and since the typo was my fault I will allow either uppercase or lowercase o in the definition of the plane. I have added a new rule for this.

Background

I like ascii art animations as I tend to call them so here is another one. I don't think this is too difficult to implement so will hopefully get some short and interesting answers.

To all fellow community members

old byte count new byte count

so we can see your progress. Thanks!

Challenge

Here is an ascii plane

--O--


Here is an ascii runway

____|     |____


The plane starts at 5 newlines above the runway. To prevent any clashes between metric and imperial systems and make this a truly international challenge I won't mention meters or feet. Example:

        --O--

____|     |____


The Plane must land exactly in the middle of the runway as shown below:

____|--O--|____


Input

The initial horizontal position of the plane is defined by an integer input which is used to reference the tip of the left wing i.e. it is between 0 and 10 inclusive.

Output

Each stage of the planes flight must be shown. Example below (input=10):

          --O--

____|     |____

--O--

____|     |____

--O--

____|     |____

--O--

____|     |____

--O--
____|     |____

____|--O--|____


To keep things simple, we are ignoring the laws of perspective. The runway stays the same size as you get closer.

Rules

• Update The middle of the plane can be either an uppercase or lowercase o but whichever is chosen must be consistent throughout the code. If your language does not support the characters above feel free to use alternative ascii only characters.
• The plane descends 1 line per frame.
• The plane can only move 1 space to the left or right each time it descends one line. It does not have to move on each line of descent. As long as it finishes on the runway it is up to you when it moves right or left. You're the pilot!
• No error handling required. You may assume that the input will always be a valid integer from 0-10 inclusive.
• Output must consist of only the characters shown above (if your language does not support them the see edited first rule) and must be the same size i.e. must start 6 lines high by 15 characters wide. The height can decrease as it progresses as in the example above.
• Program or function is fine but must produce an output as shown above.
• Leading/trailing spaces/newlines are fine by me.
• Please feel free to clear the screen between output frames if you wish. This is not a requirement.
• Standard loopholes prohibited as usual (although I don't think there are many that would help with this kind of challenge).
• This is code golf so shortest answer is obviously the winner and will probably get most votes but may not necessarily be accepted as the best answer if some really interesting solution comes along in some unexpected language, even if it is longer. Feel free to post anything that meets the rules as long as it works.

Ungolfed reference implementation in Python 2 available at Try it online! so you can see how it looks for different input values.

• I don't think it is kolmogorov-complexity as the output depends on the input – ovs Jan 18 '17 at 19:25
• Thanks for the clarification @ovs. I'll remove that tag then. – ElPedro Jan 18 '17 at 19:25
• Usually, the acceptance goes to the answer that complies best with the Objective Winning Criterion. You may get some flak if you accept another, longer answer. – Level River St Jan 18 '17 at 22:23
• Thanks @LevelRiverSt. Is there a meta post to clarify this? If not then maybe better to not accept any answer. – ElPedro Jan 18 '17 at 22:26
• btw, I have accepted a longer answer before and given credit to the shorter answer as well with no probs from the community Previous challenge. Please see my Result comment at the end of the question. Was this wrong? – ElPedro Jan 18 '17 at 22:31

# TI-BASIC, 61 bytes

Input A
A
For(B,1,5
ClrHome
Output(5,1,"----/     /----
Output(B,Ans,"--O--
Ans+6-median({5,7,Ans
End

• Do you know of an online interpreter or download (For Linux) for testing? +1 for the answer assuming it works :) – ElPedro Jan 18 '17 at 22:00
• Check out TilEm. It's the only one I could get working. – Julian Lachniet Jan 18 '17 at 22:03
• +1 for asking someone who may have had a different answer. Will certainly check out TilEm and thanks for the tip. – ElPedro Jan 18 '17 at 22:13

# JavaScript (ES6), 108 bytes

f=(a,b=5)=>b?" ".repeat(a)+--O--${ .repeat(b)}____| |____ +f(a<5?a+1:a-1,b-1):"____|--O--|____"  ## Test it f= (a,b=5)=>b?" ".repeat(a)+--O--${
.repeat(b)}____|     |____

+f(a<5?a+1:a-1,b-1):"____|--O--|____"
<input type=number min=0 max=10 oninput=o.textContent=f(+this.value)><pre id=o>

## Usage

Just call f with the index of the plane.

f(2)


## Output

  --O--

____|     |____

--O--

____|     |____

--O--

____|     |____

--O--

____|     |____

--O--
____|     |____

____|--O--|____

• You can add a <s>snack</s> stack snippet – Cows quack Jan 18 '17 at 19:52
• Every time I ask a question the first answer is Javascript! +1 – ElPedro Jan 18 '17 at 19:55
• Hey, would be nice if people posted either a Tryitonline (don't know if that is possible with Javascript) or a different solution to the 10 example shown above. Can you post the output from e.g. 2 instead? :) – ElPedro Jan 18 '17 at 19:59
• @ElPedro, you can execute JavaScript in your browser console, but there also are some online consoles. I'll add a link. I'll also change the example. – Luke Jan 18 '17 at 20:13
• Thanks. No probs. I'm into old time Javascript where you need a web page to execute it. Guess I need to get with the times :) More serverside these days. Respect for the fast and cool answer. – ElPedro Jan 18 '17 at 20:18

## Batch, 230 bytes

@echo off
set/ax=10-%1
set s=          --O--
for /l %%i in (0,1,4)do call:l %%i
echo ____^|--O--^|____
exit/b
:l
call echo %%s:~%x%%%
for /l %%j in (%1,1,3)do echo(
echo ____^|     ^|____
echo(
set/a"x-=x-5>>3,x+=5-x>>3


x is the number of spaces to remove from the beginning of the string s, so I subtract the parameter from 10. The last line is the nearest Batch has to x-=sgn(x-5).

## Perl, 94 bytes

93 bytes of code + -p flag.

$\="____| |____ ";$p="--O--";for$i(-5..-1){print$"x$_.$p.$/x-$i;$_+=5<=>$_}$\=~s/ +/$p/}{


Try it online!

• @ETHproductions Hope you enjoy the }{ (and the $" messing with the syntax highlighting). – Dada Jan 18 '17 at 20:31 # Python 2, 160 bytes i,s,p,l,r,c,x=input(),' ','--O--','____|','|____',0,4 while x>=0:print'\n'.join([s*i+p]+[s*15]*x+[l+s*5+r])+'\n';c+=1;x-=1;i=((i,i-1)[i>5],i+1)[i<5] print l+p+r  Try it online! Here is the reference implementation golfed down to 160 from 384. Still a way to go I think. Just posted for fun and to encourage a better Python answer. • You can compete in your own challenge (see this meta post). – Dada Jan 18 '17 at 20:51 • Can you just do while-~x? – FlipTack Jan 18 '17 at 20:56 • Also I think you can write the bit where you either add or subtract from i as i+=(i<5)-(i>5) – FlipTack Jan 18 '17 at 21:01 # TI-BASIC, 62 bytes :Input A :A :For(N,3,8 :ClrHome :Output(8,1,"----I I---- :Output(N,Ans,"--O-- :Ans+(Ans<6)-(Ans>6 :End  Note that TI-BASIC does not support _ or | and therefore I replaced with a capital I and -. This should not effect byte count. • OK, I'm on Linux. Can you recommend a download that I get to test this? btw, I assume it works until I find an interpreter so +1 :) – ElPedro Jan 18 '17 at 21:47 • Unfortunately, no. I do have both Wabbitemu and TilEm installed on my Windows 10 computer, but I test the code on a physical TI-84+. Sorry – Golden Ratio Jan 18 '17 at 21:54 • No problem! Just asking :) – ElPedro Jan 18 '17 at 21:58 • Due to a lot of editing of code, the fastest alternated between this post and Julian Lachniet's, until we both came to the 60 byte conclusion, at which point I added clrhome and made byte count 62 – Golden Ratio Jan 18 '17 at 22:09 • TI-Basic?! Nice! – Dave Kanter Jan 18 '17 at 23:10 ## Scala, 224 181 bytes EDIT: I had no idea you could do "string"*n to repeat it n times! Scala continues to blow my mind. Missing the if(t>0) instead of if(t==0) was a rookie mistake. Thanks for the tips, Suma! def?(x:Int,t:Int=5):Unit={var(p,o)=("--o--","") o=s"____|${if(t>0)" "*5 else p}|____\n"
for(i<-0 to t)o=if(i!=0&&i==t)" "*x+p+o else "\n"+o
println(o)
if(t>0)?(x-(x-4).signum,t-1)}


Original remarks:

I figured a recursive solution would be fun to try. I'm relatively new to Scala, so I'm certain this is far from optimal.

• You might want to read Tips for golfing in scala – corvus_192 Jan 19 '17 at 8:42
• You don't need the :Unit=. Omitting the equals sign will set the return type to Unit. – corvus_192 Jan 20 '17 at 8:21
• Also, why didn't you initialize o in the first line?. And since i is always >= 0, you can change i!=0&&i==t to i>0&i==t (3rd line). – corvus_192 Jan 20 '17 at 8:25

# Befunge-93, 136 130 bytes

&5>00p10p55+v
:::00g>:1-\v>:"____|     |_"
>:1-\v^\+55_$"--O--"10g ^\*84_$>:#,_10g::5v>:#,_@
<_v#!:-1g00+\5\-<^"____|--O--|____"


Try it online!

Explanation

&                          Read the plane position.
5                         Initialise the plane height.
>                        Begin the main loop.

00p                     Save the current height.
10p                  Save the current position.
55+:              Push two linefeed characters.

"____|     |_"    Push most of the characters for the airport string.
:::                        Duplicate the last character three times to finish it off.

00g>:1-\v               Retrieve the current height, and then push
^\+55_$that many copies of the linefeed character. "--O--" Push the characters for the plane. >:1-\v 10g Retrieve the current position, and then push ^\*84_$                      that many copies of the space character.

>:#,_               Output everything on the stack in reverse.

10g::          Retrieve the current position and make two copies to work with.
5v        If it's greater than 5
-<          then subtract 1.
+\5\           If it's less than 5 then add 1.

g00                Retrieve the current height.
-1                   Subtract 1.
_v#!:                     If it's not zero, repeat the main loop.

^"____|--O--|____"         Otherwise push the characters for the landed plane.
>:#,_@                     Output the string and exit.


# Perl 6, 9790 81 bytes

{say "{"{" "x 15}\n"x 5}____|     |____"~|("\0"x$^h+$_*(17-$h/5)~"--O--") for ^6}  Contrary to what it looks like, it outputs the *lower-case version of the plane (--o--), as allowed by the updated task description. Try it online! ### How it works Bitwise string operators FTW! { # Lambda accepting horizontal index$h.
say                                            # Print the following:
"{ "{ " " x 15 }\n" x 5 }____|     |____"  # The 15x6 background string,
~|                                         # bitwise-OR'd against:
(
"\0"                                   # The NULL-byte,
x $^h +$_*(17 - $h/5) # repeated by the plane's offset, ~ "--O--" # followed by an OR mask for the plane. ) for ^6 # Do this for all$_ from 0 to 5.
}


It works because bitwise string operators use the codepoint values of the characters at a given position in two strings, to calculate a new character at that position in the output string.
In this case:

space  OR  O   =  o
space  OR  -   =  -
any    OR  \0  =  any


For an uppercase-O plane, we could have used ~^ (string bitwise XOR), with a plane mask of \r\ro\r\r (+4 bytes for backslashes):

space  XOR   o  =  O
space  XOR  \r  =  -
any    XOR  \0  =  any


The formula for the plane's offset, h + v*(17 - h/5), was simplified from:

  v*16         # rows to the vertical current position
+ h            # columns to the horizontal starting position
+ (5 - h)*v/5  # linearly interpolated delta between horizontal start and goal


## Python 2, 107 bytes

n=input();h=5
while h:print' '*n+'--O--'+'\n'*h+'____|     |____\n';n-=cmp(n,5);h-=1
print'____|--O--|____'


Try it online

Simply hardcodes the last line for the landing plane. It can likely be golfed by re-using parts from before or being integrated into the loop.

# sed, 181 bytes + 2 for -nr flags

s/10/X/
:A
s/^/ /;y/0123456789X/-0123456789/;/[0-9]/bA;s/ -/P\n\n\n\n\n____|P|____/
:B
h;s/P([\n|])/--O--\1/;s/P/     /;s/^ *_/_/;p;/^_/q;x;s/\n//
/^ {5}$/bB;/ {6}/s/ //;s/^/ /;bB  ## Ungolfed # Add leading spaces s/10/X/ :A s/^/ / y/0123456789X/-0123456789/ /[0-9]/bA s/ -/P\n\n\n\n\n____|P|____/ :B # Place plane in appropriate spot h s/P([\n|])/--O--\1/ s/P/ / s/^ *_/_/ p /^_/q x # Movement s/\n// /^ {5}$/bB
# move left one extra, since we'll move right next line
/ {6}/s/  //
s/^/ /
bB


Usage: $echo 2 | sed -nrf flightsim.sed # Retina, 86 83 bytes .+$* --O--¶¶¶¶¶¶____|     |____
{*$¶ 2D¶ ( {5})$1
}^ {0,4}-
$& + --O-- G_  Try it online! There is probably some sort of compression I could have used on the runway and the empty space over it, but anything I tried came up more expensive than plaintext (in Retina ¶ is a newline, so you can see the initial state in plaintext on the second line). # Ruby, 94 bytes ->a{5.times{|i|puts" "*a+"--O--#{?\n*(5-i)}____| |____ ";a+=5<=>a};puts"____|--O--|____"}  Prints the plane's position followed by newlines and then the airport. Then it moves the plane by 1, -1, or 0, depending on its position relative to 5. After looping the above 5 times, it prints the plane in the airport. # 8th, 177 172 bytes : f 5 >r 5 repeat over " " swap s:* . "--O--" . ' cr r> times "____| |____\n\n" . over 5 n:cmp rot swap n:- swap n:1- dup >r while "____|--O--|____\n" . 2drop r> drop ;  The word f expects an integer between 0 and 10. Usage 4 f  Explanation : f \ n -- 5 >r \ Push vertical distance from airport to r-stack 5 repeat \ Print plane over " " swap s:* . "--O--" . \ Print airport ' cr r> times "____| |____\n\n" . \ Now on the stack we have: \ distanceFromLeftSide distanceFromAirport over \ Put distance from left side on TOS 5 n:cmp \ Compare left distance and 5. Return \ -1 if a<b, 0 if a=b and 1 if a>b rot \ Put distance from left side on TOS swap n:- \ Compute new distance from left side swap n:1- \ Decrement distance from airport dup >r \ Push new airport-distance on the r-stack while "____|--O--|____\n" . \ Print final step 2drop r> drop \ Empty s-stack and r-stack ;  ## Scala, 177, 163, 159 137 bytes def p(x:Int,t:Int=5,a:String="\n"):String=a+(if(t>0) " "*x+"--O--"+"\n"*t+"____| |____\n"+p(x-(x-4).signum,t-1)else"____|--O--|____")  Based on another answer, with significant reductions. ## QBIC, 9391 84 bytes :{X=space$(a)+@--O--┘a=a-sgn(a-5)~t>-1|?X[t|?]t=t-1?@____|+@     +_fB|\_xB+A+_fB


Dropped some bytes by replacing the declaration of X$; optimised the FOR loop that prints the distance above-ground. Explanation below is for the old version, but it basically works the same. For testing (and aesthetics) I had a slightly different version, at 103 bytes: :{_z.5|_CX=Y[a|X=X+@ ]X=X+@--O-- a=a-sgn(a-5) ~u>0|?X';[u|?]u=u-1?@____|+@ +_fC|\_xC+_tB+_fC  These are functionally identical. The second one has the addition that the screen gets cleared between frames and that it halts for 0.5 seconds between frames. # Sample output Note that I've added two newlines between frames. The most golfed code above does not add empty lines between frames, the cooler one clears the screen. Command line: 10 --O-- ____| |____ --O-- ____| |____ --O-- ____| |____ --O-- ____| |____ --O-- ____| |____ ____|--O--|____  # Explanation Since I feel this touches upon many things I really like about QBIC, and gives a good insight in how some of its functions work under the hood, I've gone a bit overboard on the explanation. Note that QBIC is, at its core, an QBasic interpreter for Codegolf. QBIC code goes in - QBasic code comes out (and is subsequently executed). :{ get the starting offset (called 'a') from the command line, and start a DO-loop ---- cool code only ---- _z.5|_C At the start of a DO-loop, pause for half a second and clear the screen ---- resume golf-mode ---- ---- #1 - The tip of the left wing is anywhere between 0 and 10 positions to the right. ---- Create the plane with the spacing in X$
X=Y          Clear X$[a| For each point in the current offset X=X+@ ] Add a space to X$
- Every capital letter in QBIC references that letter+$, a variable of type String - @ and  start and end a string literal, in this case a literal space. - ] ends one language construct (an IF, DO or FOR). Here, it's NEXT X=X+@--O-- Create the actual plane - @ and once again create a string literal. Every literal that is created in this way is assigned its own capital letter. This is our second literal, so the body of our plane is stored in B$ (A$contains the space, remember?) ---- #2 Adjust the offset for the next iteration a=a-sgn(a-5) The clever bit: We have an offset X in the range 0 - 10, and 5 attempts to get this to be == 5. X - 5 is either positive (X = 6 - 10), negative (X = 0 - 4) or 0 (X=5). sgn() returns the sign of that subtraction as a 1, -1 or 0 resp. We then sub the sign from 'a', moving it closer to 5. ---- #3 Draw the plane, the empty airspace and the landing strip ~u>0| Are we there yet? - ~ is the IF statement in QBIC - It processes everything until the | as one true/false expression - All the lower-case letters are (or better, could be) references to numeric variables. Since QBasic does not need to post-fix those, they double as 'natural' language: ignored by QBIC and passed as literal code to the QBasic beneath. - The lower-case letters q-z are kinda special: at the start of QBIC, these are set to 1 - 10. We haven't modified 'u' yet, so in the first DO-loop, u=5 ?X'; If we're still air-borne, print X$ (our plane, incl. spacers)
- ? denotes PRINT, as it does in QBasic.
- ' is a code literal in QBIC: everything until the  is not parsed, but
passed on to QBasic.
- In this case, we want a literal ; to appear after PRINT X$. This suppresses QBasic's normal line-break after PRINT. This needs to be a code literal because it is the command to read a String var from the command Line in QBIC. [u|?] FOR EACH meter above the ground, print a newline u=u-1 Descent 1 meter ?@____| Print the LHS of the landing strip +@  plus 5 spaces +_fC| plus the LHS reversed. \ ELSE - touchdown! _x Terminate the program (effectively escape the infinite DO-loop) - the _x command has an interesting property: ULX, or Upper/Lowercase Extensibility. Writing this command with an uppercase _X does something similar, yet different. The _x command terminates, and prints everything found between _x and | before quitting. Uppercase _X does not look for |, but only prints something if it is followed by a character in the ranges a-z and A-Z - it prints the contents of that variable. C+B+_fC But before we quit, print C$ (the LHS of the landing strip) and the plane,
and the LHS flipped.

---- #4 QBIC has left the building
- Did I say _x looks for a | ? Well, that gets added implicitly by QBIC at the end of
the program, or when one ( ']' ) or all ( '}' ) opened language constructs are closed.
- Also, all still opened language constructs are automatically closed at EOF.
FOR I=0TO 4?" "*X;"--O--";CHR$(10)*(4-I)?G$;"|     |";G$X=X-SGN(X-5)?NEXT?G$;"|--O--|";G$ # PHP 7, 139 bytes still awfully long for($x=$argv[1],$d=6;$d--;$x+=5<=>$x)for($i=$p=-1;$i++<$d;print"$s
")for($s=$i<$d?" ":"____| |____ ";!$i&++$p<5;)$s[$x+$p]="--O--"[$p];  takes input from command line argument; run with -r. breakdown for($x=$argv[1], // take input$y=6;$y--; // loop height from 5 to 0$x+=5<=>$x) // post increment/decrement horizontal position for($i=$p=-1;$i++<$y; // loop$i from 0 to height
print"$s\n") // 3. print for($s=$i<$y?" ":"____|     |____\n";   // 1. template=empty or runway+newline
!$i&++$p<5;)$s[$x+$p]="--O--"[$p];  // 2. if \$i=0, paint plane