Double Space

April 4, 2017

Our algorithm makes two passes over the input; the first pass counts spaces, then a new string is allocated, and the second pass copies, adding spaces as it goes:

(define (double-space oldstr)
  (define (space? str idx)
    (char=? (string-ref str idx) #\space))
  (let ((oldlen (string-length oldstr)))
    (do ((oldidx 0 (+ oldidx 1))
         (count 0 (+ count (if (space? oldstr oldidx) 1 0))))
        ((= oldidx oldlen)
          (let* ((newlen (+ oldlen count))
                 (newstr (make-string newlen #\space)))
            (do ((oldidx 0 (+ oldidx 1))
                 (newidx 0 (+ newidx (if (space? newstr newidx) 2 1))))
                ((= oldidx oldlen) newstr)
              (string-set! newstr newidx (string-ref oldstr oldidx))))))))

Here are some examples:

> (double-space "hello")
"hello"
> (double-space "hello hello")
"hello  hello"
> (double-space "hello  hello")
"hello    hello"
> (double-space "hello   hello")
"hello      hello"
> (double-space "hello hello hello")
"hello  hello  hello"
> (double-space " hello ")
"  hello  "
> (double-space "")
""
> (double-space " ")
"  "
> (double-space "  ")
"    "
> (double-space "   ")
"      "

There are other ways to do that. Here we convert the string to a list of characters, make a single pass through the list copying two spaces wherever one is found, then reverse the list and convert back to a string:

(define (double-space str)
  (let loop ((xs (string->list str)) (zs (list)))
    (if (null? xs) (list->string (reverse zs))
      (if (char=? (car xs) #\space)
          (loop (cdr xs) (cons #\space (cons #\space zs)))
          (loop (cdr xs) (cons (car xs) zs))))))

All the test cases produce identical results. You can run the program at http://ideone.com/YoEiw9.

Advertisement

Pages: 1 2

15 Responses to “Double Space”

  1. As a perl programmer this one is trivial:

    sub ds{shift=~s{ }{  }rg}
    

    if you don’t want to use s{} could do

    sub ds{join'',map{$_,' 'eq$_?' ':''}split'',shift}
    
  2. Pavel Tumilovich said

    Clojure:

    (defn dup_space
      [input]
      (apply str
             (map
               (fn [c] (if(= \space c) 
                         "  " 
                         (str c)))
               input)))
    
  3. Paul said

    Also not too difficult in Python.

    def double_space(txt):
        return txt.replace(" ", "  ")
    
  4. javascript:

    function double_space(txt){
    return txt.replace(/ /g,’ ‘);
    }

  5. Jussi Piitulainen said

    Read-write Scheme.

    (setlocale LC_ALL "") ;sigh (this is in guile 2.0.9)
    
    (define (double-space-port in out)
      (let ((o (read-char in)))
        (or (eof-object? o)
            (begin
              (write-char o out)
              (case o ((#\space) (write-char o out)))
              (double-space-port in out)))))
    
    (define (double-spaced-string s)
      (let ((out (open-output-string)))
        (double-space-port (open-input-string s) out)
        (get-output-string out)))
    
    (write (double-spaced-string "Taas mennään.  Ja äätkin näkyy!"))
    (newline)
    

    Read-write Python.

    import io
    
    def double_space_io(inio, outio):
        while True:
            o = inio.read(1)
            if not o: return
            outio.write(o)
            if o in ' ': outio.write(o)
    
    def double_space_str(s):
        outio = io.StringIO()
        double_space_io(io.StringIO(s), outio)
        return outio.getvalue()
    
    print(repr(double_space_str("Taas mennään.  Ja äätkin näkyy!")))
    
  6. Rutger said

    Took the Python generator approach. We can feed the double_space generator with characters and they get doubled up.

    import time
    
    def double_space(g):
    	while True:
    		x = next(g)
    		if x == ' ':
    			yield x
    		yield x
    
    def text_streamer(text):
    	i = 0
    	while i < len(text):
    		yield(text[i])
    		i += 1
    		time.sleep(1/10)
    
    text = "Hello  from Python !"
    s = text_streamer(text)
    
    for v in double_space(s):
    	print(v,)
    
  7. Steve said

    MUMPS:

    r !,word,! f i=1:1:$l(word,” “) w:i>1 ” ” w $p(word,” “,i)

    hello, world!
    hello, world!

  8. Globules said

    A Haskell version. (Note: cat -e prints a ‘$’ at the end of a line.)

    main :: IO ()
    main = interact (concatMap (\c -> if c == ' ' then "  " else [c]))
    
    $ printf " foo  bar   \nbaz  zot\n" | ./dblspc | cat -e
      foo    bar      $
    baz    zot$
    
  9. Jeff said

    Nothing difficult for Ruby

    `def double_space(string)
    return string.gsub(/\s/, ‘ ‘)
    end

    puts double_space(“hello word”)`

  10. dup (' ':xs) = ' ':' ':dup xs
    dup ( x :xs) =      x :dup xs
    dup      []  = []
    
  11. for non streaming algorithms the former maybe slow and memory expensive then, we can use ByteStrings (lazy or strict, depends)

    {-# LANGUAGE OverloadedStrings #-}
    import qualified Data.ByteString.Lazy.Char8 as BS
    
    dup' = BS.concatMap d
      where d ' ' = "  "
            d  x  = BS.singleton x
    
  12. […] how easy your favorite programming language makes it to work with strings. The problem is to double every blank in a string. That’s pretty simple but some languages make you deal with string allocation or perhaps, in […]

  13. jleechpe said

    Powershell makes it easy:

    Function Set-DoubleSpace ($a) {$a-replace” “,” “}

    or from STDIN

    (read-host)-replace” “,” “

  14. Aurelio said

    in Java:
    public String doubleSpaces(String in) {

    return in.replace(” “, ” “);
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: