29
\$\begingroup\$

Challenge:

Input:

You take two inputs:
- A string only containing printable ASCII (excluding spaces, tabs or new-lines)
- A printable ASCII character

Output:

The first line will contain the string-input. Every i-modulo-3 first occurrence of this character will move in a South-East direction; every i-modulo-3 second occurrence will move in a South direction; and every i-modulo-3 third occurrence will move in a South-West direction. You'll continue until the characters are about to be at their initial starting position again (which means it will wrap around from one side to the other if necessary), and then you'll print the last line with the string-input again to finish it. (Note that all test cases will end up at their initial input after at most length(input) rows, including the row containing the trailing input. It can be sooner though, as seen in this first test case below, with a length of 14, but ending after 9.)

This may all be pretty vague, so here an example:

Test case 1:

String-input: "This_is_a_test"
Character-input: 's'

Output:

This_is_a_test
    s s    s  
     ss   s   
      s  s    
      sss     
      sss     
      s  s    
     ss   s   
    s s    s  
This_is_a_test

Here is the same test case with the colored paths of the three s:

enter image description here

where the first 's' follows the green path in a South-East direction; the second 's' follows the yellow path in a South direction; and the third 's' follows the light blue path in a South-West direction. (If there would be a fourth 's' it would go in a South-East direction again, which can be seen in some of the other test cases below.)

Challenge rules:

  • The inputs will only contain printable ASCII (excluding spaces, tabs and new-lines)
  • I/O formats are flexible. Can be a new-line delimited string, character matrix, etc. Your call.
  • It is possible that the given character isn't present in the string, in which case you are allowed to either output the input-string once or twice (i.e. "test", 'a' can have either of these as possible output: "test\ntest"/"test").
  • Leading spaces are mandatory; trailing spaces are optional. One or multiple leading/trailing new-lines are allowed.

General rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code.
  • Also, please add an explanation if necessary.

Test cases / more examples:

Test case 2:

String-input: "abcabcabcabcabc"
Character-input: 'b'

Output:

abcabcabcabcabc
  b b b    b b 
   bbb      bb 
    b        b 
   bbb       bb
b b b b      b 
 b  b  b     b 
b b b   b    b
   bb    b   bb
    b     b  b 
    bb     bbb
    b b    bbb 
    b  b  b  b 
    b   bb   bb
b   b   bb   b 
abcabcabcabcabc

Here is the same test case with the colored paths of the five a:

enter image description here

Test case 3:

String-input: "only_two_paths?"
Character-input: 'o'

Output:

only_two_paths?
 o     o       
  o    o       
   o   o       
    o  o       
     o o       
      oo       
       o       
       oo      
       o o     
       o  o    
       o   o   
       o    o  
       o     o 
       o      o
only_two_paths?

Here is the same test case with the colored paths of the two o:

enter image description here

Test case 4:

String-input: "lollollollollol"
Character input: 'l'

Output:

lollollollollol
lll   ll  ll   
 ll   ll  ll   
l ll ll ll ll  
  lll l ll l ll
  llllll  ll ll
l l  ll    ll  
 ll  lll   ll  
l l l lll ll l 
  ll  l ll l  l
l l l l llll l 
 ll  lll  lll  
l l   l    ll  
  ll lll  lllll
  l l l ll l ll
lollollollollol

Here is the same test case with the colored paths of the ten l:

enter image description here

Test case 5:

String-input: "AbCdEeDcBaAbCdEeDcBa_CCCCC"
Character input: 'C'

Output:

AbCdEeDcBaAbCdEeDcBa_CCCCC
C  C        C       C  C  
 C  C       C      C  CCC 
  C  C      C     C  C C C
C  C  C     C    C  C  C  
 C  C  C    C   C  C   C  
  C  C  C   C  C  C    C  
   C  C  C  C C  C     C  
    C  C  C CC  C      C  
     C  C  CC  C       C  
      C  C CC C        C  
       C  C CC         C  
        CC CC C        C  
        CC CC  C       C  
       C  C CC  C      C  
      C  C CC C  C     C  
     C  C   C  C  C    C  
    C  C    CC  C  C   C  
   C  C     C C  C  C  C  
  C  C      C  C  C  C C  
 C  C       C   C  C  CC  
C  C        C    C  C  C  
  C         C     C  C CCC
 C          C      C  CCCC
C           C       C  C  
 C          C        CCCCC
AbCdEeDcBaAbCdEeDcBa_CCCCC

Here is the same test case with the colored paths of the seven C:

enter image description here

Test case 6:

String-input: "XyX"
Character input: 'X'

Output:

XyX
 XX
  X
XyX

Here is the same test case with the colored paths of the two X:

enter image description here

Test case 7:

String-input: "aaaa"
Character input: 'a'

Output:

aaaa
aa  
aaa 
 aaa
aaaa

Here is the same test case with the colored paths of the four a:

enter image description here

\$\endgroup\$
  • \$\begingroup\$ So when the string contains a multiple of 3 of the character, the output might have fewer rows than the length of the string? \$\endgroup\$ – Neil Mar 7 '18 at 10:53
  • \$\begingroup\$ @Neil I'm not sure if it's a multiple of 3, haven't investigated it that much. All I know is that at most length(input) everything matches up again, but it can be sooner as the first test case proves. But it seems you're indeed right about the multiple of 3 part (although I'm not 100% sure). \$\endgroup\$ – Kevin Cruijssen Mar 7 '18 at 11:05
  • \$\begingroup\$ @Neil any string with the character appearing only 3 times in a row will print 3 lines however long it is \$\endgroup\$ – Asone Tuhid Mar 7 '18 at 12:24
  • \$\begingroup\$ Are trailing new lines allowed between 2 printed lines? \$\endgroup\$ – Asone Tuhid Mar 7 '18 at 13:27
  • \$\begingroup\$ @AsoneTuhid Sorry but no. I don't care about any amount of trailing or leading new-lines before or after the entire expected output, but I won't allow in between lines. The diagonal lines wouldn't be correct anymore as well.. \$\endgroup\$ – Kevin Cruijssen Mar 7 '18 at 14:32
1
\$\begingroup\$

Stax, 24 bytes

»v↕*δó‼Γ█|q┬YM╨|·£↕fßßZo

Run and debug it online

This is the ascii representation of the same program.

YxP|Ic{{i3%v-x%%mb-!Czny&PWxP

It gets the indices of all the character, and then mutates them until they are set-wise equal to the original indices. For every change, output a string with the character at those indices.

Y                               Store character in y.  Now the inputs are x and y.
 xP                             Print x.
   |Ic                          Get all indices of y in x. Make a copy.
      {                   W     Loop until cancelled.
       {        m               Map index array using block.
        i3%v-                   Subtract i%3-1 from each element. i is the loop index.
             x%%                Modulo len(x)
                 b-!            Is the mutated array set-equal to the original?
                    C           If so, cancel W loop
                     zny&P      Print a string with y at all specified indices
                           xP   Finally, print x again
\$\endgroup\$
8
\$\begingroup\$

Perl 5, -plF 101 100 99 98 97 96 bytes

Replace the \0 by a literal 0 byte to get 96. Notice that the Try It Online link has 97 bytes because it doesn't seem possible to input a literal 0 character there.

#!/usr/bin/perl -plF
say;say$$l=~y/\0/ /runtil--$l,(s:\Q${\<>}:$$l|=v0 x((++$#$l%3*$l-$l+"@-")%@F).$&;v0:oreg^$$l)eq$_

The code golf perl highlighter thinks # start a comment. How naive 😈

Try it online!

How it works

$l is a counter for which line after the first we are on (it counts down though, so e.g. -3 for 3 lines below the top string).After printing the initial string once it repeatedly does the following.

Search the first string for occurrences of the target character and calculate at which offset it should appear: (++$#$l%3*$l-$l+"@-")%@F which is the current position plus the line number (negative) times -1, 0, 1 (cyclic). Construct a string with that many times \0 followed by the target character and or that into an accumulator $$l (that is a different accumulator for each $l and the reason $l counts down instead of up because $1, $2 etc are read-only). Simularly $#$l refers to a different array each time through the loop. The result is the $lth line but with \0 instead of spaces.

The target charcters in the first string are replaced by \0 so you end up with the original string with "holes" (with \0) at the original positions of the target character. If you xor that with the accumulator the holes get filled if and only if the accumulator has the target characters in the original positions, so the result will be the original string. That is used to terminate the loop. If the loop is not finished yet print the accumulator with \0 replaced by space.

When the loop ends the -p option once more prints the first string and the program is done.

The target character is picked up in a rather tricky way. The ${\<>} converts a line read from STDIN to a reference which is then immediately dereferenced and substituted in the regex. The \Q prefix escapes all characters that are special in a regex (like . and *). The \E is implicit. The o modifier causes the search part to never be evaluated again but just repeated in all subsequent matches (which is good since there is nothing on STDIN anymore).

\$\endgroup\$
  • \$\begingroup\$ I don't think you can put a null byte directly, but you could run it in bash or something. \$\endgroup\$ – FryAmTheEggman Mar 7 '18 at 15:07
  • \$\begingroup\$ @FryAmTheEggman Thanks, that's a nice dodge. But I don't think I will bother. People will just have to trust me that that works if they don't want to try it out themselves :-) \$\endgroup\$ – Ton Hospel Mar 7 '18 at 16:09
  • \$\begingroup\$ Completely fair, but I'll leave the comment so people can see it. Nice golf, by the way :) \$\endgroup\$ – FryAmTheEggman Mar 7 '18 at 16:17
4
\$\begingroup\$

Python 2, 199 193 191 bytes

s,c=input()
print s;l=len(s);r=range;I=j=[i for i in r(l)if s[i]==c]
while 1:
 j=[(j[i]-i%3+1)%l for i in r(len(I))]
 if sorted(j)==I:print s;break
 print''.join((' '+c)[i in j]for i in r(l))

Try it online!


If the loop can exit via exception:

Python 2, 187 bytes

s,c=input()
print s;l=len(s);r=range;I=j=[i for i in r(l)if s[i]==c]
while 1:
 j=[(j[i]-i%3+1)%l for i in r(len(I))]
 if sorted(j)==I:print s;q
 print''.join((' '+c)[i in j]for i in r(l))

Try it online!


  • -4 bytes thanks to Jonathan Frech
  • -2 bytes thanks to Lynn
\$\endgroup\$
  • \$\begingroup\$ Possible 189 bytes (exiting the loop via an exception). \$\endgroup\$ – Jonathan Frech Mar 7 '18 at 19:09
  • \$\begingroup\$ You can drop a pair of parens in (j[i]-i%3+1)%l for two bytes. \$\endgroup\$ – Lynn Mar 7 '18 at 21:51
2
\$\begingroup\$

C (gcc), 261 bytes

i,j,l,k;g(L,t,r,c)char**L;{L[r++][c]=k;c-=t?t-1?:0:-1;l<r||g(L,t,r,c<0?l-1:c%l);}f(S,K){char*s=S,*L[i=1+(l=strlen(s))];for(k=K;i--;)for(L[i]=calloc(j=l,1);j--;)L[i][j]=32;for(puts(s);s[++i];)s[i]-k||g(L,++j%3,0,i);for(i=1;strcmp(*L,L[i]);)puts(L[i++]);puts(s);}

Try it online!

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

JavaScript (Node.js), 197 194 bytes

s=>c=>{(C=console.log)(s);w=0;g=[];while(~(w=s.indexOf(c,w)))g.push(w++);h=(H=_=>g.map(x=>A[x]=c,A=Array(l=s.length).fill` `)&&A.join``)();while(h!=(y=H(g=g.map((x,i)=>(l-~x-i%3)%l))))C(y);C(s)}

Try it online!

Takes inputs in currying syntax, i.e. f(s)(c).

Not a perfect one at all, but I need JS. A lot of functions in function.

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

Ruby, 189 176 171 156 150 146 144 137 bytes

->s,c,r=0..k=s.size,b=[p,s]{d=0;g=s.tr c,n=' '*k;l=r=r.map{|i|l||c==s[i]?(n[z=(i+1-d%3)%k]=g[z]=c;d+=1;z):p}-b;g==s||b<<n&&redo;puts b,s}

Try it online!

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

Jelly, 33 bytes

3ḶNṁ+%⁹L¤‘
Ṅẹ©¥@ÇÇṢ⁻®ƊпṬị;⁶¥ṖY,Y

Try it online!


Call as a function. (dyadic link)

I found some 33-byte alternatives, but no actual improvement.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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