Vim is a great text editor for unix systems, but it's notorious for being difficult to exit.

Write a full program that will output :q to exit Vim. It should then read a single line of input, as it will then either be given a bash prompt, in which case the exit was successful, or an error, in which case there are unsaved changes.

The bash prompt will be this:

E37@vimmachine: /var/override)

While the error will be this:

E37: No write since last change (add ! to override)

Upon being given the bash prompt, the program's work is done, and it should not give any more output (except for whitespace).

Upon being given the error, your program should randomly (ie each possibility has a non-zero probability of being chosen) output :q!, to exit without saving, or :x, to save and exit.

This is so fewest bytes in each language wins!

share|improve this question
23  
I didn't know :x was a thing! I've always used :wq :) – musicman523 Jun 20 at 13:32
2  
What if my bash prompt is E37: No write since last change? That is, how can an algorithm distinguish a prompt from an error message? – anatolyg Jun 20 at 13:38
3  
@anatolyg it can't, but it also doesn't have to. The given prompt will always be the one above, that is E37@vimmachine: /var/override) – Mayube Jun 20 at 13:38
1  
Why does the prompt end with a )? – immibis Jun 21 at 0:54
2  
The given prompt will always be the one above That should be stated in the challenge spec. As is, it says looks like this, which can mean any number of things. – Dennis Jun 21 at 3:16

18 Answers 18

Python 2, 66 bytes

Saved 3 bytes thanks to @Mr.Xcoder and 4 thanks to @Mayube!

from random import*
if'('in input(':q'):print choice([':x',':q!'])

Try it online!

share|improve this answer
2  
If you switch to Python 2, you can save 1 bytes by using print instead of print(). And you can take the input with quotes – Mr. Xcoder Jun 20 at 14:39
    
@Mr.Xcoder Thanks, it actually saved me 3 bytes! – musicman523 Jun 20 at 14:43
    
Yes, I didn't see you had 2 print statements – Mr. Xcoder Jun 20 at 14:44
3  
I gave this tip to totallyhuman so it's only fair I give it to you as well. You can remove print':q' altogether and change input() to input(':q') – Mayube Jun 20 at 14:47
    
@Mayube oh that's awesome, thank you! – musicman523 Jun 20 at 14:48

Ruby, 35 bytes

p:q
p %i(q! x)[rand 2]if/\(/=~gets

Try it online!

share|improve this answer
1  
You can shave a byte by removing the space between p and :q ;) – ymbirtt Jun 20 at 16:59
1  
awesome and weird! I didn't know that, thanks @ymbirtt – André Jun 20 at 17:27

05AB1E, 19 bytes

„:q,'Nåi„:x…:q!‚.R,

Try it online!

„:q,                # Print the string ":q"
    'Nåi            # If N is in the input
        „:x         #   Push the string ":x"
           …:q!     #   Push the string ":q!"
               ‚    #   Wrap them into an array
                .R, #   Randomly print one of them
share|improve this answer

Python 2, 76 75 72 69 bytes

This answer has been out-golfed.

-1 byte thanks to Rod. -3 bytes thanks to Mayube. -3 bytes thanks to Artyer.

from random import*
print'::qx!'[random()>.5:('N'in input(':q'))*5:2]

Try it online!

share|improve this answer
    
This prints an extra newline where the challenge says it should not give any more output – musicman523 Jun 20 at 13:49
    
@Mayube May we output a newline upon terminating? @Adám sure, that's fine – Stephen S Jun 20 at 13:59
1  
random()>.5 to save a byte – Rod Jun 20 at 14:03
2  
Does the randomness have to be uniformly distributed? If not, you could do random()>0, because there is a very very small chance that random() will return 0. – mbomb007 Jun 20 at 17:09
1  
@Artyer You know what [0, 1) means, right? It means that zero is included because the range is zero-inclusive. stackoverflow.com/a/4396303/2415524 ...The easy way to remember it is that on a number line, closed dots are included, and open dots aren't. Brackets look closed, and parens look open. – mbomb007 Jun 20 at 20:34

Vimscript, 45 41 bytes

ec"q"|exe"/("|ec["q!","x"][getpid()%2]

Shaved off 4 bytes by using getpid() to get a number. (Can anyone think of a shorter way to get a number that won't be the same everywhere, all the time?)

Assuming +3 bytes for invoking Vim with -c to run the above script and - to read input from stdin:

vim -c 'ec"q"|exe"/("|ec["q!","x"][reltime()[1]%2]' -
share|improve this answer

JavaScript, 52 46 bytes

Saved 6 bytes thanks to @ETHProductions

prompt(':q')[30]&&alert(new Date%2?':q!':':x')
share|improve this answer
    
Doesn't there need to be a ! after the :q if the input is an error? – Shaggy Jun 20 at 15:30
    
@Shaggy aww, didn't notice that, there goes 9 bytes – Downgoat Jun 20 at 15:33
    
I think you can save a few bytes with prompt(':q')[30]&&.... Also, new Date%2?':x':':q!' – ETHproductions Jun 20 at 17:01
    
@ETHproductions oh yeah, thanks! not sure how I overlooked a ternary – Downgoat Jun 20 at 17:40

C# (.NET Core), 140 139 138 bytes

using static System.Console;class P{static void Main(){Write(":q");if(ReadLine()[3]==':')Write(new System.Random().Next()>9?":x":":q!");}}

Try it online!

  • 1 byte saved thanks to LiefdeWen!
  • 1 byte saved thanks to Mord Zuber!
share|improve this answer
    
Placing your program in the System namespace makes you able to shorten System.Random to Random, saving 1 byte – LiefdeWen Jun 20 at 13:48
    
@CarlosAlejo works for me in TIO, however it outputs q! not :q! – Mayube Jun 20 at 13:50
1  
@CarlosAlejo Ahh, I didn't even realize that you didn't use a namespace, the question also doesn't say uniformly random, just all possibilities should have non-zero chance so you change .Next(2)>0 to .Next()>9, it leaves a bit of a bad taste in the mouth but it's still legal. – LiefdeWen Jun 20 at 13:56
4  
using static System.Console lets you drop all C. calls, and saves you a byte – Mord Zuber Jun 20 at 16:09
1  
@MordZuber what the...? I didn't even know that was possible! Thank you! – Carlos Alejo Jun 20 at 18:28

Actually, 27 bytes

":q"ü[":x",":q!"]`⌂`J'!,cIƒ

Try it online! (Note: As TIO doesn't play nice with stdin, I've replaced the , (read from stdin) with the literal string, which you can change to test it. Also, you'll need to disable output cache in order to get a different response with the random output.)

Explanation:

":q"ü[":x",":q!"]`⌂`J'!,cIƒ
":q"ü                       - Push the literal :q and print
     [":x",":q!"]           - Push the list of literals :x and :q!
                 `⌂`J       - Push function literals ⌂ (terminate) and J (choose random element from list)
                     '!     - Push the literal !
                       ,    - Read from stdin
                        c   - Pop top two values a,b and return "a".count(b)
                         I  - Pop top three values a,b,c and return b if a is truthy and c if a is falsy
                          ƒ - Pop a function from the stack and call it
share|improve this answer

><>, 32 30 29 bytes

  • Had a redundant !o.
  • -1 byte thanks to Aaron.

iii0["@!qx:q:"ooi{=?;o!ox~oo;

Try it online!

Explanation (old)

"@!qx:q:"ooi~i~i~i{=?;o!ox~oo;
"@!qx:q:"                        Push @!qx:q: on the stack (in reverse)
         oo                      Print :q [stack: @!qx:]
           i~i~i~                Remove first 3 input characters
                 i               Load @ or : from the input (= i)
                  {              Shift stack to the left [stack: !qx:i@]
                   =?            If 4th character was @
                     ;              Exit
                                 Else
                      o             Print :
                       !o           Jump to
                         x          Random direction (left or right because
                                    up and down retrigger x)
                                       Left:
                     ;o!o                 Print x and exit.
                                       Right:
                          ~oo;            Remove x, print q! and exit.

(will update soon)

share|improve this answer
    
I'm not sure this would be allowed, but you could win one byte by reading the 3 characters to discard first, then start working on a new stack with [ : iii0[ wil leave you with an empty stack ; nice one anyway, I like how you populate all your possible outputs at the start to avoid additional quotes – Aaron Jun 21 at 20:36
    
@Aaron Thanks, that's a very neat trick! Why wouldn't it be allowed? – PidgeyUsedGust Jun 22 at 14:04
    
Because you'd be reading the input before having printed the output that leads to its production, which I suppose goes against the spirit of the challenge. However it's not like the challenge can realistically implemented with the official ><> interpreter since python will wait for the input's EOF before executing the ><> code (or something like that) – Aaron Jun 22 at 14:23

APL (Dyalog), 27 bytes

':q'⋄('!'∊⍞)/':q!' ':x'⊃⍨?2

Try it online!

':q' print this

 then

?2 random integer among the first two

⊃⍨ use that to select from

':q!' ':x' this list of two strings

()/ replicate that with, i.e. make n copies of each element in that, where n is

'!'∊⍞ is exclamation point a member of the text input? (Boolean, i.e. 0 or 1)

share|improve this answer

Batch, 98 bytes

@echo :q
@set/ps=
@if %s:~3,1%==@ exit/b
@set/an=%random%%%2
@if %n%==0 (echo :x)else echo :q!
share|improve this answer

Ruby, 33 bytes (32 code, +1 for -n flag)

p:q;$_[?!]? p([:q!,:x][$$%2]): p

I'm not too sure on the $$%2 snippet. I'm using it to generate a random bit to index my array by taking the current ruby process's pid modulo 2, and it'll be fairly unpredictable. .sample adds an extra byte.

Try it online!

share|improve this answer

JavaScript, 76 71 50 bytes

prompt(":q")[3]<"@"?alert(new Date%2?":q!":":x"):0

Saved a bunch of bytes thanks to Artyer and Neil, as well as condensing my ternaries and moving first alert to prompt (duh).

share|improve this answer
2  
Why not just call prompt() directly? (Also, are you allowed prompt(":q")?) – Neil Jun 20 at 14:28
    
You can use the time as a random number (new Date%2 instead of Math.random()>.5), and you can use prompt directly like @Neil said: prompt()[3]< – Artyer Jun 20 at 15:22
    
@Neil Why? I had been doing a .indexOf on it, before I noticed the other way to do it. Forgot to switch back, thanks! – Stephen S Jun 20 at 19:55
    
@Artyer thanks, I had thought of that and then forgot about it – Stephen S Jun 20 at 19:55

Python 2, 64 bytes

import time
if'w'in input(':q'):print'::qx!'[time.time()%2>1::2]

Try it online!

Since this is just an agglomeration of both of these Python answers, I've marked this as community wiki.

share|improve this answer

Python 2, 47 bytes

print'::qx!'[id(0)%3<2:('N'in input(':q'))*5:2]

Try it online

Explanation:

The source of randomness is id(0)%3<2. The function id returns the memory location of the parameter. Passing anything will give a non-deterministic memory address. The result will always be even, but it will only sometimes be divisible by 3. The results modulo 3 vary. So, this can be a source of randomness. Using <2 means that roughly 2/3 of the time, the resulting boolean is True.

The rest of the answer is inspired by this one.

share|improve this answer

TCL, 95 bytes

puts :q;puts [if [string match *!* [gets stdin]] {puts [lindex ":q! :x" [expr round(rand())]]}]

A simple and rather long solution in tcl...

share|improve this answer

Assembly 86Bytes Linux System Calls

global _start
_start:
mov edx,4
mov ecx,g 
mov ebx,1
mov eax,4
int 0x80
g db ':q!',10
share|improve this answer

LOGO, 37 bytes

pr ":q if 4<count rl[pr pick[:q! :x]]
share|improve this answer
    
An explanation would be great. – pajonk Jun 22 at 12:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.