The challenge is to manipulate strings using basic Vim-like commands


  • A string of text to be transformed. The input alphabet is [a-z].
  • A string of legal commands


  • The transformed string

There are a few ideas you should understand:

The cursor is represented as a location between 2 characters. | will be used to represent the cursor(s) in this explanation.

  • |foobar - The cursor at beginning of string
  • foo|bar - Cursor in the middle of the string
  • foobar| - Cursor at the end of the string

A selection is a a group of characters between 2 cursors.

  • |foobar| - The selection is foobar
  • |foo|bar - The selection is foo
  • foo|bar| - the selection is bar
  • |foobar - The selection is the empy string (both cursors at same location)

A selection is formed from the previous cursor position and the result of the current command.

Using the command > on |foo would make the selection |f|oo.

Commands can be described as functions. C<selection> is a command that has a selection parameter. The next command provides the selection.

  • D> deletes the character to the right of the cursor. f|oo -> f|o
  • DNa deletes from the cursor to the next a character f|oobar -> f|ar
  • Etc.

As you can see, commands "associate to the right"

  • DNa is parsed as (D(Na))
  • DDNa is parsed as (D(D(Na)))
  • Etc.

The insert mode command I extends until the next command.

  • DIbar> is parsed as (D(Ibar))(>).

These are the commands:

  • > - Move cursor right. > on foo|bar -> foob|ar
  • < - Move cursor left. < on foo|bar -> fo|obar
  • B - Move cursor to the beginning of the string
  • E - Move cursor to the end of the string
  • N<char> - Move cursor to place before next <char>. Na on |foobar -> foob|ar
  • P<char> - Move cursor to place after previous <char>. Po on foobar| -> foo|bar
  • I<string> - Enter/exit insert mode. Characters in <string> are inserted at the current cursor position. <string> extends until the next command. The cursor is moved to end of insertion <string>. Iquz on foo|bar -> fooquz|bar
  • D<selection> - delete characters in <selection>. f|ooba|r -> f|r. The output selection from this command is the empty string.


  • The cursor cannot move out of bounds. B<<< is the same as B. Nx is the same as E if no x can be found.
  • The cursor location always starts at the beginning of the string
  • The cursor should not be outputted
  • Commands are always uppercase, characters are lowercase.


  • No text editor scripts like Vimscript

Winning criteria:

  • It's code golf. Lowest character count wins.



  • foobar
  • >>><<>If


  • fofobar


  • foobar
  • >>>DNEDPf


  • f


  • foobar
  • >>>DDDDIbazD<Iquz>DPfDII


  • far
  • \$\begingroup\$ "<string> extends until the next command." But how do we know that it's a command rather than part of the string? \$\endgroup\$ Jan 21, 2012 at 21:59
  • \$\begingroup\$ @PeterTaylor Commands are uppercase, characters are lower. \$\endgroup\$
    – Pubby
    Jan 21, 2012 at 22:04
  • \$\begingroup\$ I'm starting to think that this question might be a bit too complicated for a code-golf tag. \$\endgroup\$
    – Mr. Llama
    Jan 23, 2012 at 15:47
  • 2
    \$\begingroup\$ The first example is like teaching a 4th grader how to multiply; the second example is like trying to teach that 4th grader algebra, and the third example is like trying to teach that 4th grader calculus. \$\endgroup\$ Jan 24, 2012 at 15:14

1 Answer 1


Haskell, 371 characters

z l b n i=p where
 p(a:c@ ~(q:u))|Just x<-a`lookup`zip"<>BEDNP"[l#c,m l#c,b#c,m b#c,z(d$k id)(\k _->k"")h(k f)c,m(n q)#u,n q#u]=x
 p('I':q:c)|q>'`'=i q c;p(_:c)=f c;p""=(++).r
d f k(q:x)=k x.f q;d f k""=k"";k&x=k"".(r x++);h q=(.snd.s q);n q k=(\(a,b)->k b.(r a++)).s q
x%c=f c""x;f=z(d(:))(&)n$ \q c->f('I':c).(q:);m f=flip.f.flip;k=const;r=reverse;(#)=(.f);s=span.(/=)

This defines a function % which returns the result of applying the string of commands to the original string.

Example usage:

> "foobar" % ">>>DNEDPf"
> "foobar" % ">>>DDDDIbazD<Iquz>DPfDII"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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