30
\$\begingroup\$

Write a program or function that takes in a nonempty single-line string. The string will either be zero or more spaces followed by one period (a particle), such as . or          ., or the string will be a sequence of one or more alternating forward and back slashes (a wave) that could start with either one, such as \ or /\/ or \/\/\/\/\/\/.

In either case, propagate the particle/wave to the right by one unit.

Specifically, in the particle case, insert a space before the ., moving it one place to the right, then output the resulting string. For example:

. .
 .  .
  .   .
   .    .
    .     .
     .      .
      .       .
       .        .

In the wave case, append either / or \ appropriately so the wave keeps alternating and it's length increases by one, then output the resulting string. For example:

//\
\\/
/\/\/
\/\/\
/\//\/\
\/\\/\/
/\/\/\/\/
\/\/\/\/\

In either case, the output may not have trailing spaces but an optional trailing newline is allowed.

The shortest code in bytes wins.

\$\endgroup\$
1
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$
    – Dennis
    Commented Aug 14, 2016 at 3:33

32 Answers 32

16
\$\begingroup\$

C, 69 bytes

p;f(char*s){p=s[strlen(s)-1]^46;p^=p?93:3022856;printf("%s%s",s,&p);}

This requires a little-endian machine, and output to a terminal that support ASCII escape codes.

p=s[strlen(s)-1]^46 grabs the last ASCII code of the input string, and XORs it with the ASCII code of a dot.

p^=p?93:3022856 will cause p to be p^93 if the ASCII code is not a (back)slash, where p^46^93 == p^115, which will toggle between back and forward slash. If p is a dot, it will instead be 3022856, which is little-endian for "\b .".

printf("%s%s",s,&p); prints the input string followed by the integer p, interpreted as a little-endian byte string.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ This is pure genius. \$\endgroup\$
    – Leaky Nun
    Commented Aug 14, 2016 at 6:22
  • \$\begingroup\$ You can save one byte by replacing 3022856 with '. \b', a multibyte character literal. Awesome answer ! \$\endgroup\$
    – Quentin
    Commented Aug 15, 2016 at 10:09
  • \$\begingroup\$ Could anyone come up with a version of this that doesn't use any stdlib stuff? :) \$\endgroup\$
    – TylerY86
    Commented Sep 26, 2016 at 2:52
12
\$\begingroup\$

Jelly, 17 14 bytes

ṪO*2.ị“ .\/\”ṭ

Try it online! or verify all test cases.

How it works

ṪO*2.ị“ .\/\”ṭ  Main link. Argument: s (string)

Ṫ               Tail; pop and yield the last character.
 O              Ordinal; map “./\” to [46, 47, 92].
  *2.           Elevate the code point to the power 2.5.
                This maps [46, 47, 92] to [14351.41, 15144.14, 81183.84].
     ị“ .\/\”   Index into that string.
                Jelly's indexing is modular, so this takes the indices modulo 5,
                which gives [1.41, 4.14, 3.84].
                Also, for a non-integer index, ị retrieves the elements at both
                adjacent integer indices (1-based). Here, these are [1, 2], [4, 5],
                and [3, 4], so we get " .", "/\", or "\/".
             ṭ  Tack; append the characters to the popped input string.
\$\endgroup\$
1
  • \$\begingroup\$ Huh. Just realised this is 22 bytes in UTF-8. Wonder if other code pages can be used to reduce the byte count of other prorams. \$\endgroup\$
    – TylerY86
    Commented Dec 7, 2019 at 1:49
7
\$\begingroup\$

CJam, 16 bytes

l)_'.={S\}"\/"?|

Try it online! or verify all test cases.

How it works

l                 Read a line from STDIN.
 )_               Shift out the last character and copy it.
   '.=            Compare the copy with a dot.
              ?   If the last character is a dot:
      {S\}            Push " " and swap the dot on top.
          "\/"    Else, push "\/".
               |  Perform set union, ordering by first occurrence.
                    " " '.  | -> " ."
                    '/ "\/" | -> "/\"
                    '\ "\/" | -> "\/"
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Note to self: learn how set union works. This seems to be where most of the bytes were saved when compared to mine. \$\endgroup\$
    – Zwei
    Commented Aug 14, 2016 at 15:56
6
\$\begingroup\$

Python, 41 bytes

lambda s:[s+'\/'[s[-1]>'/'],' '+s][s<'/']

Casework. Uses the sorted order ' ', '.', '/', '\'. For spaces and period, prepends a space. Otherwise, appends a slash or blackslash opposite to the last character.

\$\endgroup\$
5
\$\begingroup\$

Python, ​ 44 ​ ​42 bytes

lambda s:s[:-1]+"\/ /\."[-ord(s[-1])&3::3]

Replaces the last character with the correspond set of two characters. ideone link

(-2 bytes thanks to @xsot's shorter mapping function)

\$\endgroup\$
3
  • \$\begingroup\$ -ord(s[-1])&3 also gives 3 different indices. \$\endgroup\$
    – xsot
    Commented Aug 14, 2016 at 2:05
  • \$\begingroup\$ @xsot Oh nice, I didn't think of &! \$\endgroup\$
    – Sp3000
    Commented Aug 14, 2016 at 2:10
  • \$\begingroup\$ No meme this time? :'( \$\endgroup\$
    – ThreeFx
    Commented Sep 3, 2016 at 19:55
5
\$\begingroup\$

Game Maker Language, 107 bytes

s=argument0;if string_pos(" ",s)return " "+s;if string_pos(s,string_length(s))="/"s+="\"else s+="/"return s
\$\endgroup\$
5
\$\begingroup\$

Vim, 27 23 keystrokes

First vim answer ever, haven't used vim at all really even.

A/<esc>:s#//#/\\<cr>:s#\./# .<cr>

How it works: It appends a / at the end of line, subs // for /\, subs ./ for .

\$\endgroup\$
2
  • \$\begingroup\$ You can avoid escaping the /s if you use a different delimiter, for example s#//#/\\ . \$\endgroup\$
    – m-chrzan
    Commented Aug 17, 2016 at 3:42
  • \$\begingroup\$ Thanks, I had no idea anything like that existed \$\endgroup\$ Commented Aug 17, 2016 at 3:48
4
\$\begingroup\$

MATL, 19 bytes

t47<?0w}'\/'yO)o)]h

Try it online! Or verify all test cases.

Explanation

t        % Input string implicitly. Duplicate
47<      % Are entries less than 47 (i.e dot or spaces)?
?        % If all are
  0      %   Push a 0. When converted to char it will be treated as a space
  w      %   Swap, so that when concatenated the space will be at the beginning
}        % Else
  '\/'   %   Push this string
  y      %   Duplicate the input string onto the top of the stack
  O)     %   Get its last element
  o      %   Convert to number    
  )      %   Use as (modular) index to extract the appropripate entry from '\/'
]        % End
h        % Concatenate string with either leading 0 (converted to char) or
         % trailing '\'  or '/'. Implicitly display
\$\endgroup\$
3
\$\begingroup\$

CJam, 35 26 25 bytes

Saved 9 bytes thanks to dennis

Saved 1 more byte, also thanks to dennis

q:I'.&SI+IW='/=I'\+I'/+??

Try it online!

Probably poorly golfed, but I'm not too familiar with CJam. There's probably a better way to check if an element is in an array, but I couldn't find any operators for that.

Explanation:

q:I e# take input
'.& e# push union of input and ".", effectively checking if input contains it
SI+ e# push string with space in beginning
IW='/= e# push 1 if the last chsaracter in the input is /
I'\+ e# push the input with a \ appended
I'/+ e# push the input with a / appended
? e# ternary if to select correct /
? e# ternary if to select final result
\$\endgroup\$
3
  • 1
    \$\begingroup\$ W is initially -1 and ? works both with blocks and other stack items, so you can reduce your code to q:I'.#)SI+IW='/=I'\+I'/+?? \$\endgroup\$
    – Dennis
    Commented Aug 14, 2016 at 20:30
  • 1
    \$\begingroup\$ To test if a character belongs to a string, you can intersect them with &. \$\endgroup\$
    – Dennis
    Commented Aug 14, 2016 at 23:44
  • \$\begingroup\$ I am so bad at CJam lol \$\endgroup\$
    – Zwei
    Commented Aug 15, 2016 at 2:17
3
\$\begingroup\$

05AB1E, 17 15 bytes

D'.åiðì뤄\/s-J

Explanation

D'.åi              # if input contains dot
     ðì            # prepend a space
       ë           # else
        ¤„\/s-     # subtract last char of input from "\/"
              J    # join remainder to input
                   # implicitly print

Try it online

\$\endgroup\$
2
\$\begingroup\$

C, 85 bytes

j;f(char*n){j=strlen(n)-1;printf("%s%s",n[j]<47?" ":n,n[j]==46?n:n[j]==47?"\\":"/");}

Ideone

I haven't slept for about 20 hours, my code probably can be golfed a lot.

\$\endgroup\$
2
\$\begingroup\$

Brachylog, 35 bytes

t~m["\/.":X]t:"/\ "rm:?{.h" "|r.}c.

Test suite. (Slightly modified.)

\$\endgroup\$
2
\$\begingroup\$

Matlab, 74 71 62 57 bytes

@(s)[s(1:end-1) ' .'+(s(1)>46)*'/.'+(s(end)>47)*[45 -45]]

It computes the last two characters based on the s(1) (first character) - to determine if we're dealing with the \/ case, and the last character s(end) to make the correct tuple for the \/ characters.

\$\endgroup\$
2
\$\begingroup\$

Retina, 19 bytes

\.
 .
/$
/\^H
\\$
\/

^H represents the BS byte. Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Why the backspace character? \$\endgroup\$ Commented Aug 14, 2016 at 19:55
  • \$\begingroup\$ Without it, the next replacement would match the trailing backslash. For example, input / would become /\/. \$\endgroup\$
    – Dennis
    Commented Aug 14, 2016 at 19:58
2
\$\begingroup\$

><>, 47 bytes

i:0(?\
*=?$r\~:1[:"./ \/"{=?@r=?$r~~]:48
l?!;o>

Try it online!

The first line is a standard ><> input loop. The second line chooses the appropriate character from / \ to append to the string, based on the last input character. In addition, if the last input character was a ., the top two elements are switched. Finally, the stack contents are printed in reverse.

\$\endgroup\$
2
\$\begingroup\$

JavaScript, 79 70 65 58 bytes

(a,b="/\\/",i=b.indexOf(a[a.length-1]))=>i<0?" "+a:a+b[i+1]
\$\endgroup\$
6
  • 1
    \$\begingroup\$ Replace b.charAt(i+1) with b[i+1] to save some bytes. Also, this does not work for all test cases. \/ gives `/\`, for example. \$\endgroup\$ Commented Aug 15, 2016 at 13:42
  • \$\begingroup\$ @user2428118 Thanks, bug fixed and code shortened! \$\endgroup\$
    – kamoroso94
    Commented Aug 15, 2016 at 14:02
  • 1
    \$\begingroup\$ init b and i as params with a default value: (a,b=...,i=...)=> to avoid return \$\endgroup\$
    – charlie
    Commented Aug 15, 2016 at 14:35
  • \$\begingroup\$ Ah yes, I forgot about that new feature. Also was able to remove the { } as well because of this. \$\endgroup\$
    – kamoroso94
    Commented Aug 15, 2016 at 14:45
  • \$\begingroup\$ in fact, with a few more steps, you'll converge to the answer of @TylerY86 \$\endgroup\$
    – charlie
    Commented Aug 15, 2016 at 15:06
2
\$\begingroup\$

C# - 46 bytes

s=>s[0]<47?' '+s:s+(s.EndsWith("/")?'\\':'/')

Try it here.

\$\endgroup\$
2
\$\begingroup\$

Haskell, 46 45 44 bytes

f z@(x:_)|x<'/'=' ':z|x<'0'='\\':z|1<2='/':z

Takes advantage of the fact that < . < / < 0 < \ in the ASCII table to save two bytes

\$\endgroup\$
1
\$\begingroup\$

Python 2, 72 bytes

lambda x:x[:-1]+(" .","\/","/\\")[ord(x[-1])/46+(-1,1)[ord(x[-1])%46>0]]

Any help golfing more would be greatly appreciated!

This takes the last character in the input and converts it into its ASCII code to get the corresponding index in the list of two characters. Those two characters are appended to all the characters of the input up until the last one.

\$\endgroup\$
1
\$\begingroup\$

SQF, 91

Using the function-as-a-file format:

s=_this;switch(s select[(count s)-1])do{case".":{" "+s};case"\":{s+"/"};case"/":{s+"\"};}

Call as "STRING" call NAME_OF_COMPILED_FUNCTION

\$\endgroup\$
1
\$\begingroup\$

Perl, 30 + 1 (-p) = 31 bytes

s/\./ ./,s|/$|/\\|||s|\\$|\\/|

Needs -p and -M5.010 or -E to run :

perl -pE 's/\./ ./,s|/$|/\\|||s|\\$|\\/|' <<< ".
  .
    .
/
/\/" 

Straight forward implementation of the challenge. (Note that the || between the last two regex are or, as it might be hard to read, so the three regex are : s/\./ ./, and s|/$|/\\|, and s|\\$|\\/|)

\$\endgroup\$
1
\$\begingroup\$

C#, 54 bytes

s=>s.EndsWith(".")?" "+s:s+(s.EndsWith("/")?"\\":"/");
\$\endgroup\$
1
  • \$\begingroup\$ Provided a 46 byte competitor for you. :) \$\endgroup\$
    – TylerY86
    Commented Sep 3, 2016 at 19:23
1
\$\begingroup\$

PowerShell v2+, 59 58 52 51 bytes

param($n)(" $n","$n/","$n\")['.\/'.IndexOf($n[-1])]

Takes input $n, dumps it an array index operation. We select the element of the array based on the index ['.\/'.IndexOf($n[-1]) -- i.e., based on the last character of the input $n, this will result in 0, 1, or 2. That corresponds to the appropriate string of the array. In any case, the resulting string is left on the pipeline and printing is implicit.

Test cases

PS C:\Tools\Scripts\golfing> 0..7|%{' '*$_+'.'}|%{"$_ => "+(.\wave-particle-duality.ps1 "$_")}
. =>  .
 . =>   .
  . =>    .
   . =>     .
    . =>      .
     . =>       .
      . =>        .
       . =>         .

PS C:\Tools\Scripts\golfing> '/,\,/\,\/,/\/,\/\,/\/\,\/\/'-split','|%{"$_ => "+(.\wave-particle-duality.ps1 "$_")}
/ => /\
\ => \/
/\ => /\/
\/ => \/\
/\/ => /\/\
\/\ => \/\/
/\/\ => /\/\/
\/\/ => \/\/\
\$\endgroup\$
1
\$\begingroup\$

C#, 80 63 bytes

s=>{var c=s[s.Length-1];retu‌​rn c<'/'?" "+s:c>'/'?s+"/":s+"\\‌​";}
\$\endgroup\$
4
  • \$\begingroup\$ Can you get it to work using a lambda expression? \$\endgroup\$
    – TylerY86
    Commented Aug 14, 2016 at 17:09
  • \$\begingroup\$ s=>{var c=s[s.Length-1];return c<'/'?" "+s:c>'/'?s+"/":s+"\\";} 63 dotnetfiddle.net/8x79az \$\endgroup\$
    – TylerY86
    Commented Aug 14, 2016 at 17:22
  • \$\begingroup\$ s=>{var c=s[s.Length-1];return c<47?' '+s:s+(c>47?'/':'\\');} 61 dotnetfiddle.net/ykKIL1 \$\endgroup\$
    – TylerY86
    Commented Sep 3, 2016 at 19:17
  • \$\begingroup\$ Added a 46 byte competitor for you. :) \$\endgroup\$
    – TylerY86
    Commented Sep 3, 2016 at 19:28
1
\$\begingroup\$

ARM machine code on Linux, 50 bytes

Hex dump:

b580 1e41 f811 2f01 2a00 d1fb 3901 780b 1a0a 4601 2001 2704 df00 2000 a103 2202 f013 0303 2b03 4159 df00 bd80 2e202f5c 5c2f

First post here, hope I'm doing this right. This is 32-bit ARM assembly, specifically Thumb-2. The input string is a NUL-terminated string taken in through r0, the output is printed to the stdout. In C-syntax, the prototype for the function would be void func_name(char* string). It is AAPCS (ARM calling convention) complaint, if it weren't then 2 bytes could be shaved off.

Here's the equivalent assembly, with comments explaining what's happening:

    @Input: r0 is char* (the string)
    @Output: Modified string to console
    push {r7,lr} @Save r7 and the link register
    subs r1,r0,#1 @Make a copy of the char*, subtracting because we're
    @going to pre-increment.
    loop: @This loop is a little strlen routine
            ldrb r2,[r1,#1]! @In C-syntax, r2=*++r1;
            cmp r2,#0
            bne loop
    @Now r1 points to the null character that terminates the string
    subs r1,r1,#1 @Make r1 point to the last character
    ldrb r3,[r1] @Load the last character into r3
    subs r2,r1,r0 @r2=length(r0) - 1;
    mov  r1,r0 @r0 holds the original char*
    movs r0,#1 @1 is the file descriptor for stdout
    movs r7,#4 @4 is write
    swi #0

    @Now all the characters from the initial string have been printed,
    @except for the last one, which is currently in r3.

    movs r0,#1 @1 is stdout, have to reload this since the system call
    @returns in r0.
    adr r1,msg @Load msg into r1 (the pointer to the string)
    movs r2,#2 @We're going to print two more characters.

    @Now the bit magic. The ascii codes for '\', '.', and '/' map onto
    @0, 2, and 3 when bitwise anded with 3 (0b11).
    @This will be the offset into our string. However, since we must print
    @2 characters, we need our offsets to be 0, 2, and 4.
    @Therefore, we only set the carry if our value is >=3, then add with
    @carry (adcs). Thus we get the correct offset into the string msg.
    ands r3,r3,#3
    cmp r3,#3 @Sets carry if r3>=3
    adcs r1,r1,r3 @Add the offset to r1
    swi #0 @Make the system call
    pop {r7,pc} @Return and restore r7
msg:
    .ascii "\\/ ./\\" @The three different sequences of 2 characters that
    @can go at the end.
\$\endgroup\$
1
\$\begingroup\$

ECMAScript 6 / 2015 (JavaScript), 41 bytes

s=>s<'/'?' '+s:s+'\\/'[s.slice(-1)>'/'|0]

Good catch Neil.

\$\endgroup\$
4
  • \$\begingroup\$ Your output seems to be incorrect. For the slashes, your code should append the next slash, not prepend it. \$\endgroup\$
    – Dennis
    Commented Aug 14, 2016 at 7:49
  • \$\begingroup\$ Adjusted answer. \$\endgroup\$
    – TylerY86
    Commented Aug 14, 2016 at 8:20
  • \$\begingroup\$ Why not +(s+1)? \$\endgroup\$
    – Neil
    Commented Aug 14, 2016 at 9:55
  • \$\begingroup\$ Better still, s<'/'. \$\endgroup\$
    – Neil
    Commented Aug 14, 2016 at 10:07
1
\$\begingroup\$

R, 119 bytes

a=scan(,"");if((q=strsplit(a,"")[[1]][nchar(a)])=="."){cat(" ",a,sep="")}else{s=switch(q,"/"="\\","/");cat(a,s,sep="")}

Ungolfed :

a=scan(,"")
if((q=strsplit(a,"")[[1]][nchar(a)])==".")
    cat(" ",a,sep="")

else
s=switch(q,"/"="\\","/")
cat(a,s,sep="")
\$\endgroup\$
1
\$\begingroup\$

SED, 41 36 27

saved 7 thanks to charlie

 s|\.| .|;s|/$|/\\|;t;s|$|/|

uses 3 substitutions:
s/\./ ./ adds a space if there is a .
s|/$|/\\|,s|$|/| adds the appropriate slash to the end
uses | instead of / as the delimiter

t branches to the end if the second regex matches so it doesn't add the other slash

\$\endgroup\$
1
  • \$\begingroup\$ I just came to an almost identical solution: s/\./ ./;s./$./\\.;t;s.$./. -- it's 27 bytes. The 3rd substitution is simplified and on my system the -re is not needed. Also, I use . instead of # to stay visually in the input space. ;o) \$\endgroup\$
    – charlie
    Commented Aug 16, 2016 at 9:50
1
\$\begingroup\$

Turtlèd, 32 bytes (noncompeting)

l!-[*+.r_]l(/r'\r)(\r'/)(." .")$

Explanation:

[implicit]                       first cell is an asterisk

l                                move left, off the asterisk, so the '[*+.r_]' loop runs
 !                               take input into string var, char pointer=0, 1st char
  -                              decrement char pointer, mod length input             

   [*    ]                       while current cell isn't *:
     +.                          increment string pointer, and write the pointed char
       r_                        move right, write * if pointed char is last char, else " "

          l                      move left

           (/    )               if the current cell is /
             r'\r                move right, write /, move right

                  (\   )         If the current cell is \
                    r'/          move right, write /

                        (.    )  If the current cell is .
                          " ."   Write " .", the first space overwriting the existing '.'

                               $ Program won't remove leading spaces when printing

    [implicit]                   Program prints grid after finishing execution
\$\endgroup\$
1
\$\begingroup\$

Java 7, 76 bytes

String c(String i){return i.contains(".")?" "+i:i+(i.endsWith("/")?92:'/');}

Pretty straightforward.

Ungolfed & test code:

Try it here.

class M{
  static String c(String i){
    return i.contains(".")
            ? " " + i
            : i + (i.endsWith("/")
                    ? 92
                    : '/');
  }

  public static void main(String[] a){
    System.out.println(c(" ."));
    System.out.println(c("  ."));
    System.out.println(c("   ."));
    System.out.println(c("    ."));
    System.out.println(c("     ."));
    System.out.println(c("      ."));
    System.out.println(c("       ."));
    System.out.println(c("        ."));
    System.out.println(c("/"));
    System.out.println(c("\\"));
    System.out.println(c("/\\"));
    System.out.println(c("\\/"));
    System.out.println(c("/\\/"));
    System.out.println(c("\\/\\"));
    System.out.println(c("/\\/\\"));
    System.out.println(c("\\/\\/"));
  }
}

Output:

  .
   .
    .
     .
      .
       .
        .
         .
/\
\/
/\/
\/\
/\/\
\/\/
/\/\/
\/\/\
\$\endgroup\$

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.